From c93d9e4fa89d6c98e41940632c8466317861d2a7 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 4 Jul 2019 00:16:21 +0000 Subject: Daily bump. From-SVN: r273031 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 905e21d..c881b7b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190703 +20190704 -- cgit v1.1 From 4c5f7762a93f77f3d33669537dd54f9a5de28ec4 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 4 Jul 2019 01:48:57 +0000 Subject: compiler: fix indentation of select statement AST dump Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/184997 From-SVN: r273032 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/statements.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 7ca79c8..9c5c13b 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -bf66d40bc7adb438dcfac85d73bfa7b17217eed9 +197b6fdfb861f07bab7365e350b5b855cfccc290 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 968c8a0..332d63f 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -5766,6 +5766,7 @@ Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const { ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl; this->clauses_->dump_clauses(ast_dump_context); + ast_dump_context->print_indent(); ast_dump_context->ostream() << "}"; } ast_dump_context->ostream() << std::endl; -- cgit v1.1 From 9c5784fa7585c274b188f4df26bb80244ef97cb0 Mon Sep 17 00:00:00 2001 From: Chenghua Xu Date: Thu, 4 Jul 2019 01:54:02 +0000 Subject: [MIPS][Testsuite] Specify msa-fmadd.c abis. gcc/testsuite/ * gcc.target/mips/mips-fmadd.c: Rename to ... * gcc.target/mips/mips-fmadd-o32.c: ... Here; add abi=32. * gcc.target/mips/mips-fmadd-n64.c: New. From-SVN: r273033 --- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.target/mips/msa-fmadd-n64.c | 101 ++++++++++++++++++++++++++ gcc/testsuite/gcc.target/mips/msa-fmadd-o32.c | 101 ++++++++++++++++++++++++++ gcc/testsuite/gcc.target/mips/msa-fmadd.c | 101 -------------------------- 4 files changed, 208 insertions(+), 101 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/msa-fmadd-n64.c create mode 100644 gcc/testsuite/gcc.target/mips/msa-fmadd-o32.c delete mode 100644 gcc/testsuite/gcc.target/mips/msa-fmadd.c (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1695bab..aa00f0b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Chenghua Xu + + * gcc.target/mips/mips-fmadd.c: Rename to ... + * gcc.target/mips/mips-fmadd-o32.c: ... Here; add abi=32. + * gcc.target/mips/mips-fmadd-n64.c: New. + 2019-07-03 Wilco Dijkstra * gcc.dg/store_merging_27.c: Fix test for Arm. diff --git a/gcc/testsuite/gcc.target/mips/msa-fmadd-n64.c b/gcc/testsuite/gcc.target/mips/msa-fmadd-n64.c new file mode 100644 index 0000000..199b366 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msa-fmadd-n64.c @@ -0,0 +1,101 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=64 -mfp64 -mhard-float -mmsa -EL -flax-vector-conversions" } */ +/* { dg-skip-if "uses global registers" { *-*-* } { "-O0" } { "" } } */ + +typedef int v4i32 __attribute__ ((vector_size(16))); +typedef float v4f32 __attribute__ ((vector_size(16))); +typedef double v2f64 __attribute__ ((vector_size(16))); + +/* Test that MSA FMADD-like intrinsics do not use first operand for multiplication. */ + +register v4i32 a __asm__("$f24"); +register v4i32 b __asm__("$f25"); +register v4f32 c __asm__("$f26"); +register v4f32 d __asm__("$f27"); +register v2f64 e __asm__("$f28"); +register v2f64 f __asm__("$f29"); + +void +maddv_b_msa (void) +{ + a = __builtin_msa_maddv_b (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.b\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +maddv_h_msa (void) +{ + a = __builtin_msa_maddv_h (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.h\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +maddv_w_msa (void) +{ + a = __builtin_msa_maddv_w (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.w\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +maddv_d_msa (void) +{ + a = __builtin_msa_maddv_d (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.d\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +msubv_b_msa (void) +{ + a = __builtin_msa_msubv_b (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.b\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +msubv_h_msa (void) +{ + a = __builtin_msa_msubv_h (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.h\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +msubv_w_msa (void) +{ + a = __builtin_msa_msubv_w (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.w\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +msubv_d_msa (void) +{ + a = __builtin_msa_msubv_d (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.d\t\\\$w24,\\\$w25,\\\$w25" } } */ + +void +fmadd_w_msa (void) +{ + c = __builtin_msa_fmadd_w (c, d, d); +} +/* { dg-final { scan-assembler "fmadd\\\.w\t\\\$w26,\\\$w27,\\\$w27" } } */ + +void +fmadd_d_msa (void) +{ + e = __builtin_msa_fmadd_d (e, f, f); +} +/* { dg-final { scan-assembler "fmadd\\\.d\t\\\$w28,\\\$w29,\\\$w29" } } */ + +void +fmsub_w_msa (void) +{ + c = __builtin_msa_fmsub_w (c, d, d); +} +/* { dg-final { scan-assembler "fmsub\\\.w\t\\\$w26,\\\$w27,\\\$w27" } } */ + +void +fmsub_d_msa (void) +{ + e = __builtin_msa_fmsub_d (e, f, f); +} +/* { dg-final { scan-assembler "fmsub\\\.d\t\\\$w28,\\\$w29,\\\$w29" } } */ + diff --git a/gcc/testsuite/gcc.target/mips/msa-fmadd-o32.c b/gcc/testsuite/gcc.target/mips/msa-fmadd-o32.c new file mode 100644 index 0000000..8433369 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/msa-fmadd-o32.c @@ -0,0 +1,101 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=32 -mfp64 -mhard-float -mmsa -EL -flax-vector-conversions" } */ +/* { dg-skip-if "uses global registers" { *-*-* } { "-O0" } { "" } } */ + +typedef int v4i32 __attribute__ ((vector_size(16))); +typedef float v4f32 __attribute__ ((vector_size(16))); +typedef double v2f64 __attribute__ ((vector_size(16))); + +/* Test that MSA FMADD-like intrinsics do not use first operand for multiplication. */ + +register v4i32 a __asm__("$f20"); +register v4i32 b __asm__("$f22"); +register v4f32 c __asm__("$f24"); +register v4f32 d __asm__("$f26"); +register v2f64 e __asm__("$f28"); +register v2f64 f __asm__("$f30"); + +void +maddv_b_msa (void) +{ + a = __builtin_msa_maddv_b (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.b\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +maddv_h_msa (void) +{ + a = __builtin_msa_maddv_h (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.h\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +maddv_w_msa (void) +{ + a = __builtin_msa_maddv_w (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.w\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +maddv_d_msa (void) +{ + a = __builtin_msa_maddv_d (a, b, b); +} +/* { dg-final { scan-assembler "maddv\\\.d\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +msubv_b_msa (void) +{ + a = __builtin_msa_msubv_b (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.b\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +msubv_h_msa (void) +{ + a = __builtin_msa_msubv_h (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.h\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +msubv_w_msa (void) +{ + a = __builtin_msa_msubv_w (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.w\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +msubv_d_msa (void) +{ + a = __builtin_msa_msubv_d (a, b, b); +} +/* { dg-final { scan-assembler "msubv\\\.d\t\\\$w20,\\\$w22,\\\$w22" } } */ + +void +fmadd_w_msa (void) +{ + c = __builtin_msa_fmadd_w (c, d, d); +} +/* { dg-final { scan-assembler "fmadd\\\.w\t\\\$w24,\\\$w26,\\\$w26" } } */ + +void +fmadd_d_msa (void) +{ + e = __builtin_msa_fmadd_d (e, f, f); +} +/* { dg-final { scan-assembler "fmadd\\\.d\t\\\$w28,\\\$w30,\\\$w30" } } */ + +void +fmsub_w_msa (void) +{ + c = __builtin_msa_fmsub_w (c, d, d); +} +/* { dg-final { scan-assembler "fmsub\\\.w\t\\\$w24,\\\$w26,\\\$w26" } } */ + +void +fmsub_d_msa (void) +{ + e = __builtin_msa_fmsub_d (e, f, f); +} +/* { dg-final { scan-assembler "fmsub\\\.d\t\\\$w28,\\\$w30,\\\$w30" } } */ + diff --git a/gcc/testsuite/gcc.target/mips/msa-fmadd.c b/gcc/testsuite/gcc.target/mips/msa-fmadd.c deleted file mode 100644 index 9265c04..0000000 --- a/gcc/testsuite/gcc.target/mips/msa-fmadd.c +++ /dev/null @@ -1,101 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-mfp64 -mhard-float -mmsa -EL -flax-vector-conversions" } */ -/* { dg-skip-if "uses global registers" { *-*-* } { "-O0" } { "" } } */ - -typedef int v4i32 __attribute__ ((vector_size(16))); -typedef float v4f32 __attribute__ ((vector_size(16))); -typedef double v2f64 __attribute__ ((vector_size(16))); - -/* Test that MSA FMADD-like intrinsics do not use first operand for multiplication. */ - -register v4i32 a __asm__("$f20"); -register v4i32 b __asm__("$f22"); -register v4f32 c __asm__("$f24"); -register v4f32 d __asm__("$f26"); -register v2f64 e __asm__("$f28"); -register v2f64 f __asm__("$f30"); - -void -maddv_b_msa (void) -{ - a = __builtin_msa_maddv_b (a, b, b); -} -/* { dg-final { scan-assembler "maddv\\\.b\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -maddv_h_msa (void) -{ - a = __builtin_msa_maddv_h (a, b, b); -} -/* { dg-final { scan-assembler "maddv\\\.h\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -maddv_w_msa (void) -{ - a = __builtin_msa_maddv_w (a, b, b); -} -/* { dg-final { scan-assembler "maddv\\\.w\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -maddv_d_msa (void) -{ - a = __builtin_msa_maddv_d (a, b, b); -} -/* { dg-final { scan-assembler "maddv\\\.d\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -msubv_b_msa (void) -{ - a = __builtin_msa_msubv_b (a, b, b); -} -/* { dg-final { scan-assembler "msubv\\\.b\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -msubv_h_msa (void) -{ - a = __builtin_msa_msubv_h (a, b, b); -} -/* { dg-final { scan-assembler "msubv\\\.h\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -msubv_w_msa (void) -{ - a = __builtin_msa_msubv_w (a, b, b); -} -/* { dg-final { scan-assembler "msubv\\\.w\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -msubv_d_msa (void) -{ - a = __builtin_msa_msubv_d (a, b, b); -} -/* { dg-final { scan-assembler "msubv\\\.d\t\\\$w20,\\\$w22,\\\$w22" } } */ - -void -fmadd_w_msa (void) -{ - c = __builtin_msa_fmadd_w (c, d, d); -} -/* { dg-final { scan-assembler "fmadd\\\.w\t\\\$w24,\\\$w26,\\\$w26" } } */ - -void -fmadd_d_msa (void) -{ - e = __builtin_msa_fmadd_d (e, f, f); -} -/* { dg-final { scan-assembler "fmadd\\\.d\t\\\$w28,\\\$w30,\\\$w30" } } */ - -void -fmsub_w_msa (void) -{ - c = __builtin_msa_fmsub_w (c, d, d); -} -/* { dg-final { scan-assembler "fmsub\\\.w\t\\\$w24,\\\$w26,\\\$w26" } } */ - -void -fmsub_d_msa (void) -{ - e = __builtin_msa_fmsub_d (e, f, f); -} -/* { dg-final { scan-assembler "fmsub\\\.d\t\\\$w28,\\\$w30,\\\$w30" } } */ - -- cgit v1.1 From 0e68d70b7fbf4533d7b5ccd84c439026062b1a0e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 4 Jul 2019 02:20:37 +0000 Subject: compiler: optimize 0,1,2-case select statement For a select statement with zero-, one-, or two-case with a default case, we can generate simpler code instead of calling the generic selectgo. A zero-case select is just blocking the execution. A one-case select is mostly just executing the case. A two-case select with a default case is a non-blocking send or receive. We add these special cases for lowering a select statement. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/184998 From-SVN: r273034 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/gogo.cc | 3 +- gcc/go/gofrontend/runtime.def | 16 +++ gcc/go/gofrontend/statements.cc | 229 ++++++++++++++++++++++++++++++++++++++++ gcc/go/gofrontend/statements.h | 40 ++++++- 5 files changed, 285 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 9c5c13b..410afb0 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -197b6fdfb861f07bab7365e350b5b855cfccc290 +7a8e10be0ddb8909ce25a264d03b24cee4df60cc The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index fcf9a93..3abf7ea 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -6262,7 +6262,8 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) if (this->asm_name_ == "runtime.gopanic" || this->asm_name_ == "__go_runtime_error" - || this->asm_name_ == "runtime.panicdottype") + || this->asm_name_ == "runtime.panicdottype" + || this->asm_name_ == "runtime.block") flags |= Backend::function_does_not_return; } diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index f510a65..c754739 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -204,6 +204,22 @@ DEF_GO_RUNTIME(CHANRECV2, "runtime.chanrecv2", P2(CHAN, POINTER), R1(BOOL)) DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P3(POINTER, POINTER, INT), R2(INT, BOOL)) +// Non-blocking send a value on a channel, used for two-case select +// statement with a default case. +DEF_GO_RUNTIME(SELECTNBSEND, "runtime.selectnbsend", P2(CHAN, POINTER), R1(BOOL)) + +// Non-blocking receive a value from a channel, used for two-case select +// statement with a default case. +DEF_GO_RUNTIME(SELECTNBRECV, "runtime.selectnbrecv", P2(POINTER, CHAN), R1(BOOL)) + +// Non-blocking tuple receive from a channel, used for two-case select +// statement with a default case. +DEF_GO_RUNTIME(SELECTNBRECV2, "runtime.selectnbrecv2", P3(POINTER, POINTER, CHAN), + R1(BOOL)) + +// Block execution. Used for zero-case select. +DEF_GO_RUNTIME(BLOCK, "runtime.block", P0(), R0()) + // Panic. DEF_GO_RUNTIME(GOPANIC, "runtime.gopanic", P1(EFACE), R0()) diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 332d63f..1e88fab 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -5665,6 +5665,28 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function, Block* b = new Block(enclosing, loc); int ncases = this->clauses_->size(); + + // Zero-case select. Just block the execution. + if (ncases == 0) + { + Expression* call = Runtime::make_call(Runtime::BLOCK, loc, 0); + Statement *s = Statement::make_statement(call, false); + b->add_statement(s); + this->is_lowered_ = true; + return Statement::make_block_statement(b, loc); + } + + // One-case select. It is mostly just to run the case. + if (ncases == 1) + return this->lower_one_case(b); + + // Two-case select with one default case. It is a non-blocking + // send/receive. + if (ncases == 2 + && (this->clauses_->at(0).is_default() + || this->clauses_->at(1).is_default())) + return this->lower_two_case(b); + Type* scase_type = Channel_type::select_case_type(); Expression* ncases_expr = Expression::make_integer_ul(ncases, NULL, @@ -5733,6 +5755,213 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function, return Statement::make_block_statement(b, loc); } +// Lower a one-case select statement. + +Statement* +Select_statement::lower_one_case(Block* b) +{ + Select_clauses::Select_clause& scase = this->clauses_->at(0); + Location loc = this->location(); + Expression* chan = scase.channel(); + if (chan != NULL) + { + // Lower this to + // if chan == nil { block() }; send/recv; body + Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc); + b->add_statement(chantmp); + Expression* chanref = Expression::make_temporary_reference(chantmp, loc); + + Expression* nil = Expression::make_nil(loc); + Expression* cond = Expression::make_binary(OPERATOR_EQEQ, chanref, nil, loc); + Block* bnil = new Block(b, loc); + Expression* call = Runtime::make_call(Runtime::BLOCK, loc, 0); + Statement* s = Statement::make_statement(call, false); + bnil->add_statement(s); + Statement* ifs = Statement::make_if_statement(cond, bnil, NULL, loc); + b->add_statement(ifs); + + chanref = chanref->copy(); + Location cloc = scase.location(); + if (scase.is_send()) + { + s = Statement::make_send_statement(chanref, scase.val(), cloc); + b->add_statement(s); + } + else + { + if (scase.closed() == NULL && scase.closedvar() == NULL) + { + // Simple receive. + Expression* recv = Expression::make_receive(chanref, cloc); + if (scase.val() != NULL) + s = Statement::make_assignment(scase.val(), recv, cloc); + else if (scase.var() != NULL) + { + Temporary_statement *ts = + Statement::make_temporary(NULL, recv, cloc); + Expression* ref = + Expression::make_temporary_reference(ts, cloc); + s = ts; + scase.var()->var_value()->set_init(ref); + scase.var()->var_value()->clear_type_from_chan_element(); + } + else + s = Statement::make_statement(recv, false); + b->add_statement(s); + } + else + { + // Tuple receive. + Expression* lhs; + if (scase.val() != NULL) + lhs = scase.val(); + else + { + Type* valtype = chan->type()->channel_type()->element_type(); + Temporary_statement *ts = + Statement::make_temporary(valtype, NULL, cloc); + lhs = Expression::make_temporary_reference(ts, cloc); + b->add_statement(ts); + } + + Expression* lhs2; + if (scase.closed() != NULL) + lhs2 = scase.closed(); + else + { + Type* booltype = Type::make_boolean_type(); + Temporary_statement *ts = + Statement::make_temporary(booltype, NULL, cloc); + lhs2 = Expression::make_temporary_reference(ts, cloc); + b->add_statement(ts); + } + + s = Statement::make_tuple_receive_assignment(lhs, lhs2, chanref, cloc); + b->add_statement(s); + + if (scase.var() != NULL) + { + scase.var()->var_value()->set_init(lhs->copy()); + scase.var()->var_value()->clear_type_from_chan_element(); + } + + if (scase.closedvar() != NULL) + scase.closedvar()->var_value()->set_init(lhs2->copy()); + } + } + } + + Statement* bs = + Statement::make_block_statement(scase.statements(), scase.location()); + b->add_statement(bs); + + this->is_lowered_ = true; + return Statement::make_block_statement(b, loc); +} + +// Lower a two-case select statement with one default case. + +Statement* +Select_statement::lower_two_case(Block* b) +{ + Select_clauses::Select_clause& chancase = + (this->clauses_->at(0).is_default() + ? this->clauses_->at(1) + : this->clauses_->at(0)); + Select_clauses::Select_clause& defcase = + (this->clauses_->at(0).is_default() + ? this->clauses_->at(0) + : this->clauses_->at(1)); + Location loc = this->location(); + Expression* chan = chancase.channel(); + + Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc); + b->add_statement(chantmp); + Expression* chanref = Expression::make_temporary_reference(chantmp, loc); + + Block* bchan; + Expression* call; + if (chancase.is_send()) + { + // if selectnbsend(chan, &val) { body } else { default body } + + Temporary_statement* ts = Statement::make_temporary(NULL, chancase.val(), loc); + // Tell the escape analysis that the value escapes, as it may be sent + // to a channel. + ts->set_value_escapes(); + b->add_statement(ts); + + Expression* ref = Expression::make_temporary_reference(ts, loc); + Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc); + call = Runtime::make_call(Runtime::SELECTNBSEND, loc, 2, chanref, addr); + bchan = chancase.statements(); + } + else + { + Type* valtype = chan->type()->channel_type()->element_type(); + Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc); + b->add_statement(ts); + + Expression* ref = Expression::make_temporary_reference(ts, loc); + Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc); + Expression* okref = NULL; + if (chancase.closed() == NULL && chancase.closedvar() == NULL) + { + // Simple receive. + // if selectnbrecv(&lhs, chan) { body } else { default body } + call = Runtime::make_call(Runtime::SELECTNBRECV, loc, 2, addr, chanref); + } + else + { + // Tuple receive. + // if selectnbrecv2(&lhs, &ok, chan) { body } else { default body } + + Type* booltype = Type::make_boolean_type(); + Temporary_statement* ts = Statement::make_temporary(booltype, NULL, loc); + b->add_statement(ts); + + okref = Expression::make_temporary_reference(ts, loc); + Expression* okaddr = Expression::make_unary(OPERATOR_AND, okref, loc); + call = Runtime::make_call(Runtime::SELECTNBRECV2, loc, 3, addr, okaddr, + chanref); + } + + Location cloc = chancase.location(); + bchan = new Block(b, loc); + if (chancase.val() != NULL && !chancase.val()->is_sink_expression()) + { + Statement* as = Statement::make_assignment(chancase.val(), ref->copy(), + cloc); + bchan->add_statement(as); + } + else if (chancase.var() != NULL) + { + chancase.var()->var_value()->set_init(ref->copy()); + chancase.var()->var_value()->clear_type_from_chan_element(); + } + + if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression()) + { + Statement* as = Statement::make_assignment(chancase.closed(), + okref->copy(), cloc); + bchan->add_statement(as); + } + else if (chancase.closedvar() != NULL) + chancase.closedvar()->var_value()->set_init(okref->copy()); + + Statement* bs = Statement::make_block_statement(chancase.statements(), + cloc); + bchan->add_statement(bs); + } + + Statement* ifs = + Statement::make_if_statement(call, bchan, defcase.statements(), loc); + b->add_statement(ifs); + + this->is_lowered_ = true; + return Statement::make_block_statement(b, loc); +} + // Whether the select statement itself may fall through to the following // statement. diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 432da30..7c254d0 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -1061,7 +1061,7 @@ class Select_clauses // for the variable to set, and CLOSED is either NULL or a // Var_expression to set to whether the channel is closed. If VAL // is NULL, VAR may be a variable to be initialized with the - // received value, and CLOSEDVAR ma be a variable to be initialized + // received value, and CLOSEDVAR may be a variable to be initialized // with whether the channel is closed. IS_DEFAULT is true if this // is the default clause. STATEMENTS is the list of statements to // execute. @@ -1110,7 +1110,6 @@ class Select_clauses void dump_clauses(Ast_dump_context*) const; - private: // A single clause. class Select_clause { @@ -1166,8 +1165,30 @@ class Select_clauses return this->is_send_; } + // Return the value to send or the lvalue to receive into. + Expression* + val() const + { return this->val_; } + + // Return the lvalue to set to whether the channel is closed + // on a receive. + Expression* + closed() const + { return this->closed_; } + + // Return the variable to initialize, for "case a := <-ch". + Named_object* + var() const + { return this->var_; } + + // Return the variable to initialize to whether the channel + // is closed, for "case a, c := <-ch". + Named_object* + closedvar() const + { return this->closedvar_; } + // Return the statements. - const Block* + Block* statements() const { return this->statements_; } @@ -1235,6 +1256,11 @@ class Select_clauses bool is_lowered_; }; + Select_clause& + at(size_t i) + { return this->clauses_.at(i); } + + private: typedef std::vector Clauses; Clauses clauses_; @@ -1288,6 +1314,14 @@ class Select_statement : public Statement do_dump_statement(Ast_dump_context*) const; private: + // Lower a one-case select statement. + Statement* + lower_one_case(Block*); + + // Lower a two-case select statement with one defualt case. + Statement* + lower_two_case(Block*); + // The select clauses. Select_clauses* clauses_; // A temporary that holds the index value returned by selectgo. -- cgit v1.1 From a59b2e42062f2d00fb44a008cd395d0b9590c631 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Jul 2019 06:49:22 +0200 Subject: re PR rtl-optimization/90756 (g++ ICE in convert_move, at expr.c:218 on i686 and s390x) PR rtl-optimization/90756 * explow.c (promote_ssa_mode): Always use TYPE_MODE, don't bypass it for VECTOR_TYPE_P. * gcc.dg/pr90756.c: New test. From-SVN: r273036 --- gcc/ChangeLog | 6 ++++++ gcc/explow.c | 11 +---------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/pr90756.c | 26 ++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr90756.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d6758d..2cfc446 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Jakub Jelinek + + PR rtl-optimization/90756 + * explow.c (promote_ssa_mode): Always use TYPE_MODE, don't bypass it + for VECTOR_TYPE_P. + 2019-07-03 Dennis Zhang * config/aarch64/aarch64.md: Remove redundant constraints from diff --git a/gcc/explow.c b/gcc/explow.c index ba06458..aea7118 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -892,16 +892,7 @@ promote_ssa_mode (const_tree name, int *punsignedp) tree type = TREE_TYPE (name); int unsignedp = TYPE_UNSIGNED (type); - machine_mode mode = TYPE_MODE (type); - - /* Bypass TYPE_MODE when it maps vector modes to BLKmode. */ - if (mode == BLKmode) - { - gcc_assert (VECTOR_TYPE_P (type)); - mode = type->type_common.mode; - } - - machine_mode pmode = promote_mode (type, mode, &unsignedp); + machine_mode pmode = promote_mode (type, TYPE_MODE (type), &unsignedp); if (punsignedp) *punsignedp = unsignedp; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index aa00f0b..66045e5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Jakub Jelinek + + PR rtl-optimization/90756 + * gcc.dg/pr90756.c: New test. + 2019-07-04 Chenghua Xu * gcc.target/mips/mips-fmadd.c: Rename to ... diff --git a/gcc/testsuite/gcc.dg/pr90756.c b/gcc/testsuite/gcc.dg/pr90756.c new file mode 100644 index 0000000..3507aa2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr90756.c @@ -0,0 +1,26 @@ +/* PR rtl-optimization/90756 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wno-psabi" } */ +/* { dg-additional-options "-mno-sse" { target ia32 } } */ + +typedef float B __attribute__((vector_size(4 * sizeof (float)))); +typedef unsigned long long C __attribute__((vector_size(4 * sizeof (long long)))); +typedef short D __attribute__((vector_size(4 * sizeof (short)))); +B z; +void foo (C); +C bar (D); +B baz (); +D qux (B); + +void +quux (int x) +{ + B n = z, b = z; + while (1) + switch (x) + { + case 0: n = baz (); /* FALLTHRU */ + case 1: { B o = n; n = b; b = o; } /* FALLTHRU */ + case 2: { D u = qux (b); C v = bar (u); foo (v); } + } +} -- cgit v1.1 From 6c96b432c912a4c13e53df87050729554284ffa3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Jul 2019 06:54:52 +0200 Subject: re PR tree-optimization/91074 (c-c++-common/gomp/scan-3.c fails with ICE starting with r272958) PR tree-optimization/91074 * omp-low.c (lower_omp_for_scan): Set DECL_GIMPLE_REG_P on cplx temporary. From-SVN: r273037 --- gcc/ChangeLog | 4 ++++ gcc/omp-low.c | 1 + 2 files changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2cfc446..8aed90a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2019-07-04 Jakub Jelinek + PR tree-optimization/91074 + * omp-low.c (lower_omp_for_scan): Set DECL_GIMPLE_REG_P on cplx + temporary. + PR rtl-optimization/90756 * explow.c (promote_ssa_mode): Always use TYPE_MODE, don't bypass it for VECTOR_TYPE_P. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 98a9df5..6e5b532 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -9699,6 +9699,7 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, gimple_seq_add_stmt (body_p, g); tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false)); + DECL_GIMPLE_REG_P (cplx) = 1; g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok); gimple_call_set_lhs (g, cplx); gimple_seq_add_stmt (body_p, g); -- cgit v1.1 From 6218005284d4cf4e9645eb20feb9cf02819b94c9 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Jul 2019 06:55:59 +0200 Subject: omp-low.c (lower_omp_scan): Call lower_omp on stmt's body in worksharing loop scans. * omp-low.c (lower_omp_scan): Call lower_omp on stmt's body in worksharing loop scans. From-SVN: r273038 --- gcc/ChangeLog | 3 +++ gcc/omp-low.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8aed90a..5d3d359 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,8 @@ 2019-07-04 Jakub Jelinek + * omp-low.c (lower_omp_scan): Call lower_omp on stmt's body + in worksharing loop scans. + PR tree-optimization/91074 * omp-low.c (lower_omp_for_scan): Set DECL_GIMPLE_REG_P on cplx temporary. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 6e5b532..7e85d48 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -8874,8 +8874,10 @@ lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx) gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT); gsi_insert_seq_after (gsi_p, before, GSI_SAME_STMT); gsi_replace (gsi_p, gimple_build_nop (), true); + return; } - else if (before) + lower_omp (gimple_omp_body_ptr (stmt), octx); + if (before) { gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (stmt)); gsi_insert_seq_before (&gsi, before, GSI_SAME_STMT); -- cgit v1.1 From 6b150619545449f40d14acb87d636535e1e838ac Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Jul 2019 07:10:52 +0200 Subject: re PR tree-optimization/91069 (Miscompare of 453.povray since r272843) PR middle-end/91069 * gcc.dg/pr91069.c (v2df): Use 2 * sizeof (double) instead of hardcoded 16 for better portability. (v2di): Change from long vector to long long vector. Use 2 * sizeof (long long) instead of hardcoded 16. From-SVN: r273039 --- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.dg/pr91069.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 66045e5..a438167 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2019-07-04 Jakub Jelinek + PR middle-end/91069 + * gcc.dg/pr91069.c (v2df): Use 2 * sizeof (double) instead of + hardcoded 16 for better portability. + (v2di): Change from long vector to long long vector. Use + 2 * sizeof (long long) instead of hardcoded 16. + PR rtl-optimization/90756 * gcc.dg/pr90756.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr91069.c b/gcc/testsuite/gcc.dg/pr91069.c index 221da30..fdb2cfd 100644 --- a/gcc/testsuite/gcc.dg/pr91069.c +++ b/gcc/testsuite/gcc.dg/pr91069.c @@ -1,8 +1,8 @@ /* { dg-do run } */ /* { dg-options "-std=gnu11" } */ -typedef double v2df __attribute__((vector_size(16))); -typedef long v2di __attribute__((vector_size(16))); +typedef double v2df __attribute__((vector_size(2 * sizeof (double)))); +typedef long long v2di __attribute__((vector_size(2 * sizeof (long long)))); void foo (v2df *res, v2df *src) { -- cgit v1.1 From 75da268e1a563a1a52389cd2ecee12d07c45a655 Mon Sep 17 00:00:00 2001 From: Prathamesh Kulkarni Date: Thu, 4 Jul 2019 06:48:42 +0000 Subject: re PR target/88833 ([SVE] Redundant moves for WHILELO-based loops) 2019-07-04 Prathamesh Kulkarni PR target/88833 * fwprop.c (reg_single_def_p): New function. (propagate_rtx_1): Add unconditional else inside RTX_EXTRA case. (forward_propagate_into): New parameter reg_prop_only with default value false. Propagate def's src into loop only if SET_SRC and SET_DEST of def_set have single definitions. Likewise if reg_prop_only is set to true. (fwprop): New param fwprop_addr_p. Integrate fwprop_addr into fwprop. (fwprop_addr): Remove. (pass_rtl_fwprop_addr::execute): Call fwprop with arg set to true. (pass_rtl_fwprop::execute): Call fwprop with arg set to false. * simplify-rtx.c (simplify_subreg): Add case for vector comparison. * config/i386/sse.md (UNSPEC_BLENDV): Adjust pattern. testsuite/ * gfortran.dg/pr88833.f90: New test. From-SVN: r273040 --- gcc/ChangeLog | 19 +++++ gcc/config/i386/sse.md | 7 +- gcc/fwprop.c | 130 +++++++++++++++++++++++----------- gcc/simplify-rtx.c | 11 +++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gfortran.dg/pr88833.f90 | 9 +++ 6 files changed, 136 insertions(+), 45 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/pr88833.f90 (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d3d359..624cf76 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2019-07-04 Prathamesh Kulkarni + + PR target/88833 + * fwprop.c (reg_single_def_p): New function. + (propagate_rtx_1): Add unconditional else inside RTX_EXTRA case. + (forward_propagate_into): New parameter reg_prop_only + with default value false. + Propagate def's src into loop only if SET_SRC and SET_DEST + of def_set have single definitions. + Likewise if reg_prop_only is set to true. + (fwprop): New param fwprop_addr_p. + Integrate fwprop_addr into fwprop. + (fwprop_addr): Remove. + (pass_rtl_fwprop_addr::execute): Call fwprop with arg set + to true. + (pass_rtl_fwprop::execute): Call fwprop with arg set to false. + * simplify-rtx.c (simplify_subreg): Add case for vector comparison. + * config/i386/sse.md (UNSPEC_BLENDV): Adjust pattern. + 2019-07-04 Jakub Jelinek * omp-low.c (lower_omp_scan): Call lower_omp on stmt's body diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 8f50cb1..3fa4560 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -16784,10 +16784,9 @@ (unspec:VF_128_256 [(match_operand:VF_128_256 1 "register_operand" "0,0,x") (match_operand:VF_128_256 2 "vector_operand" "YrBm,*xBm,xm") - (subreg:VF_128_256 - (lt: - (match_operand: 3 "register_operand" "Yz,Yz,x") - (match_operand: 4 "const0_operand" "C,C,C")) 0)] + (lt:VF_128_256 + (match_operand: 3 "register_operand" "Yz,Yz,x") + (match_operand: 4 "const0_operand" "C,C,C"))] UNSPEC_BLENDV))] "TARGET_SSE4_1" "#" diff --git a/gcc/fwprop.c b/gcc/fwprop.c index 45703fe..e6f3752 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -448,6 +448,18 @@ enum { PR_OPTIMIZE_FOR_SPEED = 4 }; +/* Check that X has a single def. */ + +static bool +reg_single_def_p (rtx x) +{ + if (!REG_P (x)) + return false; + + int regno = REGNO (x); + return (DF_REG_DEF_COUNT (regno) == 1 + && !bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)), regno)); +} /* Replace all occurrences of OLD in *PX with NEW and try to simplify the resulting expression. Replace *PX with a new RTL expression if an @@ -547,6 +559,54 @@ propagate_rtx_1 (rtx *px, rtx old_rtx, rtx new_rtx, int flags) tem = simplify_gen_subreg (mode, op0, GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x)); } + + else + { + rtvec vec; + rtvec newvec; + const char *fmt = GET_RTX_FORMAT (code); + rtx op; + + for (int i = 0; fmt[i]; i++) + switch (fmt[i]) + { + case 'E': + vec = XVEC (x, i); + newvec = vec; + for (int j = 0; j < GET_NUM_ELEM (vec); j++) + { + op = RTVEC_ELT (vec, j); + valid_ops &= propagate_rtx_1 (&op, old_rtx, new_rtx, flags); + if (op != RTVEC_ELT (vec, j)) + { + if (newvec == vec) + { + newvec = shallow_copy_rtvec (vec); + if (!tem) + tem = shallow_copy_rtx (x); + XVEC (tem, i) = newvec; + } + RTVEC_ELT (newvec, j) = op; + } + } + break; + + case 'e': + if (XEXP (x, i)) + { + op = XEXP (x, i); + valid_ops &= propagate_rtx_1 (&op, old_rtx, new_rtx, flags); + if (op != XEXP (x, i)) + { + if (!tem) + tem = shallow_copy_rtx (x); + XEXP (tem, i) = op; + } + } + break; + } + } + break; case RTX_OBJ: @@ -1370,10 +1430,11 @@ forward_propagate_and_simplify (df_ref use, rtx_insn *def_insn, rtx def_set) /* Given a use USE of an insn, if it has a single reaching definition, try to forward propagate it into that insn. - Return true if cfg cleanup will be needed. */ + Return true if cfg cleanup will be needed. + REG_PROP_ONLY is true if we should only propagate register copies. */ static bool -forward_propagate_into (df_ref use) +forward_propagate_into (df_ref use, bool reg_prop_only = false) { df_ref def; rtx_insn *def_insn, *use_insn; @@ -1394,10 +1455,6 @@ forward_propagate_into (df_ref use) if (DF_REF_IS_ARTIFICIAL (def)) return false; - /* Do not propagate loop invariant definitions inside the loop. */ - if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father) - return false; - /* Check if the use is still present in the insn! */ use_insn = DF_REF_INSN (use); if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE) @@ -1415,6 +1472,19 @@ forward_propagate_into (df_ref use) if (!def_set) return false; + if (reg_prop_only + && (!reg_single_def_p (SET_SRC (def_set)) + || !reg_single_def_p (SET_DEST (def_set)))) + return false; + + /* Allow propagations into a loop only for reg-to-reg copies, since + replacing one register by another shouldn't increase the cost. */ + + if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father + && (!reg_single_def_p (SET_SRC (def_set)) + || !reg_single_def_p (SET_DEST (def_set)))) + return false; + /* Only try one kind of propagation. If two are possible, we'll do it on the following iterations. */ if (forward_propagate_and_simplify (use, def_insn, def_set) @@ -1483,7 +1553,7 @@ gate_fwprop (void) } static unsigned int -fwprop (void) +fwprop (bool fwprop_addr_p) { unsigned i; @@ -1502,11 +1572,16 @@ fwprop (void) df_ref use = DF_USES_GET (i); if (use) - if (DF_REF_TYPE (use) == DF_REF_REG_USE - || DF_REF_BB (use)->loop_father == NULL - /* The outer most loop is not really a loop. */ - || loop_outer (DF_REF_BB (use)->loop_father) == NULL) - forward_propagate_into (use); + { + if (DF_REF_TYPE (use) == DF_REF_REG_USE + || DF_REF_BB (use)->loop_father == NULL + /* The outer most loop is not really a loop. */ + || loop_outer (DF_REF_BB (use)->loop_father) == NULL) + forward_propagate_into (use, fwprop_addr_p); + + else if (fwprop_addr_p) + forward_propagate_into (use, false); + } } fwprop_done (); @@ -1537,7 +1612,7 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { return gate_fwprop (); } - virtual unsigned int execute (function *) { return fwprop (); } + virtual unsigned int execute (function *) { return fwprop (false); } }; // class pass_rtl_fwprop @@ -1549,33 +1624,6 @@ make_pass_rtl_fwprop (gcc::context *ctxt) return new pass_rtl_fwprop (ctxt); } -static unsigned int -fwprop_addr (void) -{ - unsigned i; - - fwprop_init (); - - /* Go through all the uses. df_uses_create will create new ones at the - end, and we'll go through them as well. */ - for (i = 0; i < DF_USES_TABLE_SIZE (); i++) - { - if (!propagations_left) - break; - - df_ref use = DF_USES_GET (i); - if (use) - if (DF_REF_TYPE (use) != DF_REF_REG_USE - && DF_REF_BB (use)->loop_father != NULL - /* The outer most loop is not really a loop. */ - && loop_outer (DF_REF_BB (use)->loop_father) != NULL) - forward_propagate_into (use); - } - - fwprop_done (); - return 0; -} - namespace { const pass_data pass_data_rtl_fwprop_addr = @@ -1600,7 +1648,7 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { return gate_fwprop (); } - virtual unsigned int execute (function *) { return fwprop_addr (); } + virtual unsigned int execute (function *) { return fwprop (true); } }; // class pass_rtl_fwprop_addr diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 89a46a9..dd2acd4 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -6697,6 +6697,17 @@ simplify_subreg (machine_mode outermode, rtx op, } } + /* If OP is a vector comparison and the subreg is not changing the + number of elements or the size of the elements, change the result + of the comparison to the new mode. */ + if (COMPARISON_P (op) + && VECTOR_MODE_P (outermode) + && VECTOR_MODE_P (innermode) + && known_eq (GET_MODE_NUNITS (outermode), GET_MODE_NUNITS (innermode)) + && known_eq (GET_MODE_UNIT_SIZE (outermode), + GET_MODE_UNIT_SIZE (innermode))) + return simplify_gen_relational (GET_CODE (op), outermode, innermode, + XEXP (op, 0), XEXP (op, 1)); return NULL_RTX; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a438167..5bcd7fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Prathamesh Kulkarni + + PR target/88833 + * gfortran.dg/pr88833.f90: New test. + 2019-07-04 Jakub Jelinek PR middle-end/91069 diff --git a/gcc/testsuite/gfortran.dg/pr88833.f90 b/gcc/testsuite/gfortran.dg/pr88833.f90 new file mode 100644 index 0000000..224e6ce --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr88833.f90 @@ -0,0 +1,9 @@ +! { dg-do assemble { target aarch64_asm_sve_ok } } +! { dg-options "-O3 -march=armv8.2-a+sve --save-temps" } + +subroutine foo(x) + real :: x(100) + x = x + 10 +end subroutine foo + +! { dg-final { scan-assembler {\twhilelo\tp[0-9]+\.s, wzr, (w[0-9]+).*\twhilelo\tp[0-9]+\.s, w[0-9]+, \1} } } -- cgit v1.1 From 6f01ad76c11eacc9f32539f769e4cb3fd169466a Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Jul 2019 09:25:28 +0200 Subject: re PR tree-optimization/91063 (ICE in set_vinfo_for_stmt, at tree-vectorizer.c:676) PR tree-optimization/91063 * tree-vect-stmts.c (vect_init_vector): Call gsi_remove to remove stmt from stmts sequence before calling vect_init_vector_1. Formatting fix. * gcc.dg/gomp/pr91063.c: New test. From-SVN: r273041 --- gcc/ChangeLog | 7 +++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/gomp/pr91063.c | 17 +++++++++++++++++ gcc/tree-vect-stmts.c | 10 +++++++--- 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/gomp/pr91063.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 624cf76..99a653c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-04 Jakub Jelinek + + PR tree-optimization/91063 + * tree-vect-stmts.c (vect_init_vector): Call gsi_remove to remove + stmt from stmts sequence before calling vect_init_vector_1. + Formatting fix. + 2019-07-04 Prathamesh Kulkarni PR target/88833 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5bcd7fb..9021bd7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Jakub Jelinek + + PR tree-optimization/91063 + * gcc.dg/gomp/pr91063.c: New test. + 2019-07-04 Prathamesh Kulkarni PR target/88833 diff --git a/gcc/testsuite/gcc.dg/gomp/pr91063.c b/gcc/testsuite/gcc.dg/gomp/pr91063.c new file mode 100644 index 0000000..32938f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr91063.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/91063 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fopenmp-simd" } */ +/* { dg-additional-options "-mavx512f" { target { i?86-*-* x86_64-*-* } } } */ + +struct S { void *s; }; + +int +foo (struct S *x) +{ + int r = 0; + int i; +#pragma omp simd reduction (+ : r) + for (i = 0; i < 64; ++i) + r += (int) (x->s != 0); + return r; +} diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 313b1b9..ead079d 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -1496,15 +1496,19 @@ vect_init_vector (stmt_vec_info stmt_info, tree val, tree type, promotion of invariant/external defs. */ val = gimple_convert (&stmts, TREE_TYPE (type), val); for (gimple_stmt_iterator gsi2 = gsi_start (stmts); - !gsi_end_p (gsi2); gsi_next (&gsi2)) - vect_init_vector_1 (stmt_info, gsi_stmt (gsi2), gsi); + !gsi_end_p (gsi2); ) + { + init_stmt = gsi_stmt (gsi2); + gsi_remove (&gsi2, false); + vect_init_vector_1 (stmt_info, init_stmt, gsi); + } } } val = build_vector_from_val (type, val); } new_temp = vect_get_new_ssa_name (type, vect_simple_var, "cst_"); - init_stmt = gimple_build_assign (new_temp, val); + init_stmt = gimple_build_assign (new_temp, val); vect_init_vector_1 (stmt_info, init_stmt, gsi); return new_temp; } -- cgit v1.1 From ee7904e91fcdafd4211f89e0244354467d78a3c2 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 4 Jul 2019 07:35:12 +0000 Subject: tree-ssa-sccvn.h (vn_reference_lookup): Add last_vuse_ptr argument. 2019-07-04 Richard Biener * tree-ssa-sccvn.h (vn_reference_lookup): Add last_vuse_ptr argument. * tree-ssa-sccvn.c (last_vuse_ptr, vn_walk_kind): Move globals into... (struct vn_walk_cb_data): New callback data struct. (vn_reference_lookup_2): Adjust. (vn_reference_lookup_3): Likewise. (vn_reference_lookup_pieces): Likewise. (vn_reference_lookup): Likewise, get last_vuse_ptr argument. (visit_reference_op_load): Adjust. From-SVN: r273042 --- gcc/ChangeLog | 13 ++++++++++++ gcc/tree-ssa-sccvn.c | 58 +++++++++++++++++++++++++++++----------------------- gcc/tree-ssa-sccvn.h | 3 ++- 3 files changed, 47 insertions(+), 27 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 99a653c..932eca2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2019-07-04 Richard Biener + + * tree-ssa-sccvn.h (vn_reference_lookup): Add last_vuse_ptr + argument. + * tree-ssa-sccvn.c (last_vuse_ptr, vn_walk_kind): Move + globals into... + (struct vn_walk_cb_data): New callback data struct. + (vn_reference_lookup_2): Adjust. + (vn_reference_lookup_3): Likewise. + (vn_reference_lookup_pieces): Likewise. + (vn_reference_lookup): Likewise, get last_vuse_ptr argument. + (visit_reference_op_load): Adjust. + 2019-07-04 Jakub Jelinek PR tree-optimization/91063 diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 6b39d63..22dd801 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -131,8 +131,6 @@ along with GCC; see the file COPYING3. If not see /* There's no BB_EXECUTABLE but we can use BB_VISITED. */ #define BB_EXECUTABLE BB_VISITED -static tree *last_vuse_ptr; -static vn_lookup_kind vn_walk_kind; static vn_lookup_kind default_vn_walk_kind; /* vn_nary_op hashtable helpers. */ @@ -1648,18 +1646,26 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult) return NULL_TREE; } +struct vn_walk_cb_data +{ + vn_reference_t vr; + tree *last_vuse_ptr; + vn_lookup_kind vn_walk_kind; +}; + /* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_ with the current VUSE and performs the expression lookup. */ static void * -vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *vr_) +vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *data_) { - vn_reference_t vr = (vn_reference_t)vr_; + vn_walk_cb_data *data = (vn_walk_cb_data *)data_; + vn_reference_t vr = data->vr; vn_reference_s **slot; hashval_t hash; - if (last_vuse_ptr) - *last_vuse_ptr = vuse; + if (data->last_vuse_ptr) + *data->last_vuse_ptr = vuse; /* Fixup vuse and hash. */ if (vr->vuse) @@ -1929,10 +1935,11 @@ basic_block vn_context_bb; *DISAMBIGUATE_ONLY is set to true. */ static void * -vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, +vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, bool *disambiguate_only) { - vn_reference_t vr = (vn_reference_t)vr_; + vn_walk_cb_data *data = (vn_walk_cb_data *)data_; + vn_reference_t vr = data->vr; gimple *def_stmt = SSA_NAME_DEF_STMT (vuse); tree base = ao_ref_base (ref); HOST_WIDE_INT offseti, maxsizei; @@ -1979,7 +1986,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, accesses as we then can use TBAA to disambiguate against the clobbering statement when looking up a load (thus the VN_WALKREWRITE guard). */ - if (vn_walk_kind == VN_WALKREWRITE + if (data->vn_walk_kind == VN_WALKREWRITE && is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) /* The overlap restriction breaks down when either access @@ -1992,16 +1999,16 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, || (get_alias_set (lhs) != 0 && ao_ref_alias_set (ref) != 0))) { - tree *saved_last_vuse_ptr = last_vuse_ptr; + tree *saved_last_vuse_ptr = data->last_vuse_ptr; /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ - last_vuse_ptr = NULL; + data->last_vuse_ptr = NULL; tree saved_vuse = vr->vuse; hashval_t saved_hashcode = vr->hashcode; - void *res = vn_reference_lookup_2 (ref, gimple_vuse (def_stmt), vr); + void *res = vn_reference_lookup_2 (ref, gimple_vuse (def_stmt), data); /* Need to restore vr->vuse and vr->hashcode. */ vr->vuse = saved_vuse; vr->hashcode = saved_hashcode; - last_vuse_ptr = saved_last_vuse_ptr; + data->last_vuse_ptr = saved_last_vuse_ptr; if (res && res != (void *)-1) { vn_reference_t vnresult = (vn_reference_t) res; @@ -2306,7 +2313,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, /* 5) For aggregate copies translate the reference through them if the copy kills ref. */ - else if (vn_walk_kind == VN_WALKREWRITE + else if (data->vn_walk_kind == VN_WALKREWRITE && gimple_assign_single_p (def_stmt) && (DECL_P (gimple_assign_rhs1 (def_stmt)) || TREE_CODE (gimple_assign_rhs1 (def_stmt)) == MEM_REF @@ -2426,7 +2433,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, *ref = r; /* Do not update last seen VUSE after translating. */ - last_vuse_ptr = NULL; + data->last_vuse_ptr = NULL; /* Keep looking for the adjusted *REF / VR pair. */ return NULL; @@ -2434,7 +2441,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, /* 6) For memcpy copies translate the reference through them if the copy kills ref. */ - else if (vn_walk_kind == VN_WALKREWRITE + else if (data->vn_walk_kind == VN_WALKREWRITE && is_gimple_reg_type (vr->type) /* ??? Handle BCOPY as well. */ && (gimple_call_builtin_p (def_stmt, BUILT_IN_MEMCPY) @@ -2584,7 +2591,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, *ref = r; /* Do not update last seen VUSE after translating. */ - last_vuse_ptr = NULL; + data->last_vuse_ptr = NULL; /* Keep looking for the adjusted *REF / VR pair. */ return NULL; @@ -2645,13 +2652,13 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type, { ao_ref r; unsigned limit = PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS); - vn_walk_kind = kind; + vn_walk_cb_data data = { &vr1, NULL, kind }; if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands)) *vnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, vn_reference_lookup_2, vn_reference_lookup_3, - vuse_valueize, limit, &vr1); + vuse_valueize, limit, &data); gcc_checking_assert (vr1.operands == shared_lookup_references); } @@ -2666,11 +2673,12 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type, not exist in the hash table or if the result field of the structure was NULL.. VNRESULT will be filled in with the vn_reference_t stored in the hashtable if one exists. When TBAA_P is false assume - we are looking up a store and treat it as having alias-set zero. */ + we are looking up a store and treat it as having alias-set zero. + *LAST_VUSE_PTR will be updated with the VUSE the value lookup succeeded. */ tree vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, - vn_reference_t *vnresult, bool tbaa_p) + vn_reference_t *vnresult, bool tbaa_p, tree *last_vuse_ptr) { vec operands; struct vn_reference_s vr1; @@ -2703,12 +2711,12 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, ao_ref_init (&r, op); if (! tbaa_p) r.ref_alias_set = r.base_alias_set = 0; - vn_walk_kind = kind; + vn_walk_cb_data data = { &vr1, last_vuse_ptr, kind }; wvnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, vn_reference_lookup_2, vn_reference_lookup_3, - vuse_valueize, limit, &vr1); + vuse_valueize, limit, &data); gcc_checking_assert (vr1.operands == shared_lookup_references); if (wvnresult) { @@ -4063,10 +4071,8 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt) tree result; last_vuse = gimple_vuse (stmt); - last_vuse_ptr = &last_vuse; result = vn_reference_lookup (op, gimple_vuse (stmt), - default_vn_walk_kind, NULL, true); - last_vuse_ptr = NULL; + default_vn_walk_kind, NULL, true, &last_vuse); /* We handle type-punning through unions by value-numbering based on offset and size of the access. Be prepared to handle a diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h index bd661bc..93718b2 100644 --- a/gcc/tree-ssa-sccvn.h +++ b/gcc/tree-ssa-sccvn.h @@ -234,7 +234,8 @@ vec vn_reference_operands_for_lookup (tree); tree vn_reference_lookup_pieces (tree, alias_set_type, tree, vec , vn_reference_t *, vn_lookup_kind); -tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *, bool); +tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *, bool, + tree * = NULL); void vn_reference_lookup_call (gcall *, vn_reference_t *, vn_reference_t); vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree, vec , -- cgit v1.1 From dcd59a994affdd191d7025269b18a1043f80a47f Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 4 Jul 2019 08:05:03 +0000 Subject: [Ada] Spurious dimensionality error on aggregate with "others" assoc. This patch fixes a spurious dimensionality error on an array aggregate with a single "others' clause whose expression is a dimensioned entity, The expansion of the aggregate may create copies of the expression, and the dimensionality check must use the type of the expression to retrieve the proper dimension information to check against the dimensions of the array component type. 2019-07-04 Ed Schonberg gcc/ada/ * sem_dim.adb (Analyze_Dimension_Array_Aggregate): If the component is an entity name, its dimensions are those of its type. gcc/testsuite/ * gnat.dg/dimensions2.adb, gnat.dg/dimensions2_phys.ads, gnat.dg/dimensions2_real_numbers.ads: New testcase. From-SVN: r273043 --- gcc/ada/ChangeLog | 6 ++ gcc/ada/sem_dim.adb | 15 +++- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gnat.dg/dimensions2.adb | 20 ++++++ gcc/testsuite/gnat.dg/dimensions2_phys.ads | 80 ++++++++++++++++++++++ gcc/testsuite/gnat.dg/dimensions2_real_numbers.ads | 3 + 6 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/dimensions2.adb create mode 100644 gcc/testsuite/gnat.dg/dimensions2_phys.ads create mode 100644 gcc/testsuite/gnat.dg/dimensions2_real_numbers.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c28a942..62f031c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Ed Schonberg + + * sem_dim.adb (Analyze_Dimension_Array_Aggregate): If the + component is an entity name, its dimensions are those of its + type. + 2019-07-03 Bob Duff * doc/gnat_ugn/gnat_utility_programs.rst: Document new flags in diff --git a/gcc/ada/sem_dim.adb b/gcc/ada/sem_dim.adb index 43b1f23..26c8008 100644 --- a/gcc/ada/sem_dim.adb +++ b/gcc/ada/sem_dim.adb @@ -1233,8 +1233,9 @@ package body Sem_Dim is Dims_Of_Comp_Typ : constant Dimension_Type := Dimensions_Of (Comp_Typ); Exps : constant List_Id := Expressions (N); - Comp : Node_Id; - Expr : Node_Id; + Comp : Node_Id; + Dims_Of_Expr : Dimension_Type; + Expr : Node_Id; Error_Detected : Boolean := False; -- This flag is used in order to indicate if an error has been detected @@ -1281,11 +1282,19 @@ package body Sem_Dim is -- (may happen when an aggregate is converted into a positional -- aggregate). We also must verify that this is a scalar component, -- and not a subaggregate of a multidimensional aggregate. + -- The expression may be an identifier that has been copied several + -- times during expansion, its dimensions are those of its type. + + if Is_Entity_Name (Expr) then + Dims_Of_Expr := Dimensions_Of (Etype (Expr)); + else + Dims_Of_Expr := Dimensions_Of (Expr); + end if; if Comes_From_Source (Original_Node (Expr)) and then Present (Etype (Expr)) and then Is_Numeric_Type (Etype (Expr)) - and then Dimensions_Of (Expr) /= Dims_Of_Comp_Typ + and then Dims_Of_Expr /= Dims_Of_Comp_Typ and then Sloc (Comp) /= Sloc (Prev (Comp)) then -- Check if an error has already been encountered so far diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9021bd7..7147482 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Ed Schonberg + + * gnat.dg/dimensions2.adb, gnat.dg/dimensions2_phys.ads, + gnat.dg/dimensions2_real_numbers.ads: New testcase. + 2019-07-04 Jakub Jelinek PR tree-optimization/91063 diff --git a/gcc/testsuite/gnat.dg/dimensions2.adb b/gcc/testsuite/gnat.dg/dimensions2.adb new file mode 100644 index 0000000..630a44f --- /dev/null +++ b/gcc/testsuite/gnat.dg/dimensions2.adb @@ -0,0 +1,20 @@ +-- { dg-do compile } + +with Dimensions2_phys; use Dimensions2_phys; + +procedure Dimensions2 is + + zero_flow : constant Volumetric_Flow := 0.0 * m**3 / h; + type Node_Flow_Scenario_T is array (Positive range <>) + of Volumetric_Flow with + default_component_value => zero_flow; + subtype Max_Node_Flow_Scenario_T + is Node_Flow_Scenario_T (Natural (1) .. 48); + flow_value_array : Max_Node_Flow_Scenario_T := (1..48 => zero_flow); + flow_value_array1 : Max_Node_Flow_Scenario_T + := (Max_Node_Flow_Scenario_T'Range=> zero_flow); + flow_value_array2 : Max_Node_Flow_Scenario_T := (others => zero_flow); + +begin + null; +end Dimensions2; diff --git a/gcc/testsuite/gnat.dg/dimensions2_phys.ads b/gcc/testsuite/gnat.dg/dimensions2_phys.ads new file mode 100644 index 0000000..675352a --- /dev/null +++ b/gcc/testsuite/gnat.dg/dimensions2_phys.ads @@ -0,0 +1,80 @@ +with ada.numerics.generic_elementary_functions; +with Dimensions2_real_numbers; + +package Dimensions2_Phys is + + type si_type is new Dimensions2_real_numbers.Real with + dimension_system => + ((unit_name => meter, unit_symbol => 'm', dim_symbol => 'L'), + (unit_name => kilogram, unit_symbol => "kg", dim_symbol => 'M'), + (unit_name => second, unit_symbol => 's', dim_symbol => 'T'), + (unit_name => ampere, unit_symbol => 'A', dim_symbol => 'I'), + (unit_name => kelvin, unit_symbol => 'K', dim_symbol => "Theta"), + (unit_name => mole, unit_symbol => "mol", dim_symbol => 'N'), + (unit_name => euro, unit_symbol => "EUR", dim_symbol => 'E')); + + subtype distance is Si_Type with + dimension => (symbol => 'm', meter => 1, others => 0); + + subtype mass is Si_Type with + dimension => (symbol => "kg", kilogram => 1, others => 0); + + subtype time is Si_Type with + dimension => (symbol => 's', second => 1, others => 0); + + subtype electric_current is Si_Type with + dimension => (symbol => 'A', ampere => 1, others => 0); + + subtype temperature is Si_Type with + dimension => (symbol => 'K', kelvin => 1, others => 0); + + subtype amount_of_substance is Si_Type with + dimension => (symbol => "mol", mole => 1, others => 0); + + pragma warnings (off, "*assumed to be*"); + subtype pressure_barg is Dimensions2_real_numbers.Real; + m : constant Distance := 1.0; + kg : constant Mass := 1.0; + s : constant Time := 1.0; + a : constant Electric_Current := 1.0; + k : constant Temperature := 1.0; + mol : constant Amount_Of_Substance := 1.0; + min : constant Time := 1.0; + h : constant Time := 60.0 * min; + + subtype frequency is Si_Type with + dimension => (symbol => "Hz", second => -1, others => 0); + + subtype massflow is Si_Type with + dimension => (symbol => "kg/s", + kilogram => 1, second => -1, others => 0); + + subtype molar_heat_capacity is Si_Type with + dimension => (symbol => "J/(K*mol)", meter => 2, kilogram => 1, + second => -2, kelvin => -1, mole => -1, others => 0); + + subtype molar_flow is Si_Type with + dimension => (symbol => "mol/s", second => -1, mole => 1, others => 0); + + subtype pressure is Si_Type with + dimension => + (symbol => "Pa", meter => -1, kilogram => 1, second => -2, others => 0); + + subtype ratio is Si_Type range 0.0 .. 1.0; + + subtype scalar is Si_Type; + + subtype specific_heat_capacity is Si_Type with + dimension => (symbol => "J/(K*kg)", meter => 2, second => -2, + kelvin => -1, others => 0); + + subtype speed is Si_Type with + dimension => (symbol => "m/s", meter => 1, second => -1, others => 0); + + subtype volume is Si_Type with + dimension => (symbol => "m^3", meter => 3, others => 0); + + subtype volumetric_flow is Si_Type with + dimension => (symbol => "m^3/s", meter => 3, second => -1, others => 0); + +end Dimensions2_Phys; diff --git a/gcc/testsuite/gnat.dg/dimensions2_real_numbers.ads b/gcc/testsuite/gnat.dg/dimensions2_real_numbers.ads new file mode 100644 index 0000000..e7cda0b --- /dev/null +++ b/gcc/testsuite/gnat.dg/dimensions2_real_numbers.ads @@ -0,0 +1,3 @@ +package Dimensions2_Real_Numbers is + type Real is new Long_Float; +end; -- cgit v1.1 From 1708a783b500003d88940ba6ef417efaf045bbc1 Mon Sep 17 00:00:00 2001 From: Thomas Quinot Date: Thu, 4 Jul 2019 08:05:08 +0000 Subject: [Ada] Get_Scos: Remove bogus, dead code The nonsensical snippet was found by Codepeer. No behavior change. 2019-07-04 Thomas Quinot gcc/ada/ * get_scos.adb: Remove bogus, dead code. From-SVN: r273044 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/get_scos.adb | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 62f031c..ee34c62 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Thomas Quinot + + * get_scos.adb: Remove bogus, dead code. + 2019-07-04 Ed Schonberg * sem_dim.adb (Analyze_Dimension_Array_Aggregate): If the diff --git a/gcc/ada/get_scos.adb b/gcc/ada/get_scos.adb index 27cf190..bf6df5e 100644 --- a/gcc/ada/get_scos.adb +++ b/gcc/ada/get_scos.adb @@ -179,12 +179,6 @@ procedure Get_SCOs is Skipc; C := Nextc; exit when C /= LF and then C /= CR; - - if C = ' ' then - Skip_Spaces; - C := Nextc; - exit when C /= LF and then C /= CR; - end if; end loop; end Skip_EOL; -- cgit v1.1 From b7d5159ec9fcc229e47392dc0dfec191d361b398 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Thu, 4 Jul 2019 08:05:13 +0000 Subject: [Ada] GNAT.Sockets: fix socket timeout on recent Windows versions 2019-07-04 Dmitriy Anisimkov gcc/ada/ * doc/gnat_ugn/platform_specific_information.rst: Document Windows socket timeout particularity. * gnat_ugn.texi: Regenerate. * gsocket.h: Include versionhelpers.h. * socket.c (__gnat_minus_500ms): New function. * libgnat/g-sothco.ads (Minus_500ms_Windows_Timeout): New imported function. * libgnat/g-socket.adb (Set_Socket_Option): Refactor to remove 500ms from the requested timeout only on old Windows version. From-SVN: r273045 --- gcc/ada/ChangeLog | 12 + .../doc/gnat_ugn/platform_specific_information.rst | 43 ++++ gcc/ada/gnat_ugn.texi | 246 ++++++++++++--------- gcc/ada/gsocket.h | 1 + gcc/ada/libgnat/g-socket.adb | 26 ++- gcc/ada/libgnat/g-sothco.ads | 7 + gcc/ada/socket.c | 11 + 7 files changed, 238 insertions(+), 108 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ee34c62..789dc5d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,15 @@ +2019-07-04 Dmitriy Anisimkov + + * doc/gnat_ugn/platform_specific_information.rst: Document + Windows socket timeout particularity. + * gnat_ugn.texi: Regenerate. + * gsocket.h: Include versionhelpers.h. + * socket.c (__gnat_minus_500ms): New function. + * libgnat/g-sothco.ads (Minus_500ms_Windows_Timeout): New + imported function. + * libgnat/g-socket.adb (Set_Socket_Option): Refactor to remove + 500ms from the requested timeout only on old Windows version. + 2019-07-04 Thomas Quinot * get_scos.adb: Remove bogus, dead code. diff --git a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst index eaae612..53f4d98 100644 --- a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst +++ b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst @@ -488,6 +488,49 @@ and:: Ada.Command_Line.Argument (1) -> "'*.txt'" +Windows Socket Timeouts +----------------------- + +Microsoft Windows desktops older than ``8.0`` and Microsoft Windows Servers +older than ``2019`` set a socket timeout 500 milliseconds longer than the value +set by setsockopt with ``SO_RCVTIMEO`` and ``SO_SNDTIMEO`` options. The GNAT +runtime makes a correction for the difference in the corresponding Windows +versions. For Windows Server starting with version ``2019``, the user must +provide a manifest file for the GNAT runtime to be able to recognize that +the Windows version does not need the timeout correction. The manifest file +should be located in the same directory as the executable file, and its file +name must match the executable name suffixed by ``.manifest``. For example, +if the executable name is :file:`sock_wto.exe`, then the manifest file name +has to be :file:`sock_wto.exe.manifest`. The manifest file must contain at +least the following data:: + + + + + + + + + + + + + + + + + + + +Without the manifest file, the socket timeout is going to be overcorrected on +these Windows Server versions and the actual time is going to be 500 +milliseconds shorter than what was set with GNAT.Sockets.Set_Socket_Option. +Note that on Microsoft Windows versions where correction is necessary, there +is no way to set a socket timeout shorter than 500 ms. If a socket timeout +shorter than 500 ms is needed on these Windows versions, a call to +Check_Selector should be added before any socket read or write operations. + + .. _Mixed-Language_Programming_on_Windows: Mixed-Language Programming on Windows diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 7371a76..8551a17b 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -463,6 +463,7 @@ Microsoft Windows Topics * CONSOLE and WINDOWS subsystems:: * Temporary Files:: * Disabling Command Line Argument Expansion:: +* Windows Socket Timeouts:: * Mixed-Language Programming on Windows:: * Windows Specific Add-Ons:: @@ -23909,6 +23910,7 @@ platforms. * CONSOLE and WINDOWS subsystems:: * Temporary Files:: * Disabling Command Line Argument Expansion:: +* Windows Socket Timeouts:: * Mixed-Language Programming on Windows:: * Windows Specific Add-Ons:: @@ -24082,7 +24084,7 @@ file will be created. This is particularly useful in networked environments where you may not have write access to some directories. -@node Disabling Command Line Argument Expansion,Mixed-Language Programming on Windows,Temporary Files,Microsoft Windows Topics +@node Disabling Command Line Argument Expansion,Windows Socket Timeouts,Temporary Files,Microsoft Windows Topics @anchor{gnat_ugn/platform_specific_information disabling-command-line-argument-expansion}@anchor{1e1} @subsection Disabling Command Line Argument Expansion @@ -24153,8 +24155,54 @@ and: Ada.Command_Line.Argument (1) -> "'*.txt'" @end example -@node Mixed-Language Programming on Windows,Windows Specific Add-Ons,Disabling Command Line Argument Expansion,Microsoft Windows Topics -@anchor{gnat_ugn/platform_specific_information id13}@anchor{1e2}@anchor{gnat_ugn/platform_specific_information mixed-language-programming-on-windows}@anchor{1e3} +@node Windows Socket Timeouts,Mixed-Language Programming on Windows,Disabling Command Line Argument Expansion,Microsoft Windows Topics +@anchor{gnat_ugn/platform_specific_information windows-socket-timeouts}@anchor{1e2} +@subsection Windows Socket Timeouts + + +Microsoft Windows desktops older than @code{8.0} and Microsoft Windows Servers +older than @code{2019} set a socket timeout 500 milliseconds longer than the value +set by setsockopt with @code{SO_RCVTIMEO} and @code{SO_SNDTIMEO} options. The GNAT +runtime makes a correction for the difference in the corresponding Windows +versions. For Windows Server starting with version @code{2019}, the user must +provide a manifest file for the GNAT runtime to be able to recognize that +the Windows version does not need the timeout correction. The manifest file +should be located in the same directory as the executable file, and its file +name must match the executable name suffixed by @code{.manifest}. For example, +if the executable name is @code{sock_wto.exe}, then the manifest file name +has to be @code{sock_wto.exe.manifest}. The manifest file must contain at +least the following data: + +@example + + + + + + + + + + + + + + + + + +@end example + +Without the manifest file, the socket timeout is going to be overcorrected on +these Windows Server versions and the actual time is going to be 500 +milliseconds shorter than what was set with GNAT.Sockets.Set_Socket_Option. +Note that on Microsoft Windows versions where correction is necessary, there +is no way to set a socket timeout shorter than 500 ms. If a socket timeout +shorter than 500 ms is needed on these Windows versions, a call to +Check_Selector should be added before any socket read or write operations. + +@node Mixed-Language Programming on Windows,Windows Specific Add-Ons,Windows Socket Timeouts,Microsoft Windows Topics +@anchor{gnat_ugn/platform_specific_information id13}@anchor{1e3}@anchor{gnat_ugn/platform_specific_information mixed-language-programming-on-windows}@anchor{1e4} @subsection Mixed-Language Programming on Windows @@ -24176,12 +24224,12 @@ to use the Microsoft tools for your C++ code, you have two choices: Encapsulate your C++ code in a DLL to be linked with your Ada application. In this case, use the Microsoft or whatever environment to build the DLL and use GNAT to build your executable -(@ref{1e4,,Using DLLs with GNAT}). +(@ref{1e5,,Using DLLs with GNAT}). @item Or you can encapsulate your Ada code in a DLL to be linked with the other part of your application. In this case, use GNAT to build the DLL -(@ref{1e5,,Building DLLs with GNAT Project files}) and use the Microsoft +(@ref{1e6,,Building DLLs with GNAT Project files}) and use the Microsoft or whatever environment to build your executable. @end itemize @@ -24238,7 +24286,7 @@ native SEH support is used. @end menu @node Windows Calling Conventions,Introduction to Dynamic Link Libraries DLLs,,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information windows-calling-conventions}@anchor{1e6}@anchor{gnat_ugn/platform_specific_information id14}@anchor{1e7} +@anchor{gnat_ugn/platform_specific_information windows-calling-conventions}@anchor{1e7}@anchor{gnat_ugn/platform_specific_information id14}@anchor{1e8} @subsubsection Windows Calling Conventions @@ -24283,7 +24331,7 @@ are available for Windows: @end menu @node C Calling Convention,Stdcall Calling Convention,,Windows Calling Conventions -@anchor{gnat_ugn/platform_specific_information c-calling-convention}@anchor{1e8}@anchor{gnat_ugn/platform_specific_information id15}@anchor{1e9} +@anchor{gnat_ugn/platform_specific_information c-calling-convention}@anchor{1e9}@anchor{gnat_ugn/platform_specific_information id15}@anchor{1ea} @subsubsection @code{C} Calling Convention @@ -24325,10 +24373,10 @@ is missing, as in the above example, this parameter is set to be the When importing a variable defined in C, you should always use the @code{C} calling convention unless the object containing the variable is part of a DLL (in which case you should use the @code{Stdcall} calling -convention, @ref{1ea,,Stdcall Calling Convention}). +convention, @ref{1eb,,Stdcall Calling Convention}). @node Stdcall Calling Convention,Win32 Calling Convention,C Calling Convention,Windows Calling Conventions -@anchor{gnat_ugn/platform_specific_information stdcall-calling-convention}@anchor{1ea}@anchor{gnat_ugn/platform_specific_information id16}@anchor{1eb} +@anchor{gnat_ugn/platform_specific_information stdcall-calling-convention}@anchor{1eb}@anchor{gnat_ugn/platform_specific_information id16}@anchor{1ec} @subsubsection @code{Stdcall} Calling Convention @@ -24425,7 +24473,7 @@ Note that to ease building cross-platform bindings this convention will be handled as a @code{C} calling convention on non-Windows platforms. @node Win32 Calling Convention,DLL Calling Convention,Stdcall Calling Convention,Windows Calling Conventions -@anchor{gnat_ugn/platform_specific_information win32-calling-convention}@anchor{1ec}@anchor{gnat_ugn/platform_specific_information id17}@anchor{1ed} +@anchor{gnat_ugn/platform_specific_information win32-calling-convention}@anchor{1ed}@anchor{gnat_ugn/platform_specific_information id17}@anchor{1ee} @subsubsection @code{Win32} Calling Convention @@ -24433,7 +24481,7 @@ This convention, which is GNAT-specific is fully equivalent to the @code{Stdcall} calling convention described above. @node DLL Calling Convention,,Win32 Calling Convention,Windows Calling Conventions -@anchor{gnat_ugn/platform_specific_information id18}@anchor{1ee}@anchor{gnat_ugn/platform_specific_information dll-calling-convention}@anchor{1ef} +@anchor{gnat_ugn/platform_specific_information id18}@anchor{1ef}@anchor{gnat_ugn/platform_specific_information dll-calling-convention}@anchor{1f0} @subsubsection @code{DLL} Calling Convention @@ -24441,7 +24489,7 @@ This convention, which is GNAT-specific is fully equivalent to the @code{Stdcall} calling convention described above. @node Introduction to Dynamic Link Libraries DLLs,Using DLLs with GNAT,Windows Calling Conventions,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id19}@anchor{1f0}@anchor{gnat_ugn/platform_specific_information introduction-to-dynamic-link-libraries-dlls}@anchor{1f1} +@anchor{gnat_ugn/platform_specific_information id19}@anchor{1f1}@anchor{gnat_ugn/platform_specific_information introduction-to-dynamic-link-libraries-dlls}@anchor{1f2} @subsubsection Introduction to Dynamic Link Libraries (DLLs) @@ -24525,10 +24573,10 @@ As a side note, an interesting difference between Microsoft DLLs and Unix shared libraries, is the fact that on most Unix systems all public routines are exported by default in a Unix shared library, while under Windows it is possible (but not required) to list exported routines in -a definition file (see @ref{1f2,,The Definition File}). +a definition file (see @ref{1f3,,The Definition File}). @node Using DLLs with GNAT,Building DLLs with GNAT Project files,Introduction to Dynamic Link Libraries DLLs,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id20}@anchor{1f3}@anchor{gnat_ugn/platform_specific_information using-dlls-with-gnat}@anchor{1e4} +@anchor{gnat_ugn/platform_specific_information id20}@anchor{1f4}@anchor{gnat_ugn/platform_specific_information using-dlls-with-gnat}@anchor{1e5} @subsubsection Using DLLs with GNAT @@ -24619,7 +24667,7 @@ example a fictitious DLL called @code{API.dll}. @end menu @node Creating an Ada Spec for the DLL Services,Creating an Import Library,,Using DLLs with GNAT -@anchor{gnat_ugn/platform_specific_information id21}@anchor{1f4}@anchor{gnat_ugn/platform_specific_information creating-an-ada-spec-for-the-dll-services}@anchor{1f5} +@anchor{gnat_ugn/platform_specific_information id21}@anchor{1f5}@anchor{gnat_ugn/platform_specific_information creating-an-ada-spec-for-the-dll-services}@anchor{1f6} @subsubsection Creating an Ada Spec for the DLL Services @@ -24659,7 +24707,7 @@ end API; @end quotation @node Creating an Import Library,,Creating an Ada Spec for the DLL Services,Using DLLs with GNAT -@anchor{gnat_ugn/platform_specific_information id22}@anchor{1f6}@anchor{gnat_ugn/platform_specific_information creating-an-import-library}@anchor{1f7} +@anchor{gnat_ugn/platform_specific_information id22}@anchor{1f7}@anchor{gnat_ugn/platform_specific_information creating-an-import-library}@anchor{1f8} @subsubsection Creating an Import Library @@ -24673,7 +24721,7 @@ as in this case it is possible to link directly against the DLL. Otherwise read on. @geindex Definition file -@anchor{gnat_ugn/platform_specific_information the-definition-file}@anchor{1f2} +@anchor{gnat_ugn/platform_specific_information the-definition-file}@anchor{1f3} @subsubheading The Definition File @@ -24721,17 +24769,17 @@ EXPORTS @end table Note that you must specify the correct suffix (@code{@@@emph{nn}}) -(see @ref{1e6,,Windows Calling Conventions}) for a Stdcall +(see @ref{1e7,,Windows Calling Conventions}) for a Stdcall calling convention function in the exported symbols list. There can actually be other sections in a definition file, but these sections are not relevant to the discussion at hand. -@anchor{gnat_ugn/platform_specific_information create-def-file-automatically}@anchor{1f8} +@anchor{gnat_ugn/platform_specific_information create-def-file-automatically}@anchor{1f9} @subsubheading Creating a Definition File Automatically You can automatically create the definition file @code{API.def} -(see @ref{1f2,,The Definition File}) from a DLL. +(see @ref{1f3,,The Definition File}) from a DLL. For that use the @code{dlltool} program as follows: @quotation @@ -24741,7 +24789,7 @@ $ dlltool API.dll -z API.def --export-all-symbols @end example Note that if some routines in the DLL have the @code{Stdcall} convention -(@ref{1e6,,Windows Calling Conventions}) with stripped @code{@@@emph{nn}} +(@ref{1e7,,Windows Calling Conventions}) with stripped @code{@@@emph{nn}} suffix then you'll have to edit @code{api.def} to add it, and specify @code{-k} to @code{gnatdll} when creating the import library. @@ -24765,13 +24813,13 @@ tells you what symbol is expected. You just have to go back to the definition file and add the right suffix. @end itemize @end quotation -@anchor{gnat_ugn/platform_specific_information gnat-style-import-library}@anchor{1f9} +@anchor{gnat_ugn/platform_specific_information gnat-style-import-library}@anchor{1fa} @subsubheading GNAT-Style Import Library To create a static import library from @code{API.dll} with the GNAT tools you should create the .def file, then use @code{gnatdll} tool -(see @ref{1fa,,Using gnatdll}) as follows: +(see @ref{1fb,,Using gnatdll}) as follows: @quotation @@ -24787,15 +24835,15 @@ definition file name is @code{xyz.def}, the import library name will be @code{libxyz.a}. Note that in the previous example option @code{-e} could have been removed because the name of the definition file (before the @code{.def} suffix) is the same as the name of the -DLL (@ref{1fa,,Using gnatdll} for more information about @code{gnatdll}). +DLL (@ref{1fb,,Using gnatdll} for more information about @code{gnatdll}). @end quotation -@anchor{gnat_ugn/platform_specific_information msvs-style-import-library}@anchor{1fb} +@anchor{gnat_ugn/platform_specific_information msvs-style-import-library}@anchor{1fc} @subsubheading Microsoft-Style Import Library A Microsoft import library is needed only if you plan to make an Ada DLL available to applications developed with Microsoft -tools (@ref{1e3,,Mixed-Language Programming on Windows}). +tools (@ref{1e4,,Mixed-Language Programming on Windows}). To create a Microsoft-style import library for @code{API.dll} you should create the .def file, then build the actual import library using @@ -24819,7 +24867,7 @@ See the Microsoft documentation for further details about the usage of @end quotation @node Building DLLs with GNAT Project files,Building DLLs with GNAT,Using DLLs with GNAT,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id23}@anchor{1fc}@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnat-project-files}@anchor{1e5} +@anchor{gnat_ugn/platform_specific_information id23}@anchor{1fd}@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnat-project-files}@anchor{1e6} @subsubsection Building DLLs with GNAT Project files @@ -24835,7 +24883,7 @@ when inside the @code{DllMain} routine which is used for auto-initialization of shared libraries, so it is not possible to have library level tasks in SALs. @node Building DLLs with GNAT,Building DLLs with gnatdll,Building DLLs with GNAT Project files,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnat}@anchor{1fd}@anchor{gnat_ugn/platform_specific_information id24}@anchor{1fe} +@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnat}@anchor{1fe}@anchor{gnat_ugn/platform_specific_information id24}@anchor{1ff} @subsubsection Building DLLs with GNAT @@ -24866,7 +24914,7 @@ $ gcc -shared -shared-libgcc -o api.dll obj1.o obj2.o ... It is important to note that in this case all symbols found in the object files are automatically exported. It is possible to restrict the set of symbols to export by passing to @code{gcc} a definition -file (see @ref{1f2,,The Definition File}). +file (see @ref{1f3,,The Definition File}). For example: @example @@ -24904,7 +24952,7 @@ $ gnatmake main -Iapilib -bargs -shared -largs -Lapilib -lAPI @end quotation @node Building DLLs with gnatdll,Ada DLLs and Finalization,Building DLLs with GNAT,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnatdll}@anchor{1ff}@anchor{gnat_ugn/platform_specific_information id25}@anchor{200} +@anchor{gnat_ugn/platform_specific_information building-dlls-with-gnatdll}@anchor{200}@anchor{gnat_ugn/platform_specific_information id25}@anchor{201} @subsubsection Building DLLs with gnatdll @@ -24912,8 +24960,8 @@ $ gnatmake main -Iapilib -bargs -shared -largs -Lapilib -lAPI @geindex building Note that it is preferred to use GNAT Project files -(@ref{1e5,,Building DLLs with GNAT Project files}) or the built-in GNAT -DLL support (@ref{1fd,,Building DLLs with GNAT}) or to build DLLs. +(@ref{1e6,,Building DLLs with GNAT Project files}) or the built-in GNAT +DLL support (@ref{1fe,,Building DLLs with GNAT}) or to build DLLs. This section explains how to build DLLs containing Ada code using @code{gnatdll}. These DLLs will be referred to as Ada DLLs in the @@ -24929,20 +24977,20 @@ non-Ada applications are as follows: You need to mark each Ada entity exported by the DLL with a @code{C} or @code{Stdcall} calling convention to avoid any Ada name mangling for the entities exported by the DLL -(see @ref{201,,Exporting Ada Entities}). You can +(see @ref{202,,Exporting Ada Entities}). You can skip this step if you plan to use the Ada DLL only from Ada applications. @item Your Ada code must export an initialization routine which calls the routine @code{adainit} generated by @code{gnatbind} to perform the elaboration of -the Ada code in the DLL (@ref{202,,Ada DLLs and Elaboration}). The initialization +the Ada code in the DLL (@ref{203,,Ada DLLs and Elaboration}). The initialization routine exported by the Ada DLL must be invoked by the clients of the DLL to initialize the DLL. @item When useful, the DLL should also export a finalization routine which calls routine @code{adafinal} generated by @code{gnatbind} to perform the -finalization of the Ada code in the DLL (@ref{203,,Ada DLLs and Finalization}). +finalization of the Ada code in the DLL (@ref{204,,Ada DLLs and Finalization}). The finalization routine exported by the Ada DLL must be invoked by the clients of the DLL when the DLL services are no further needed. @@ -24952,11 +25000,11 @@ of the programming languages to which you plan to make the DLL available. @item You must provide a definition file listing the exported entities -(@ref{1f2,,The Definition File}). +(@ref{1f3,,The Definition File}). @item Finally you must use @code{gnatdll} to produce the DLL and the import -library (@ref{1fa,,Using gnatdll}). +library (@ref{1fb,,Using gnatdll}). @end itemize Note that a relocatable DLL stripped using the @code{strip} @@ -24976,7 +25024,7 @@ chapter of the @emph{GPRbuild User's Guide}. @end menu @node Limitations When Using Ada DLLs from Ada,Exporting Ada Entities,,Building DLLs with gnatdll -@anchor{gnat_ugn/platform_specific_information limitations-when-using-ada-dlls-from-ada}@anchor{204} +@anchor{gnat_ugn/platform_specific_information limitations-when-using-ada-dlls-from-ada}@anchor{205} @subsubsection Limitations When Using Ada DLLs from Ada @@ -24997,7 +25045,7 @@ It is completely safe to exchange plain elementary, array or record types, Windows object handles, etc. @node Exporting Ada Entities,Ada DLLs and Elaboration,Limitations When Using Ada DLLs from Ada,Building DLLs with gnatdll -@anchor{gnat_ugn/platform_specific_information exporting-ada-entities}@anchor{201}@anchor{gnat_ugn/platform_specific_information id26}@anchor{205} +@anchor{gnat_ugn/platform_specific_information exporting-ada-entities}@anchor{202}@anchor{gnat_ugn/platform_specific_information id26}@anchor{206} @subsubsection Exporting Ada Entities @@ -25097,10 +25145,10 @@ end API; Note that if you do not export the Ada entities with a @code{C} or @code{Stdcall} convention you will have to provide the mangled Ada names in the definition file of the Ada DLL -(@ref{206,,Creating the Definition File}). +(@ref{207,,Creating the Definition File}). @node Ada DLLs and Elaboration,,Exporting Ada Entities,Building DLLs with gnatdll -@anchor{gnat_ugn/platform_specific_information ada-dlls-and-elaboration}@anchor{202}@anchor{gnat_ugn/platform_specific_information id27}@anchor{207} +@anchor{gnat_ugn/platform_specific_information ada-dlls-and-elaboration}@anchor{203}@anchor{gnat_ugn/platform_specific_information id27}@anchor{208} @subsubsection Ada DLLs and Elaboration @@ -25118,7 +25166,7 @@ the Ada elaboration routine @code{adainit} generated by the GNAT binder (@ref{b4,,Binding with Non-Ada Main Programs}). See the body of @code{Initialize_Api} for an example. Note that the GNAT binder is automatically invoked during the DLL build process by the @code{gnatdll} -tool (@ref{1fa,,Using gnatdll}). +tool (@ref{1fb,,Using gnatdll}). When a DLL is loaded, Windows systematically invokes a routine called @code{DllMain}. It would therefore be possible to call @code{adainit} @@ -25131,7 +25179,7 @@ time), which means that the GNAT run-time will deadlock waiting for the newly created task to complete its initialization. @node Ada DLLs and Finalization,Creating a Spec for Ada DLLs,Building DLLs with gnatdll,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id28}@anchor{208}@anchor{gnat_ugn/platform_specific_information ada-dlls-and-finalization}@anchor{203} +@anchor{gnat_ugn/platform_specific_information id28}@anchor{209}@anchor{gnat_ugn/platform_specific_information ada-dlls-and-finalization}@anchor{204} @subsubsection Ada DLLs and Finalization @@ -25146,10 +25194,10 @@ routine @code{adafinal} generated by the GNAT binder See the body of @code{Finalize_Api} for an example. As already pointed out the GNAT binder is automatically invoked during the DLL build process by the @code{gnatdll} tool -(@ref{1fa,,Using gnatdll}). +(@ref{1fb,,Using gnatdll}). @node Creating a Spec for Ada DLLs,GNAT and Windows Resources,Ada DLLs and Finalization,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id29}@anchor{209}@anchor{gnat_ugn/platform_specific_information creating-a-spec-for-ada-dlls}@anchor{20a} +@anchor{gnat_ugn/platform_specific_information id29}@anchor{20a}@anchor{gnat_ugn/platform_specific_information creating-a-spec-for-ada-dlls}@anchor{20b} @subsubsection Creating a Spec for Ada DLLs @@ -25207,7 +25255,7 @@ end API; @end menu @node Creating the Definition File,Using gnatdll,,Creating a Spec for Ada DLLs -@anchor{gnat_ugn/platform_specific_information creating-the-definition-file}@anchor{206}@anchor{gnat_ugn/platform_specific_information id30}@anchor{20b} +@anchor{gnat_ugn/platform_specific_information creating-the-definition-file}@anchor{207}@anchor{gnat_ugn/platform_specific_information id30}@anchor{20c} @subsubsection Creating the Definition File @@ -25243,7 +25291,7 @@ EXPORTS @end quotation @node Using gnatdll,,Creating the Definition File,Creating a Spec for Ada DLLs -@anchor{gnat_ugn/platform_specific_information using-gnatdll}@anchor{1fa}@anchor{gnat_ugn/platform_specific_information id31}@anchor{20c} +@anchor{gnat_ugn/platform_specific_information using-gnatdll}@anchor{1fb}@anchor{gnat_ugn/platform_specific_information id31}@anchor{20d} @subsubsection Using @code{gnatdll} @@ -25454,7 +25502,7 @@ asks @code{gnatlink} to generate the routines @code{DllMain} and is loaded into memory. @item -@code{gnatdll} uses @code{dlltool} (see @ref{20d,,Using dlltool}) to build the +@code{gnatdll} uses @code{dlltool} (see @ref{20e,,Using dlltool}) to build the export table (@code{api.exp}). The export table contains the relocation information in a form which can be used during the final link to ensure that the Windows loader is able to place the DLL anywhere in memory. @@ -25493,7 +25541,7 @@ $ gnatbind -n api $ gnatlink api api.exp -o api.dll -mdll @end example @end itemize -@anchor{gnat_ugn/platform_specific_information using-dlltool}@anchor{20d} +@anchor{gnat_ugn/platform_specific_information using-dlltool}@anchor{20e} @subsubheading Using @code{dlltool} @@ -25552,7 +25600,7 @@ DLL in the static import library generated by @code{dlltool} with switch @item @code{-k} Kill @code{@@@emph{nn}} from exported names -(@ref{1e6,,Windows Calling Conventions} +(@ref{1e7,,Windows Calling Conventions} for a discussion about @code{Stdcall}-style symbols. @end table @@ -25608,7 +25656,7 @@ Use @code{assembler-name} as the assembler. The default is @code{as}. @end table @node GNAT and Windows Resources,Using GNAT DLLs from Microsoft Visual Studio Applications,Creating a Spec for Ada DLLs,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information gnat-and-windows-resources}@anchor{20e}@anchor{gnat_ugn/platform_specific_information id32}@anchor{20f} +@anchor{gnat_ugn/platform_specific_information gnat-and-windows-resources}@anchor{20f}@anchor{gnat_ugn/platform_specific_information id32}@anchor{210} @subsubsection GNAT and Windows Resources @@ -25703,7 +25751,7 @@ the corresponding Microsoft documentation. @end menu @node Building Resources,Compiling Resources,,GNAT and Windows Resources -@anchor{gnat_ugn/platform_specific_information building-resources}@anchor{210}@anchor{gnat_ugn/platform_specific_information id33}@anchor{211} +@anchor{gnat_ugn/platform_specific_information building-resources}@anchor{211}@anchor{gnat_ugn/platform_specific_information id33}@anchor{212} @subsubsection Building Resources @@ -25723,7 +25771,7 @@ complete description of the resource script language can be found in the Microsoft documentation. @node Compiling Resources,Using Resources,Building Resources,GNAT and Windows Resources -@anchor{gnat_ugn/platform_specific_information compiling-resources}@anchor{212}@anchor{gnat_ugn/platform_specific_information id34}@anchor{213} +@anchor{gnat_ugn/platform_specific_information compiling-resources}@anchor{213}@anchor{gnat_ugn/platform_specific_information id34}@anchor{214} @subsubsection Compiling Resources @@ -25765,7 +25813,7 @@ $ windres -i myres.res -o myres.o @end quotation @node Using Resources,,Compiling Resources,GNAT and Windows Resources -@anchor{gnat_ugn/platform_specific_information using-resources}@anchor{214}@anchor{gnat_ugn/platform_specific_information id35}@anchor{215} +@anchor{gnat_ugn/platform_specific_information using-resources}@anchor{215}@anchor{gnat_ugn/platform_specific_information id35}@anchor{216} @subsubsection Using Resources @@ -25785,7 +25833,7 @@ $ gnatmake myprog -largs myres.o @end quotation @node Using GNAT DLLs from Microsoft Visual Studio Applications,Debugging a DLL,GNAT and Windows Resources,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information using-gnat-dll-from-msvs}@anchor{216}@anchor{gnat_ugn/platform_specific_information using-gnat-dlls-from-microsoft-visual-studio-applications}@anchor{217} +@anchor{gnat_ugn/platform_specific_information using-gnat-dll-from-msvs}@anchor{217}@anchor{gnat_ugn/platform_specific_information using-gnat-dlls-from-microsoft-visual-studio-applications}@anchor{218} @subsubsection Using GNAT DLLs from Microsoft Visual Studio Applications @@ -25819,7 +25867,7 @@ $ gprbuild -p mylib.gpr @item Produce a .def file for the symbols you need to interface with, either by hand or automatically with possibly some manual adjustments -(see @ref{1f8,,Creating Definition File Automatically}): +(see @ref{1f9,,Creating Definition File Automatically}): @end enumerate @quotation @@ -25836,7 +25884,7 @@ $ dlltool libmylib.dll -z libmylib.def --export-all-symbols Make sure that MSVS command-line tools are accessible on the path. @item -Create the Microsoft-style import library (see @ref{1fb,,MSVS-Style Import Library}): +Create the Microsoft-style import library (see @ref{1fc,,MSVS-Style Import Library}): @end enumerate @quotation @@ -25878,7 +25926,7 @@ or copy the DLL into into the directory containing the .exe. @end enumerate @node Debugging a DLL,Setting Stack Size from gnatlink,Using GNAT DLLs from Microsoft Visual Studio Applications,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information id36}@anchor{218}@anchor{gnat_ugn/platform_specific_information debugging-a-dll}@anchor{219} +@anchor{gnat_ugn/platform_specific_information id36}@anchor{219}@anchor{gnat_ugn/platform_specific_information debugging-a-dll}@anchor{21a} @subsubsection Debugging a DLL @@ -25916,7 +25964,7 @@ tools suite used to build the DLL. @end menu @node Program and DLL Both Built with GCC/GNAT,Program Built with Foreign Tools and DLL Built with GCC/GNAT,,Debugging a DLL -@anchor{gnat_ugn/platform_specific_information id37}@anchor{21a}@anchor{gnat_ugn/platform_specific_information program-and-dll-both-built-with-gcc-gnat}@anchor{21b} +@anchor{gnat_ugn/platform_specific_information id37}@anchor{21b}@anchor{gnat_ugn/platform_specific_information program-and-dll-both-built-with-gcc-gnat}@anchor{21c} @subsubsection Program and DLL Both Built with GCC/GNAT @@ -25926,7 +25974,7 @@ the process. Let's suppose here that the main procedure is named @code{ada_main} and that in the DLL there is an entry point named @code{ada_dll}. -The DLL (@ref{1f1,,Introduction to Dynamic Link Libraries (DLLs)}) and +The DLL (@ref{1f2,,Introduction to Dynamic Link Libraries (DLLs)}) and program must have been built with the debugging information (see GNAT -g switch). Here are the step-by-step instructions for debugging it: @@ -25966,7 +26014,7 @@ you can use the standard approach to debug the whole program (@ref{24,,Running and Debugging Ada Programs}). @node Program Built with Foreign Tools and DLL Built with GCC/GNAT,,Program and DLL Both Built with GCC/GNAT,Debugging a DLL -@anchor{gnat_ugn/platform_specific_information program-built-with-foreign-tools-and-dll-built-with-gcc-gnat}@anchor{21c}@anchor{gnat_ugn/platform_specific_information id38}@anchor{21d} +@anchor{gnat_ugn/platform_specific_information program-built-with-foreign-tools-and-dll-built-with-gcc-gnat}@anchor{21d}@anchor{gnat_ugn/platform_specific_information id38}@anchor{21e} @subsubsection Program Built with Foreign Tools and DLL Built with GCC/GNAT @@ -25983,7 +26031,7 @@ example some C code built with Microsoft Visual C) and that there is a DLL named @code{test.dll} containing an Ada entry point named @code{ada_dll}. -The DLL (see @ref{1f1,,Introduction to Dynamic Link Libraries (DLLs)}) must have +The DLL (see @ref{1f2,,Introduction to Dynamic Link Libraries (DLLs)}) must have been built with debugging information (see the GNAT @code{-g} option). @subsubheading Debugging the DLL Directly @@ -26122,7 +26170,7 @@ approach to debug a program as described in @ref{24,,Running and Debugging Ada Programs}. @node Setting Stack Size from gnatlink,Setting Heap Size from gnatlink,Debugging a DLL,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information setting-stack-size-from-gnatlink}@anchor{136}@anchor{gnat_ugn/platform_specific_information id39}@anchor{21e} +@anchor{gnat_ugn/platform_specific_information setting-stack-size-from-gnatlink}@anchor{136}@anchor{gnat_ugn/platform_specific_information id39}@anchor{21f} @subsubsection Setting Stack Size from @code{gnatlink} @@ -26165,7 +26213,7 @@ because the comma is a separator for this option. @end itemize @node Setting Heap Size from gnatlink,,Setting Stack Size from gnatlink,Mixed-Language Programming on Windows -@anchor{gnat_ugn/platform_specific_information setting-heap-size-from-gnatlink}@anchor{137}@anchor{gnat_ugn/platform_specific_information id40}@anchor{21f} +@anchor{gnat_ugn/platform_specific_information setting-heap-size-from-gnatlink}@anchor{137}@anchor{gnat_ugn/platform_specific_information id40}@anchor{220} @subsubsection Setting Heap Size from @code{gnatlink} @@ -26198,7 +26246,7 @@ because the comma is a separator for this option. @end itemize @node Windows Specific Add-Ons,,Mixed-Language Programming on Windows,Microsoft Windows Topics -@anchor{gnat_ugn/platform_specific_information windows-specific-add-ons}@anchor{220}@anchor{gnat_ugn/platform_specific_information win32-specific-addons}@anchor{221} +@anchor{gnat_ugn/platform_specific_information windows-specific-add-ons}@anchor{221}@anchor{gnat_ugn/platform_specific_information win32-specific-addons}@anchor{222} @subsection Windows Specific Add-Ons @@ -26211,7 +26259,7 @@ This section describes the Windows specific add-ons. @end menu @node Win32Ada,wPOSIX,,Windows Specific Add-Ons -@anchor{gnat_ugn/platform_specific_information win32ada}@anchor{222}@anchor{gnat_ugn/platform_specific_information id41}@anchor{223} +@anchor{gnat_ugn/platform_specific_information win32ada}@anchor{223}@anchor{gnat_ugn/platform_specific_information id41}@anchor{224} @subsubsection Win32Ada @@ -26242,7 +26290,7 @@ gprbuild p.gpr @end quotation @node wPOSIX,,Win32Ada,Windows Specific Add-Ons -@anchor{gnat_ugn/platform_specific_information id42}@anchor{224}@anchor{gnat_ugn/platform_specific_information wposix}@anchor{225} +@anchor{gnat_ugn/platform_specific_information id42}@anchor{225}@anchor{gnat_ugn/platform_specific_information wposix}@anchor{226} @subsubsection wPOSIX @@ -26275,7 +26323,7 @@ gprbuild p.gpr @end quotation @node Mac OS Topics,,Microsoft Windows Topics,Platform-Specific Information -@anchor{gnat_ugn/platform_specific_information mac-os-topics}@anchor{2d}@anchor{gnat_ugn/platform_specific_information id43}@anchor{226} +@anchor{gnat_ugn/platform_specific_information mac-os-topics}@anchor{2d}@anchor{gnat_ugn/platform_specific_information id43}@anchor{227} @section Mac OS Topics @@ -26290,7 +26338,7 @@ platform. @end menu @node Codesigning the Debugger,,,Mac OS Topics -@anchor{gnat_ugn/platform_specific_information codesigning-the-debugger}@anchor{227} +@anchor{gnat_ugn/platform_specific_information codesigning-the-debugger}@anchor{228} @subsection Codesigning the Debugger @@ -26371,7 +26419,7 @@ the location where you installed GNAT. Also, be sure that users are in the Unix group @code{_developer}. @node Example of Binder Output File,Elaboration Order Handling in GNAT,Platform-Specific Information,Top -@anchor{gnat_ugn/example_of_binder_output example-of-binder-output-file}@anchor{e}@anchor{gnat_ugn/example_of_binder_output doc}@anchor{228}@anchor{gnat_ugn/example_of_binder_output id1}@anchor{229} +@anchor{gnat_ugn/example_of_binder_output example-of-binder-output-file}@anchor{e}@anchor{gnat_ugn/example_of_binder_output doc}@anchor{229}@anchor{gnat_ugn/example_of_binder_output id1}@anchor{22a} @chapter Example of Binder Output File @@ -27123,7 +27171,7 @@ elaboration code in your own application). @c -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit @node Elaboration Order Handling in GNAT,Inline Assembler,Example of Binder Output File,Top -@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-order-handling-in-gnat}@anchor{f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat doc}@anchor{22a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id1}@anchor{22b} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-order-handling-in-gnat}@anchor{f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat doc}@anchor{22b}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id1}@anchor{22c} @chapter Elaboration Order Handling in GNAT @@ -27157,7 +27205,7 @@ GNAT, either automatically or with explicit programming features. @end menu @node Elaboration Code,Elaboration Order,,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-code}@anchor{22c}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id2}@anchor{22d} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-code}@anchor{22d}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id2}@anchor{22e} @section Elaboration Code @@ -27299,7 +27347,7 @@ elaborated. @end itemize @node Elaboration Order,Checking the Elaboration Order,Elaboration Code,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-order}@anchor{22e}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id3}@anchor{22f} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-order}@anchor{22f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id3}@anchor{230} @section Elaboration Order @@ -27449,7 +27497,7 @@ avoids ABE problems should be chosen, however a compiler may not always find such an order due to complications with respect to control and data flow. @node Checking the Elaboration Order,Controlling the Elaboration Order in Ada,Elaboration Order,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id4}@anchor{230}@anchor{gnat_ugn/elaboration_order_handling_in_gnat checking-the-elaboration-order}@anchor{231} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id4}@anchor{231}@anchor{gnat_ugn/elaboration_order_handling_in_gnat checking-the-elaboration-order}@anchor{232} @section Checking the Elaboration Order @@ -27511,7 +27559,7 @@ order. @end itemize @node Controlling the Elaboration Order in Ada,Controlling the Elaboration Order in GNAT,Checking the Elaboration Order,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-ada}@anchor{232}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id5}@anchor{233} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-ada}@anchor{233}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id5}@anchor{234} @section Controlling the Elaboration Order in Ada @@ -27839,7 +27887,7 @@ is that the program continues to stay in the last state (one or more correct orders exist) even if maintenance changes the bodies of targets. @node Controlling the Elaboration Order in GNAT,Common Elaboration-model Traits,Controlling the Elaboration Order in Ada,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id6}@anchor{234}@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-gnat}@anchor{235} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id6}@anchor{235}@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-gnat}@anchor{236} @section Controlling the Elaboration Order in GNAT @@ -27915,7 +27963,7 @@ The dynamic, legacy, and static models can be relaxed using compiler switch may not diagnose certain elaboration issues or install run-time checks. @node Common Elaboration-model Traits,Dynamic Elaboration Model in GNAT,Controlling the Elaboration Order in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat common-elaboration-model-traits}@anchor{236}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{237} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat common-elaboration-model-traits}@anchor{237}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{238} @section Common Elaboration-model Traits @@ -27984,7 +28032,7 @@ data and control flow. The warnings can be suppressed selectively with @code{pra Warnigns (Off)} or globally with compiler switch @code{-gnatwL}. @node Dynamic Elaboration Model in GNAT,Static Elaboration Model in GNAT,Common Elaboration-model Traits,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat dynamic-elaboration-model-in-gnat}@anchor{238}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id8}@anchor{239} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat dynamic-elaboration-model-in-gnat}@anchor{239}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id8}@anchor{23a} @section Dynamic Elaboration Model in GNAT @@ -28041,7 +28089,7 @@ is in effect. @end example @node Static Elaboration Model in GNAT,SPARK Elaboration Model in GNAT,Dynamic Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat static-elaboration-model-in-gnat}@anchor{23a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{23b} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat static-elaboration-model-in-gnat}@anchor{23b}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{23c} @section Static Elaboration Model in GNAT @@ -28184,7 +28232,7 @@ elaborated prior to the body of @code{Static_Model}. @end itemize @node SPARK Elaboration Model in GNAT,Legacy Elaboration Model in GNAT,Static Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{23c}@anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-elaboration-model-in-gnat}@anchor{23d} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{23d}@anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-elaboration-model-in-gnat}@anchor{23e} @section SPARK Elaboration Model in GNAT @@ -28207,7 +28255,7 @@ external, and compiler switch @code{-gnatd.v} is in effect. @end example @node Legacy Elaboration Model in GNAT,Mixing Elaboration Models,SPARK Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat legacy-elaboration-model-in-gnat}@anchor{23e} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat legacy-elaboration-model-in-gnat}@anchor{23f} @section Legacy Elaboration Model in GNAT @@ -28218,7 +28266,7 @@ in terms of diagnostics and run-time checks. The legacy elaboration model is enabled with compiler switch @code{-gnatH}. @node Mixing Elaboration Models,Elaboration Circularities,Legacy Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{23f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id11}@anchor{240} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{240}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id11}@anchor{241} @section Mixing Elaboration Models @@ -28262,7 +28310,7 @@ warning: "y.ads" which has static elaboration checks The warnings can be suppressed by binder switch @code{-ws}. @node Elaboration Circularities,Resolving Elaboration Circularities,Mixing Elaboration Models,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{241}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{242} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{242}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{243} @section Elaboration Circularities @@ -28321,7 +28369,7 @@ they @emph{with}, must be elaborated prior to @code{Client}. However, @code{Serv @code{Client}, and this leads to a circularity. @node Resolving Elaboration Circularities,Resolving Task Issues,Elaboration Circularities,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id13}@anchor{243}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-elaboration-circularities}@anchor{244} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id13}@anchor{244}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-elaboration-circularities}@anchor{245} @section Resolving Elaboration Circularities @@ -28489,7 +28537,7 @@ run-time checks. @end itemize @node Resolving Task Issues,Elaboration-related Compiler Switches,Resolving Elaboration Circularities,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id14}@anchor{245}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-task-issues}@anchor{246} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id14}@anchor{246}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-task-issues}@anchor{247} @section Resolving Task Issues @@ -28785,7 +28833,7 @@ static model will verify that no entry calls take place at elaboration time. @end itemize @node Elaboration-related Compiler Switches,Summary of Procedures for Elaboration Control,Resolving Task Issues,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{247}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id15}@anchor{248} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{248}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id15}@anchor{249} @section Elaboration-related Compiler Switches @@ -28962,7 +29010,7 @@ checks. The example above will still fail at run time with an ABE. @end table @node Summary of Procedures for Elaboration Control,Inspecting the Chosen Elaboration Order,Elaboration-related Compiler Switches,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat summary-of-procedures-for-elaboration-control}@anchor{249}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id16}@anchor{24a} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat summary-of-procedures-for-elaboration-control}@anchor{24a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id16}@anchor{24b} @section Summary of Procedures for Elaboration Control @@ -28996,7 +29044,7 @@ indicate why a server unit must be elaborated prior to a client unit. @item If the warnings produced by the static model indicate that a task is -involved, consider the options in section @ref{245,,Resolving Task Issues}. +involved, consider the options in section @ref{246,,Resolving Task Issues}. @item If none of the steps outlined above resolve the circularity, use a more @@ -29027,7 +29075,7 @@ Use the relaxed legacy dynamic elaboration model, with compiler switches @end itemize @node Inspecting the Chosen Elaboration Order,,Summary of Procedures for Elaboration Control,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat inspecting-the-chosen-elaboration-order}@anchor{24b}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id17}@anchor{24c} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat inspecting-the-chosen-elaboration-order}@anchor{24c}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id17}@anchor{24d} @section Inspecting the Chosen Elaboration Order @@ -29164,7 +29212,7 @@ gdbstr (body) @end example @node Inline Assembler,GNU Free Documentation License,Elaboration Order Handling in GNAT,Top -@anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10}@anchor{gnat_ugn/inline_assembler doc}@anchor{24d}@anchor{gnat_ugn/inline_assembler id1}@anchor{24e} +@anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10}@anchor{gnat_ugn/inline_assembler doc}@anchor{24e}@anchor{gnat_ugn/inline_assembler id1}@anchor{24f} @chapter Inline Assembler @@ -29223,7 +29271,7 @@ and with assembly language programming. @end menu @node Basic Assembler Syntax,A Simple Example of Inline Assembler,,Inline Assembler -@anchor{gnat_ugn/inline_assembler id2}@anchor{24f}@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{250} +@anchor{gnat_ugn/inline_assembler id2}@anchor{250}@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{251} @section Basic Assembler Syntax @@ -29339,7 +29387,7 @@ Intel: Destination first; for example @code{mov eax, 4}@w{ } @node A Simple Example of Inline Assembler,Output Variables in Inline Assembler,Basic Assembler Syntax,Inline Assembler -@anchor{gnat_ugn/inline_assembler a-simple-example-of-inline-assembler}@anchor{251}@anchor{gnat_ugn/inline_assembler id3}@anchor{252} +@anchor{gnat_ugn/inline_assembler a-simple-example-of-inline-assembler}@anchor{252}@anchor{gnat_ugn/inline_assembler id3}@anchor{253} @section A Simple Example of Inline Assembler @@ -29488,7 +29536,7 @@ If there are no errors, @code{as} will generate an object file @code{nothing.out}. @node Output Variables in Inline Assembler,Input Variables in Inline Assembler,A Simple Example of Inline Assembler,Inline Assembler -@anchor{gnat_ugn/inline_assembler id4}@anchor{253}@anchor{gnat_ugn/inline_assembler output-variables-in-inline-assembler}@anchor{254} +@anchor{gnat_ugn/inline_assembler id4}@anchor{254}@anchor{gnat_ugn/inline_assembler output-variables-in-inline-assembler}@anchor{255} @section Output Variables in Inline Assembler @@ -29855,7 +29903,7 @@ end Get_Flags_3; @end quotation @node Input Variables in Inline Assembler,Inlining Inline Assembler Code,Output Variables in Inline Assembler,Inline Assembler -@anchor{gnat_ugn/inline_assembler id5}@anchor{255}@anchor{gnat_ugn/inline_assembler input-variables-in-inline-assembler}@anchor{256} +@anchor{gnat_ugn/inline_assembler id5}@anchor{256}@anchor{gnat_ugn/inline_assembler input-variables-in-inline-assembler}@anchor{257} @section Input Variables in Inline Assembler @@ -29944,7 +29992,7 @@ _increment__incr.1: @end quotation @node Inlining Inline Assembler Code,Other Asm Functionality,Input Variables in Inline Assembler,Inline Assembler -@anchor{gnat_ugn/inline_assembler id6}@anchor{257}@anchor{gnat_ugn/inline_assembler inlining-inline-assembler-code}@anchor{258} +@anchor{gnat_ugn/inline_assembler id6}@anchor{258}@anchor{gnat_ugn/inline_assembler inlining-inline-assembler-code}@anchor{259} @section Inlining Inline Assembler Code @@ -30015,7 +30063,7 @@ movl %esi,%eax thus saving the overhead of stack frame setup and an out-of-line call. @node Other Asm Functionality,,Inlining Inline Assembler Code,Inline Assembler -@anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{259}@anchor{gnat_ugn/inline_assembler id7}@anchor{25a} +@anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{25a}@anchor{gnat_ugn/inline_assembler id7}@anchor{25b} @section Other @code{Asm} Functionality @@ -30030,7 +30078,7 @@ and @code{Volatile}, which inhibits unwanted optimizations. @end menu @node The Clobber Parameter,The Volatile Parameter,,Other Asm Functionality -@anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{25b}@anchor{gnat_ugn/inline_assembler id8}@anchor{25c} +@anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{25c}@anchor{gnat_ugn/inline_assembler id8}@anchor{25d} @subsection The @code{Clobber} Parameter @@ -30094,7 +30142,7 @@ Use 'register' name @code{memory} if you changed a memory location @end itemize @node The Volatile Parameter,,The Clobber Parameter,Other Asm Functionality -@anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{25d}@anchor{gnat_ugn/inline_assembler id9}@anchor{25e} +@anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{25e}@anchor{gnat_ugn/inline_assembler id9}@anchor{25f} @subsection The @code{Volatile} Parameter @@ -30130,7 +30178,7 @@ to @code{True} only if the compiler's optimizations have created problems. @node GNU Free Documentation License,Index,Inline Assembler,Top -@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{25f}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{260} +@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{260}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{261} @chapter GNU Free Documentation License diff --git a/gcc/ada/gsocket.h b/gcc/ada/gsocket.h index 1821b1b..c44e134 100644 --- a/gcc/ada/gsocket.h +++ b/gcc/ada/gsocket.h @@ -82,6 +82,7 @@ #ifdef __MINGW32__ #include #include +#include #undef EACCES #define EACCES WSAEACCES diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb index 476a213..ef6071b 100644 --- a/gcc/ada/libgnat/g-socket.adb +++ b/gcc/ada/libgnat/g-socket.adb @@ -2643,21 +2643,29 @@ package body GNAT.Sockets is => if Is_Windows then - -- On Windows, the timeout is a DWORD in milliseconds, and - -- the actual timeout is 500 ms + the given value (unless it - -- is 0). + -- On Windows, the timeout is a DWORD in milliseconds - U4 := C.unsigned (Option.Timeout / 0.001); + Len := U4'Size / 8; + Add := U4'Address; - if U4 > 500 then - U4 := U4 - 500; + U4 := C.unsigned (Option.Timeout / 0.001); - elsif U4 > 0 then + if Option.Timeout > 0.0 and then U4 = 0 then + -- Avoid round to zero. Zero timeout mean unlimited. U4 := 1; end if; - Len := U4'Size / 8; - Add := U4'Address; + -- Old windows versions actual timeout is 500 ms + the given + -- value (unless it is 0). + + if Minus_500ms_Windows_Timeout /= 0 then + if U4 > 500 then + U4 := U4 - 500; + + elsif U4 > 0 then + U4 := 1; + end if; + end if; else VT := To_Timeval (Option.Timeout); diff --git a/gcc/ada/libgnat/g-sothco.ads b/gcc/ada/libgnat/g-sothco.ads index dc47f92..c62161d 100644 --- a/gcc/ada/libgnat/g-sothco.ads +++ b/gcc/ada/libgnat/g-sothco.ads @@ -438,6 +438,11 @@ package GNAT.Sockets.Thin_Common is renames Short_To_Network; -- Symmetric operation + function Minus_500ms_Windows_Timeout return C.int; + -- Microsoft Windows desktop older then 8.0 and Microsoft Windows Server + -- older than 2019 need timeout correction for 500 milliseconds. This + -- routine returns 1 for such versions. + private pragma Import (C, Get_Socket_From_Set, "__gnat_get_socket_from_set"); pragma Import (C, Is_Socket_In_Set, "__gnat_is_socket_in_set"); @@ -470,4 +475,6 @@ private pragma Import (C, Hostent_H_Length, "__gnat_hostent_h_length"); pragma Import (C, Hostent_H_Addr, "__gnat_hostent_h_addr"); + pragma Import (C, Minus_500ms_Windows_Timeout, "__gnat_minus_500ms"); + end GNAT.Sockets.Thin_Common; diff --git a/gcc/ada/socket.c b/gcc/ada/socket.c index a265e01..8fc8415 100644 --- a/gcc/ada/socket.c +++ b/gcc/ada/socket.c @@ -803,4 +803,15 @@ const char * __gnat_gai_strerror(int errcode) { #endif +int __gnat_minus_500ms() { +#if defined (_WIN32) + // Windows Server 2019 and Windows 8.0 do not need 500 millisecond socket + // timeout correction. + return !(IsWindows8OrGreater() && !IsWindowsServer() + || IsWindowsVersionOrGreater(10, 0, 17763)); +#else + return 0; +#endif +} + #endif /* defined(HAVE_SOCKETS) */ -- cgit v1.1 From cd93d2d89d3a59e034263b1d1d657286b1074ead Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 4 Jul 2019 08:05:17 +0000 Subject: [Ada] Reduce emitted code size in CCG for aggregate assignment 2019-07-04 Arnaud Charlet gcc/ada/ * exp_aggr.adb (Check_Component): Take into account type conversions. From-SVN: r273046 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_aggr.adb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 789dc5d..4de9db7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Arnaud Charlet + + * exp_aggr.adb (Check_Component): Take into account type + conversions. + 2019-07-04 Dmitriy Anisimkov * doc/gnat_ugn/platform_specific_information.rst: Document diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index b5bd222..80523e9 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -5549,7 +5549,8 @@ package body Exp_Aggr is or else (Nkind (Comp) = N_Selected_Component and then Check_Component (Prefix (Comp))) - or else (Nkind (Comp) = N_Unchecked_Type_Conversion + or else (Nkind_In (Comp, N_Unchecked_Type_Conversion, + N_Type_Conversion) and then Check_Component (Expression (Comp))); end Check_Component; -- cgit v1.1 From a0766a8258f014ac2715d8c49fcaf83b3eb62a00 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 4 Jul 2019 08:05:23 +0000 Subject: [Ada] CCG: restrict folding for boolean tests 2019-07-04 Arnaud Charlet gcc/ada/ * exp_ch4.adb (Expand_Short_Circuit_Operator): Strip N_Variable_Reference_Marker when checking for the presence of actions. From-SVN: r273047 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/exp_ch4.adb | 31 ++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4de9db7..1a86a4d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,11 @@ 2019-07-04 Arnaud Charlet + * exp_ch4.adb (Expand_Short_Circuit_Operator): Strip + N_Variable_Reference_Marker when checking for the presence of + actions. + +2019-07-04 Arnaud Charlet + * exp_aggr.adb (Check_Component): Take into account type conversions. diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index b9aa4a5..7ba4283 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -12391,6 +12391,10 @@ package body Exp_Ch4 is -- For Opnd a boolean expression, return a Boolean expression equivalent -- to Opnd /= Shortcut_Value. + function Useful (Actions : List_Id) return Boolean; + -- Return True if Actions is not empty and contains useful nodes to + -- process. + -------------------- -- Make_Test_Expr -- -------------------- @@ -12404,6 +12408,31 @@ package body Exp_Ch4 is end if; end Make_Test_Expr; + ------------ + -- Useful -- + ------------ + + function Useful (Actions : List_Id) return Boolean is + L : Node_Id; + begin + if Present (Actions) then + L := First (Actions); + + -- For now "useful" means not N_Variable_Reference_Marker. + -- Consider stripping other nodes in the future. + + while Present (L) loop + if Nkind (L) /= N_Variable_Reference_Marker then + return True; + end if; + + Next (L); + end loop; + end if; + + return False; + end Useful; + -- Local variables Op_Var : Entity_Id; @@ -12463,7 +12492,7 @@ package body Exp_Ch4 is -- must only be executed if the right operand of the short circuit is -- executed and not otherwise. - if Present (Actions (N)) then + if Useful (Actions (N)) then Actlist := Actions (N); -- The old approach is to expand: -- cgit v1.1 From d8be36d2873dd1cf9586790ff6c91dc17f37daa6 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Thu, 4 Jul 2019 08:05:27 +0000 Subject: [Ada] Keep assertions in internal units enabled for GNATprove In GNATprove mode the assertion policy is now always enabled, even when analysing internal units. Otherwise, assertion expressions (e.g. Default_Initial_Condition) in internal units (e.g. Ada.Text_IO) disappear in the semantic analysis phase of the frontend and the GNATprove backend can't see them. No frontend test provided, because only the GNATprove backend is affected (and there appear to be no difference in the output with -gnatG switch, because the expansion of Default_Initial_Condition is not attached to the AST). 2019-07-04 Piotr Trojanek gcc/ada/ * opt.adb (Set_Config_Switches): Keep assertions policy as enabled when analysing internal units in GNATprove mode. From-SVN: r273048 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/opt.adb | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1a86a4d..ea1d75d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Piotr Trojanek + + * opt.adb (Set_Config_Switches): Keep assertions policy as + enabled when analysing internal units in GNATprove mode. + 2019-07-04 Arnaud Charlet * exp_ch4.adb (Expand_Short_Circuit_Operator): Strip diff --git a/gcc/ada/opt.adb b/gcc/ada/opt.adb index 43d340b..05f9059 100644 --- a/gcc/ada/opt.adb +++ b/gcc/ada/opt.adb @@ -248,7 +248,13 @@ package body Opt is SPARK_Mode_Pragma := SPARK_Mode_Pragma_Config; else - if GNAT_Mode_Config then + -- In GNATprove mode assertions should be always enabled, even + -- when analysing internal units. + + if GNATprove_Mode then + pragma Assert (Assertions_Enabled); + null; + elsif GNAT_Mode_Config then Assertions_Enabled := Assertions_Enabled_Config; else Assertions_Enabled := False; -- cgit v1.1 From 4ff5aa0c05b3a42a454d76275cf7e1f17cbb7412 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 4 Jul 2019 08:05:31 +0000 Subject: [Ada] CCG: reduce generated temporaries 2019-07-04 Arnaud Charlet gcc/ada/ * exp_aggr.adb (In_Place_Assign_OK): Moved to top level and add support for record aggregates. (Component_Check): Use Is_CCG_Supported_Aggregate instead of a similar local predicate. (Convert_To_Assignments): Take advantage of In_Place_Assign_OK predicate when possible. (Is_CCG_Supported_Aggregate): Return False for records with representation clauses and fix the logic for dealing with nested aggregates. From-SVN: r273049 --- gcc/ada/ChangeLog | 12 ++ gcc/ada/exp_aggr.adb | 573 +++++++++++++++++++++++++-------------------------- 2 files changed, 296 insertions(+), 289 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ea1d75d..46f30aa 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,15 @@ +2019-07-04 Arnaud Charlet + + * exp_aggr.adb (In_Place_Assign_OK): Moved to top level and add + support for record aggregates. + (Component_Check): Use Is_CCG_Supported_Aggregate instead of a + similar local predicate. + (Convert_To_Assignments): Take advantage of In_Place_Assign_OK + predicate when possible. + (Is_CCG_Supported_Aggregate): Return False for records with + representation clauses and fix the logic for dealing with nested + aggregates. + 2019-07-04 Piotr Trojanek * opt.adb (Set_Config_Switches): Keep assertions policy as diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 80523e9..7099d93 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -217,6 +217,11 @@ package body Exp_Aggr is -- defaults. An aggregate for a type with mutable components must be -- expanded into individual assignments. + function In_Place_Assign_OK (N : Node_Id) return Boolean; + -- Predicate to determine whether an aggregate assignment can be done in + -- place, because none of the new values can depend on the components of + -- the target of the assignment. + procedure Initialize_Discriminants (N : Node_Id; Typ : Entity_Id); -- If the type of the aggregate is a type extension with renamed discrimi- -- nants, we must initialize the hidden discriminants of the parent. @@ -646,24 +651,8 @@ package body Exp_Aggr is -- Checks 11: The C code generator cannot handle aggregates that are -- not part of an object declaration. - if Modify_Tree_For_C then - declare - Par : Node_Id := Parent (N); - - begin - -- Skip enclosing nested aggregates and their qualified - -- expressions. - - while Nkind (Par) = N_Aggregate - or else Nkind (Par) = N_Qualified_Expression - loop - Par := Parent (Par); - end loop; - - if Nkind (Par) /= N_Object_Declaration then - return False; - end if; - end; + if Modify_Tree_For_C and then not Is_CCG_Supported_Aggregate (N) then + return False; end if; -- Checks on components @@ -4134,6 +4123,254 @@ package body Exp_Aggr is Insert_Actions_After (Decl, Aggr_Code); end Convert_Array_Aggr_In_Allocator; + ------------------------ + -- In_Place_Assign_OK -- + ------------------------ + + function In_Place_Assign_OK (N : Node_Id) return Boolean is + Is_Array : constant Boolean := Is_Array_Type (Etype (N)); + + Aggr_In : Node_Id; + Aggr_Lo : Node_Id; + Aggr_Hi : Node_Id; + Obj_In : Node_Id; + Obj_Lo : Node_Id; + Obj_Hi : Node_Id; + + function Safe_Aggregate (Aggr : Node_Id) return Boolean; + -- Check recursively that each component of a (sub)aggregate does not + -- depend on the variable being assigned to. + + function Safe_Component (Expr : Node_Id) return Boolean; + -- Verify that an expression cannot depend on the variable being + -- assigned to. Room for improvement here (but less than before). + + -------------------- + -- Safe_Aggregate -- + -------------------- + + function Safe_Aggregate (Aggr : Node_Id) return Boolean is + Expr : Node_Id; + + begin + if Nkind (Parent (Aggr)) = N_Iterated_Component_Association then + return False; + end if; + + if Present (Expressions (Aggr)) then + Expr := First (Expressions (Aggr)); + while Present (Expr) loop + if Nkind (Expr) = N_Aggregate then + if not Safe_Aggregate (Expr) then + return False; + end if; + + elsif not Safe_Component (Expr) then + return False; + end if; + + Next (Expr); + end loop; + end if; + + if Present (Component_Associations (Aggr)) then + Expr := First (Component_Associations (Aggr)); + while Present (Expr) loop + if Nkind (Expression (Expr)) = N_Aggregate then + if not Safe_Aggregate (Expression (Expr)) then + return False; + end if; + + -- If association has a box, no way to determine yet + -- whether default can be assigned in place. + + elsif Box_Present (Expr) then + return False; + + elsif not Safe_Component (Expression (Expr)) then + return False; + end if; + + Next (Expr); + end loop; + end if; + + return True; + end Safe_Aggregate; + + -------------------- + -- Safe_Component -- + -------------------- + + function Safe_Component (Expr : Node_Id) return Boolean is + Comp : Node_Id := Expr; + + function Check_Component (Comp : Node_Id) return Boolean; + -- Do the recursive traversal, after copy + + --------------------- + -- Check_Component -- + --------------------- + + function Check_Component (Comp : Node_Id) return Boolean is + begin + if Is_Overloaded (Comp) then + return False; + end if; + + return Compile_Time_Known_Value (Comp) + + or else (Is_Entity_Name (Comp) + and then Present (Entity (Comp)) + and then Ekind (Entity (Comp)) not in Type_Kind + and then No (Renamed_Object (Entity (Comp)))) + + or else (Nkind (Comp) = N_Attribute_Reference + and then Check_Component (Prefix (Comp))) + + or else (Nkind (Comp) in N_Binary_Op + and then Check_Component (Left_Opnd (Comp)) + and then Check_Component (Right_Opnd (Comp))) + + or else (Nkind (Comp) in N_Unary_Op + and then Check_Component (Right_Opnd (Comp))) + + or else (Nkind (Comp) = N_Selected_Component + and then Is_Array + and then Check_Component (Prefix (Comp))) + + or else (Nkind_In (Comp, N_Unchecked_Type_Conversion, + N_Type_Conversion) + and then Check_Component (Expression (Comp))); + end Check_Component; + + -- Start of processing for Safe_Component + + begin + -- If the component appears in an association that may correspond + -- to more than one element, it is not analyzed before expansion + -- into assignments, to avoid side effects. We analyze, but do not + -- resolve the copy, to obtain sufficient entity information for + -- the checks that follow. If component is overloaded we assume + -- an unsafe function call. + + if not Analyzed (Comp) then + if Is_Overloaded (Expr) then + return False; + + elsif Nkind (Expr) = N_Aggregate + and then not Is_Others_Aggregate (Expr) + then + return False; + + elsif Nkind (Expr) = N_Allocator then + + -- For now, too complex to analyze + + return False; + + elsif Nkind (Parent (Expr)) = + N_Iterated_Component_Association + then + -- Ditto for iterated component associations, which in + -- general require an enclosing loop and involve nonstatic + -- expressions. + + return False; + end if; + + Comp := New_Copy_Tree (Expr); + Set_Parent (Comp, Parent (Expr)); + Analyze (Comp); + end if; + + if Nkind (Comp) = N_Aggregate then + return Safe_Aggregate (Comp); + else + return Check_Component (Comp); + end if; + end Safe_Component; + + -- Start of processing for In_Place_Assign_OK + + begin + -- By-copy semantic cannot be guaranteed for controlled objects or + -- objects with discriminants. + + if Needs_Finalization (Etype (N)) + or else Has_Discriminants (Etype (N)) + then + return False; + + elsif Is_Array and then Present (Component_Associations (N)) then + + -- On assignment, sliding can take place, so we cannot do the + -- assignment in place unless the bounds of the aggregate are + -- statically equal to those of the target. + + -- If the aggregate is given by an others choice, the bounds are + -- derived from the left-hand side, and the assignment is safe if + -- the expression is. + + if Is_Others_Aggregate (N) then + return + Safe_Component + (Expression (First (Component_Associations (N)))); + end if; + + Aggr_In := First_Index (Etype (N)); + + if Nkind (Parent (N)) = N_Assignment_Statement then + Obj_In := First_Index (Etype (Name (Parent (N)))); + + else + -- Context is an allocator. Check bounds of aggregate against + -- given type in qualified expression. + + pragma Assert (Nkind (Parent (Parent (N))) = N_Allocator); + Obj_In := First_Index (Etype (Entity (Subtype_Mark (Parent (N))))); + end if; + + while Present (Aggr_In) loop + Get_Index_Bounds (Aggr_In, Aggr_Lo, Aggr_Hi); + Get_Index_Bounds (Obj_In, Obj_Lo, Obj_Hi); + + if not Compile_Time_Known_Value (Aggr_Lo) + or else not Compile_Time_Known_Value (Obj_Lo) + or else not Compile_Time_Known_Value (Obj_Hi) + or else Expr_Value (Aggr_Lo) /= Expr_Value (Obj_Lo) + then + return False; + + -- For an assignment statement we require static matching of + -- bounds. Ditto for an allocator whose qualified expression + -- is a constrained type. If the expression in the allocator + -- is an unconstrained array, we accept an upper bound that + -- is not static, to allow for nonstatic expressions of the + -- base type. Clearly there are further possibilities (with + -- diminishing returns) for safely building arrays in place + -- here. + + elsif Nkind (Parent (N)) = N_Assignment_Statement + or else Is_Constrained (Etype (Parent (N))) + then + if not Compile_Time_Known_Value (Aggr_Hi) + or else Expr_Value (Aggr_Hi) /= Expr_Value (Obj_Hi) + then + return False; + end if; + end if; + + Next_Index (Aggr_In); + Next_Index (Obj_In); + end loop; + end if; + + -- Now check the component values themselves + + return Safe_Aggregate (N); + end In_Place_Assign_OK; + ---------------------------- -- Convert_To_Assignments -- ---------------------------- @@ -4232,10 +4469,11 @@ package body Exp_Aggr is Establish_Transient_Scope (N, Manage_Sec_Stack => False); end if; - -- If the aggregate is nonlimited, create a temporary. If it is limited - -- and context is an assignment, this is a subaggregate for an enclosing - -- aggregate being expanded. It must be built in place, so use target of - -- the current assignment. + -- If the aggregate is nonlimited, create a temporary since aggregates + -- have "by copy" semantic. If it is limited and context is an + -- assignment, this is a subaggregate for an enclosing aggregate being + -- expanded. It must be built in place, so use target of the current + -- assignment. if Is_Limited_Type (Typ) and then Nkind (Parent (N)) = N_Assignment_Statement @@ -4245,16 +4483,14 @@ package body Exp_Aggr is Build_Record_Aggr_Code (N, Typ, Target_Expr)); Rewrite (Parent (N), Make_Null_Statement (Loc)); - -- Generating C, do not declare a temporary to initialize an aggregate - -- assigned to Out or In_Out parameters whose type has no discriminants. - -- This avoids stack overflow errors at run time. + -- Do not declare a temporary to initialize an aggregate assigned to an + -- identifier when in place assignment is possible preserving the + -- by-copy semantic of aggregates. This avoids large stack usage and + -- generates more efficient code. - elsif Modify_Tree_For_C - and then Nkind (Parent (N)) = N_Assignment_Statement + elsif Nkind (Parent (N)) = N_Assignment_Statement and then Nkind (Name (Parent (N))) = N_Identifier - and then Ekind_In (Entity (Name (Parent (N))), E_Out_Parameter, - E_In_Out_Parameter) - and then not Has_Discriminants (Etype (Entity (Name (Parent (N))))) + and then In_Place_Assign_OK (N) then Target_Expr := New_Copy_Tree (Name (Parent (N))); Insert_Actions (Parent (N), @@ -4945,11 +5181,6 @@ package body Exp_Aggr is -- subaggregate we start the computation from. Dim is the dimension -- corresponding to the subaggregate. - function In_Place_Assign_OK return Boolean; - -- Simple predicate to determine whether an aggregate assignment can - -- be done in place, because none of the new values can depend on the - -- components of the target of the assignment. - procedure Others_Check (Sub_Aggr : Node_Id; Dim : Pos); -- Checks that if an others choice is present in any subaggregate, no -- aggregate index is outside the bounds of the index constraint. @@ -5437,243 +5668,6 @@ package body Exp_Aggr is end if; end Compute_Others_Present; - ------------------------ - -- In_Place_Assign_OK -- - ------------------------ - - function In_Place_Assign_OK return Boolean is - Aggr_In : Node_Id; - Aggr_Lo : Node_Id; - Aggr_Hi : Node_Id; - Obj_In : Node_Id; - Obj_Lo : Node_Id; - Obj_Hi : Node_Id; - - function Safe_Aggregate (Aggr : Node_Id) return Boolean; - -- Check recursively that each component of a (sub)aggregate does not - -- depend on the variable being assigned to. - - function Safe_Component (Expr : Node_Id) return Boolean; - -- Verify that an expression cannot depend on the variable being - -- assigned to. Room for improvement here (but less than before). - - -------------------- - -- Safe_Aggregate -- - -------------------- - - function Safe_Aggregate (Aggr : Node_Id) return Boolean is - Expr : Node_Id; - - begin - if Nkind (Parent (Aggr)) = N_Iterated_Component_Association then - return False; - end if; - - if Present (Expressions (Aggr)) then - Expr := First (Expressions (Aggr)); - while Present (Expr) loop - if Nkind (Expr) = N_Aggregate then - if not Safe_Aggregate (Expr) then - return False; - end if; - - elsif not Safe_Component (Expr) then - return False; - end if; - - Next (Expr); - end loop; - end if; - - if Present (Component_Associations (Aggr)) then - Expr := First (Component_Associations (Aggr)); - while Present (Expr) loop - if Nkind (Expression (Expr)) = N_Aggregate then - if not Safe_Aggregate (Expression (Expr)) then - return False; - end if; - - -- If association has a box, no way to determine yet - -- whether default can be assigned in place. - - elsif Box_Present (Expr) then - return False; - - elsif not Safe_Component (Expression (Expr)) then - return False; - end if; - - Next (Expr); - end loop; - end if; - - return True; - end Safe_Aggregate; - - -------------------- - -- Safe_Component -- - -------------------- - - function Safe_Component (Expr : Node_Id) return Boolean is - Comp : Node_Id := Expr; - - function Check_Component (Comp : Node_Id) return Boolean; - -- Do the recursive traversal, after copy - - --------------------- - -- Check_Component -- - --------------------- - - function Check_Component (Comp : Node_Id) return Boolean is - begin - if Is_Overloaded (Comp) then - return False; - end if; - - return Compile_Time_Known_Value (Comp) - - or else (Is_Entity_Name (Comp) - and then Present (Entity (Comp)) - and then No (Renamed_Object (Entity (Comp)))) - - or else (Nkind (Comp) = N_Attribute_Reference - and then Check_Component (Prefix (Comp))) - - or else (Nkind (Comp) in N_Binary_Op - and then Check_Component (Left_Opnd (Comp)) - and then Check_Component (Right_Opnd (Comp))) - - or else (Nkind (Comp) in N_Unary_Op - and then Check_Component (Right_Opnd (Comp))) - - or else (Nkind (Comp) = N_Selected_Component - and then Check_Component (Prefix (Comp))) - - or else (Nkind_In (Comp, N_Unchecked_Type_Conversion, - N_Type_Conversion) - and then Check_Component (Expression (Comp))); - end Check_Component; - - -- Start of processing for Safe_Component - - begin - -- If the component appears in an association that may correspond - -- to more than one element, it is not analyzed before expansion - -- into assignments, to avoid side effects. We analyze, but do not - -- resolve the copy, to obtain sufficient entity information for - -- the checks that follow. If component is overloaded we assume - -- an unsafe function call. - - if not Analyzed (Comp) then - if Is_Overloaded (Expr) then - return False; - - elsif Nkind (Expr) = N_Aggregate - and then not Is_Others_Aggregate (Expr) - then - return False; - - elsif Nkind (Expr) = N_Allocator then - - -- For now, too complex to analyze - - return False; - - elsif Nkind (Parent (Expr)) = - N_Iterated_Component_Association - then - -- Ditto for iterated component associations, which in - -- general require an enclosing loop and involve nonstatic - -- expressions. - - return False; - end if; - - Comp := New_Copy_Tree (Expr); - Set_Parent (Comp, Parent (Expr)); - Analyze (Comp); - end if; - - if Nkind (Comp) = N_Aggregate then - return Safe_Aggregate (Comp); - else - return Check_Component (Comp); - end if; - end Safe_Component; - - -- Start of processing for In_Place_Assign_OK - - begin - if Present (Component_Associations (N)) then - - -- On assignment, sliding can take place, so we cannot do the - -- assignment in place unless the bounds of the aggregate are - -- statically equal to those of the target. - - -- If the aggregate is given by an others choice, the bounds are - -- derived from the left-hand side, and the assignment is safe if - -- the expression is. - - if Is_Others_Aggregate (N) then - return - Safe_Component - (Expression (First (Component_Associations (N)))); - end if; - - Aggr_In := First_Index (Etype (N)); - - if Nkind (Parent (N)) = N_Assignment_Statement then - Obj_In := First_Index (Etype (Name (Parent (N)))); - - else - -- Context is an allocator. Check bounds of aggregate against - -- given type in qualified expression. - - pragma Assert (Nkind (Parent (Parent (N))) = N_Allocator); - Obj_In := - First_Index (Etype (Entity (Subtype_Mark (Parent (N))))); - end if; - - while Present (Aggr_In) loop - Get_Index_Bounds (Aggr_In, Aggr_Lo, Aggr_Hi); - Get_Index_Bounds (Obj_In, Obj_Lo, Obj_Hi); - - if not Compile_Time_Known_Value (Aggr_Lo) - or else not Compile_Time_Known_Value (Obj_Lo) - or else not Compile_Time_Known_Value (Obj_Hi) - or else Expr_Value (Aggr_Lo) /= Expr_Value (Obj_Lo) - then - return False; - - -- For an assignment statement we require static matching of - -- bounds. Ditto for an allocator whose qualified expression - -- is a constrained type. If the expression in the allocator - -- is an unconstrained array, we accept an upper bound that - -- is not static, to allow for nonstatic expressions of the - -- base type. Clearly there are further possibilities (with - -- diminishing returns) for safely building arrays in place - -- here. - - elsif Nkind (Parent (N)) = N_Assignment_Statement - or else Is_Constrained (Etype (Parent (N))) - then - if not Compile_Time_Known_Value (Aggr_Hi) - or else Expr_Value (Aggr_Hi) /= Expr_Value (Obj_Hi) - then - return False; - end if; - end if; - - Next_Index (Aggr_In); - Next_Index (Obj_In); - end loop; - end if; - - -- Now check the component values themselves - - return Safe_Aggregate (N); - end In_Place_Assign_OK; - ------------------ -- Others_Check -- ------------------ @@ -6256,11 +6250,11 @@ package body Exp_Aggr is else Maybe_In_Place_OK := (Nkind (Parent (N)) = N_Assignment_Statement - and then In_Place_Assign_OK) + and then In_Place_Assign_OK (N)) or else (Nkind (Parent (Parent (N))) = N_Allocator - and then In_Place_Assign_OK); + and then In_Place_Assign_OK (N)); end if; -- If this is an array of tasks, it will be expanded into build-in-place @@ -7686,30 +7680,31 @@ package body Exp_Aggr is function Is_CCG_Supported_Aggregate (N : Node_Id) return Boolean is - In_Obj_Decl : Boolean := False; - P : Node_Id := Parent (N); + P : Node_Id := Parent (N); begin - while Present (P) loop - if Nkind (P) = N_Object_Declaration then - In_Obj_Decl := True; - end if; + -- Aggregates are not supported for non standard rep clauses since + -- they may lead to extra padding fields in CCG. + + if Ekind (Etype (N)) in Record_Kind + and then Has_Non_Standard_Rep (Etype (N)) + then + return False; + end if; + while Present (P) and then Nkind (P) = N_Aggregate loop P := Parent (P); end loop; -- Cases where aggregates are supported by the CCG backend - if In_Obj_Decl then - if Nkind (Parent (N)) = N_Object_Declaration then - return True; + if Nkind (P) = N_Object_Declaration then + return True; - elsif Nkind (Parent (N)) = N_Qualified_Expression - and then Nkind_In (Parent (Parent (N)), N_Allocator, - N_Object_Declaration) - then - return True; - end if; + elsif Nkind (P) = N_Qualified_Expression + and then Nkind_In (Parent (P), N_Allocator, N_Object_Declaration) + then + return True; end if; return False; -- cgit v1.1 From b04fe972e31570bfb09ae398576c1c79847a9f28 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 4 Jul 2019 08:05:36 +0000 Subject: [Ada] Better error messages for ownership errors in SPARK When SPARK code does not follow the ownership rules of SPARK RM 3.10, the error message now points to a location explaining why the object has a more restricted permission than the expected one. There is no impact on compilation. 2019-07-04 Yannick Moy gcc/ada/ * sem_spark.adb (Explanation, Get_Expl): New functions to get the explanation for a permission mismatch. (Perm_Error, Perm_Mismatch, Perm_Error_Loop_Exit): Take explanation into account for issuing a more precise error message. (Set_Perm_Prefixes, Set_Perm_Extensions, Set_Perm_Extensions_Move): Pass suitable argument for the explanation node. From-SVN: r273050 --- gcc/ada/ChangeLog | 11 +++ gcc/ada/sem_spark.adb | 247 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 196 insertions(+), 62 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 46f30aa..127c243 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2019-07-04 Yannick Moy + + * sem_spark.adb (Explanation, Get_Expl): New functions to get + the explanation for a permission mismatch. + (Perm_Error, Perm_Mismatch, Perm_Error_Loop_Exit): Take + explanation into account for issuing a more precise error + message. + (Set_Perm_Prefixes, Set_Perm_Extensions, + Set_Perm_Extensions_Move): Pass suitable argument for the + explanation node. + 2019-07-04 Arnaud Charlet * exp_aggr.adb (In_Place_Assign_OK): Moved to top level and add diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index b4e816e..82ddb16 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -137,6 +137,9 @@ package body Sem_SPARK is -- corresponds to both "observing" and "owning" types in SPARK RM -- 3.10. To be used when moving the path. + Explanation : Node_Id; + -- Node that can be used in an explanation for a permission mismatch + case Kind is -- An entire object is either a leaf (an object which cannot be -- extended further in a path) or a subtree in folded form (which @@ -217,6 +220,7 @@ package body Sem_SPARK is function Children_Permission (T : Perm_Tree_Access) return Perm_Kind; function Component (T : Perm_Tree_Access) return Perm_Tree_Maps.Instance; + function Explanation (T : Perm_Tree_Access) return Node_Id; function Get_All (T : Perm_Tree_Access) return Perm_Tree_Access; function Get_Elem (T : Perm_Tree_Access) return Perm_Tree_Access; function Is_Node_Deep (T : Perm_Tree_Access) return Boolean; @@ -257,6 +261,7 @@ package body Sem_SPARK is (N : Node_Id; Exp_Perm : Perm_Kind; Act_Perm : Perm_Kind; + Expl : Node_Id; Forbidden_Perm : Boolean := False); -- Issues a continuation error message about a mismatch between a -- desired permission Exp_Perm and a permission obtained Act_Perm. N @@ -428,6 +433,15 @@ package body Sem_SPARK is Free_Perm_Tree_Dealloc (PT); end Free_Tree; + ----------------- + -- Explanation -- + ----------------- + + function Explanation (T : Perm_Tree_Access) return Node_Id is + begin + return T.all.Tree.Explanation; + end Explanation; + ------------- -- Get_All -- ------------- @@ -503,22 +517,34 @@ package body Sem_SPARK is (N : Node_Id; Exp_Perm : Perm_Kind; Act_Perm : Perm_Kind; + Expl : Node_Id; Forbidden_Perm : Boolean := False) is begin + Error_Msg_Sloc := Sloc (Expl); + if Forbidden_Perm then - if Exp_Perm = Act_Perm then - Error_Msg_N ("\got forbidden state `" - & Perm_Kind'Image (Exp_Perm), N); + if Exp_Perm = No_Access then + Error_Msg_N ("\object was moved #", N); else - Error_Msg_N ("\forbidden state `" - & Perm_Kind'Image (Exp_Perm) & "`, got `" - & Perm_Kind'Image (Act_Perm) & "`", N); + raise Program_Error; end if; else - Error_Msg_N ("\expected state `" - & Perm_Kind'Image (Exp_Perm) & "` at least, got `" - & Perm_Kind'Image (Act_Perm) & "`", N); + case Exp_Perm is + when Write_Perm => + if Act_Perm = Read_Only then + Error_Msg_N + ("\object was declared as not writeable #", N); + else + Error_Msg_N ("\object was moved #", N); + end if; + + when Read_Only => + Error_Msg_N ("\object was moved #", N); + + when No_Access => + raise Program_Error; + end case; end if; end Perm_Mismatch; @@ -575,8 +601,11 @@ package body Sem_SPARK is type Perm_Or_Tree (R : Result_Kind) is record case R is - when Folded => Found_Permission : Perm_Kind; - when Unfolded => Tree_Access : Perm_Tree_Access; + when Folded => + Found_Permission : Perm_Kind; + Explanation : Node_Id; + when Unfolded => + Tree_Access : Perm_Tree_Access; end case; end record; @@ -650,6 +679,10 @@ package body Sem_SPARK is -- Check that type Typ is either not deep, or that it is an observing or -- owning type according to SPARK RM 3.10 + function Get_Expl (N : Node_Or_Entity_Id) return Node_Id; + -- The function that takes a name as input and returns an explanation node + -- for the permission associated with it. + function Get_Observed_Or_Borrowed_Expr (Expr : Node_Id) return Node_Id; pragma Precondition (Is_Path_Expression (Expr)); -- Return the expression being borrowed/observed when borrowing or @@ -732,6 +765,7 @@ package body Sem_SPARK is (N : Node_Id; Perm : Perm_Kind; Found_Perm : Perm_Kind; + Expl : Node_Id; Forbidden_Perm : Boolean := False); -- A procedure that is called when the permissions found contradict the -- rules established by the RM. This function is called with the node and @@ -742,7 +776,8 @@ package body Sem_SPARK is (E : Entity_Id; Subp : Entity_Id; Perm : Perm_Kind; - Found_Perm : Perm_Kind); + Found_Perm : Perm_Kind; + Expl : Node_Id); -- A procedure that is called when the permissions found contradict the -- rules established by the RM at the end of subprograms. This function is -- called with the node, the node of the returning function, and the @@ -772,12 +807,18 @@ package body Sem_SPARK is -- subprogram indeed have Read_Write permission at the end of the -- subprogram execution. - procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind); + procedure Set_Perm_Extensions + (T : Perm_Tree_Access; + P : Perm_Kind; + Expl : Node_Id); -- This procedure takes an access to a permission tree and modifies the -- tree so that any strict extensions of the given tree become of the -- access specified by parameter P. - procedure Set_Perm_Extensions_Move (T : Perm_Tree_Access; E : Entity_Id); + procedure Set_Perm_Extensions_Move + (T : Perm_Tree_Access; + E : Entity_Id; + Expl : Node_Id); -- Set permissions to -- No for any extension with more .all -- W for any deep extension with same number of .all @@ -785,7 +826,8 @@ package body Sem_SPARK is function Set_Perm_Prefixes (N : Node_Id; - Perm : Perm_Kind_Option) return Perm_Tree_Access; + Perm : Perm_Kind_Option; + Expl : Node_Id) return Perm_Tree_Access; pragma Precondition (Is_Path_Expression (N)); -- This function modifies the permissions of a given node in the permission -- environment as well as all the prefixes of the path, to the new @@ -817,7 +859,8 @@ package body Sem_SPARK is Typ : Entity_Id; Kind : Formal_Kind; Subp : Entity_Id; - Global_Var : Boolean); + Global_Var : Boolean; + Expl : Node_Id); -- Auxiliary procedure to Setup_Parameters and Setup_Globals procedure Setup_Parameters (Subp : Entity_Id); @@ -1106,6 +1149,7 @@ package body Sem_SPARK is if Perm = No_Access then Perm_Error (Expr, No_Access, No_Access, + Expl => Get_Expl (Expr), Forbidden_Perm => True); return; end if; @@ -1114,6 +1158,7 @@ package body Sem_SPARK is if Perm = No_Access then Perm_Error (Expr, No_Access, No_Access, + Expl => Get_Expl (Expr_Root), Forbidden_Perm => True); return; end if; @@ -1133,7 +1178,7 @@ package body Sem_SPARK is Perm := Get_Perm (Expr); if Perm /= Read_Write then - Perm_Error (Expr, Read_Write, Perm); + Perm_Error (Expr, Read_Write, Perm, Expl => Get_Expl (Expr)); return; end if; @@ -1331,6 +1376,7 @@ package body Sem_SPARK is (Tree => (Kind => Entire_Object, Is_Node_Deep => True, + Explanation => Decl, Permission => Read_Write, Children_Permission => Read_Write)); begin @@ -1819,7 +1865,8 @@ package body Sem_SPARK is (E : Entity_Id; Loop_Id : Node_Id; Perm : Perm_Kind; - Found_Perm : Perm_Kind); + Found_Perm : Perm_Kind; + Expl : Node_Id); -- A procedure that is called when the permissions found contradict -- the rules established by the RM at the exit of loops. This function -- is called with the entity, the node of the enclosing loop, the @@ -1889,14 +1936,15 @@ package body Sem_SPARK is begin if not (Permission (Tree) >= Perm) then Perm_Error_Loop_Exit - (E, Stmt, Permission (Tree), Perm); + (E, Stmt, Permission (Tree), Perm, Explanation (Tree)); end if; case Kind (Tree) is when Entire_Object => if not (Children_Permission (Tree) >= Perm) then Perm_Error_Loop_Exit - (E, Stmt, Children_Permission (Tree), Perm); + (E, Stmt, Children_Permission (Tree), Perm, + Explanation (Tree)); end if; @@ -1934,14 +1982,15 @@ package body Sem_SPARK is begin if not (Perm >= Permission (Tree)) then Perm_Error_Loop_Exit - (E, Stmt, Permission (Tree), Perm); + (E, Stmt, Permission (Tree), Perm, Explanation (Tree)); end if; case Kind (Tree) is when Entire_Object => if not (Perm >= Children_Permission (Tree)) then Perm_Error_Loop_Exit - (E, Stmt, Children_Permission (Tree), Perm); + (E, Stmt, Children_Permission (Tree), Perm, + Explanation (Tree)); end if; when Reference => @@ -1974,7 +2023,8 @@ package body Sem_SPARK is (E => E, Loop_Id => Stmt, Perm => Permission (New_Tree), - Found_Perm => Permission (Orig_Tree)); + Found_Perm => Permission (Orig_Tree), + Expl => Explanation (New_Tree)); end if; case Kind (New_Tree) is @@ -1994,7 +2044,8 @@ package body Sem_SPARK is Perm_Error_Loop_Exit (E, Stmt, Children_Permission (New_Tree), - Children_Permission (Orig_Tree)); + Children_Permission (Orig_Tree), + Explanation (New_Tree)); end if; when Reference => @@ -2101,14 +2152,16 @@ package body Sem_SPARK is (E : Entity_Id; Loop_Id : Node_Id; Perm : Perm_Kind; - Found_Perm : Perm_Kind) + Found_Perm : Perm_Kind; + Expl : Node_Id) is begin Error_Msg_Node_2 := Loop_Id; Error_Msg_N ("insufficient permission for & when exiting loop &", E); Perm_Mismatch (Exp_Perm => Perm, Act_Perm => Found_Perm, - N => Loop_Id); + N => Loop_Id, + Expl => Expl); end Perm_Error_Loop_Exit; -- Local variables @@ -2836,7 +2889,7 @@ package body Sem_SPARK is Perm := Get_Perm (Obj); if Perm /= Read_Write then - Perm_Error (Decl, Read_Write, Perm); + Perm_Error (Decl, Read_Write, Perm, Expl => Get_Expl (Obj)); end if; if Ekind_In (Subp, E_Procedure, E_Entry) @@ -3044,6 +3097,51 @@ package body Sem_SPARK is end case; end Check_Type; + -------------- + -- Get_Expl -- + -------------- + + function Get_Expl (N : Node_Or_Entity_Id) return Node_Id is + begin + -- Special case for the object declared in an extended return statement + + if Nkind (N) = N_Defining_Identifier then + declare + C : constant Perm_Tree_Access := + Get (Current_Perm_Env, Unique_Entity (N)); + begin + pragma Assert (C /= null); + return Explanation (C); + end; + + -- The expression is a call to a traversal function + + elsif Is_Traversal_Function_Call (N) then + return N; + + -- The expression is directly rooted in an object + + elsif Present (Get_Root_Object (N, Through_Traversal => False)) then + declare + Tree_Or_Perm : constant Perm_Or_Tree := Get_Perm_Or_Tree (N); + begin + case Tree_Or_Perm.R is + when Folded => + return Tree_Or_Perm.Explanation; + + when Unfolded => + pragma Assert (Tree_Or_Perm.Tree_Access /= null); + return Explanation (Tree_Or_Perm.Tree_Access); + end case; + end; + + -- The expression is a function call, an allocation, or null + + else + return N; + end if; + end Get_Expl; + ----------------------------------- -- Get_Observed_Or_Borrowed_Expr -- ----------------------------------- @@ -3159,7 +3257,9 @@ package body Sem_SPARK is when Entire_Object => return (R => Folded, Found_Permission => - Children_Permission (C.Tree_Access)); + Children_Permission (C.Tree_Access), + Explanation => + Explanation (C.Tree_Access)); when Reference => pragma Assert (Nkind (N) = N_Explicit_Dereference); @@ -3208,7 +3308,7 @@ package body Sem_SPARK is function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access is begin - return Set_Perm_Prefixes (N, None); + return Set_Perm_Prefixes (N, None, Empty); end Get_Perm_Tree; --------------------- @@ -3912,6 +4012,7 @@ package body Sem_SPARK is (N : Node_Id; Perm : Perm_Kind; Found_Perm : Perm_Kind; + Expl : Node_Id; Forbidden_Perm : Boolean := False) is procedure Set_Root_Object @@ -3975,7 +4076,7 @@ package body Sem_SPARK is Error_Msg_NE ("insufficient permission for &", N, Root); end if; - Perm_Mismatch (N, Perm, Found_Perm, Forbidden_Perm); + Perm_Mismatch (N, Perm, Found_Perm, Expl, Forbidden_Perm); end Perm_Error; ------------------------------- @@ -3986,13 +4087,14 @@ package body Sem_SPARK is (E : Entity_Id; Subp : Entity_Id; Perm : Perm_Kind; - Found_Perm : Perm_Kind) + Found_Perm : Perm_Kind; + Expl : Node_Id) is begin Error_Msg_Node_2 := Subp; Error_Msg_NE ("insufficient permission for & when returning from &", Subp, E); - Perm_Mismatch (Subp, Perm, Found_Perm); + Perm_Mismatch (Subp, Perm, Found_Perm, Expl); end Perm_Error_Subprogram_End; ------------------ @@ -4035,7 +4137,7 @@ package body Sem_SPARK is if Is_Prefix_Or_Almost (Pref => Borrowed, Expr => Expr) then Error_Msg_Sloc := Sloc (Borrowed); - Error_Msg_N ("expression was borrowed #", Expr); + Error_Msg_N ("object was borrowed #", Expr); end if; Key := Get_Next_Key (Current_Borrowers); @@ -4071,7 +4173,7 @@ package body Sem_SPARK is if Is_Prefix_Or_Almost (Pref => Observed, Expr => Expr) then Error_Msg_Sloc := Sloc (Observed); - Error_Msg_N ("expression was observed #", Expr); + Error_Msg_N ("object was observed #", Expr); end if; Key := Get_Next_Key (Current_Observers); @@ -4134,7 +4236,7 @@ package body Sem_SPARK is -- Check path is readable if Perm not in Read_Perm then - Perm_Error (Expr, Read_Only, Perm); + Perm_Error (Expr, Read_Only, Perm, Expl => Get_Expl (Expr)); return; end if; @@ -4158,7 +4260,7 @@ package body Sem_SPARK is if not Is_Deep (Expr_Type) then if Perm not in Read_Perm then - Perm_Error (Expr, Read_Only, Perm); + Perm_Error (Expr, Read_Only, Perm, Expl => Get_Expl (Expr)); end if; return; end if; @@ -4167,7 +4269,7 @@ package body Sem_SPARK is -- the source object (if any) shall be Unrestricted. if Perm /= Read_Write then - Perm_Error (Expr, Read_Write, Perm); + Perm_Error (Expr, Read_Write, Perm, Expl => Get_Expl (Expr)); return; end if; @@ -4182,7 +4284,7 @@ package body Sem_SPARK is -- For assignment, check W permission if Perm not in Write_Perm then - Perm_Error (Expr, Write_Only, Perm); + Perm_Error (Expr, Write_Only, Perm, Expl => Get_Expl (Expr)); return; end if; @@ -4201,7 +4303,7 @@ package body Sem_SPARK is -- For borrowing, check RW permission if Perm /= Read_Write then - Perm_Error (Expr, Read_Write, Perm); + Perm_Error (Expr, Read_Write, Perm, Expl => Get_Expl (Expr)); return; end if; @@ -4220,7 +4322,7 @@ package body Sem_SPARK is -- For borrowing, check R permission if Perm not in Read_Perm then - Perm_Error (Expr, Read_Only, Perm); + Perm_Error (Expr, Read_Only, Perm, Expl => Get_Expl (Expr)); return; end if; end case; @@ -4259,10 +4361,10 @@ package body Sem_SPARK is if Present (Get_Root_Object (Expr)) then declare Tree : constant Perm_Tree_Access := - Set_Perm_Prefixes (Expr, Write_Only); + Set_Perm_Prefixes (Expr, Write_Only, Expl => Expr); begin pragma Assert (Tree /= null); - Set_Perm_Extensions_Move (Tree, Etype (Expr)); + Set_Perm_Extensions_Move (Tree, Etype (Expr), Expl => Expr); end; end if; @@ -4283,7 +4385,7 @@ package body Sem_SPARK is Tree : constant Perm_Tree_Access := Get_Perm_Tree (Expr); begin Tree.all.Tree.Permission := Read_Write; - Set_Perm_Extensions (Tree, Read_Write); + Set_Perm_Extensions (Tree, Read_Write, Expl => Expr); -- Normalize the permission tree @@ -4390,7 +4492,8 @@ package body Sem_SPARK is (E => Id, Subp => Subp, Perm => Read_Write, - Found_Perm => Permission (Tree)); + Found_Perm => Permission (Tree), + Expl => Explanation (Tree)); end if; end; end Return_Parameter_Or_Global; @@ -4418,7 +4521,10 @@ package body Sem_SPARK is -- Set_Perm_Extensions -- ------------------------- - procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind) is + procedure Set_Perm_Extensions + (T : Perm_Tree_Access; + P : Perm_Kind; + Expl : Node_Id) is procedure Free_Perm_Tree_Children (T : Perm_Tree_Access); -- Free the permission tree of children if any, prio to replacing T @@ -4462,6 +4568,7 @@ package body Sem_SPARK is Free_Perm_Tree_Children (T); T.all.Tree := Perm_Tree'(Kind => Entire_Object, Is_Node_Deep => Is_Node_Deep (T), + Explanation => Expl, Permission => Permission (T), Children_Permission => P); end Set_Perm_Extensions; @@ -4471,14 +4578,15 @@ package body Sem_SPARK is ------------------------------ procedure Set_Perm_Extensions_Move - (T : Perm_Tree_Access; - E : Entity_Id) + (T : Perm_Tree_Access; + E : Entity_Id; + Expl : Node_Id) is begin -- Shallow extensions are set to RW if not Is_Node_Deep (T) then - Set_Perm_Extensions (T, Read_Write); + Set_Perm_Extensions (T, Read_Write, Expl => Expl); return; end if; @@ -4502,12 +4610,14 @@ package body Sem_SPARK is (Tree => (Kind => Entire_Object, Is_Node_Deep => Is_Node_Deep (T), + Explanation => Expl, Permission => Read_Write, Children_Permission => Read_Write)); begin - Set_Perm_Extensions_Move (C, Component_Type (E)); + Set_Perm_Extensions_Move (C, Component_Type (E), Expl); T.all.Tree := (Kind => Array_Component, Is_Node_Deep => Is_Node_Deep (T), + Explanation => Expl, Permission => Write_Only, Get_Elem => C); end; @@ -4525,9 +4635,10 @@ package body Sem_SPARK is (Tree => (Kind => Entire_Object, Is_Node_Deep => Is_Deep (Etype (Comp)), + Explanation => Expl, Permission => Read_Write, Children_Permission => Read_Write)); - Set_Perm_Extensions_Move (C, Etype (Comp)); + Set_Perm_Extensions_Move (C, Etype (Comp), Expl); Perm_Tree_Maps.Set (Hashtbl, Comp, C); Next_Component_Or_Discriminant (Comp); end loop; @@ -4535,6 +4646,7 @@ package body Sem_SPARK is T.all.Tree := (Kind => Record_Component, Is_Node_Deep => Is_Node_Deep (T), + Explanation => Expl, Permission => Write_Only, Component => Hashtbl); end; @@ -4542,14 +4654,14 @@ package body Sem_SPARK is -- Otherwise, extensions are set to NO when others => - Set_Perm_Extensions (T, No_Access); + Set_Perm_Extensions (T, No_Access, Expl); end case; when Reference => - Set_Perm_Extensions (T, No_Access); + Set_Perm_Extensions (T, No_Access, Expl); when Array_Component => - Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E)); + Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E), Expl); when Record_Component => declare @@ -4561,7 +4673,7 @@ package body Sem_SPARK is while Present (Comp) loop C := Perm_Tree_Maps.Get (Component (T), Comp); pragma Assert (C /= null); - Set_Perm_Extensions_Move (C, Etype (Comp)); + Set_Perm_Extensions_Move (C, Etype (Comp), Expl); Next_Component_Or_Discriminant (Comp); end loop; end; @@ -4574,7 +4686,8 @@ package body Sem_SPARK is function Set_Perm_Prefixes (N : Node_Id; - Perm : Perm_Kind_Option) return Perm_Tree_Access + Perm : Perm_Kind_Option; + Expl : Node_Id) return Perm_Tree_Access is begin case Nkind (N) is @@ -4602,7 +4715,7 @@ package body Sem_SPARK is when N_Explicit_Dereference => declare C : constant Perm_Tree_Access := - Set_Perm_Prefixes (Prefix (N), Perm); + Set_Perm_Prefixes (Prefix (N), Perm, Expl); pragma Assert (C /= null); pragma Assert (Kind (C) = Entire_Object or else Kind (C) = Reference); @@ -4635,6 +4748,7 @@ package body Sem_SPARK is (Tree => (Kind => Entire_Object, Is_Node_Deep => Is_Deep (Etype (N)), + Explanation => Expl, Permission => Child_P, Children_Permission => Child_P)); begin @@ -4644,6 +4758,7 @@ package body Sem_SPARK is C.all.Tree := (Kind => Reference, Is_Node_Deep => Is_Node_Deep (C), + Explanation => Expl, Permission => Permission (C), Get_All => D); return D; @@ -4654,7 +4769,7 @@ package body Sem_SPARK is when N_Selected_Component => declare C : constant Perm_Tree_Access := - Set_Perm_Prefixes (Prefix (N), Perm); + Set_Perm_Prefixes (Prefix (N), Perm, Expl); pragma Assert (C /= null); pragma Assert (Kind (C) = Entire_Object or else Kind (C) = Record_Component); @@ -4708,6 +4823,7 @@ package body Sem_SPARK is (Tree => (Kind => Entire_Object, Is_Node_Deep => Is_Deep (Etype (Comp)), + Explanation => Expl, Permission => P, Children_Permission => Child_P)); Perm_Tree_Maps.Set (Hashtbl, Comp, D); @@ -4723,6 +4839,7 @@ package body Sem_SPARK is C.all.Tree := (Kind => Record_Component, Is_Node_Deep => Is_Node_Deep (C), + Explanation => Expl, Permission => Permission (C), Component => Hashtbl); return D_This; @@ -4735,7 +4852,7 @@ package body Sem_SPARK is => declare C : constant Perm_Tree_Access := - Set_Perm_Prefixes (Prefix (N), Perm); + Set_Perm_Prefixes (Prefix (N), Perm, Expl); pragma Assert (C /= null); pragma Assert (Kind (C) = Entire_Object or else Kind (C) = Array_Component); @@ -4768,6 +4885,7 @@ package body Sem_SPARK is (Tree => (Kind => Entire_Object, Is_Node_Deep => Is_Node_Deep (C), + Explanation => Expl, Permission => Child_P, Children_Permission => Child_P)); begin @@ -4777,6 +4895,7 @@ package body Sem_SPARK is C.all.Tree := (Kind => Array_Component, Is_Node_Deep => Is_Node_Deep (C), + Explanation => Expl, Permission => Permission (C), Get_Elem => D); return D; @@ -4788,7 +4907,7 @@ package body Sem_SPARK is | N_Type_Conversion | N_Unchecked_Type_Conversion => - return Set_Perm_Prefixes (Expression (N), Perm); + return Set_Perm_Prefixes (Expression (N), Perm, Expl); when others => raise Program_Error; @@ -4893,7 +5012,8 @@ package body Sem_SPARK is Typ => Typ, Kind => Kind, Subp => Subp, - Global_Var => Global_Var); + Global_Var => Global_Var, + Expl => Expr); end Setup_Global; procedure Setup_Globals_Inst is new Handle_Globals (Setup_Global); @@ -4913,7 +5033,8 @@ package body Sem_SPARK is Typ : Entity_Id; Kind : Formal_Kind; Subp : Entity_Id; - Global_Var : Boolean) + Global_Var : Boolean; + Expl : Node_Id) is Perm : Perm_Kind_Option; @@ -4989,6 +5110,7 @@ package body Sem_SPARK is (Tree => (Kind => Entire_Object, Is_Node_Deep => Is_Deep (Etype (Id)), + Explanation => Expl, Permission => Perm, Children_Permission => Perm)); begin @@ -5011,7 +5133,8 @@ package body Sem_SPARK is Typ => Underlying_Type (Etype (Formal)), Kind => Ekind (Formal), Subp => Subp, - Global_Var => False); + Global_Var => False, + Expl => Formal); Next_Formal (Formal); end loop; end Setup_Parameters; -- cgit v1.1 From bc1146e5e0979421b5dc2c9c005c355443c2fe24 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 4 Jul 2019 08:05:40 +0000 Subject: [Ada] Minor reformatting 2019-07-04 Hristian Kirtchev gcc/ada/ * erroutc.adb, exp_aggr.adb, inline.adb, opt.adb, sem_ch3.adb: Minor reformatting. From-SVN: r273051 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/erroutc.adb | 1 + gcc/ada/exp_aggr.adb | 44 +++++++++++++++++++++----------------------- gcc/ada/inline.adb | 10 +++++----- gcc/ada/opt.adb | 1 + gcc/ada/sem_ch3.adb | 6 ++++-- 6 files changed, 37 insertions(+), 30 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 127c243..6f300dc 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Hristian Kirtchev + + * erroutc.adb, exp_aggr.adb, inline.adb, opt.adb, sem_ch3.adb: + Minor reformatting. + 2019-07-04 Yannick Moy * sem_spark.adb (Explanation, Get_Expl): New functions to get diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb index 0c8ef5d..2ea0c2d 100644 --- a/gcc/ada/erroutc.adb +++ b/gcc/ada/erroutc.adb @@ -1606,6 +1606,7 @@ package body Erroutc is if Start <= Cur_Loc and then Cur_Loc <= Stop then return True; end if; + Cur_Loc := Instantiation_Location (Cur_Loc); end loop; diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 7099d93..7c41477 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -1343,11 +1343,11 @@ package body Exp_Aggr is -- transient scope, which leads to premature finalization. -- This in-place expansion is not performed for limited transient - -- objects because the initialization is already done in-place. + -- objects, because the initialization is already done in place. if In_Place_Expansion then - -- Suppress the removal of side effects by general analysis + -- Suppress the removal of side effects by general analysis, -- because this behavior is emulated here. This avoids the -- generation of a transient scope, which leads to out-of-order -- adjustment and finalization. @@ -4181,8 +4181,8 @@ package body Exp_Aggr is return False; end if; - -- If association has a box, no way to determine yet - -- whether default can be assigned in place. + -- If association has a box, no way to determine yet whether + -- default can be assigned in place. elsif Box_Present (Expr) then return False; @@ -4239,8 +4239,8 @@ package body Exp_Aggr is and then Is_Array and then Check_Component (Prefix (Comp))) - or else (Nkind_In (Comp, N_Unchecked_Type_Conversion, - N_Type_Conversion) + or else (Nkind_In (Comp, N_Type_Conversion, + N_Unchecked_Type_Conversion) and then Check_Component (Expression (Comp))); end Check_Component; @@ -4269,12 +4269,10 @@ package body Exp_Aggr is return False; - elsif Nkind (Parent (Expr)) = - N_Iterated_Component_Association - then - -- Ditto for iterated component associations, which in - -- general require an enclosing loop and involve nonstatic - -- expressions. + elsif Nkind (Parent (Expr)) = N_Iterated_Component_Association then + + -- Ditto for iterated component associations, which in general + -- require an enclosing loop and involve nonstatic expressions. return False; end if; @@ -4469,8 +4467,8 @@ package body Exp_Aggr is Establish_Transient_Scope (N, Manage_Sec_Stack => False); end if; - -- If the aggregate is nonlimited, create a temporary since aggregates - -- have "by copy" semantic. If it is limited and context is an + -- If the aggregate is nonlimited, create a temporary, since aggregates + -- have "by copy" semantics. If it is limited and context is an -- assignment, this is a subaggregate for an enclosing aggregate being -- expanded. It must be built in place, so use target of the current -- assignment. @@ -4484,7 +4482,7 @@ package body Exp_Aggr is Rewrite (Parent (N), Make_Null_Statement (Loc)); -- Do not declare a temporary to initialize an aggregate assigned to an - -- identifier when in place assignment is possible preserving the + -- identifier when in-place assignment is possible, preserving the -- by-copy semantic of aggregates. This avoids large stack usage and -- generates more efficient code. @@ -5122,7 +5120,7 @@ package body Exp_Aggr is -- case pass it as is to Gigi. Note that a necessary condition for -- static processing is that the aggregate be fully positional. - -- 5. If in place aggregate expansion is possible (i.e. no need to create + -- 5. If in-place aggregate expansion is possible (i.e. no need to create -- a temporary) then mark the aggregate as such and return. Otherwise -- create a new temporary and generate the appropriate initialization -- code. @@ -5146,7 +5144,7 @@ package body Exp_Aggr is -- The type of each index In_Place_Assign_OK_For_Declaration : Boolean := False; - -- True if we are to generate an in place assignment for a declaration + -- True if we are to generate an in-place assignment for a declaration Maybe_In_Place_OK : Boolean; -- If the type is neither controlled nor packed and the aggregate @@ -6214,7 +6212,7 @@ package body Exp_Aggr is -- STEP 4 - -- Look if in place aggregate expansion is possible + -- Check whether in-place aggregate expansion is possible -- For object declarations we build the aggregate in place, unless -- the array is bit-packed. @@ -6366,7 +6364,7 @@ package body Exp_Aggr is -- Step 5 - -- In place aggregate expansion is not possible + -- In-place aggregate expansion is not possible else Maybe_In_Place_OK := False; @@ -6418,11 +6416,11 @@ package body Exp_Aggr is Target := New_Copy (Tmp); end if; - -- If we are to generate an in place assignment for a declaration or + -- If we are to generate an in-place assignment for a declaration or -- an assignment statement, and the assignment can be done directly -- by the back end, then do not expand further. - -- ??? We can also do that if in place expansion is not possible but + -- ??? We can also do that if in-place expansion is not possible but -- then we could go into an infinite recursion. if (In_Place_Assign_OK_For_Declaration or else Maybe_In_Place_OK) @@ -7683,8 +7681,8 @@ package body Exp_Aggr is P : Node_Id := Parent (N); begin - -- Aggregates are not supported for non standard rep clauses since - -- they may lead to extra padding fields in CCG. + -- Aggregates are not supported for nonstandard rep clauses, since they + -- may lead to extra padding fields in CCG. if Ekind (Etype (N)) in Record_Kind and then Has_Non_Standard_Rep (Etype (N)) diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb index b2038a6..907975e 100644 --- a/gcc/ada/inline.adb +++ b/gcc/ada/inline.adb @@ -2481,8 +2481,7 @@ package body Inline is -- thunk generated for it. Replace a return statement with an assignment -- to the target of the call, with appropriate conversions if needed. - function Process_Formals_In_Aspects (N : Node_Id) - return Traverse_Result; + function Process_Formals_In_Aspects (N : Node_Id) return Traverse_Result; -- Because aspects are linked indirectly to the rest of the tree, -- replacement of formals appearing in aspect specifications must -- be performed in a separate pass, using an instantiation of the @@ -2832,10 +2831,11 @@ package body Inline is -- Process_Formals_In_Aspects -- -------------------------------- - function Process_Formals_In_Aspects (N : Node_Id) - return Traverse_Result + function Process_Formals_In_Aspects + (N : Node_Id) return Traverse_Result is A : Node_Id; + begin if Has_Aspects (N) then A := First (Aspect_Specifications (N)); @@ -2849,7 +2849,7 @@ package body Inline is end Process_Formals_In_Aspects; procedure Replace_Formals_In_Aspects is - new Traverse_Proc (Process_Formals_In_Aspects); + new Traverse_Proc (Process_Formals_In_Aspects); ------------------ -- Process_Sloc -- diff --git a/gcc/ada/opt.adb b/gcc/ada/opt.adb index 05f9059..4ceffb0 100644 --- a/gcc/ada/opt.adb +++ b/gcc/ada/opt.adb @@ -254,6 +254,7 @@ package body Opt is if GNATprove_Mode then pragma Assert (Assertions_Enabled); null; + elsif GNAT_Mode_Config then Assertions_Enabled := Assertions_Enabled_Config; else diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 75a0099..a82c2bc 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -930,7 +930,8 @@ package body Sem_Ch3 is -- declaration may include an expression that is an allocator, whose -- expansion needs the proper Master for the created tasks. - if Nkind (Related_Nod) = N_Object_Declaration and then Expander_Active + if Expander_Active + and then Nkind (Related_Nod) = N_Object_Declaration then if Is_Limited_Record (Desig_Type) and then Is_Class_Wide_Type (Desig_Type) @@ -940,7 +941,8 @@ package body Sem_Ch3 is -- Similarly, if the type is an anonymous access that designates -- tasks, create a master entity for it in the current context. - elsif Has_Task (Desig_Type) and then Comes_From_Source (Related_Nod) + elsif Has_Task (Desig_Type) + and then Comes_From_Source (Related_Nod) then Build_Master_Entity (Defining_Identifier (Related_Nod)); Build_Master_Renaming (Anon_Type); -- cgit v1.1 From 3d53efa6921534027dbe5d408ac274736dc43d9c Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 4 Jul 2019 08:05:45 +0000 Subject: [Ada] Skip code not in SPARK for ownership analysis Ownership rules for pointer support should only apply to code marked in SPARK. There is no impact on compilation. 2019-07-04 Yannick Moy gcc/ada/ * sem_spark.adb (Check_Package_Spec, Check_Package_Body): Only analyze parts of the code marked in SPARK. From-SVN: r273052 --- gcc/ada/ChangeLog | 5 ++++ gcc/ada/sem_spark.adb | 72 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 28 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6f300dc..07c3747 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Yannick Moy + + * sem_spark.adb (Check_Package_Spec, Check_Package_Body): Only + analyze parts of the code marked in SPARK. + 2019-07-04 Hristian Kirtchev * erroutc.adb, exp_aggr.adb, inline.adb, opt.adb, sem_ch3.adb: diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 82ddb16..1b1ba0f 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -2364,39 +2364,43 @@ package body Sem_SPARK is Save_In_Elab : constant Boolean := Inside_Elaboration; Spec : constant Node_Id := Package_Specification (Corresponding_Spec (Pack)); - Prag : constant Node_Id := SPARK_Pragma (Defining_Entity (Pack)); + Id : constant Entity_Id := Defining_Entity (Pack); + Prag : constant Node_Id := SPARK_Pragma (Id); + Aux_Prag : constant Node_Id := SPARK_Aux_Pragma (Id); Saved_Env : Perm_Env; begin - -- Only SPARK bodies are analyzed - - if No (Prag) - or else Get_SPARK_Mode_From_Annotation (Prag) /= Opt.On + if Present (Prag) + and then Get_SPARK_Mode_From_Annotation (Prag) = Opt.On then - return; - end if; + Inside_Elaboration := True; - Inside_Elaboration := True; + -- Save environment and put a new one in place - -- Save environment and put a new one in place + Move_Env (Current_Perm_Env, Saved_Env); - Move_Env (Current_Perm_Env, Saved_Env); + -- Reanalyze package spec to have its variables in the environment - -- Reanalyze package spec to have its variables in the environment + Check_List (Visible_Declarations (Spec)); + Check_List (Private_Declarations (Spec)); - Check_List (Visible_Declarations (Spec)); - Check_List (Private_Declarations (Spec)); + -- Check declarations and statements in the special mode for + -- elaboration. - -- Check declarations and statements in the special mode for elaboration + Check_List (Declarations (Pack)); - Check_List (Declarations (Pack)); - Check_Node (Handled_Statement_Sequence (Pack)); + if Present (Aux_Prag) + and then Get_SPARK_Mode_From_Annotation (Aux_Prag) = Opt.On + then + Check_Node (Handled_Statement_Sequence (Pack)); + end if; - -- Restore the saved environment and free the current one + -- Restore the saved environment and free the current one - Move_Env (Saved_Env, Current_Perm_Env); + Move_Env (Saved_Env, Current_Perm_Env); - Inside_Elaboration := Save_In_Elab; + Inside_Elaboration := Save_In_Elab; + end if; end Check_Package_Body; ------------------------ @@ -2406,25 +2410,37 @@ package body Sem_SPARK is procedure Check_Package_Spec (Pack : Node_Id) is Save_In_Elab : constant Boolean := Inside_Elaboration; Spec : constant Node_Id := Specification (Pack); + Id : constant Entity_Id := Defining_Entity (Pack); + Prag : constant Node_Id := SPARK_Pragma (Id); + Aux_Prag : constant Node_Id := SPARK_Aux_Pragma (Id); Saved_Env : Perm_Env; begin - Inside_Elaboration := True; + if Present (Prag) + and then Get_SPARK_Mode_From_Annotation (Prag) = Opt.On + then + Inside_Elaboration := True; - -- Save environment and put a new one in place + -- Save environment and put a new one in place - Move_Env (Current_Perm_Env, Saved_Env); + Move_Env (Current_Perm_Env, Saved_Env); - -- Check declarations in the special mode for elaboration + -- Check declarations in the special mode for elaboration - Check_List (Visible_Declarations (Spec)); - Check_List (Private_Declarations (Spec)); + Check_List (Visible_Declarations (Spec)); - -- Restore the saved environment and free the current one + if Present (Aux_Prag) + and then Get_SPARK_Mode_From_Annotation (Aux_Prag) = Opt.On + then + Check_List (Private_Declarations (Spec)); + end if; - Move_Env (Saved_Env, Current_Perm_Env); + -- Restore the saved environment and free the current one - Inside_Elaboration := Save_In_Elab; + Move_Env (Saved_Env, Current_Perm_Env); + + Inside_Elaboration := Save_In_Elab; + end if; end Check_Package_Spec; ------------------------------- -- cgit v1.1 From c3c41b296a71e77742d3edb3494945537cd72983 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 4 Jul 2019 08:05:50 +0000 Subject: [Ada] Unnesting: handle conditional expressions 2019-07-04 Ed Schonberg gcc/ada/ * exp_unst.adb: Handle conditional expressions. From-SVN: r273053 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/exp_unst.adb | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 07c3747..c60ab6d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Ed Schonberg + + * exp_unst.adb: Handle conditional expressions. + 2019-07-04 Yannick Moy * sem_spark.adb (Check_Package_Spec, Check_Package_Body): Only diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb index b81b1b9..6717610 100644 --- a/gcc/ada/exp_unst.adb +++ b/gcc/ada/exp_unst.adb @@ -598,6 +598,33 @@ package body Exp_Unst is then Note_Uplevel_Bound (Prefix (N), Ref); + -- Conditional expressions. + + elsif Nkind (N) = N_If_Expression then + declare + Expr : Node_Id; + + begin + Expr := First (Expressions (N)); + while Present (Expr) loop + Note_Uplevel_Bound (Expr, Ref); + Next (Expr); + end loop; + end; + + elsif Nkind (N) = N_Case_Expression then + declare + Alternative : Node_Id; + + begin + Note_Uplevel_Bound (Expression (N), Ref); + + Alternative := First (Alternatives (N)); + while Present (Alternative) loop + Note_Uplevel_Bound (Expression (Alternative), Ref); + end loop; + end; + -- Conversion case elsif Nkind (N) = N_Type_Conversion then -- cgit v1.1 From 7273107b948b81edc084b33e8e8fd4f3b4115f72 Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Thu, 4 Jul 2019 08:05:55 +0000 Subject: [Ada] Hang on expansion of library-level instantiation This patch fixes an issue whereby instantiation of a generic at the library-level may cause a hang or crash during compilation due to inappropriate expansion of generic actuals. 2019-07-04 Justin Squirek gcc/ada/ * sem_ch12.adb (Perform_Appropriate_Analysis): Added for selecting which type of analysis based on wheither the instantiation is a generic at the library-level. In which case expansion during analysis. (Preanalyze_Actuals): Modify calls to Analyze to use the new routine. gcc/testsuite/ * gnat.dg/generic_inst4.adb, gnat.dg/generic_inst4_gen.ads, gnat.dg/generic_inst4_inst.ads, gnat.dg/generic_inst4_typ.ads: New testcase. From-SVN: r273054 --- gcc/ada/ChangeLog | 9 ++++++ gcc/ada/sem_ch12.adb | 42 ++++++++++++++++++++++------ gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gnat.dg/generic_inst4.adb | 7 +++++ gcc/testsuite/gnat.dg/generic_inst4_gen.ads | 3 ++ gcc/testsuite/gnat.dg/generic_inst4_inst.ads | 5 ++++ gcc/testsuite/gnat.dg/generic_inst4_typ.ads | 7 +++++ 7 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/generic_inst4.adb create mode 100644 gcc/testsuite/gnat.dg/generic_inst4_gen.ads create mode 100644 gcc/testsuite/gnat.dg/generic_inst4_inst.ads create mode 100644 gcc/testsuite/gnat.dg/generic_inst4_typ.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c60ab6d..597e331 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-04 Justin Squirek + + * sem_ch12.adb (Perform_Appropriate_Analysis): Added for + selecting which type of analysis based on wheither the + instantiation is a generic at the library-level. In which case + expansion during analysis. + (Preanalyze_Actuals): Modify calls to Analyze to use the new + routine. + 2019-07-04 Ed Schonberg * exp_unst.adb: Handle conditional expressions. diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 42feab0..43beb83 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -14103,6 +14103,29 @@ package body Sem_Ch12 is ------------------------ procedure Preanalyze_Actuals (N : Node_Id; Inst : Entity_Id := Empty) is + + procedure Perform_Appropriate_Analysis (N : Node_Id); + -- Determine if the actuals we are analyzing come from a generic + -- instantiation that is a library unit and dispatch accordingly. + + ---------------------------------- + -- Perform_Appropriate_Analysis -- + ---------------------------------- + + procedure Perform_Appropriate_Analysis (N : Node_Id) is + begin + -- When we have a library instantiation we cannot allow any expansion + -- to occur, since there may be no place to put it. Instead, in that + -- case we perform a preanalysis of the actual. + + if Present (Inst) and then Is_Compilation_Unit (Inst) then + Preanalyze (N); + + else + Analyze (N); + end if; + end Perform_Appropriate_Analysis; + Assoc : Node_Id; Act : Node_Id; Errs : constant Nat := Serious_Errors_Detected; @@ -14113,6 +14136,8 @@ package body Sem_Ch12 is Vis : Boolean := False; -- Saved visibility status of the current homograph + -- Start of processing for Preanalyze_Actuals + begin Assoc := First (Generic_Associations (N)); @@ -14154,10 +14179,10 @@ package body Sem_Ch12 is null; elsif Nkind (Act) = N_Attribute_Reference then - Analyze (Prefix (Act)); + Perform_Appropriate_Analysis (Prefix (Act)); elsif Nkind (Act) = N_Explicit_Dereference then - Analyze (Prefix (Act)); + Perform_Appropriate_Analysis (Prefix (Act)); elsif Nkind (Act) = N_Allocator then declare @@ -14165,7 +14190,7 @@ package body Sem_Ch12 is begin if Nkind (Expr) = N_Subtype_Indication then - Analyze (Subtype_Mark (Expr)); + Perform_Appropriate_Analysis (Subtype_Mark (Expr)); -- Analyze separately each discriminant constraint, when -- given with a named association. @@ -14177,9 +14202,10 @@ package body Sem_Ch12 is Constr := First (Constraints (Constraint (Expr))); while Present (Constr) loop if Nkind (Constr) = N_Discriminant_Association then - Analyze (Expression (Constr)); + Perform_Appropriate_Analysis + (Expression (Constr)); else - Analyze (Constr); + Perform_Appropriate_Analysis (Constr); end if; Next (Constr); @@ -14187,12 +14213,12 @@ package body Sem_Ch12 is end; else - Analyze (Expr); + Perform_Appropriate_Analysis (Expr); end if; end; elsif Nkind (Act) /= N_Operator_Symbol then - Analyze (Act); + Perform_Appropriate_Analysis (Act); -- Within a package instance, mark actuals that are limited -- views, so their use can be moved to the body of the @@ -14213,7 +14239,7 @@ package body Sem_Ch12 is -- warnings complaining about the generic being unreferenced, -- before abandoning the instantiation. - Analyze (Name (N)); + Perform_Appropriate_Analysis (Name (N)); if Is_Entity_Name (Name (N)) and then Etype (Name (N)) /= Any_Type diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7147482..cf953b5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Justin Squirek + + * gnat.dg/generic_inst4.adb, gnat.dg/generic_inst4_gen.ads, + gnat.dg/generic_inst4_inst.ads, gnat.dg/generic_inst4_typ.ads: + New testcase. + 2019-07-04 Ed Schonberg * gnat.dg/dimensions2.adb, gnat.dg/dimensions2_phys.ads, diff --git a/gcc/testsuite/gnat.dg/generic_inst4.adb b/gcc/testsuite/gnat.dg/generic_inst4.adb new file mode 100644 index 0000000..c1b2496 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst4.adb @@ -0,0 +1,7 @@ +-- { dg-do compile } + +with Generic_Inst4_Inst; +procedure Generic_Inst4 is +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/generic_inst4_gen.ads b/gcc/testsuite/gnat.dg/generic_inst4_gen.ads new file mode 100644 index 0000000..a1c039e --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst4_gen.ads @@ -0,0 +1,3 @@ +generic + Param : String; +package Generic_Inst4_Gen is end; diff --git a/gcc/testsuite/gnat.dg/generic_inst4_inst.ads b/gcc/testsuite/gnat.dg/generic_inst4_inst.ads new file mode 100644 index 0000000..1660d67 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst4_inst.ads @@ -0,0 +1,5 @@ +with Generic_Inst4_Gen; +with Generic_Inst4_Typ; use Generic_Inst4_Typ; +package Generic_Inst4_Inst is new Generic_Inst4_Gen ( + Param => "SHARING;" & -- ERROR + Generic_Inst4_Typ.New_Int'image (Generic_Inst4_Typ.T'size/8)); diff --git a/gcc/testsuite/gnat.dg/generic_inst4_typ.ads b/gcc/testsuite/gnat.dg/generic_inst4_typ.ads new file mode 100644 index 0000000..5f80029 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst4_typ.ads @@ -0,0 +1,7 @@ +package Generic_Inst4_Typ is + subtype New_Int is Natural; + type T is + record + X : Integer; + end record; +end; -- cgit v1.1 From 194dc648e4b40ac705103cfc92dff0c11b82fb5a Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 4 Jul 2019 08:06:00 +0000 Subject: [Ada] Fix crash in SPARK ownership checking Analysis could crash on extended return of a non-deep type, now fixed. This has no impact on compilation. 2019-07-04 Yannick Moy gcc/ada/ * sem_spark.adb (Check_Statement): Only check permission of object in extended return when it is of a deep type. From-SVN: r273055 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_spark.adb | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 597e331..d49d331 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Yannick Moy + + * sem_spark.adb (Check_Statement): Only check permission of + object in extended return when it is of a deep type. + 2019-07-04 Justin Squirek * sem_ch12.adb (Perform_Appropriate_Analysis): Added for diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 1b1ba0f..fb46e62 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -2902,10 +2902,13 @@ package body Sem_SPARK is Check_List (Return_Object_Declarations (Stmt)); Check_Node (Handled_Statement_Sequence (Stmt)); - Perm := Get_Perm (Obj); + if Is_Deep (Etype (Obj)) then + Perm := Get_Perm (Obj); - if Perm /= Read_Write then - Perm_Error (Decl, Read_Write, Perm, Expl => Get_Expl (Obj)); + if Perm /= Read_Write then + Perm_Error (Decl, Read_Write, Perm, + Expl => Get_Expl (Obj)); + end if; end if; if Ekind_In (Subp, E_Procedure, E_Entry) -- cgit v1.1 From 9193307b56ea03321bb66e2f7e30c6e98d724efc Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 4 Jul 2019 08:06:05 +0000 Subject: [Ada] Synchronized object definition in SPARK updated The definition of what types yield synchronized objected in SPARK has been updated to see through the privacy boundary. 2019-07-04 Yannick Moy gcc/ada/ * sem_util.adb (Yields_Synchronized_Object): Adapt to new SPARK rule. gcc/testsuite/ * gnat.dg/synchronized2.adb, gnat.dg/synchronized2.ads, gnat.dg/synchronized2_pkg.ads: New testcase. From-SVN: r273056 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_util.adb | 11 ++++++++++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/synchronized2.adb | 5 +++++ gcc/testsuite/gnat.dg/synchronized2.ads | 4 ++++ gcc/testsuite/gnat.dg/synchronized2_pkg.ads | 5 +++++ 6 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/synchronized2.adb create mode 100644 gcc/testsuite/gnat.dg/synchronized2.ads create mode 100644 gcc/testsuite/gnat.dg/synchronized2_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d49d331..665b2b0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-04 Yannick Moy + * sem_util.adb (Yields_Synchronized_Object): Adapt to new SPARK + rule. + +2019-07-04 Yannick Moy + * sem_spark.adb (Check_Statement): Only check permission of object in extended return when it is of a deep type. diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 77eefdc..0fdbed6 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -26442,6 +26442,7 @@ package body Sem_Util is -- synchronized object. if Etype (Typ) /= Typ + and then not Is_Private_Type (Etype (Typ)) and then not Yields_Synchronized_Object (Etype (Typ)) then return False; @@ -26457,11 +26458,19 @@ package body Sem_Util is elsif Is_Synchronized_Interface (Typ) then return True; - -- A task type yelds a synchronized object by default + -- A task type yields a synchronized object by default elsif Is_Task_Type (Typ) then return True; + -- A private type yields a synchronized object if its underlying type + -- does. + + elsif Is_Private_Type (Typ) + and then Present (Underlying_Type (Typ)) + then + return Yields_Synchronized_Object (Underlying_Type (Typ)); + -- Otherwise the type does not yield a synchronized object else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cf953b5..fc041c82 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Yannick Moy + + * gnat.dg/synchronized2.adb, gnat.dg/synchronized2.ads, + gnat.dg/synchronized2_pkg.ads: New testcase. + 2019-07-04 Justin Squirek * gnat.dg/generic_inst4.adb, gnat.dg/generic_inst4_gen.ads, diff --git a/gcc/testsuite/gnat.dg/synchronized2.adb b/gcc/testsuite/gnat.dg/synchronized2.adb new file mode 100644 index 0000000..1c111ef --- /dev/null +++ b/gcc/testsuite/gnat.dg/synchronized2.adb @@ -0,0 +1,5 @@ +with Synchronized2_Pkg; +package body Synchronized2 with SPARK_Mode, Refined_State => (State => C) is + C : Synchronized2_Pkg.T; + procedure Dummy is null; +end; diff --git a/gcc/testsuite/gnat.dg/synchronized2.ads b/gcc/testsuite/gnat.dg/synchronized2.ads new file mode 100644 index 0000000..780edeb --- /dev/null +++ b/gcc/testsuite/gnat.dg/synchronized2.ads @@ -0,0 +1,4 @@ +-- { dg-do compile } +package Synchronized2 with SPARK_Mode, Abstract_State => (State with Synchronous) is + procedure Dummy; +end; diff --git a/gcc/testsuite/gnat.dg/synchronized2_pkg.ads b/gcc/testsuite/gnat.dg/synchronized2_pkg.ads new file mode 100644 index 0000000..57cae9c --- /dev/null +++ b/gcc/testsuite/gnat.dg/synchronized2_pkg.ads @@ -0,0 +1,5 @@ +package Synchronized2_Pkg with SPARK_Mode is + type T is limited private; +private + task type T; +end; -- cgit v1.1 From 965a269d8bbaca4a96b1327607c9dc42ad9484d4 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Thu, 4 Jul 2019 08:06:10 +0000 Subject: [Ada] Minor typo fixes 2019-07-04 Piotr Trojanek gcc/ada/ * sem_util.adb (Yields_Synchronized_Object): Fix typos in comments. From-SVN: r273057 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_util.adb | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 665b2b0..34a86ca 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Piotr Trojanek + + * sem_util.adb (Yields_Synchronized_Object): Fix typos in + comments. + 2019-07-04 Yannick Moy * sem_util.adb (Yields_Synchronized_Object): Adapt to new SPARK diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 0fdbed6..4d19c61 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -26407,12 +26407,12 @@ package body Sem_Util is -- A record type or type extension yields a synchronized object when its -- discriminants (if any) lack default values and all components are of - -- a type that yelds a synchronized object. + -- a type that yields a synchronized object. elsif Is_Record_Type (Typ) then -- Inspect all entities defined in the scope of the type, looking for - -- components of a type that does not yeld a synchronized object or + -- components of a type that does not yield a synchronized object or -- for discriminants with default values. Id := First_Entity (Typ); -- cgit v1.1 From 7cbdab5aa839ffd54dccbde6430905bb9c596201 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 4 Jul 2019 08:06:14 +0000 Subject: [Ada] Spurious error on 'First in a generic context This patch fixes a spurious error on an attribute reference within an aspect specification for an unconstrained array type when the corresponding type declaration appears within a generic unit. 2019-07-04 Ed Schonberg gcc/ada/ * sem_attr.adb (Check_Array_Type): An array type attribute such as 'First can be applied to an unconstrained array tyope when the attribute reference appears within an aspect specification and the prefix is a current instance, given that the prefix of the attribute will become a formal of the subprogram that implements the aspect (typically a predicate check). gcc/testsuite/ * gnat.dg/aspect2.adb, gnat.dg/aspect2.ads: New testcase. From-SVN: r273058 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/sem_attr.adb | 5 ++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/aspect2.adb | 5 +++++ gcc/testsuite/gnat.dg/aspect2.ads | 30 ++++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/aspect2.adb create mode 100644 gcc/testsuite/gnat.dg/aspect2.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 34a86ca..be26421 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-04 Ed Schonberg + + * sem_attr.adb (Check_Array_Type): An array type attribute such + as 'First can be applied to an unconstrained array tyope when + the attribute reference appears within an aspect specification + and the prefix is a current instance, given that the prefix of + the attribute will become a formal of the subprogram that + implements the aspect (typically a predicate check). + 2019-07-04 Piotr Trojanek * sem_util.adb (Yields_Synchronized_Object): Fix typos in diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index bdc76c3..fd2c6d6 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -1634,7 +1634,9 @@ package body Sem_Attr is raise Bad_Attribute; end if; - -- Normal case of array type or subtype + -- Normal case of array type or subtype. Note that if the + -- prefix is a current instance of a type declaration it + -- appears within an aspect specification and is legal. Check_Either_E0_Or_E1; Check_Dereference; @@ -1643,6 +1645,7 @@ package body Sem_Attr is if not Is_Constrained (P_Type) and then Is_Entity_Name (P) and then Is_Type (Entity (P)) + and then not Is_Current_Instance (P) then -- Note: we do not call Error_Attr here, since we prefer to -- continue, using the relevant index type of the array, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fc041c82..dd22271 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Ed Schonberg + + * gnat.dg/aspect2.adb, gnat.dg/aspect2.ads: New testcase. + 2019-07-04 Yannick Moy * gnat.dg/synchronized2.adb, gnat.dg/synchronized2.ads, diff --git a/gcc/testsuite/gnat.dg/aspect2.adb b/gcc/testsuite/gnat.dg/aspect2.adb new file mode 100644 index 0000000..acf3329 --- /dev/null +++ b/gcc/testsuite/gnat.dg/aspect2.adb @@ -0,0 +1,5 @@ +-- { dg-do compile } + +package body Aspect2 is + procedure Foo is null; +end Aspect2; diff --git a/gcc/testsuite/gnat.dg/aspect2.ads b/gcc/testsuite/gnat.dg/aspect2.ads new file mode 100644 index 0000000..73d3fe0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/aspect2.ads @@ -0,0 +1,30 @@ +with Ada.Containers.Functional_Vectors; +with Ada.Containers; use Ada.Containers; + +generic + type Element_Type (<>) is private; + type Element_Model (<>) is private; + with function Model (X : Element_Type) return Element_Model is <>; + with function Copy (X : Element_Type) return Element_Type is <>; +package Aspect2 with SPARK_Mode is + pragma Unevaluated_Use_Of_Old (Allow); + + type Vector is private; + + function Length (V : Vector) return Natural; + + procedure Foo; + +private + type Element_Access is access Element_Type; + type Element_Array is array (Positive range <>) of Element_Access with + Dynamic_Predicate => Element_Array'First = 1; + type Element_Array_Access is access Element_Array; + type Vector is record + Top : Natural := 0; + Content : Element_Array_Access; + end record; + + function Length (V : Vector) return Natural is + (V.Top); +end Aspect2; -- cgit v1.1 From dd4d8a71980487ddb4ac6c1ad0a1b8fb6c143592 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 4 Jul 2019 08:06:19 +0000 Subject: [Ada] Assertion failure on Default_Initial_Condition This patch prevents the association of a Default_Initial_Condition with an incomplete type whose full view is the private type or private extension subject to the aspect/pragma. 2019-07-04 Hristian Kirtchev gcc/ada/ * sem_util.adb (Propagate_DIC_Attributes): Do not propagate the Default_Initial_Condition attributes to an incomplete type. gcc/testsuite/ * gnat.dg/default_initial_condition.adb, gnat.dg/default_initial_condition_pack.adb, gnat.dg/default_initial_condition_pack.ads: New testcase. From-SVN: r273059 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_util.adb | 7 +++++++ gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gnat.dg/default_initial_condition.adb | 12 ++++++++++++ gcc/testsuite/gnat.dg/default_initial_condition_pack.adb | 7 +++++++ gcc/testsuite/gnat.dg/default_initial_condition_pack.ads | 12 ++++++++++++ 6 files changed, 49 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/default_initial_condition.adb create mode 100644 gcc/testsuite/gnat.dg/default_initial_condition_pack.adb create mode 100644 gcc/testsuite/gnat.dg/default_initial_condition_pack.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index be26421..2925c84 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Hristian Kirtchev + + * sem_util.adb (Propagate_DIC_Attributes): Do not propagate the + Default_Initial_Condition attributes to an incomplete type. + 2019-07-04 Ed Schonberg * sem_attr.adb (Check_Array_Type): An array type attribute such diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 4d19c61..868e93e 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -23327,6 +23327,13 @@ package body Sem_Util is if From_Typ = Typ then return; + + -- Nothing to do when the destination denotes an incomplete type + -- because the DIC is associated with the current instance of a + -- private type, thus it can never apply to an incomplete type. + + elsif Is_Incomplete_Type (Typ) then + return; end if; DIC_Proc := DIC_Procedure (From_Typ); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dd22271..2b1a479 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Hristian Kirtchev + + * gnat.dg/default_initial_condition.adb, + gnat.dg/default_initial_condition_pack.adb, + gnat.dg/default_initial_condition_pack.ads: New testcase. + 2019-07-04 Ed Schonberg * gnat.dg/aspect2.adb, gnat.dg/aspect2.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/default_initial_condition.adb b/gcc/testsuite/gnat.dg/default_initial_condition.adb new file mode 100644 index 0000000..5ba94a6 --- /dev/null +++ b/gcc/testsuite/gnat.dg/default_initial_condition.adb @@ -0,0 +1,12 @@ +-- { dg-do run } +-- { dg-options "-gnata" } + +with Default_Initial_Condition_Pack; use Default_Initial_Condition_Pack; + +procedure Default_Initial_Condition is + Obj : T; +begin + if not DIC_Called then + raise Program_Error; + end if; +end Default_Initial_Condition; diff --git a/gcc/testsuite/gnat.dg/default_initial_condition_pack.adb b/gcc/testsuite/gnat.dg/default_initial_condition_pack.adb new file mode 100644 index 0000000..abcd491 --- /dev/null +++ b/gcc/testsuite/gnat.dg/default_initial_condition_pack.adb @@ -0,0 +1,7 @@ +package body Default_Initial_Condition_Pack is + function Is_OK (Val : T) return Boolean is + begin + DIC_Called := True; + return True; + end Is_OK; +end Default_Initial_Condition_Pack; diff --git a/gcc/testsuite/gnat.dg/default_initial_condition_pack.ads b/gcc/testsuite/gnat.dg/default_initial_condition_pack.ads new file mode 100644 index 0000000..c461bf2 --- /dev/null +++ b/gcc/testsuite/gnat.dg/default_initial_condition_pack.ads @@ -0,0 +1,12 @@ +package Default_Initial_Condition_Pack is + type T; + type T is private + with Default_Initial_Condition => Is_OK (T); + + function Is_OK (Val : T) return Boolean; + + DIC_Called : Boolean := False; + +private + type T is null record; +end Default_Initial_Condition_Pack; -- cgit v1.1 From b27f2c40019569ba7c4d7e38edb3e2ebcd0593c6 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Thu, 4 Jul 2019 08:06:25 +0000 Subject: [Ada] Do not create a master unless Tasking_Allowed 2019-07-04 Bob Duff gcc/ada/ * sem_ch3.adb (Access_Definition): Do not create a master unless Tasking_Allowed. Otherwise, this fails on restricted runtimes. From-SVN: r273060 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_ch3.adb | 1 + 2 files changed, 6 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2925c84..f11f78b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Bob Duff + + * sem_ch3.adb (Access_Definition): Do not create a master unless + Tasking_Allowed. Otherwise, this fails on restricted runtimes. + 2019-07-04 Hristian Kirtchev * sem_util.adb (Propagate_DIC_Attributes): Do not propagate the diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index a82c2bc..ec86266 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -935,6 +935,7 @@ package body Sem_Ch3 is then if Is_Limited_Record (Desig_Type) and then Is_Class_Wide_Type (Desig_Type) + and then Tasking_Allowed then Build_Class_Wide_Master (Anon_Type); -- cgit v1.1 From fa528281a9d056bf5beb867333ea4eea638a102d Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Thu, 4 Jul 2019 08:06:30 +0000 Subject: [Ada] Missing actual for generated initialization procedure This patch fixes an issue whereby the use of an allocator with a composite type containing null-excluding components may lead to a compile time error due to incorrect code generation. 2019-07-04 Justin Squirek gcc/ada/ * exp_ch3.adb (Build_Initialization_Call): Fixup *_skip_null_excluding_check argument to handle new default. (Init_Formals): Make *_skip_null_excluding_check formal default to False * exp_ch4.adb (Expand_N_Allocator): Add comment to note heavy code duplication gcc/testsuite/ * gnat.dg/allocator.adb: New testcase. From-SVN: r273061 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/exp_ch3.adb | 31 ++++++++++++++----------------- gcc/ada/exp_ch4.adb | 3 +++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/allocator.adb | 11 +++++++++++ 5 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/allocator.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f11f78b..b5e9bd6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-04 Justin Squirek + + * exp_ch3.adb (Build_Initialization_Call): Fixup + *_skip_null_excluding_check argument to handle new default. + (Init_Formals): Make *_skip_null_excluding_check formal default + to False + * exp_ch4.adb (Expand_N_Allocator): Add comment to note heavy + code duplication + 2019-07-04 Bob Duff * sem_ch3.adb (Access_Definition): Do not create a master unless diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 753c5fb..49fcfd7 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -1555,23 +1555,19 @@ package body Exp_Ch3 is -- Handle the optionally generated formal *_skip_null_excluding_checks - if Needs_Conditional_Null_Excluding_Check (Full_Init_Type) then - - -- Look at the associated node for the object we are referencing - -- and verify that we are expanding a call to an Init_Proc for an - -- internally generated object declaration before passing True and - -- skipping the relevant checks. - - if Nkind (Id_Ref) in N_Has_Entity - and then Comes_From_Source (Associated_Node (Id_Ref)) - then - Append_To (Args, New_Occurrence_Of (Standard_True, Loc)); - - -- Otherwise, we pass False to perform null-excluding checks - - else - Append_To (Args, New_Occurrence_Of (Standard_False, Loc)); - end if; + -- Look at the associated node for the object we are referencing and + -- verify that we are expanding a call to an Init_Proc for an internally + -- generated object declaration before passing True and skipping the + -- relevant checks. + + if Needs_Conditional_Null_Excluding_Check (Full_Init_Type) + and then Nkind (Id_Ref) in N_Has_Entity + and then (Comes_From_Source (Id_Ref) + or else (Present (Associated_Node (Id_Ref)) + and then Comes_From_Source + (Associated_Node (Id_Ref)))) + then + Append_To (Args, New_Occurrence_Of (Standard_True, Loc)); end if; -- Add discriminant values if discriminants are present @@ -8695,6 +8691,7 @@ package body Exp_Ch3 is Make_Defining_Identifier (Loc, New_External_Name (Chars (Component_Type (Typ)), "_skip_null_excluding_check")), + Expression => New_Occurrence_Of (Standard_False, Loc), In_Present => True, Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc))); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7ba4283..7a757e4 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4751,6 +4751,9 @@ package body Exp_Ch4 is -- Case of initialization procedure present, must be called + -- NOTE: There is a *huge* amount of code duplication here from + -- Build_Initialization_Call. We should probably refactor??? + else Check_Restriction (No_Default_Initialization, N); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2b1a479..c4b0046 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Justin Squirek + + * gnat.dg/allocator.adb: New testcase. + 2019-07-04 Hristian Kirtchev * gnat.dg/default_initial_condition.adb, diff --git a/gcc/testsuite/gnat.dg/allocator.adb b/gcc/testsuite/gnat.dg/allocator.adb new file mode 100644 index 0000000..c3840aa --- /dev/null +++ b/gcc/testsuite/gnat.dg/allocator.adb @@ -0,0 +1,11 @@ +-- { dg-do compile } + +procedure Allocator is + type Object_Type is not null access all Integer; + type Object_Array is array (Positive range <>) of Object_Type; + type Object_Array_Ptr is access Object_Array; + type Data_Ptr is access Object_Array_Ptr; + Copy : Data_Ptr := new Object_Array_Ptr; +begin + Copy.all := new Object_Array (1..2); +end; -- cgit v1.1 From bdbb2a405541671bb427f6ff2f463a98c62b0a46 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 4 Jul 2019 08:06:35 +0000 Subject: [Ada] Bug in composition of equality for variant records This patch fixes an omission in the construction of equality routines for variant records, to take into account user-defined equality functions for components of the record. Previously the constructed equality routine for variant records used the predefined equality for all components, When composavility of equality was introduced for untagged records, expansion of record equality was modified properly, but not for the case of variant records, which use a different and more complex process to build the equality function. 2019-07-04 Ed Schonberg gcc/ada/ * exp_ch4.ads, exp_ch4.adb (Build_Eq_Call): New visible subprogram, extracted from Expand_Composite_Equality, to handle properly the composition of equality for variant record types. * exp_ch3.adb (MAke_Eq_If): Use Build_Eq_Call for each component, to handle properly the case of a component with a user-defined equality. Revert to predefined equality if the user-defined operation is abstract, to maintain compatibility with older versions, gcc/testsuite/ * gnat.dg/equal6.adb, gnat.dg/equal6_types.adb, gnat.dg/equal6_types.ads: New testcase. From-SVN: r273062 --- gcc/ada/ChangeLog | 11 ++++ gcc/ada/exp_ch3.adb | 63 ++++++++++++++++++---- gcc/ada/exp_ch4.adb | 96 +++++++++++++++++----------------- gcc/ada/exp_ch4.ads | 14 +++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gnat.dg/equal6.adb | 29 ++++++++++ gcc/testsuite/gnat.dg/equal6_types.adb | 15 ++++++ gcc/testsuite/gnat.dg/equal6_types.ads | 49 +++++++++++++++++ 8 files changed, 223 insertions(+), 59 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/equal6.adb create mode 100644 gcc/testsuite/gnat.dg/equal6_types.adb create mode 100644 gcc/testsuite/gnat.dg/equal6_types.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b5e9bd6..1d6d8c0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2019-07-04 Ed Schonberg + + * exp_ch4.ads, exp_ch4.adb (Build_Eq_Call): New visible + subprogram, extracted from Expand_Composite_Equality, to handle + properly the composition of equality for variant record types. + * exp_ch3.adb (MAke_Eq_If): Use Build_Eq_Call for each + component, to handle properly the case of a component with a + user-defined equality. Revert to predefined equality if the + user-defined operation is abstract, to maintain compatibility + with older versions, + 2019-07-04 Justin Squirek * exp_ch3.adb (Build_Initialization_Call): Fixup diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 49fcfd7..6308b42 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -9477,6 +9477,11 @@ package body Exp_Ch3 is -- or a null statement if the list L is empty + -- Equality may be user-defined for a given component type, in which case + -- a function call is constructed instead of an operator node. This is an + -- Ada 2012 change in the composability of equality for untagged composite + -- types. + function Make_Eq_If (E : Entity_Id; L : List_Id) return Node_Id @@ -9485,6 +9490,8 @@ package body Exp_Ch3 is C : Node_Id; Field_Name : Name_Id; Cond : Node_Id; + Next_Test : Node_Id; + Typ : Entity_Id; begin if No (L) then @@ -9495,6 +9502,7 @@ package body Exp_Ch3 is C := First_Non_Pragma (L); while Present (C) loop + Typ := Etype (Defining_Identifier (C)); Field_Name := Chars (Defining_Identifier (C)); -- The tags must not be compared: they are not part of the value. @@ -9507,22 +9515,55 @@ package body Exp_Ch3 is -- discriminants could be picked up in the private type case. if Field_Name = Name_uParent - and then Is_Interface (Etype (Defining_Identifier (C))) + and then Is_Interface (Typ) then null; elsif Field_Name /= Name_uTag then - Evolve_Or_Else (Cond, - Make_Op_Ne (Loc, - Left_Opnd => - Make_Selected_Component (Loc, - Prefix => Make_Identifier (Loc, Name_X), - Selector_Name => Make_Identifier (Loc, Field_Name)), + declare + Lhs : constant Node_Id := + Make_Selected_Component (Loc, + Prefix => Make_Identifier (Loc, Name_X), + Selector_Name => Make_Identifier (Loc, Field_Name)); - Right_Opnd => - Make_Selected_Component (Loc, - Prefix => Make_Identifier (Loc, Name_Y), - Selector_Name => Make_Identifier (Loc, Field_Name)))); + Rhs : constant Node_Id := + Make_Selected_Component (Loc, + Prefix => Make_Identifier (Loc, Name_Y), + Selector_Name => Make_Identifier (Loc, Field_Name)); + Eq_Call : Node_Id; + + begin + -- Build equality code with a user-defined operator, if + -- available, and with the predefined "=" otherwise. + -- For compatibility with older Ada versions, and preserve + -- the workings of some ASIS tools, we also use the + -- predefined operation if the component-type equality + -- is abstract, rather than raising Program_Error. + + if Ada_Version < Ada_2012 then + Next_Test := Make_Op_Ne (Loc, Lhs, Rhs); + + else + Eq_Call := Build_Eq_Call (Typ, Loc, Lhs, Rhs); + + if No (Eq_Call) then + Next_Test := Make_Op_Ne (Loc, Lhs, Rhs); + + -- If a component has a defined abstract equality, + -- its application raises Program_Error on that + -- component and therefore on the current variant. + + elsif Nkind (Eq_Call) = N_Raise_Program_Error then + Set_Etype (Eq_Call, Standard_Boolean); + Next_Test := Make_Op_Not (Loc, Eq_Call); + + else + Next_Test := Make_Op_Not (Loc, Eq_Call); + end if; + end if; + end; + + Evolve_Or_Else (Cond, Next_Test); end if; Next_Non_Pragma (C); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7a757e4..cacc9d4 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -2338,52 +2338,6 @@ package body Exp_Ch4 is Full_Type : Entity_Id; Eq_Op : Entity_Id; - function Find_Primitive_Eq return Node_Id; - -- AI05-0123: Locate primitive equality for type if it exists, and - -- build the corresponding call. If operation is abstract, replace - -- call with an explicit raise. Return Empty if there is no primitive. - - ----------------------- - -- Find_Primitive_Eq -- - ----------------------- - - function Find_Primitive_Eq return Node_Id is - Prim_E : Elmt_Id; - Prim : Node_Id; - - begin - Prim_E := First_Elmt (Collect_Primitive_Operations (Typ)); - while Present (Prim_E) loop - Prim := Node (Prim_E); - - -- Locate primitive equality with the right signature - - if Chars (Prim) = Name_Op_Eq - and then Etype (First_Formal (Prim)) = - Etype (Next_Formal (First_Formal (Prim))) - and then Etype (Prim) = Standard_Boolean - then - if Is_Abstract_Subprogram (Prim) then - return - Make_Raise_Program_Error (Loc, - Reason => PE_Explicit_Raise); - - else - return - Make_Function_Call (Loc, - Name => New_Occurrence_Of (Prim, Loc), - Parameter_Associations => New_List (Lhs, Rhs)); - end if; - end if; - - Next_Elmt (Prim_E); - end loop; - - -- If not found, predefined operation will be used - - return Empty; - end Find_Primitive_Eq; - -- Start of processing for Expand_Composite_Equality begin @@ -2654,7 +2608,7 @@ package body Exp_Ch4 is -- a primitive equality declared for it. declare - Op : constant Node_Id := Find_Primitive_Eq; + Op : constant Node_Id := Build_Eq_Call (Typ, Loc, Lhs, Rhs); begin -- Use user-defined primitive if it exists, otherwise use @@ -12599,7 +12553,53 @@ package body Exp_Ch4 is Adjust_Result_Type (N, Typ); end Expand_Short_Circuit_Operator; - ------------------------------------- + ----------------------- + -- Build_Eq_Call -- + ----------------------- + + function Build_Eq_Call + (Typ : Entity_Id; + Loc : Source_Ptr; + Lhs : Node_Id; + Rhs : Node_Id) return Node_Id + is + Prim_E : Elmt_Id; + Prim : Node_Id; + + begin + Prim_E := First_Elmt (Collect_Primitive_Operations (Typ)); + while Present (Prim_E) loop + Prim := Node (Prim_E); + + -- Locate primitive equality with the right signature + + if Chars (Prim) = Name_Op_Eq + and then Etype (First_Formal (Prim)) = + Etype (Next_Formal (First_Formal (Prim))) + and then Etype (Prim) = Standard_Boolean + then + if Is_Abstract_Subprogram (Prim) then + return + Make_Raise_Program_Error (Loc, + Reason => PE_Explicit_Raise); + + else + return + Make_Function_Call (Loc, + Name => New_Occurrence_Of (Prim, Loc), + Parameter_Associations => New_List (Lhs, Rhs)); + end if; + end if; + + Next_Elmt (Prim_E); + end loop; + + -- If not found, predefined operation will be used + + return Empty; + end Build_Eq_Call; + + ------------------------------------ -- Fixup_Universal_Fixed_Operation -- ------------------------------------- diff --git a/gcc/ada/exp_ch4.ads b/gcc/ada/exp_ch4.ads index 5ff9fc4..f2deaae 100644 --- a/gcc/ada/exp_ch4.ads +++ b/gcc/ada/exp_ch4.ads @@ -29,6 +29,20 @@ with Types; use Types; package Exp_Ch4 is + function Build_Eq_Call + (Typ : Entity_Id; + Loc : Source_Ptr; + Lhs : Node_Id; + Rhs : Node_Id) return Node_Id; + -- AI05-0123: Locate primitive equality for type if it exists, and build + -- the corresponding call. If operation is abstract, replace call with + -- an explicit raise. Return Empty if there is no primitive. + -- Used in the construction of record-equality routines for records here + -- and for variant records in exp_ch3.adb. These two paths are distinct + -- for historical but also technical reasons: for variant records the + -- constructed function includes a case statement with nested returns, + -- while for records without variants only a simple expression is needed. + procedure Expand_N_Allocator (N : Node_Id); procedure Expand_N_And_Then (N : Node_Id); procedure Expand_N_Case_Expression (N : Node_Id); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c4b0046..996a0ec 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Ed Schonberg + + * gnat.dg/equal6.adb, gnat.dg/equal6_types.adb, + gnat.dg/equal6_types.ads: New testcase. + 2019-07-04 Justin Squirek * gnat.dg/allocator.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/equal6.adb b/gcc/testsuite/gnat.dg/equal6.adb new file mode 100644 index 0000000..dea772f --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal6.adb @@ -0,0 +1,29 @@ +-- { dg-do run } +with Text_IO; +with Equal6_Types; use Equal6_Types; + +procedure Equal6 is + Packets_In : To_Evc_Optional_Packet_List_T; + Packets_Out : To_Evc_Optional_Packet_List_T; +begin + Packets_In.list (1) := + (Data_Used_Outside_Ertms_System => + (Mail_Box => + (Receiver => 31, + Data => (Length => 12, Message => (0, others => 0))))); + + Packets_Out.list (1) := + (Data_Used_Outside_Ertms_System => + (Mail_Box => + (Receiver => 31, + Data => (Length => 12, Message => (0, others => 1))))); + + if not (Packets_In = Packets_Out) then + raise Program_Error; + end if; + + if not (Equal1_Called and then Equal2_Called) then + raise Program_Error; + end if; + +end Equal6; diff --git a/gcc/testsuite/gnat.dg/equal6_types.adb b/gcc/testsuite/gnat.dg/equal6_types.adb new file mode 100644 index 0000000..7105b07 --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal6_types.adb @@ -0,0 +1,15 @@ +package body Equal6_Types is + + function "=" (L, R : in Mail_Box_Data_T) return Boolean is + use type Bits_T; + begin + Equal1_Called := True; + return L.Message (1) = R.Message (1); + end "="; + + function "=" (L, R : in To_Evc_Optional_Packet_List_T) return Boolean is + begin + Equal2_Called := True; + return L.List (1) = R.List (1); + end "="; +end Equal6_Types; diff --git a/gcc/testsuite/gnat.dg/equal6_types.ads b/gcc/testsuite/gnat.dg/equal6_types.ads new file mode 100644 index 0000000..90ec52bb --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal6_types.ads @@ -0,0 +1,49 @@ +package Equal6_Types is + type Bit_T is range 0 .. 1; + + type Bits_T is array (Positive range <>) of Bit_T; + + type Nid_Xuser_T is range 0 .. 511; + + Dispatch_P44_To_Ntc_C : constant Nid_Xuser_T := 102; + + type Mail_Box_Data_T is record + Length : Natural; + Message : Bits_T (1 .. 200); + end record; + function "=" (L, R : in Mail_Box_Data_T) return Boolean; + Equal1_Called : Boolean := False; + + type Mail_Box_T (Receiver : Nid_Xuser_T := Nid_Xuser_T'First) is record + Data : Mail_Box_Data_T; + case Receiver is + when Dispatch_P44_To_Ntc_C => + Stm_Id : Positive; + when others => + null; + end case; + end record; + + type Data_Used_Outside_Ertms_System_T is record + Mail_Box : Mail_Box_T; + end record; + + type To_Evc_Optional_Packet_T + is record + Data_Used_Outside_Ertms_System : Data_Used_Outside_Ertms_System_T; + end record; + + type To_Evc_Optional_Packet_List_Length_T is range 0 .. 50; + type To_Evc_Optional_Packet_Map_T is + array + (To_Evc_Optional_Packet_List_Length_T range <>) + of To_Evc_Optional_Packet_T; + + type To_Evc_Optional_Packet_List_T is record + List : To_Evc_Optional_Packet_Map_T + (1 .. To_Evc_Optional_Packet_List_Length_T'Last); + end record; + function "=" (L, R : in To_Evc_Optional_Packet_List_T) return Boolean; + Equal2_Called : Boolean := False; + +end Equal6_Types; -- cgit v1.1 From e3a79ce3c18fc6e1df6176e506095c7f8bac30ab Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Thu, 4 Jul 2019 08:06:40 +0000 Subject: [Ada] Spurious error on incomplete tagged formal parameter This patch fixes an issue whereby a check for competing controlling formals led to a spurious dispatching error due to an incomplete type being used within a subprogram specification. 2019-07-04 Justin Squirek gcc/ada/ * sem_disp.adb (Check_Controlling_Formals): Obtain the full view before type comparison. gcc/testsuite/ * gnat.dg/tagged2.adb, gnat.dg/tagged2.ads: New testcase. From-SVN: r273063 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_disp.adb | 8 ++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/tagged2.adb | 9 +++++++++ gcc/testsuite/gnat.dg/tagged2.ads | 9 +++++++++ 5 files changed, 35 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/tagged2.adb create mode 100644 gcc/testsuite/gnat.dg/tagged2.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1d6d8c0..e476413 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Justin Squirek + + * sem_disp.adb (Check_Controlling_Formals): Obtain the full view + before type comparison. + 2019-07-04 Ed Schonberg * exp_ch4.ads, exp_ch4.adb (Build_Eq_Call): New visible diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb index a2f753b..92486cd 100644 --- a/gcc/ada/sem_disp.adb +++ b/gcc/ada/sem_disp.adb @@ -210,6 +210,14 @@ package body Sem_Disp is Ctrl_Type := Check_Controlling_Type (Etype (Formal), Subp); if Present (Ctrl_Type) then + -- Obtain the full type in case we are looking at an incomplete + -- view. + + if Ekind (Ctrl_Type) = E_Incomplete_Type + and then Present (Full_View (Ctrl_Type)) + then + Ctrl_Type := Full_View (Ctrl_Type); + end if; -- When controlling type is concurrent and declared within a -- generic or inside an instance use corresponding record type. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 996a0ec..6873356 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Justin Squirek + + * gnat.dg/tagged2.adb, gnat.dg/tagged2.ads: New testcase. + 2019-07-04 Ed Schonberg * gnat.dg/equal6.adb, gnat.dg/equal6_types.adb, diff --git a/gcc/testsuite/gnat.dg/tagged2.adb b/gcc/testsuite/gnat.dg/tagged2.adb new file mode 100644 index 0000000..2cf9fc5 --- /dev/null +++ b/gcc/testsuite/gnat.dg/tagged2.adb @@ -0,0 +1,9 @@ +-- { dg-do compile } + +package body Tagged2 is + + procedure Get_Parent + (DeviceX : Device; + Parent : out Device) is null; + +end Tagged2; diff --git a/gcc/testsuite/gnat.dg/tagged2.ads b/gcc/testsuite/gnat.dg/tagged2.ads new file mode 100644 index 0000000..8bbc485 --- /dev/null +++ b/gcc/testsuite/gnat.dg/tagged2.ads @@ -0,0 +1,9 @@ +package Tagged2 is + type Device; + + procedure Get_Parent + (DeviceX : Device; + Parent : out Device); + + type Device is tagged null record; +end Tagged2; -- cgit v1.1 From 3cc0fae4334466cc8da40e454455b08e83c9e932 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 4 Jul 2019 08:06:45 +0000 Subject: [Ada] SPARK_Mode Off now allowed inside subprogram The rule on SPARK_Mode have been modified so that it is now possible to have a subprogram or package declared with SPARK_Mode Off inside a subprogram. 2019-07-04 Yannick Moy gcc/ada/ * sem_prag.adb (Check_Library_Level_Entity): Update for new rule on SPARK_Mode. gcc/testsuite/ * gnat.dg/spark3.adb: New testcase. From-SVN: r273064 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_prag.adb | 11 ++++++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/spark3.adb | 20 ++++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/spark3.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e476413..f5c2927 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Yannick Moy + + * sem_prag.adb (Check_Library_Level_Entity): Update for new rule + on SPARK_Mode. + 2019-07-04 Justin Squirek * sem_disp.adb (Check_Controlling_Formals): Obtain the full view diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index b499dbd..d841426 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -23189,7 +23189,16 @@ package body Sem_Prag is -- Start of processing for Check_Library_Level_Entity begin - if not Is_Library_Level_Entity (E) then + -- A SPARK_Mode of On shall only apply to library-level + -- entities, except for those in generic instances, which are + -- ignored (even if the entity gets SPARK_Mode pragma attached + -- in the AST, its effect is not taken into account unless the + -- context already provides SPARK_Mode of On in GNATprove). + + if Get_SPARK_Mode_From_Annotation (N) = On + and then not Is_Library_Level_Entity (E) + and then Instantiation_Location (Sloc (N)) = No_Location + then Error_Msg_Name_1 := Pname; Error_Msg_N (Fix_Error (Msg_1), N); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6873356..3502e68 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Yannick Moy + + * gnat.dg/spark3.adb: New testcase. + 2019-07-04 Justin Squirek * gnat.dg/tagged2.adb, gnat.dg/tagged2.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/spark3.adb b/gcc/testsuite/gnat.dg/spark3.adb new file mode 100644 index 0000000..3c9908a --- /dev/null +++ b/gcc/testsuite/gnat.dg/spark3.adb @@ -0,0 +1,20 @@ +-- { dg-do compile } + +procedure SPARK3 (X : in out Integer) with SPARK_Mode is + + procedure Q (X : in out Integer) with SPARK_Mode => Off is + begin + X := X + 1; + end Q; + + procedure R (X : in out Integer); + + procedure R (X : in out Integer) with SPARK_Mode => Off is + begin + Q (X); + end R; + +begin + R (X); + X := X + 1; +end SPARK3; -- cgit v1.1 From 901a52ba7d5c1f530e60f0b615ee16889786532a Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Thu, 4 Jul 2019 08:06:49 +0000 Subject: [Ada] Expr. func. with private formal rejected in nested Ghost package The compiler prematurely freezes a private type that is the type of a formal parameter of an expression function declared within a nested, inactivated Ghost package, resulting is an error complaining that the private type must be fully defined at that point. This is fixed by testing for Ignored_Ghost_Entity in the condition guarding the code that performs Mask_Unfrozen_Types for an expression function without a separate declaration, ensuring that the expression function's profile isn't frozen prematurely. 2019-07-04 Gary Dismukes gcc/ada/ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): The special treatment of calling Mask_Unfrozen_Types must also be done in the case of an Ignored_Ghost_Entity, because Expander_Active is False in that case. gcc/testsuite/ * gnat.dg/ghost5.adb, gnat.dg/ghost5.ads, gnat.dg/ghost5_parent.ads: New testcase. From-SVN: r273065 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch6.adb | 7 +++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/ghost5.adb | 5 +++++ gcc/testsuite/gnat.dg/ghost5.ads | 5 +++++ gcc/testsuite/gnat.dg/ghost5_parent.ads | 14 ++++++++++++++ 6 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/ghost5.adb create mode 100644 gcc/testsuite/gnat.dg/ghost5.ads create mode 100644 gcc/testsuite/gnat.dg/ghost5_parent.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f5c2927..5eb10d2 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-04 Gary Dismukes + + * sem_ch6.adb (Analyze_Subprogram_Body_Helper): The special + treatment of calling Mask_Unfrozen_Types must also be done in + the case of an Ignored_Ghost_Entity, because Expander_Active is + False in that case. + 2019-07-04 Yannick Moy * sem_prag.adb (Check_Library_Level_Entity): Update for new rule diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index cf1b0e7..d238b9d 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -3689,7 +3689,7 @@ package body Sem_Ch6 is -- generated. Freeze nodes, if any, are inserted before the current -- body. These freeze actions are also needed in ASIS mode and in -- Compile_Only mode to enable the proper back-end type annotations. - -- They are necessary in any case to insure order of elaboration + -- They are necessary in any case to ensure proper elaboration order -- in gigi. if Nkind (N) = N_Subprogram_Body @@ -3698,13 +3698,16 @@ package body Sem_Ch6 is and then Serious_Errors_Detected = 0 and then (Expander_Active or else ASIS_Mode - or else Operating_Mode = Check_Semantics) + or else Operating_Mode = Check_Semantics + or else Is_Ignored_Ghost_Entity (Spec_Id)) then -- The body generated for an expression function that is not a -- completion is a freeze point neither for the profile nor for -- anything else. That's why, in order to prevent any freezing -- during analysis, we need to mask types declared outside the -- expression (and in an outer scope) that are not yet frozen. + -- This also needs to be done in the case of an ignored Ghost + -- expression function, where the expander isn't active. Set_Is_Frozen (Spec_Id); Mask_Types := Mask_Unfrozen_Types (Spec_Id); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3502e68..dd1aa0d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Gary Dismukes + + * gnat.dg/ghost5.adb, gnat.dg/ghost5.ads, + gnat.dg/ghost5_parent.ads: New testcase. + 2019-07-04 Yannick Moy * gnat.dg/spark3.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/ghost5.adb b/gcc/testsuite/gnat.dg/ghost5.adb new file mode 100644 index 0000000..8aad8d4 --- /dev/null +++ b/gcc/testsuite/gnat.dg/ghost5.adb @@ -0,0 +1,5 @@ +-- { dg-do compile } + +package body Ghost5 is + procedure Foo is null; +end Ghost5; diff --git a/gcc/testsuite/gnat.dg/ghost5.ads b/gcc/testsuite/gnat.dg/ghost5.ads new file mode 100644 index 0000000..f58ff39 --- /dev/null +++ b/gcc/testsuite/gnat.dg/ghost5.ads @@ -0,0 +1,5 @@ +with Ghost5_Parent; +generic +package Ghost5 is + procedure Foo; +end Ghost5; diff --git a/gcc/testsuite/gnat.dg/ghost5_parent.ads b/gcc/testsuite/gnat.dg/ghost5_parent.ads new file mode 100644 index 0000000..cab7f31 --- /dev/null +++ b/gcc/testsuite/gnat.dg/ghost5_parent.ads @@ -0,0 +1,14 @@ +package Ghost5_Parent is + + type Priv is private; + + package Nested with Ghost is + function Func1 (X : Priv) return Boolean is (True); -- Error flagged here + function Func2 (X : Priv) return Boolean is (False); + end Nested; + +private + + type Priv is new Integer; + +end Ghost5_Parent; -- cgit v1.1 From 0839ffce2ddfe5aa3fb4b7cd8b51610f4c116bcb Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 4 Jul 2019 08:06:54 +0000 Subject: [Ada] Management of internal data structures in Sem_Elab This patch modifies the timing of Sem_Elab's internal data structure creation and destruction, and adds the concept of "active" elaboration compiler phase. The elaboration phase of the compiler is active after the frontend initializes Sem_Elab. It is at this point that all internal data structures of Sem_Elab are created and become ready to accept data. The elaboration phase of the compiler is completed after all elaboration scenarios are examined, all ABE checks are intalled, and diagnostics are emitted. It is at this point that all internal data structures of Sem_Elab are destroyed. Further attempts to reintroduce data into Sem_Elab by subsequent compiler phases are cut off. Compilation using GCC unaffected. 2019-07-04 Hristian Kirtchev gcc/ada/ * sem_elab.adb: Add new type Elaboration_Phase_Status along with a global to keep track of the elaboration phase status. Initialize all internal data structures to Nil for services Elaborated_Units, Internal_Representation, and Scenario_Storage. (Build_Call_Marker): Do not create a call marker when the elaboration phase is not active. (Build_Variable_Reference_Marker): Do not create a call marker when the elaboration phase is not active. (Check_Elaboration_Scenarios): Destroy all internal structures when the elaboration phase does not have to run. Do not execute when the elaboration phase is not active. (Elaboration_Phase_Active): New routine. (Finalize_All_Data_Structures): New routine. (Initialize): Initialize all internal data structures and signal that the elaboration phase has started. (Initialize_All_Data_Structures): New routine. (Initialize_Elaborated_Units): Initialize all internal data structures. (Initialize_Internal_Representation): Initialize all internal data structures. (Initialize_Scenario_Storage): Initialize all internal data structures. (Kill_Elaboration_Scenario): Do not execute when the elaboration phase is not active. (Set_Elaboration_Phase): New routine. (Update_Elaboration_Scenario): Do not execute when the elaboration phase is not active. From-SVN: r273066 --- gcc/ada/ChangeLog | 30 +++++++++ gcc/ada/sem_elab.adb | 182 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 176 insertions(+), 36 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 5eb10d2..9d46f39 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,33 @@ +2019-07-04 Hristian Kirtchev + + * sem_elab.adb: Add new type Elaboration_Phase_Status along with + a global to keep track of the elaboration phase status. + Initialize all internal data structures to Nil for services + Elaborated_Units, Internal_Representation, and Scenario_Storage. + (Build_Call_Marker): Do not create a call marker when the + elaboration phase is not active. + (Build_Variable_Reference_Marker): Do not create a call marker + when the elaboration phase is not active. + (Check_Elaboration_Scenarios): Destroy all internal structures + when the elaboration phase does not have to run. Do not execute + when the elaboration phase is not active. + (Elaboration_Phase_Active): New routine. + (Finalize_All_Data_Structures): New routine. + (Initialize): Initialize all internal data structures and signal + that the elaboration phase has started. + (Initialize_All_Data_Structures): New routine. + (Initialize_Elaborated_Units): Initialize all internal data + structures. + (Initialize_Internal_Representation): Initialize all internal + data structures. + (Initialize_Scenario_Storage): Initialize all internal data + structures. + (Kill_Elaboration_Scenario): Do not execute when the elaboration + phase is not active. + (Set_Elaboration_Phase): New routine. + (Update_Elaboration_Scenario): Do not execute when the + elaboration phase is not active. + 2019-07-04 Gary Dismukes * sem_ch6.adb (Analyze_Subprogram_Body_Helper): The special diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb index f57b3b1..ce0950d 100644 --- a/gcc/ada/sem_elab.adb +++ b/gcc/ada/sem_elab.adb @@ -676,6 +676,22 @@ package body Sem_Elab is -- Kinds -- ----------- + -- The following type enumerates all possible elaboration phase statutes + + type Elaboration_Phase_Status is + (Inactive, + -- The elaboration phase of the compiler has not started yet + + Active, + -- The elaboration phase of the compiler is currently in progress + + Completed); + -- The elaboration phase of the compiler has finished + + Elaboration_Phase : Elaboration_Phase_Status := Inactive; + -- The status of the elaboration phase. Use routine Set_Elaboration_Phase + -- to alter its value. + -- The following type enumerates all subprogram body traversal modes type Body_Traversal_Kind is @@ -1958,6 +1974,14 @@ package body Sem_Elab is -- Return the type of subprogram Subp_Id's first formal parameter. If the -- subprogram lacks formal parameters, return Empty. + function Elaboration_Phase_Active return Boolean; + pragma Inline (Elaboration_Phase_Active); + -- Determine whether the elaboration phase of the compilation has started + + procedure Finalize_All_Data_Structures; + pragma Inline (Finalize_All_Data_Structures); + -- Destroy all internal data structures + function Has_Body (Pack_Decl : Node_Id) return Boolean; pragma Inline (Has_Body); -- Determine whether package declaration Pack_Decl has a corresponding body @@ -1984,6 +2008,10 @@ package body Sem_Elab is -- context ignoring enclosing library levels. Nested_OK should be set when -- the context of N1 can enclose that of N2. + procedure Initialize_All_Data_Structures; + pragma Inline (Initialize_All_Data_Structures); + -- Create all internal data structures + function Instantiated_Generic (Inst : Node_Id) return Entity_Id; pragma Inline (Instantiated_Generic); -- Obtain the generic instantiated by instance Inst @@ -2027,6 +2055,10 @@ package body Sem_Elab is pragma Inline (Scenario); -- Return the appropriate scenario node for scenario N + procedure Set_Elaboration_Phase (Status : Elaboration_Phase_Status); + pragma Inline (Set_Elaboration_Phase); + -- Change the status of the elaboration phase of the compiler to Status + procedure Spec_And_Body_From_Entity (Id : Node_Id; Spec_Decl : out Node_Id; @@ -3572,6 +3604,12 @@ package body Sem_Elab is elsif Preanalysis_Active then return; + -- Nothing to do when the elaboration phase of the compiler is not + -- active. + + elsif not Elaboration_Phase_Active then + return; + -- Nothing to do when the input does not denote a call or a requeue elsif not Nkind_In (N, N_Entry_Call_Statement, @@ -3789,6 +3827,13 @@ package body Sem_Elab is -- Start of processing for Build_Variable_Reference_Marker begin + -- Nothing to do when the elaboration phase of the compiler is not + -- active. + + if not Elaboration_Phase_Active then + return; + end if; + Marker := Make_Variable_Reference_Marker (Sloc (N)); -- Inherit the attributes of the original variable reference @@ -3887,23 +3932,23 @@ package body Sem_Elab is -- to carry out this action. if Legacy_Elaboration_Checks then + Finalize_All_Data_Structures; return; -- Nothing to do for ASIS because ABE checks and diagnostics are not -- performed in this mode. elsif ASIS_Mode then + Finalize_All_Data_Structures; return; - end if; - -- Create all internal data structures + -- Nothing to do when the elaboration phase of the compiler is not + -- active. - Initialize_Body_Processor; - Initialize_Early_Call_Region_Processor; - Initialize_Elaborated_Units; - Initialize_Internal_Representation; - Initialize_Invocation_Graph; - Initialize_Scenario_Storage; + elsif not Elaboration_Phase_Active then + Finalize_All_Data_Structures; + return; + end if; -- Restore the original elaboration model which was in effect when the -- scenarios were first recorded. The model may be specified by pragma @@ -3949,14 +3994,11 @@ package body Sem_Elab is Record_Invocation_Graph; - -- Destroy all internal data structures + -- Destroy all internal data structures and complete the elaboration + -- phase of the compiler. - Finalize_Body_Processor; - Finalize_Early_Call_Region_Processor; - Finalize_Elaborated_Units; - Finalize_Internal_Representation; - Finalize_Invocation_Graph; - Finalize_Scenario_Storage; + Finalize_All_Data_Structures; + Set_Elaboration_Phase (Completed); end Check_Elaboration_Scenarios; --------------------- @@ -7676,8 +7718,7 @@ package body Sem_Elab is -- The following map relates an elaboration attributes of a unit to the -- unit. - Unit_To_Attributes_Map : UA_Map.Dynamic_Hash_Table := - UA_Map.Create (250); + Unit_To_Attributes_Map : UA_Map.Dynamic_Hash_Table := UA_Map.Nil; ------------------ -- Constructors -- @@ -8519,7 +8560,7 @@ package body Sem_Elab is procedure Initialize_Elaborated_Units is begin - null; + Unit_To_Attributes_Map := UA_Map.Create (250); end Initialize_Elaborated_Units; ---------------------------------- @@ -8800,6 +8841,29 @@ package body Sem_Elab is end With_Clause; end Elaborated_Units; + ------------------------------ + -- Elaboration_Phase_Active -- + ------------------------------ + + function Elaboration_Phase_Active return Boolean is + begin + return Elaboration_Phase = Active; + end Elaboration_Phase_Active; + + ---------------------------------- + -- Finalize_All_Data_Structures -- + ---------------------------------- + + procedure Finalize_All_Data_Structures is + begin + Finalize_Body_Processor; + Finalize_Early_Call_Region_Processor; + Finalize_Elaborated_Units; + Finalize_Internal_Representation; + Finalize_Invocation_Graph; + Finalize_Scenario_Storage; + end Finalize_All_Data_Structures; + ----------------------------- -- Find_Enclosing_Instance -- ----------------------------- @@ -10072,8 +10136,28 @@ package body Sem_Elab is -- each time it is transformed into another node. Set_Rewriting_Proc (Update_Elaboration_Scenario'Access); + + -- Create all internal data structures and activate the elaboration + -- phase of the compiler. + + Initialize_All_Data_Structures; + Set_Elaboration_Phase (Active); end Initialize; + ------------------------------------ + -- Initialize_All_Data_Structures -- + ------------------------------------ + + procedure Initialize_All_Data_Structures is + begin + Initialize_Body_Processor; + Initialize_Early_Call_Region_Processor; + Initialize_Elaborated_Units; + Initialize_Internal_Representation; + Initialize_Invocation_Graph; + Initialize_Scenario_Storage; + end Initialize_All_Data_Structures; + -------------------------- -- Instantiated_Generic -- -------------------------- @@ -10201,8 +10285,7 @@ package body Sem_Elab is -- The following map relates target representations to entities - Entity_To_Target_Map : ETT_Map.Dynamic_Hash_Table := - ETT_Map.Create (500); + Entity_To_Target_Map : ETT_Map.Dynamic_Hash_Table := ETT_Map.Nil; procedure Destroy (S_Id : in out Scenario_Rep_Id); -- Destroy a scenario representation S_Id @@ -10221,8 +10304,7 @@ package body Sem_Elab is -- The following map relates scenario representations to nodes - Node_To_Scenario_Map : NTS_Map.Dynamic_Hash_Table := - NTS_Map.Create (500); + Node_To_Scenario_Map : NTS_Map.Dynamic_Hash_Table := NTS_Map.Nil; -- The following table stores all scenario representations @@ -11058,7 +11140,8 @@ package body Sem_Elab is procedure Initialize_Internal_Representation is begin - null; + Entity_To_Target_Map := ETT_Map.Create (500); + Node_To_Scenario_Map := NTS_Map.Create (500); end Initialize_Internal_Representation; ------------------------- @@ -13422,6 +13505,12 @@ package body Sem_Elab is if Legacy_Elaboration_Checks then return; + + -- Nothing to do when the elaboration phase of the compiler is not + -- active. + + elsif not Elaboration_Phase_Active then + return; end if; -- Eliminate a recorded scenario when it appears within dead code @@ -13785,6 +13874,12 @@ package body Sem_Elab is elsif Preanalysis_Active then return; + + -- Nothing to do when the elaboration phase of the compiler is not + -- active. + + elsif not Elaboration_Phase_Active then + return; end if; Scen_Lvl := Find_Enclosing_Level (Scen); @@ -13889,16 +13984,11 @@ package body Sem_Elab is -- The following sets store all scenarios - Declaration_Scenarios : NE_Set.Membership_Set := - NE_Set.Create (1000); - Dynamic_ABE_Check_Scenarios : NE_Set.Membership_Set := - NE_Set.Create (500); - Library_Body_Scenarios : NE_Set.Membership_Set := - NE_Set.Create (1000); - Library_Spec_Scenarios : NE_Set.Membership_Set := - NE_Set.Create (1000); - SPARK_Scenarios : NE_Set.Membership_Set := - NE_Set.Create (100); + Declaration_Scenarios : NE_Set.Membership_Set := NE_Set.Nil; + Dynamic_ABE_Check_Scenarios : NE_Set.Membership_Set := NE_Set.Nil; + Library_Body_Scenarios : NE_Set.Membership_Set := NE_Set.Nil; + Library_Spec_Scenarios : NE_Set.Membership_Set := NE_Set.Nil; + SPARK_Scenarios : NE_Set.Membership_Set := NE_Set.Nil; ------------------------------- -- Finalize_Scenario_Storage -- @@ -13919,7 +14009,11 @@ package body Sem_Elab is procedure Initialize_Scenario_Storage is begin - null; + Declaration_Scenarios := NE_Set.Create (1000); + Dynamic_ABE_Check_Scenarios := NE_Set.Create (500); + Library_Body_Scenarios := NE_Set.Create (1000); + Library_Spec_Scenarios := NE_Set.Create (1000); + SPARK_Scenarios := NE_Set.Create (100); end Initialize_Scenario_Storage; ------------------------------ @@ -14796,6 +14890,15 @@ package body Sem_Elab is end Is_Up_Level_Target; end Semantics; + --------------------------- + -- Set_Elaboration_Phase -- + --------------------------- + + procedure Set_Elaboration_Phase (Status : Elaboration_Phase_Status) is + begin + Elaboration_Phase := Status; + end Set_Elaboration_Phase; + --------------------- -- SPARK_Processor -- --------------------- @@ -15700,17 +15803,24 @@ package body Sem_Elab is procedure Update_Elaboration_Scenario (New_N : Node_Id; Old_N : Node_Id) is begin + -- Nothing to do when the elaboration phase of the compiler is not + -- active. + + if not Elaboration_Phase_Active then + return; + -- Nothing to do when the old and new scenarios are one and the same - if Old_N = New_N then + elsif Old_N = New_N then return; + end if; -- A scenario is being transformed by Atree.Rewrite. Update all relevant -- internal data structures to reflect this change. This ensures that a -- potential run-time conditional ABE check or a guaranteed ABE failure -- is inserted at the proper place in the tree. - elsif Is_Scenario (Old_N) then + if Is_Scenario (Old_N) then Replace_Scenario (Old_N, New_N); end if; end Update_Elaboration_Scenario; -- cgit v1.1 From cb2ce45bfeca0a99aba1136d02dcb9ae491e477d Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 4 Jul 2019 08:07:00 +0000 Subject: [Ada] Spurious error on instantiation and limited_with_clause This patch fixes a spurious error during the construction of an instance body in the inlining phase of the frontend, when the package declaration for the main unit has a limited_with_clause on some unit P, and the main unit itself does not have a corresponding regular with_clause, but some other unit in the context has with_clause that has compiled P. P must be removed from visibility to prevent conflicts with homonyms in the generic body to be instantiated. The following must compile quietly: gcc -c gpr2-project-view.adb ---- package GNATCOLL is end GNATCOLL; package GNATCOLL.Refcount is generic type Element_Type (<>) is private; package Shared_Pointers is type Ref is tagged private; type Element_Access is access all Element_Type; type Reference_Type (Element : access Element_Type) is limited null record; function Unchecked_Get (Self : Ref'Class) return Element_Access; function Get (Self : Ref'Class) return Reference_Type is ((Element => Unchecked_Get (Self))); private type Ref is tagged null record; end Shared_Pointers; type Refcounted is abstract tagged null record; generic type Encapsulated is abstract new Refcounted with private; package Smart_Pointers is type Encapsulated_Access is access all Encapsulated'Class; type Ref is tagged private; procedure Set (Self : in out Ref; Data : Encapsulated'Class); procedure Set (Self : in out Ref; Data : access Encapsulated'Class); private type Ref is tagged null record; end Smart_Pointers; end GNATCOLL.Refcount; ---- package body GNATCOLL.Refcount is package body Shared_Pointers is function Unchecked_Get (Self : Ref'Class) return Element_Access is begin return null; end Unchecked_Get; end Shared_Pointers; package body Smart_Pointers is procedure Set (Self : in out Ref; Data : access Encapsulated'Class) is begin null; end Set; procedure Set (Self : in out Ref; Data : Encapsulated'Class) is Tmp : constant Encapsulated_Access := new Encapsulated'Class'(Data); begin Set (Self, Tmp); end Set; end Smart_Pointers; end GNATCOLL.Refcount; ---- package GPR2 is end GPR2; ---- package GPR2.Parser is end GPR2.Parser; ---- with GPR_Parser.Analysis; package GPR2.Parser.Project is end GPR2.Parser.Project; ---- package GPR2.Project is end GPR2.Project; ---- with GPR2.Parser.Project; package GPR2.Project.Configuration is end GPR2.Project.Configuration; ---- with GPR2.Project.Configuration; with GPR2.Unit.Set; package GPR2.Project.Definition is end GPR2.Project.Definition; ---- limited with GPR2.Unit.Set; package GPR2.Project.View is procedure Require_Body; end GPR2.Project.View; ---- with GPR2.Project.Definition; package body GPR2.Project.View is procedure Require_Body is null; end GPR2.Project.View; ---- package GPR2.Unit is end GPR2.Unit; package GPR2.Unit.Set is end GPR2.Unit.Set; ... package GPR_Parser is end GPR_Parser; ---- with GNATCOLL.Refcount; package GPR_Parser.Analysis is type Unit_Provider_Interface is null record; package Unit_Provider_References is new GNATCOLL.Refcount.Shared_Pointers (Unit_Provider_Interface); end GPR_Parser.Analysis; 2019-07-04 Ed Schonberg gcc/ada/ * sem_ch10.adb (Remove_Context_Clauses): Handle properly the removal of a limited_with_clause which appears in the library unit oF the main unit, when some other unit in the context has a regular with_clause on the same unit, to prevent spurious visibility errors in the subsequent analysis of pending instance bodies. From-SVN: r273067 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/sem_ch10.adb | 28 ++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9d46f39..be3241e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-04 Ed Schonberg + + * sem_ch10.adb (Remove_Context_Clauses): Handle properly the + removal of a limited_with_clause which appears in the library + unit oF the main unit, when some other unit in the context has a + regular with_clause on the same unit, to prevent spurious + visibility errors in the subsequent analysis of pending instance + bodies. + 2019-07-04 Hristian Kirtchev * sem_elab.adb: Add new type Elaboration_Phase_Status along with diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb index 407e84f..b8d7c6a 100644 --- a/gcc/ada/sem_ch10.adb +++ b/gcc/ada/sem_ch10.adb @@ -6379,22 +6379,38 @@ package body Sem_Ch10 is begin -- Ada 2005 (AI-50217): We remove the context clauses in two phases: - -- limited-views first and regular-views later (to maintain the - -- stack model). + -- limited-views first and regular-views later (to maintain the stack + -- model). -- First Phase: Remove limited_with context clauses Item := First (Context_Items (N)); while Present (Item) loop - -- We are interested only in with clauses which got installed - -- on entry. + -- We are interested only in with clauses that got installed on entry if Nkind (Item) = N_With_Clause and then Limited_Present (Item) - and then Limited_View_Installed (Item) then - Remove_Limited_With_Clause (Item); + if Limited_View_Installed (Item) then + Remove_Limited_With_Clause (Item); + + -- An unusual case: If the library unit of the Main_Unit has + -- a limited with_clause on some unit P and the context somewhere + -- includes a with_clause on P, P has been analyzed. The entity + -- for P is still visible, which in general is harmless because + -- this is the end of the compilation, but it can affect pending + -- instantiations that may have been generated elsewhere, so it + -- it is necessary to remove U from visibility so that inlining + -- and the analysis of instance bodies can proceed cleanly. + + elsif Current_Sem_Unit = Main_Unit + and then Serious_Errors_Detected = 0 + and then not Implicit_With (Item) + then + Set_Is_Immediately_Visible + (Defining_Entity (Unit (Library_Unit (Item))), False); + end if; end if; Next (Item); -- cgit v1.1 From 2beb5444be68bc9b1e580947c133bf3b7e26b8d1 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 4 Jul 2019 08:07:04 +0000 Subject: [Ada] Fix capitalization and parenthesis glitches in GNAT RM 2019-07-04 Eric Botcazou gcc/ada/ * doc/gnat_rm/implementation_defined_pragmas.rst: Fix capitalization and parenthesis glitches. * gnat_rm.texi: Regenerate. From-SVN: r273068 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst | 7 +++---- gcc/ada/gnat_rm.texi | 7 +++---- 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index be3241e..602bef5 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Eric Botcazou + + * doc/gnat_rm/implementation_defined_pragmas.rst: Fix + capitalization and parenthesis glitches. + * gnat_rm.texi: Regenerate. + 2019-07-04 Ed Schonberg * sem_ch10.adb (Remove_Context_Clauses): Handle properly the diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst index 955a137..c2e4a4e 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst @@ -7312,11 +7312,10 @@ methods can be used to enable validity checking for mode ``in`` and The form ALL_CHECKS activates all standard checks (its use is equivalent -to the use of the :switch:`gnatva` switch. +to the use of the :switch:`gnatVa` switch). -The forms with ``Off`` and ``On`` -can be used to temporarily disable validity checks -as shown in the following example: +The forms with ``Off`` and ``On`` can be used to temporarily disable +validity checks as shown in the following example: .. code-block:: ada diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 39a24ab..268ae30 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -8779,11 +8779,10 @@ $ gcc -c -gnatVim ... @end itemize The form ALL_CHECKS activates all standard checks (its use is equivalent -to the use of the @code{gnatva} switch. +to the use of the @code{gnatVa} switch). -The forms with @code{Off} and @code{On} -can be used to temporarily disable validity checks -as shown in the following example: +The forms with @code{Off} and @code{On} can be used to temporarily disable +validity checks as shown in the following example: @example pragma Validity_Checks ("c"); -- validity checks for copies -- cgit v1.1 From 38818659c388491abe7ab11f8757c1ad2acd1506 Mon Sep 17 00:00:00 2001 From: Joffrey Huguet Date: Thu, 4 Jul 2019 08:07:09 +0000 Subject: [Ada] Add preconditions in Ada.Task_Identification This patch is needed to check for the Ada RM C.7.1(15) rule in SPARK. 2019-07-04 Joffrey Huguet gcc/ada/ * libgnarl/a-taside.ads: Add assertion policy to ignore preconditions. (Abort_Task, Is_Terminated, Is_Callable): Add preconditions. From-SVN: r273069 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/libgnarl/a-taside.ads | 9 +++++++++ 2 files changed, 15 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 602bef5..cc88f7f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Joffrey Huguet + + * libgnarl/a-taside.ads: Add assertion policy to ignore + preconditions. + (Abort_Task, Is_Terminated, Is_Callable): Add preconditions. + 2019-07-04 Eric Botcazou * doc/gnat_rm/implementation_defined_pragmas.rst: Fix diff --git a/gcc/ada/libgnarl/a-taside.ads b/gcc/ada/libgnarl/a-taside.ads index 4939d1e..6bdb252 100644 --- a/gcc/ada/libgnarl/a-taside.ads +++ b/gcc/ada/libgnarl/a-taside.ads @@ -33,6 +33,12 @@ -- -- ------------------------------------------------------------------------------ +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. +-- This is enforced by setting the corresponding assertion policy to Ignore. + +pragma Assertion_Policy (Pre => Ignore); + with System; with System.Tasking; @@ -67,17 +73,20 @@ is pragma Inline (Environment_Task); procedure Abort_Task (T : Task_Id) with + Pre => T /= Null_Task_Id, Global => null; pragma Inline (Abort_Task); -- Note: parameter is mode IN, not IN OUT, per AI-00101 function Is_Terminated (T : Task_Id) return Boolean with Volatile_Function, + Pre => T /= Null_Task_Id, Global => Tasking_State; pragma Inline (Is_Terminated); function Is_Callable (T : Task_Id) return Boolean with Volatile_Function, + Pre => T /= Null_Task_Id, Global => Tasking_State; pragma Inline (Is_Callable); -- cgit v1.1 From eedc5882dd635ce9cfaa650c790081b5130749af Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 4 Jul 2019 08:07:14 +0000 Subject: [Ada] Minor reformatting 2019-07-04 Hristian Kirtchev gcc/ada/ * exp_ch3.adb, exp_ch4.adb, exp_ch4.ads, exp_ch5.adb, exp_ch7.adb, exp_ch9.adb, exp_ch11.adb, exp_unst.adb, rtsfind.ads, sem_attr.adb, sem_ch10.adb, sem_ch12.adb, sem_ch13.adb, sem_dim.adb, sem_disp.adb, xref_lib.adb: Minor reformatting. From-SVN: r273070 --- gcc/ada/ChangeLog | 8 +++++ gcc/ada/exp_ch11.adb | 4 +-- gcc/ada/exp_ch3.adb | 17 +++++----- gcc/ada/exp_ch4.adb | 94 ++++++++++++++++++++++++++-------------------------- gcc/ada/exp_ch4.ads | 31 +++++++++-------- gcc/ada/exp_ch5.adb | 4 +-- gcc/ada/exp_ch7.adb | 2 +- gcc/ada/exp_ch9.adb | 6 ++-- gcc/ada/exp_unst.adb | 2 +- gcc/ada/rtsfind.ads | 34 +++++++++---------- gcc/ada/sem_attr.adb | 2 +- gcc/ada/sem_ch10.adb | 6 ++-- gcc/ada/sem_ch12.adb | 9 ++--- gcc/ada/sem_ch13.adb | 2 +- gcc/ada/sem_dim.adb | 6 ++-- gcc/ada/sem_disp.adb | 1 + gcc/ada/xref_lib.adb | 2 +- 17 files changed, 120 insertions(+), 110 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cc88f7f..65aabe5 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-04 Hristian Kirtchev + + * exp_ch3.adb, exp_ch4.adb, exp_ch4.ads, exp_ch5.adb, + exp_ch7.adb, exp_ch9.adb, exp_ch11.adb, exp_unst.adb, + rtsfind.ads, sem_attr.adb, sem_ch10.adb, sem_ch12.adb, + sem_ch13.adb, sem_dim.adb, sem_disp.adb, xref_lib.adb: Minor + reformatting. + 2019-07-04 Joffrey Huguet * libgnarl/a-taside.ads: Add assertion policy to ignore diff --git a/gcc/ada/exp_ch11.adb b/gcc/ada/exp_ch11.adb index 7296e6f..29d8718 100644 --- a/gcc/ada/exp_ch11.adb +++ b/gcc/ada/exp_ch11.adb @@ -1308,8 +1308,8 @@ package body Exp_Ch11 is Append_To (L, Make_Character_Literal (Loc, - Chars => Name_uA, - Char_Literal_Value => UI_From_Int (Character'Pos ('A')))); + Chars => Name_uA, + Char_Literal_Value => UI_From_Int (Character'Pos ('A')))); -- Name_Length component: Nam'Length diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 6308b42..e48c188 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -4848,7 +4848,7 @@ package body Exp_Ch3 is Make_Range (Sloc (Enumeration_Rep_Expr (Ent)), Low_Bound => Make_Integer_Literal (Loc, - Intval => Enumeration_Rep (Ent)), + Intval => Enumeration_Rep (Ent)), High_Bound => Make_Integer_Literal (Loc, Intval => Last_Repval))), @@ -9486,10 +9486,11 @@ package body Exp_Ch3 is (E : Entity_Id; L : List_Id) return Node_Id is - Loc : constant Source_Ptr := Sloc (E); + Loc : constant Source_Ptr := Sloc (E); + C : Node_Id; - Field_Name : Name_Id; Cond : Node_Id; + Field_Name : Name_Id; Next_Test : Node_Id; Typ : Entity_Id; @@ -9534,11 +9535,11 @@ package body Exp_Ch3 is begin -- Build equality code with a user-defined operator, if - -- available, and with the predefined "=" otherwise. - -- For compatibility with older Ada versions, and preserve - -- the workings of some ASIS tools, we also use the - -- predefined operation if the component-type equality - -- is abstract, rather than raising Program_Error. + -- available, and with the predefined "=" otherwise. For + -- compatibility with older Ada versions, and preserve the + -- workings of some ASIS tools, we also use the predefined + -- operation if the component-type equality is abstract, + -- rather than raising Program_Error. if Ada_Version < Ada_2012 then Next_Test := Make_Op_Ne (Loc, Lhs, Rhs); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index cacc9d4..0d4c294 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -415,6 +415,52 @@ package body Exp_Ch4 is return; end Build_Boolean_Array_Proc_Call; + ----------------------- + -- Build_Eq_Call -- + ----------------------- + + function Build_Eq_Call + (Typ : Entity_Id; + Loc : Source_Ptr; + Lhs : Node_Id; + Rhs : Node_Id) return Node_Id + is + Prim : Node_Id; + Prim_E : Elmt_Id; + + begin + Prim_E := First_Elmt (Collect_Primitive_Operations (Typ)); + while Present (Prim_E) loop + Prim := Node (Prim_E); + + -- Locate primitive equality with the right signature + + if Chars (Prim) = Name_Op_Eq + and then Etype (First_Formal (Prim)) = + Etype (Next_Formal (First_Formal (Prim))) + and then Etype (Prim) = Standard_Boolean + then + if Is_Abstract_Subprogram (Prim) then + return + Make_Raise_Program_Error (Loc, + Reason => PE_Explicit_Raise); + + else + return + Make_Function_Call (Loc, + Name => New_Occurrence_Of (Prim, Loc), + Parameter_Associations => New_List (Lhs, Rhs)); + end if; + end if; + + Next_Elmt (Prim_E); + end loop; + + -- If not found, predefined operation will be used + + return Empty; + end Build_Eq_Call; + -------------------------------- -- Displace_Allocator_Pointer -- -------------------------------- @@ -1938,7 +1984,7 @@ package body Exp_Ch4 is Parameter_Specifications => Formals, Result_Definition => New_Occurrence_Of (Standard_Boolean, Loc)), - Declarations => Decls, + Declarations => Decls, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, @@ -12553,52 +12599,6 @@ package body Exp_Ch4 is Adjust_Result_Type (N, Typ); end Expand_Short_Circuit_Operator; - ----------------------- - -- Build_Eq_Call -- - ----------------------- - - function Build_Eq_Call - (Typ : Entity_Id; - Loc : Source_Ptr; - Lhs : Node_Id; - Rhs : Node_Id) return Node_Id - is - Prim_E : Elmt_Id; - Prim : Node_Id; - - begin - Prim_E := First_Elmt (Collect_Primitive_Operations (Typ)); - while Present (Prim_E) loop - Prim := Node (Prim_E); - - -- Locate primitive equality with the right signature - - if Chars (Prim) = Name_Op_Eq - and then Etype (First_Formal (Prim)) = - Etype (Next_Formal (First_Formal (Prim))) - and then Etype (Prim) = Standard_Boolean - then - if Is_Abstract_Subprogram (Prim) then - return - Make_Raise_Program_Error (Loc, - Reason => PE_Explicit_Raise); - - else - return - Make_Function_Call (Loc, - Name => New_Occurrence_Of (Prim, Loc), - Parameter_Associations => New_List (Lhs, Rhs)); - end if; - end if; - - Next_Elmt (Prim_E); - end loop; - - -- If not found, predefined operation will be used - - return Empty; - end Build_Eq_Call; - ------------------------------------ -- Fixup_Universal_Fixed_Operation -- ------------------------------------- diff --git a/gcc/ada/exp_ch4.ads b/gcc/ada/exp_ch4.ads index f2deaae..44872fd 100644 --- a/gcc/ada/exp_ch4.ads +++ b/gcc/ada/exp_ch4.ads @@ -29,20 +29,6 @@ with Types; use Types; package Exp_Ch4 is - function Build_Eq_Call - (Typ : Entity_Id; - Loc : Source_Ptr; - Lhs : Node_Id; - Rhs : Node_Id) return Node_Id; - -- AI05-0123: Locate primitive equality for type if it exists, and build - -- the corresponding call. If operation is abstract, replace call with - -- an explicit raise. Return Empty if there is no primitive. - -- Used in the construction of record-equality routines for records here - -- and for variant records in exp_ch3.adb. These two paths are distinct - -- for historical but also technical reasons: for variant records the - -- constructed function includes a case statement with nested returns, - -- while for records without variants only a simple expression is needed. - procedure Expand_N_Allocator (N : Node_Id); procedure Expand_N_And_Then (N : Node_Id); procedure Expand_N_Case_Expression (N : Node_Id); @@ -88,13 +74,26 @@ package Exp_Ch4 is procedure Expand_N_Unchecked_Expression (N : Node_Id); procedure Expand_N_Unchecked_Type_Conversion (N : Node_Id); + function Build_Eq_Call + (Typ : Entity_Id; + Loc : Source_Ptr; + Lhs : Node_Id; + Rhs : Node_Id) return Node_Id; + -- AI05-0123: Locate primitive equality for type if it exists, and build + -- the corresponding call. If operation is abstract, replace call with + -- an explicit raise. Return Empty if there is no primitive. + -- Used in the construction of record-equality routines for records here + -- and for variant records in exp_ch3.adb. These two paths are distinct + -- for historical but also technical reasons: for variant records the + -- constructed function includes a case statement with nested returns, + -- while for records without variants only a simple expression is needed. + function Expand_Record_Equality (Nod : Node_Id; Typ : Entity_Id; Lhs : Node_Id; Rhs : Node_Id; - Bodies : List_Id) - return Node_Id; + Bodies : List_Id) return Node_Id; -- Expand a record equality into an expression that compares the fields -- individually to yield the required Boolean result. Loc is the -- location for the generated nodes. Typ is the type of the record, and diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index b1b0f55..664ede8 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -3304,7 +3304,7 @@ package body Exp_Ch5 is Declarations => New_List (Elmt_Decl), Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, - Statements => Stats)))); + Statements => Stats)))); else Elmt_Ref := @@ -3330,7 +3330,7 @@ package body Exp_Ch5 is Declarations => New_List (Elmt_Decl), Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (New_Loop))); + Statements => New_List (New_Loop))); end if; -- The element is only modified in expanded code, so it appears as diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 4209785..1e17b19 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -3873,7 +3873,7 @@ package body Exp_Ch7 is Attribute_Name => Name_Range, Expressions => New_List ( Make_Integer_Literal (Loc, Dim))))), - Statements => Free_One_Dimension (Dim + 1))); + Statements => Free_One_Dimension (Dim + 1))); end if; end Free_One_Dimension; diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 0f83d57..03f133f 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -869,7 +869,7 @@ package body Exp_Ch9 is Make_Implicit_Exception_Handler (Loc, Exception_Choices => New_List (Ohandle), - Statements => New_List ( + Statements => New_List ( Make_Procedure_Call_Statement (Sloc (Stats), Name => New_Occurrence_Of ( RTE (RE_Exceptional_Complete_Rendezvous), Sloc (Stats)), @@ -3792,7 +3792,7 @@ package body Exp_Ch9 is Make_Implicit_Exception_Handler (EH_Loc, Exception_Choices => New_List (Ohandle), - Statements => New_List ( + Statements => New_List ( Make_Procedure_Call_Statement (EH_Loc, Name => Complete, Parameter_Associations => New_List ( @@ -10639,7 +10639,7 @@ package body Exp_Ch9 is Statements => New_List ( Make_Implicit_If_Statement (N, - Condition => Cond, + Condition => Cond, Then_Statements => New_List ( Make_Select_Call ( New_Occurrence_Of (RTE (RE_Simple_Mode), Loc)), diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb index 6717610..f146a6f 100644 --- a/gcc/ada/exp_unst.adb +++ b/gcc/ada/exp_unst.adb @@ -598,7 +598,7 @@ package body Exp_Unst is then Note_Uplevel_Bound (Prefix (N), Ref); - -- Conditional expressions. + -- Conditional expressions elsif Nkind (N) = N_If_Expression then declare diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads index 47ad874..eab6f4f 100644 --- a/gcc/ada/rtsfind.ads +++ b/gcc/ada/rtsfind.ads @@ -2755,23 +2755,23 @@ package Rtsfind is RE_W_WC => System_Stream_Attributes, RE_W_WWC => System_Stream_Attributes, - RE_Storage_Array_Input => System_Strings_Stream_Ops, - RE_Storage_Array_Input_Blk_IO => System_Strings_Stream_Ops, - RE_Storage_Array_Output => System_Strings_Stream_Ops, - RE_Storage_Array_Output_Blk_IO => System_Strings_Stream_Ops, - RE_Storage_Array_Read => System_Strings_Stream_Ops, - RE_Storage_Array_Read_Blk_IO => System_Strings_Stream_Ops, - RE_Storage_Array_Write => System_Strings_Stream_Ops, - RE_Storage_Array_Write_Blk_IO => System_Strings_Stream_Ops, - - RE_Stream_Element_Array_Input => System_Strings_Stream_Ops, - RE_Stream_Element_Array_Input_Blk_IO => System_Strings_Stream_Ops, - RE_Stream_Element_Array_Output => System_Strings_Stream_Ops, - RE_Stream_Element_Array_Output_Blk_IO => System_Strings_Stream_Ops, - RE_Stream_Element_Array_Read => System_Strings_Stream_Ops, - RE_Stream_Element_Array_Read_Blk_IO => System_Strings_Stream_Ops, - RE_Stream_Element_Array_Write => System_Strings_Stream_Ops, - RE_Stream_Element_Array_Write_Blk_IO => System_Strings_Stream_Ops, + RE_Storage_Array_Input => System_Strings_Stream_Ops, + RE_Storage_Array_Input_Blk_IO => System_Strings_Stream_Ops, + RE_Storage_Array_Output => System_Strings_Stream_Ops, + RE_Storage_Array_Output_Blk_IO => System_Strings_Stream_Ops, + RE_Storage_Array_Read => System_Strings_Stream_Ops, + RE_Storage_Array_Read_Blk_IO => System_Strings_Stream_Ops, + RE_Storage_Array_Write => System_Strings_Stream_Ops, + RE_Storage_Array_Write_Blk_IO => System_Strings_Stream_Ops, + + RE_Stream_Element_Array_Input => System_Strings_Stream_Ops, + RE_Stream_Element_Array_Input_Blk_IO => System_Strings_Stream_Ops, + RE_Stream_Element_Array_Output => System_Strings_Stream_Ops, + RE_Stream_Element_Array_Output_Blk_IO => System_Strings_Stream_Ops, + RE_Stream_Element_Array_Read => System_Strings_Stream_Ops, + RE_Stream_Element_Array_Read_Blk_IO => System_Strings_Stream_Ops, + RE_Stream_Element_Array_Write => System_Strings_Stream_Ops, + RE_Stream_Element_Array_Write_Blk_IO => System_Strings_Stream_Ops, RE_String_Input => System_Strings_Stream_Ops, RE_String_Input_Blk_IO => System_Strings_Stream_Ops, diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index fd2c6d6..a3f9ffd 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -11421,7 +11421,7 @@ package body Sem_Attr is if Present (Lo) then Rewrite (P, Make_Indexed_Component (Loc, - Prefix => Relocate_Node (Prefix (P)), + Prefix => Relocate_Node (Prefix (P)), Expressions => New_List (Lo))); Analyze_And_Resolve (P); diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb index b8d7c6a..c66296b 100644 --- a/gcc/ada/sem_ch10.adb +++ b/gcc/ada/sem_ch10.adb @@ -6395,8 +6395,8 @@ package body Sem_Ch10 is if Limited_View_Installed (Item) then Remove_Limited_With_Clause (Item); - -- An unusual case: If the library unit of the Main_Unit has - -- a limited with_clause on some unit P and the context somewhere + -- An unusual case: If the library unit of the Main_Unit has a + -- limited with_clause on some unit P and the context somewhere -- includes a with_clause on P, P has been analyzed. The entity -- for P is still visible, which in general is harmless because -- this is the end of the compilation, but it can affect pending @@ -6409,7 +6409,7 @@ package body Sem_Ch10 is and then not Implicit_With (Item) then Set_Is_Immediately_Visible - (Defining_Entity (Unit (Library_Unit (Item))), False); + (Defining_Entity (Unit (Library_Unit (Item))), False); end if; end if; diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 43beb83..0df4d96 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -6002,7 +6002,7 @@ package body Sem_Ch12 is Make_Parameter_Specification (Loc, Defining_Identifier => F1, Parameter_Type => New_Occurrence_Of (Op_Type, Loc))), - Result_Definition => New_Occurrence_Of (Ret_Type, Loc)); + Result_Definition => New_Occurrence_Of (Ret_Type, Loc)); if Is_Binary then Append_To (Parameter_Specifications (Spec), @@ -14103,7 +14103,6 @@ package body Sem_Ch12 is ------------------------ procedure Preanalyze_Actuals (N : Node_Id; Inst : Entity_Id := Empty) is - procedure Perform_Appropriate_Analysis (N : Node_Id); -- Determine if the actuals we are analyzing come from a generic -- instantiation that is a library unit and dispatch accordingly. @@ -14120,15 +14119,17 @@ package body Sem_Ch12 is if Present (Inst) and then Is_Compilation_Unit (Inst) then Preanalyze (N); - else Analyze (N); end if; end Perform_Appropriate_Analysis; + -- Local variables + + Errs : constant Nat := Serious_Errors_Detected; + Assoc : Node_Id; Act : Node_Id; - Errs : constant Nat := Serious_Errors_Detected; Cur : Entity_Id := Empty; -- Current homograph of the instance name diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 2a4afb8..b18f74b 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -5511,7 +5511,7 @@ package body Sem_Ch13 is -- Default_Iterator -- ---------------------- - when Attribute_Default_Iterator => Default_Iterator : declare + when Attribute_Default_Iterator => Default_Iterator : declare Func : Entity_Id; Typ : Entity_Id; diff --git a/gcc/ada/sem_dim.adb b/gcc/ada/sem_dim.adb index 26c8008..9f15174 100644 --- a/gcc/ada/sem_dim.adb +++ b/gcc/ada/sem_dim.adb @@ -399,9 +399,9 @@ package body Sem_Dim is function "+" (Left, Right : Rational) return Rational is R : constant Rational := - Rational'(Numerator => Left.Numerator * Right.Denominator + - Left.Denominator * Right.Numerator, - Denominator => Left.Denominator * Right.Denominator); + Rational'(Numerator => Left.Numerator * Right.Denominator + + Left.Denominator * Right.Numerator, + Denominator => Left.Denominator * Right.Denominator); begin return Reduce (R); end "+"; diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb index 92486cd..475092b 100644 --- a/gcc/ada/sem_disp.adb +++ b/gcc/ada/sem_disp.adb @@ -210,6 +210,7 @@ package body Sem_Disp is Ctrl_Type := Check_Controlling_Type (Etype (Formal), Subp); if Present (Ctrl_Type) then + -- Obtain the full type in case we are looking at an incomplete -- view. diff --git a/gcc/ada/xref_lib.adb b/gcc/ada/xref_lib.adb index 8b9c70a..4d400f3 100644 --- a/gcc/ada/xref_lib.adb +++ b/gcc/ada/xref_lib.adb @@ -1876,7 +1876,7 @@ package body Xref_Lib is end if; exception - when No_Xref_Information => null; + when No_Xref_Information => null; end; end loop; end Search_Xref; -- cgit v1.1 From 7cbe60de258f6d09561d4fe32dac8892b52520fe Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 4 Jul 2019 08:07:19 +0000 Subject: [Ada] Clean up support for validity checks in the compiler This removes old code in the parser that serves no useful purpose and fixes minor issues in the Validsw package. No functional changes. 2019-07-04 Eric Botcazou gcc/ada/ * gnat1drv.adb (Adjust_Global_Switches): Use proper interface to set the validity settings in CodePeer mode. * par-load.adb (Load): Remove all code dealing with validity settings. * validsw.ads (Validity_Check_Copies): Alphabetize. * validsw.adb (Reset_Validity_Check_Options): Set all options to off. (Save_Validity_Check_Options): Save all options. From-SVN: r273071 --- gcc/ada/ChangeLog | 11 +++++++++++ gcc/ada/gnat1drv.adb | 3 +-- gcc/ada/par-load.adb | 16 ++-------------- gcc/ada/validsw.adb | 9 +++++---- gcc/ada/validsw.ads | 48 ++++++++++++++++++++++++------------------------ 5 files changed, 43 insertions(+), 44 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 65aabe5..3ea8e47 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2019-07-04 Eric Botcazou + + * gnat1drv.adb (Adjust_Global_Switches): Use proper interface to + set the validity settings in CodePeer mode. + * par-load.adb (Load): Remove all code dealing with validity + settings. + * validsw.ads (Validity_Check_Copies): Alphabetize. + * validsw.adb (Reset_Validity_Check_Options): Set all options to + off. + (Save_Validity_Check_Options): Save all options. + 2019-07-04 Hristian Kirtchev * exp_ch3.adb, exp_ch4.adb, exp_ch4.ads, exp_ch5.adb, diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 1f5817a..ded754d 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -379,8 +379,7 @@ procedure Gnat1drv is -- enough useful info. Reset_Validity_Check_Options; - Validity_Check_Default := True; - Validity_Check_Copies := True; + Set_Validity_Check_Options ("dc"); Check_Validity_Of_Parameters := False; -- Turn off style check options and ignore any style check pragmas diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb index cb95500..70bc5cb 100644 --- a/gcc/ada/par-load.adb +++ b/gcc/ada/par-load.adb @@ -36,7 +36,6 @@ with Uname; use Uname; with Osint; use Osint; with Sinput.L; use Sinput.L; with Stylesw; use Stylesw; -with Validsw; use Validsw; with GNAT.Spelling_Checker; use GNAT.Spelling_Checker; @@ -61,10 +60,6 @@ procedure Load is Save_Style_Checks : Style_Check_Options; -- Save style check so it can be restored later - Save_Validity_Check : Boolean; - Save_Validity_Checks : Validity_Check_Options; - -- Save validity check so it can be restored later - With_Cunit : Node_Id; -- Compilation unit node for withed unit @@ -134,9 +129,6 @@ begin Save_Style_Check_Options (Save_Style_Checks); Save_Style_Check := Opt.Style_Check; - Save_Validity_Check_Options (Save_Validity_Checks); - Save_Validity_Check := Opt.Validity_Checks_On; - -- If main unit, set Main_Unit_Entity (this will get overwritten if -- the main unit has a separate spec, that happens later on in Load) @@ -318,11 +310,10 @@ begin or else Nkind (Unit (Curunit)) in N_Generic_Instantiation or else Nkind (Unit (Curunit)) in N_Renaming_Declaration then - -- Turn style and validity checks off for parent unit + -- Turn style checks off for parent unit if not GNAT_Mode then Reset_Style_Check_Options; - Reset_Validity_Check_Options; end if; Spec_Name := Get_Parent_Spec_Name (Unit_Name (Cur_Unum)); @@ -356,11 +347,10 @@ begin end if; end if; - -- Now we load with'ed units, with style/validity checks turned off + -- Now we load with'ed units, with style checks turned off if not GNAT_Mode then Reset_Style_Check_Options; - Reset_Validity_Check_Options; end if; -- Load the context items in two rounds: the first round handles normal @@ -470,6 +460,4 @@ begin Set_Style_Check_Options (Save_Style_Checks); Opt.Style_Check := Save_Style_Check; - Set_Validity_Check_Options (Save_Validity_Checks); - Opt.Validity_Checks_On := Save_Validity_Check; end Load; diff --git a/gcc/ada/validsw.adb b/gcc/ada/validsw.adb index d08299d..ae155c3 100644 --- a/gcc/ada/validsw.adb +++ b/gcc/ada/validsw.adb @@ -36,11 +36,12 @@ package body Validsw is begin Validity_Check_Components := False; Validity_Check_Copies := False; - Validity_Check_Default := True; + Validity_Check_Default := False; Validity_Check_Floating_Point := False; Validity_Check_In_Out_Params := False; Validity_Check_In_Params := False; Validity_Check_Operands := False; + Validity_Check_Parameters := False; Validity_Check_Returns := False; Validity_Check_Subscripts := False; Validity_Check_Tests := False; @@ -73,14 +74,14 @@ package body Validsw is Options (K) := ' '; end loop; - Add ('n', not Validity_Check_Default); - - Add ('c', Validity_Check_Copies); Add ('e', Validity_Check_Components); + Add ('c', Validity_Check_Copies); + Add ('d', Validity_Check_Default); Add ('f', Validity_Check_Floating_Point); Add ('i', Validity_Check_In_Params); Add ('m', Validity_Check_In_Out_Params); Add ('o', Validity_Check_Operands); + Add ('p', Validity_Check_Parameters); Add ('r', Validity_Check_Returns); Add ('s', Validity_Check_Subscripts); Add ('t', Validity_Check_Tests); diff --git a/gcc/ada/validsw.ads b/gcc/ada/validsw.ads index 2dadc5c..5197bdf 100644 --- a/gcc/ada/validsw.ads +++ b/gcc/ada/validsw.ads @@ -40,33 +40,33 @@ package Validsw is -- or in the argument of a Validity_Checks pragma to activate the option. -- The corresponding upper case letter deactivates the option. + Validity_Check_Components : Boolean := False; + -- Controls validity checking for assignment to elementary components of + -- records. If this switch is set to True using -gnatVe, or an 'e' in the + -- argument of Validity_Checks pragma, then the right-hand side of an + -- assignment to such a component is checked for validity. + Validity_Check_Copies : Boolean := False; -- Controls the validity checking of copies. If this switch is set to - -- true using -gnatVc, or a 'c' in the argument of a Validity_Checks - -- pragma, then the right side of assignments and also initializing + -- True using -gnatVc, or a 'c' in the argument of a Validity_Checks + -- pragma, then the right-hand side of assignments and also initializing -- expressions in object declarations are checked for validity. - Validity_Check_Components : Boolean := False; - -- Controls validity checking for assignment to elementary components of - -- records. If this switch is set true using -gnatVe, or an 'e' in the - -- argument of Validity_Checks pragma, then the right hand of an assignment - -- to such a component is checked for validity. - Validity_Check_Default : Boolean := True; -- Controls default (reference manual) validity checking. If this switch is -- set to True using -gnatVd or a 'd' in the argument of a Validity_Checks - -- pragma (or the initial default value is used, set True), then left side - -- subscripts and case statement arguments are checked for validity. This - -- switch is also set by default if no -gnatV switch is used and no + -- pragma (or the initial default value is used, set True), then left-hand + -- side subscripts and case statement arguments are checked for validity. + -- This switch is also set by default if no -gnatV switch is used and no -- Validity_Checks pragma is processed. Validity_Check_Floating_Point : Boolean := False; - -- Normally validity checking applies only to discrete values (integer - -- and enumeration types). If this switch is set to True using -gnatVf - -- or an 'f' in the argument of a Validity_Checks pragma, then floating- - -- point values are also checked. The context in which such checks - -- occur depends on other flags, e.g. if Validity_Check_Copies is also - -- set then floating-point values on the right side of an assignment + -- Normally validity checking applies only to discrete values (integer and + -- enumeration types). If this switch is set to True using -gnatVf or an + -- 'f' in the argument of a Validity_Checks pragma, then floating-point + -- values are also checked. If the context in which such checks occur + -- depends on other flags, e.g. if Validity_Check_Copies is also set, + -- then floating-point values on the right-hand side of an assignment -- will be validity checked. Validity_Check_In_Out_Params : Boolean := False; @@ -103,13 +103,13 @@ package Validsw is -- pragma, then the expression in a RETURN statement is validity checked. Validity_Check_Subscripts : Boolean := False; - -- Controls validity checking of subscripts. If this switch is set to - -- True using -gnatVs, or an 's' in the argument of a Validity_Checks - -- pragma, then all subscripts are checked for validity. Note that left - -- side subscript checking is controlled also by Validity_Check_Default. - -- If Validity_Check_Subscripts is True, then all subscripts are checked, - -- otherwise if Validity_Check_Default is True, then left side subscripts - -- are checked, otherwise no subscripts are checked. + -- Controls validity checking of subscripts. If this switch is set to True + -- using -gnatVs, or an 's' in the argument of a Validity_Checks pragma, + -- then all subscripts are checked for validity. Note that left-hand side + -- subscript checking is also controlled by Validity_Check_Default. If + -- Validity_Check_Subscripts is True, then all subscripts are checked, + -- otherwise if Validity_Check_Default is True, then left-hand side + -- subscripts are checked; otherwise no subscripts are checked. Validity_Check_Tests : Boolean := False; -- Controls validity checking of tests that occur in conditions (i.e. the -- cgit v1.1 From 07c91770f821ae9f6a567fb79b7f2ed675dfeaff Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Thu, 4 Jul 2019 08:07:24 +0000 Subject: [Ada] Spurious error on non-default C++ constructor The frontend reports spurious errors on C++ non-default constructors that have formals whose type is an access to subprogram. 2019-07-04 Javier Miranda gcc/ada/ * exp_tss.adb (Init_Proc): Adding missing support for access to subprograms and access to protected subprograms of non-default C++ constructors. gcc/testsuite/ * gnat.dg/cpp_constructor.adb, gnat.dg/cpp_constructor_fp.ads, gnat.dg/cpp_constructor_useit.ads: New testcase. From-SVN: r273072 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/exp_tss.adb | 16 ++++++++++++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/cpp_constructor.adb | 12 ++++++++++++ gcc/testsuite/gnat.dg/cpp_constructor_fp.ads | 10 ++++++++++ gcc/testsuite/gnat.dg/cpp_constructor_useit.ads | 8 ++++++++ 6 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/cpp_constructor.adb create mode 100644 gcc/testsuite/gnat.dg/cpp_constructor_fp.ads create mode 100644 gcc/testsuite/gnat.dg/cpp_constructor_useit.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 3ea8e47..45c5f39 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Javier Miranda + + * exp_tss.adb (Init_Proc): Adding missing support for access to + subprograms and access to protected subprograms of non-default + C++ constructors. + 2019-07-04 Eric Botcazou * gnat1drv.adb (Adjust_Global_Switches): Use proper interface to diff --git a/gcc/ada/exp_tss.adb b/gcc/ada/exp_tss.adb index 388be48..8ef05e2 100644 --- a/gcc/ada/exp_tss.adb +++ b/gcc/ada/exp_tss.adb @@ -32,6 +32,7 @@ with Lib; use Lib; with Restrict; use Restrict; with Rident; use Rident; with Sem_Aux; use Sem_Aux; +with Sem_Ch6; use Sem_Ch6; with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; @@ -275,8 +276,8 @@ package body Exp_Tss is then exit; - elsif Ekind (Etype (E1)) /= E_Anonymous_Access_Type - and then Ekind (Etype (E2)) /= E_Anonymous_Access_Type + elsif not Is_Anonymous_Access_Type (Etype (E1)) + and then not Is_Anonymous_Access_Type (Etype (E2)) and then Etype (E1) /= Etype (E2) then exit; @@ -287,6 +288,17 @@ package body Exp_Tss is /= Directly_Designated_Type (Etype (E2)) then exit; + + elsif Ekind_In (Etype (E1), + E_Anonymous_Access_Subprogram_Type, + E_Anonymous_Access_Protected_Subprogram_Type) + and then Ekind_In (Etype (E2), + E_Anonymous_Access_Subprogram_Type, + E_Anonymous_Access_Protected_Subprogram_Type) + and then not Conforming_Types + (Etype (E1), Etype (E2), Fully_Conformant) + then + exit; end if; E1 := Next_Formal (E1); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dd1aa0d..8960175 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Javier Miranda + + * gnat.dg/cpp_constructor.adb, gnat.dg/cpp_constructor_fp.ads, + gnat.dg/cpp_constructor_useit.ads: New testcase. + 2019-07-04 Gary Dismukes * gnat.dg/ghost5.adb, gnat.dg/ghost5.ads, diff --git a/gcc/testsuite/gnat.dg/cpp_constructor.adb b/gcc/testsuite/gnat.dg/cpp_constructor.adb new file mode 100644 index 0000000..1ecae1b --- /dev/null +++ b/gcc/testsuite/gnat.dg/cpp_constructor.adb @@ -0,0 +1,12 @@ +-- { dg-do compile } + +with Interfaces.C; use Interfaces.C; +with Cpp_Constructor_FP; +with Cpp_Constructor_Useit; + +procedure Cpp_Constructor is + F : Cpp_Constructor_FP.Class := + Cpp_Constructor_FP.Constructor (Cpp_Constructor_Useit.My_Fn'Access); +begin + null; +end Cpp_Constructor; diff --git a/gcc/testsuite/gnat.dg/cpp_constructor_fp.ads b/gcc/testsuite/gnat.dg/cpp_constructor_fp.ads new file mode 100644 index 0000000..3ee4b3e --- /dev/null +++ b/gcc/testsuite/gnat.dg/cpp_constructor_fp.ads @@ -0,0 +1,10 @@ +with Interfaces.C; use Interfaces.C; + +package Cpp_Constructor_FP is + type Class is limited record null; end record + with Convention => Cpp, Import; + + function Constructor + (Fn : access function (Val : int) return int) return Class; + pragma Cpp_Constructor (Constructor, External_Name => "foo"); +end Cpp_Constructor_FP; diff --git a/gcc/testsuite/gnat.dg/cpp_constructor_useit.ads b/gcc/testsuite/gnat.dg/cpp_constructor_useit.ads new file mode 100644 index 0000000..1f30464 --- /dev/null +++ b/gcc/testsuite/gnat.dg/cpp_constructor_useit.ads @@ -0,0 +1,8 @@ +with Interfaces.C; use Interfaces.C; + +package Cpp_Constructor_Useit is + function My_Fn (Val : int) return int + with Convention => Cpp; + + function My_Fn (Val : int) return int is (Val + 1); +end Cpp_Constructor_Useit; -- cgit v1.1 From 70980ea225624d49591ae24262c55f2328517b62 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 4 Jul 2019 13:38:28 +0200 Subject: Fix loading of lto_section on strict alignment targets (PR lto/91078). 2019-07-04 Martin Liska PR lto/91078 * lto-common.c (lto_file_finalize): Use memcpy to set file_data->lto_section_header. From-SVN: r273077 --- gcc/lto/ChangeLog | 6 ++++++ gcc/lto/lto-common.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 23ad84e..871598c 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 Martin Liska + + PR lto/91078 + * lto-common.c (lto_file_finalize): Use memcpy to set + file_data->lto_section_header. + 2019-07-03 Martin Liska * lto-common.c: Read LTO section and verify header. diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c index bc8c2b4..3c6d7b2 100644 --- a/gcc/lto/lto-common.c +++ b/gcc/lto/lto-common.c @@ -2199,7 +2199,7 @@ lto_file_finalize (struct lto_file_decl_data *file_data, lto_file *file) return; } - file_data->lto_section_header = *(const lto_section *)data; + memcpy (&file_data->lto_section_header, data, sizeof (lto_section)); lto_check_version (file_data->lto_section_header.major_version, file_data->lto_section_header.minor_version, file_data->file_name); -- cgit v1.1 From 8862ed139a6ac3d28dc75ccbaa1dd36f47c8f9dd Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Thu, 4 Jul 2019 11:43:47 +0000 Subject: Improve OpenMP map diagnostics. 2019-07-04 Andrew Stubbs gcc/cp/ * cp-tree.h (cp_omp_emit_unmappable_type_notes): New prototype. * decl.c (cp_finish_decl): Call cp_omp_emit_unmappable_type_notes. * decl2.c (cp_omp_mappable_type): Move contents to ... (cp_omp_mappable_type_1): ... here and add note output. (cp_omp_emit_unmappable_type_notes): New function. * semantics.c (finish_omp_clauses): Call cp_omp_emit_unmappable_type_notes in four places. gcc/testsuite/ * g++.dg/gomp/unmappable-1.C: New file. From-SVN: r273078 --- gcc/cp/ChangeLog | 10 ++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 7 +++-- gcc/cp/decl2.c | 54 ++++++++++++++++++++++++++------ gcc/cp/semantics.c | 4 +++ gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/g++.dg/gomp/unmappable-1.C | 20 ++++++++++++ 7 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/unmappable-1.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7031d8d..c1dfb7c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2019-07-04 Andrew Stubbs + + * cp-tree.h (cp_omp_emit_unmappable_type_notes): New prototype. + * decl.c (cp_finish_decl): Call cp_omp_emit_unmappable_type_notes. + * decl2.c (cp_omp_mappable_type): Move contents to ... + (cp_omp_mappable_type_1): ... here and add note output. + (cp_omp_emit_unmappable_type_notes): New function. + * semantics.c (finish_omp_clauses): Call + cp_omp_emit_unmappable_type_notes in four places. + 2019-07-03 Martin Liska * call.c (build_new_op_1): Remove diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a1849f6..e814bc9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6536,6 +6536,7 @@ extern int parm_index (tree); extern tree vtv_start_verification_constructor_init_function (void); extern tree vtv_finish_verification_constructor_init_function (tree); extern bool cp_omp_mappable_type (tree); +extern bool cp_omp_emit_unmappable_type_notes (tree); extern void cp_check_const_attributes (tree); /* in error.c */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bb9d19a..a178b22 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7433,8 +7433,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, DECL_ATTRIBUTES (decl)); complete_type (TREE_TYPE (decl)); if (!cp_omp_mappable_type (TREE_TYPE (decl))) - error ("%q+D in declare target directive does not have mappable type", - decl); + { + error ("%q+D in declare target directive does not have mappable" + " type", decl); + cp_omp_emit_unmappable_type_notes (TREE_TYPE (decl)); + } else if (!lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)) && !lookup_attribute ("omp declare target link", diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 206f04c..b415716 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1406,32 +1406,68 @@ cp_check_const_attributes (tree attributes) } } -/* Return true if TYPE is an OpenMP mappable type. */ -bool -cp_omp_mappable_type (tree type) +/* Return true if TYPE is an OpenMP mappable type. + If NOTES is non-zero, emit a note message for each problem. */ +static bool +cp_omp_mappable_type_1 (tree type, bool notes) { + bool result = true; + /* Mappable type has to be complete. */ if (type == error_mark_node || !COMPLETE_TYPE_P (type)) - return false; + { + if (notes) + { + tree decl = TYPE_MAIN_DECL (type); + inform ((decl ? DECL_SOURCE_LOCATION (decl) : input_location), + "incomplete type %qT is not mappable", type); + } + result = false; + } /* Arrays have mappable type if the elements have mappable type. */ while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); /* A mappable type cannot contain virtual members. */ if (CLASS_TYPE_P (type) && CLASSTYPE_VTABLES (type)) - return false; + { + if (notes) + inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)), + "type %qT with virtual members is not mappable", type); + result = false; + } /* All data members must be non-static. */ if (CLASS_TYPE_P (type)) { tree field; for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (VAR_P (field)) - return false; + { + if (notes) + inform (DECL_SOURCE_LOCATION (field), + "static field %qD is not mappable", field); + result = false; + } /* All fields must have mappable types. */ else if (TREE_CODE (field) == FIELD_DECL - && !cp_omp_mappable_type (TREE_TYPE (field))) - return false; + && !cp_omp_mappable_type_1 (TREE_TYPE (field), notes)) + result = false; } - return true; + return result; +} + +/* Return true if TYPE is an OpenMP mappable type. */ +bool +cp_omp_mappable_type (tree type) +{ + return cp_omp_mappable_type_1 (type, false); +} + +/* Return true if TYPE is an OpenMP mappable type. + Emit an error messages if not. */ +bool +cp_omp_emit_unmappable_type_notes (tree type) +{ + return cp_omp_mappable_type_1 (type, true); } /* Return the last pushed declaration for the symbol DECL or NULL diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 4f71ac7..cd24490 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7090,6 +7090,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "array section does not have mappable type " "in %qs clause", omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); remove = true; } while (TREE_CODE (t) == ARRAY_REF) @@ -7158,6 +7159,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) error_at (OMP_CLAUSE_LOCATION (c), "%qE does not have a mappable type in %qs clause", t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); remove = true; } while (TREE_CODE (t) == COMPONENT_REF) @@ -7236,6 +7238,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) error_at (OMP_CLAUSE_LOCATION (c), "%qD does not have a mappable type in %qs clause", t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); remove = true; } else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP @@ -7384,6 +7387,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) error_at (OMP_CLAUSE_LOCATION (c), "%qD does not have a mappable type in %qs clause", t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); remove = true; } if (remove) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8960175..a974b11 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Andrew Stubbs + + * g++.dg/gomp/unmappable-1.C: New file. + 2019-07-04 Javier Miranda * gnat.dg/cpp_constructor.adb, gnat.dg/cpp_constructor_fp.ads, diff --git a/gcc/testsuite/g++.dg/gomp/unmappable-1.C b/gcc/testsuite/g++.dg/gomp/unmappable-1.C new file mode 100644 index 0000000..d00ccb5 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/unmappable-1.C @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +class C /* { dg-message "type .C. with virtual members is not mappable" } */ +{ +public: + static int static_member; /* { dg-message "static field .C::static_member. is not mappable" } */ + virtual void f() {} +}; + +extern C v[]; + +int +main () +{ +#pragma omp target map(v) /* { dg-error ".v. does not have a mappable type in .map. clause" } */ + /* { dg-message "incomplete type .C \\\[\\\]. is not mappable" "" { target *-*-* } .-1 } */ + { + } +} -- cgit v1.1 From f5fa046faa7f97662312e17aaab6da9713fe7518 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 4 Jul 2019 14:52:22 +0200 Subject: tree-ssa-alias.c (decl_refs_may_alias_p): Add size1 and size2 parameters; return early for must-alias. * tree-ssa-alias.c (decl_refs_may_alias_p): Add size1 and size2 parameters; return early for must-alias. (indirect_ref_may_alias_decl_p): Likewise; when establishing outer types match, try nonoverlapping_component_refs if must-alias is not obvious. (indirect_refs_may_alias_p): Likewise. (refs_may_alias_p_2): Likewise. * gcc.dg/tree-ssa/alias-access-path-3.c: New testcase. * gcc.dg/tree-ssa/alias-access-path-8.c: New testcase. From-SVN: r273079 --- gcc/ChangeLog | 10 ++++ gcc/testsuite/ChangeLog | 5 ++ .../gcc.dg/tree-ssa/alias-access-path-3.c | 22 +++++++++ .../gcc.dg/tree-ssa/alias-access-path-8.c | 21 +++++++++ gcc/tree-ssa-alias.c | 54 ++++++++++++++++++---- 5 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 932eca2..5f88909 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-07-04 Jan Hubicka + + * tree-ssa-alias.c (decl_refs_may_alias_p): Add size1 and size2 + parameters; return early for must-alias. + (indirect_ref_may_alias_decl_p): Likewise; when establishing + outer types match, try nonoverlapping_component_refs + if must-alias is not obvious. + (indirect_refs_may_alias_p): Likewise. + (refs_may_alias_p_2): Likewise. + 2019-07-04 Richard Biener * tree-ssa-sccvn.h (vn_reference_lookup): Add last_vuse_ptr diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a974b11..a89a218 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Jan Hubicka + + * gcc.dg/tree-ssa/alias-access-path-3.c: New testcase. + * gcc.dg/tree-ssa/alias-access-path-8.c: New testcase. + 2019-07-04 Andrew Stubbs * g++.dg/gomp/unmappable-1.C: New file. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-3.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-3.c new file mode 100644 index 0000000..ef4ffac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-3.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ +struct a {int v1; + int v2;}; +struct b {struct a a[0];}; + +int +test (struct b *bptr1, struct b *bptr2, int i, int j) +{ + bptr1->a[i].v1=123; + bptr2->a[j].v2=1; + return bptr1->a[i].v1; +} +int +test2 (struct b *bptr1, struct b *bptr2, int i, int j) +{ + bptr1->a[i].v1=123; + bptr2->a[j].v1=1; + return bptr1->a[i].v1; +} +/* test should be optimized, while test2 should not. */ +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre1"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c new file mode 100644 index 0000000..1d5b57a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre3" } */ +struct a { + int val; +}; +struct b { + struct a a[10],a2[10]; +}; +struct c { + struct b b[10]; +} *cptr,*cptr2; + + +int +test (int i, int j, int k, int l) +{ + cptr->b[i].a[j].val=123; + cptr2->b[k].a2[l].val=2; + return cptr->b[i].a[j].val; +} +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre3"} } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index c3c127a..d76656e 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1452,8 +1452,10 @@ nonoverlapping_component_refs_p (const_tree x, const_tree y) static bool decl_refs_may_alias_p (tree ref1, tree base1, poly_int64 offset1, poly_int64 max_size1, + poly_int64 size1, tree ref2, tree base2, - poly_int64 offset2, poly_int64 max_size2) + poly_int64 offset2, poly_int64 max_size2, + poly_int64 size2) { gcc_checking_assert (DECL_P (base1) && DECL_P (base2)); @@ -1466,6 +1468,10 @@ decl_refs_may_alias_p (tree ref1, tree base1, if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) return false; + /* If there is must alias, there is no use disambiguating further. */ + if (known_eq (size1, max_size1) && known_eq (size2, max_size2)) + return true; + /* For components with variable position, the above test isn't sufficient, so we disambiguate component references manually. */ if (ref1 && ref2 @@ -1487,10 +1493,12 @@ decl_refs_may_alias_p (tree ref1, tree base1, static bool indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, poly_int64 offset1, poly_int64 max_size1, + poly_int64 size1, alias_set_type ref1_alias_set, alias_set_type base1_alias_set, tree ref2 ATTRIBUTE_UNUSED, tree base2, poly_int64 offset2, poly_int64 max_size2, + poly_int64 size2, alias_set_type ref2_alias_set, alias_set_type base2_alias_set, bool tbaa_p) { @@ -1598,7 +1606,19 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, && (TREE_CODE (TREE_TYPE (base1)) != ARRAY_TYPE || (TYPE_SIZE (TREE_TYPE (base1)) && TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) == INTEGER_CST))) - return ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2); + { + if (!ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2)) + return false; + if (!ref1 || !ref2 + /* If there is must alias, there is no use disambiguating further. */ + || (known_eq (size1, max_size1) && known_eq (size2, max_size2))) + return true; + int res = nonoverlapping_component_refs_since_match_p (base1, ref1, + base2, ref2); + if (res == -1) + return !nonoverlapping_component_refs_p (ref1, ref2); + return !res; + } /* Do access-path based disambiguation. */ if (ref1 && ref2 @@ -1623,10 +1643,12 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, static bool indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, poly_int64 offset1, poly_int64 max_size1, + poly_int64 size1, alias_set_type ref1_alias_set, alias_set_type base1_alias_set, tree ref2 ATTRIBUTE_UNUSED, tree base2, poly_int64 offset2, poly_int64 max_size2, + poly_int64 size2, alias_set_type ref2_alias_set, alias_set_type base2_alias_set, bool tbaa_p) { @@ -1671,6 +1693,9 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, if (!ranges_maybe_overlap_p (offset1 + moff1, max_size1, offset2 + moff2, max_size2)) return false; + /* If there is must alias, there is no use disambiguating further. */ + if (known_eq (size1, max_size1) && known_eq (size2, max_size2)) + return true; if (ref1 && ref2) { int res = nonoverlapping_component_refs_since_match_p (NULL, ref1, @@ -1717,7 +1742,18 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1, can overlap by an exact multiple of their element size. See gcc.dg/torture/alias-2.c. */ && TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE) - return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2); + { + if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2)) + return false; + if (!ref1 || !ref2 + || (known_eq (size1, max_size1) && known_eq (size2, max_size2))) + return true; + int res = nonoverlapping_component_refs_since_match_p (base1, ref1, + base2, ref2); + if (res == -1) + return !nonoverlapping_component_refs_p (ref1, ref2); + return !res; + } /* Do access-path based disambiguation. */ if (ref1 && ref2 @@ -1802,7 +1838,9 @@ refs_may_alias_p_2 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p) var2_p = DECL_P (base2); if (var1_p && var2_p) return decl_refs_may_alias_p (ref1->ref, base1, offset1, max_size1, - ref2->ref, base2, offset2, max_size2); + ref1->size, + ref2->ref, base2, offset2, max_size2, + ref2->size); /* Handle restrict based accesses. ??? ao_ref_base strips inner MEM_REF [&decl], recover from that @@ -1870,21 +1908,21 @@ refs_may_alias_p_2 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p) /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */ if (var1_p && ind2_p) return indirect_ref_may_alias_decl_p (ref2->ref, base2, - offset2, max_size2, + offset2, max_size2, ref2->size, ao_ref_alias_set (ref2), ao_ref_base_alias_set (ref2), ref1->ref, base1, - offset1, max_size1, + offset1, max_size1, ref1->size, ao_ref_alias_set (ref1), ao_ref_base_alias_set (ref1), tbaa_p); else if (ind1_p && ind2_p) return indirect_refs_may_alias_p (ref1->ref, base1, - offset1, max_size1, + offset1, max_size1, ref1->size, ao_ref_alias_set (ref1), ao_ref_base_alias_set (ref1), ref2->ref, base2, - offset2, max_size2, + offset2, max_size2, ref2->size, ao_ref_alias_set (ref2), ao_ref_base_alias_set (ref2), tbaa_p); -- cgit v1.1 From 5bb8f28194ee8271357051441db27decbd74d5c5 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Thu, 4 Jul 2019 13:22:39 +0000 Subject: s-osinte__kfreebsd-gnu.ads (clockid_t): Make type definition public. 2019-07-04 James Clarke * libgnarl/s-osinte__kfreebsd-gnu.ads (clockid_t): Make type definition public. (CLOCK_REALTIME): Make value public. From-SVN: r273080 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads | 8 ++------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 45c5f39..bc6f2e0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-04 James Clarke + + * libgnarl/s-osinte__kfreebsd-gnu.ads (clockid_t): Make type + definition public. + (CLOCK_REALTIME): Make value public. + 2019-07-04 Javier Miranda * exp_tss.adb (Init_Proc): Adding missing support for access to diff --git a/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads b/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads index f46bbda..aa6c1a8 100644 --- a/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads +++ b/gcc/ada/libgnarl/s-osinte__kfreebsd-gnu.ads @@ -206,9 +206,8 @@ package System.OS_Interface is function nanosleep (rqtp, rmtp : access timespec) return int; pragma Import (C, nanosleep, "nanosleep"); - type clockid_t is private; - - CLOCK_REALTIME : constant clockid_t; + type clockid_t is new int; + CLOCK_REALTIME : constant clockid_t := 0; function clock_gettime (clock_id : clockid_t; @@ -607,9 +606,6 @@ private end record; pragma Convention (C, timespec); - type clockid_t is new int; - CLOCK_REALTIME : constant clockid_t := 0; - type pthread_attr_t is record detachstate : int; schedpolicy : int; -- cgit v1.1 From 5cee32399049534903f3ddb0bf55657b909492f4 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 4 Jul 2019 13:55:15 +0000 Subject: re PR tree-optimization/90911 (456.hmmer regression with r272239) 2019-07-04 Richard Biener PR tree-optimization/90911 * tree-vectorizer.h (_loop_vec_info::scalar_loop_scaling): New field. (LOOP_VINFO_SCALAR_LOOP_SCALING): new. * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Initialize scalar_loop_scaling. (vect_transform_loop): Scale scalar loop profile if needed. * tree-vect-loop-manip.c (vect_loop_versioning): When re-using the loop copy from if-conversion adjust edge probabilities and scale the vectorized loop body profile, queue the scalar profile for updating after peeling. From-SVN: r273082 --- gcc/ChangeLog | 13 +++++++++++++ gcc/tree-vect-loop-manip.c | 13 +++++++++++-- gcc/tree-vect-loop.c | 5 +++++ gcc/tree-vectorizer.h | 4 ++++ 4 files changed, 33 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5f88909..591e297 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2019-07-04 Richard Biener + + PR tree-optimization/90911 + * tree-vectorizer.h (_loop_vec_info::scalar_loop_scaling): New field. + (LOOP_VINFO_SCALAR_LOOP_SCALING): new. + * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Initialize + scalar_loop_scaling. + (vect_transform_loop): Scale scalar loop profile if needed. + * tree-vect-loop-manip.c (vect_loop_versioning): When re-using + the loop copy from if-conversion adjust edge probabilities + and scale the vectorized loop body profile, queue the scalar + profile for updating after peeling. + 2019-07-04 Jan Hubicka * tree-ssa-alias.c (decl_refs_may_alias_p): Add size1 and size2 diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index c5cabc8..bd8fffb 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -3114,8 +3114,17 @@ vect_loop_versioning (loop_vec_info loop_vinfo, GSI_SAME_STMT); } - /* ??? if-conversion uses profile_probability::always () but - prob below is profile_probability::likely (). */ + /* if-conversion uses profile_probability::always () for both paths, + reset the paths probabilities appropriately. */ + edge te, fe; + extract_true_false_edges_from_block (condition_bb, &te, &fe); + te->probability = prob; + fe->probability = prob.invert (); + /* We can scale loops counts immediately but have to postpone + scaling the scalar loop because we re-use it during peeling. */ + scale_loop_frequencies (loop_to_version, te->probability); + LOOP_VINFO_SCALAR_LOOP_SCALING (loop_vinfo) = fe->probability; + nloop = scalar_loop; if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index c46cd9d..b49ab15 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -833,6 +833,7 @@ _loop_vec_info::_loop_vec_info (struct loop *loop_in, vec_info_shared *shared) operands_swapped (false), no_data_dependencies (false), has_mask_store (false), + scalar_loop_scaling (profile_probability::uninitialized ()), scalar_loop (NULL), orig_loop_info (NULL) { @@ -8557,6 +8558,10 @@ vect_transform_loop (loop_vec_info loop_vinfo) epilogue = vect_do_peeling (loop_vinfo, niters, nitersm1, &niters_vector, &step_vector, &niters_vector_mult_vf, th, check_profitability, niters_no_overflow); + if (LOOP_VINFO_SCALAR_LOOP (loop_vinfo) + && LOOP_VINFO_SCALAR_LOOP_SCALING (loop_vinfo).initialized_p ()) + scale_loop_frequencies (LOOP_VINFO_SCALAR_LOOP (loop_vinfo), + LOOP_VINFO_SCALAR_LOOP_SCALING (loop_vinfo)); if (niters_vector == NULL_TREE) { diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 0dd29f8..f7432f0 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -548,6 +548,9 @@ typedef struct _loop_vec_info : public vec_info { /* Mark loops having masked stores. */ bool has_mask_store; + /* Queued scaling factor for the scalar loop. */ + profile_probability scalar_loop_scaling; + /* If if-conversion versioned this loop before conversion, this is the loop version without if-conversion. */ struct loop *scalar_loop; @@ -603,6 +606,7 @@ typedef struct _loop_vec_info : public vec_info { #define LOOP_VINFO_PEELING_FOR_NITER(L) (L)->peeling_for_niter #define LOOP_VINFO_NO_DATA_DEPENDENCIES(L) (L)->no_data_dependencies #define LOOP_VINFO_SCALAR_LOOP(L) (L)->scalar_loop +#define LOOP_VINFO_SCALAR_LOOP_SCALING(L) (L)->scalar_loop_scaling #define LOOP_VINFO_HAS_MASK_STORE(L) (L)->has_mask_store #define LOOP_VINFO_SCALAR_ITERATION_COST(L) (L)->scalar_cost_vec #define LOOP_VINFO_SINGLE_SCALAR_ITERATION_COST(L) (L)->single_scalar_iteration_cost -- cgit v1.1 From e57c896e86c4257741b574d99d7cacbfda219755 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 4 Jul 2019 13:56:12 +0000 Subject: re PR ipa/91062 (gcc.dg/ipa/ipa-pta-1.c dump contains garbage when gcc was configured with --enable-checking=all) 2019-07-04 Richard Biener PR ipa/91062 * tree-pass.h (execute_all_ipa_transforms): Add a flag parameter whether to disable GC collection. * passes.c (execute_one_ipa_transform_pass): Likewise, and honor it. (execute_all_ipa_transforms): Likewise and pass it down. * cgraph.c (cgraph_node::get_body): Do not invoke garbage collection from applying IPA transforms. * cgraphunit.c (cgraph_node::expand): Allow garbage collection from applying IPA transforms. From-SVN: r273083 --- gcc/ChangeLog | 13 +++++++++++++ gcc/cgraph.c | 2 +- gcc/cgraphunit.c | 2 +- gcc/passes.c | 9 +++++---- gcc/tree-pass.h | 2 +- 5 files changed, 21 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 591e297..19ab956 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,18 @@ 2019-07-04 Richard Biener + PR ipa/91062 + * tree-pass.h (execute_all_ipa_transforms): Add a flag + parameter whether to disable GC collection. + * passes.c (execute_one_ipa_transform_pass): Likewise, and + honor it. + (execute_all_ipa_transforms): Likewise and pass it down. + * cgraph.c (cgraph_node::get_body): Do not invoke garbage + collection from applying IPA transforms. + * cgraphunit.c (cgraph_node::expand): Allow garbage collection + from applying IPA transforms. + +2019-07-04 Richard Biener + PR tree-optimization/90911 * tree-vectorizer.h (_loop_vec_info::scalar_loop_scaling): New field. (LOOP_VINFO_SCALAR_LOOP_SCALING): new. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index d161db9..a7e3bcf 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -3618,7 +3618,7 @@ cgraph_node::get_body (void) set_dump_file (NULL); push_cfun (DECL_STRUCT_FUNCTION (decl)); - execute_all_ipa_transforms (); + execute_all_ipa_transforms (true); cgraph_edge::rebuild_edges (); free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f4d6688..5999b9e 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -2184,7 +2184,7 @@ cgraph_node::expand (void) bitmap_obstack_initialize (®_obstack); /* FIXME, only at RTL generation*/ - execute_all_ipa_transforms (); + execute_all_ipa_transforms (false); /* Perform all tree transforms and optimizations. */ diff --git a/gcc/passes.c b/gcc/passes.c index c6331cb..bd56004 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -2182,7 +2182,7 @@ execute_ipa_summary_passes (ipa_opt_pass_d *ipa_pass) static void execute_one_ipa_transform_pass (struct cgraph_node *node, - ipa_opt_pass_d *ipa_pass) + ipa_opt_pass_d *ipa_pass, bool do_not_collect) { opt_pass *pass = ipa_pass; unsigned int todo_after = 0; @@ -2228,14 +2228,14 @@ execute_one_ipa_transform_pass (struct cgraph_node *node, redirect_edge_var_map_empty (); /* Signal this is a suitable GC collection point. */ - if (!(todo_after & TODO_do_not_ggc_collect)) + if (!do_not_collect && !(todo_after & TODO_do_not_ggc_collect)) ggc_collect (); } /* For the current function, execute all ipa transforms. */ void -execute_all_ipa_transforms (void) +execute_all_ipa_transforms (bool do_not_collect) { struct cgraph_node *node; if (!cfun) @@ -2247,7 +2247,8 @@ execute_all_ipa_transforms (void) unsigned int i; for (i = 0; i < node->ipa_transforms_to_apply.length (); i++) - execute_one_ipa_transform_pass (node, node->ipa_transforms_to_apply[i]); + execute_one_ipa_transform_pass (node, node->ipa_transforms_to_apply[i], + do_not_collect); node->ipa_transforms_to_apply.release (); } } diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 3a0b380..b27dbdd 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -632,7 +632,7 @@ extern bool execute_one_pass (opt_pass *); extern void execute_pass_list (function *, opt_pass *); extern void execute_ipa_pass_list (opt_pass *); extern void execute_ipa_summary_passes (ipa_opt_pass_d *); -extern void execute_all_ipa_transforms (void); +extern void execute_all_ipa_transforms (bool); extern void execute_all_ipa_stmt_fixups (struct cgraph_node *, gimple **); extern bool pass_init_dump_file (opt_pass *); extern void pass_fini_dump_file (opt_pass *); -- cgit v1.1 From ebebc928d8b0d17676e751848892f927373b1fe5 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 4 Jul 2019 15:00:00 +0000 Subject: introduce EH_ELSE_EXPR tree and gimplifier I found GIMPLE_EH_ELSE offered exactly the semantics I needed for some Ada changes yet to be contributed, but GIMPLE_EH_ELSE was only built by GIMPLE passes, and I needed to build earlier something that eventually became GIMPLE_EH_ELSE. This patch does that, introducing an EH_ELSE_EXPR tree, and logic to dump it and to gimplify it. for gcc/ChangeLog * doc/generic.texi (Cleanups): Document EH_ELSE_EXPR. * except.c: Likewise. * expr.c (expand_expr_real_1): Reject it. * gimplify.c (gimplify_expr): Gimplify it, within TRY_FINALLY_EXPR. * tree-dump.c (dequeue_and_dump): Dump it. * tree-pretty-print.c (dump_generic_node): Likewise. * tree.c (block_may_fallthru): Handle it. * tree.def (EH_ELSE_EXPR): Introduce it. * gimple-pretty-print.c (dump_gimple_try): Dump TRY_FINALLY with GIMPLE_EH_ELSE as try/finally/else. From-SVN: r273084 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/doc/generic.texi | 5 +++++ gcc/except.c | 12 ++++++------ gcc/expr.c | 1 + gcc/gimple-pretty-print.c | 20 +++++++++++++++++++- gcc/gimplify.c | 18 +++++++++++++++++- gcc/tree-dump.c | 1 + gcc/tree-pretty-print.c | 28 +++++++++++++++++++++++++--- gcc/tree.c | 3 +++ gcc/tree.def | 9 ++++++++- 10 files changed, 99 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 19ab956..41b8b14 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-07-04 Alexandre Oliva + + * doc/generic.texi (Cleanups): Document EH_ELSE_EXPR. + * except.c: Likewise. + * expr.c (expand_expr_real_1): Reject it. + * gimplify.c (gimplify_expr): Gimplify it, within + TRY_FINALLY_EXPR. + * tree-dump.c (dequeue_and_dump): Dump it. + * tree-pretty-print.c (dump_generic_node): Likewise. + * tree.c (block_may_fallthru): Handle it. + * tree.def (EH_ELSE_EXPR): Introduce it. + * gimple-pretty-print.c (dump_gimple_try): Dump TRY_FINALLY + with GIMPLE_EH_ELSE as try/finally/else. + 2019-07-04 Richard Biener PR ipa/91062 diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index 67f7ad5..8901d5f 100644 --- a/gcc/doc/generic.texi +++ b/gcc/doc/generic.texi @@ -2180,6 +2180,11 @@ After the second sequence is executed, if it completes normally by falling off the end, execution continues wherever the first sequence would have continued, by falling off the end, or doing a goto, etc. +If the second sequence is an @code{EH_ELSE_EXPR} selector, then the +sequence in its first operand is used when the first sequence completes +normally, and that in its second operand is used for exceptional +cleanups, i.e., when an exception propagates out of the first sequence. + @code{TRY_FINALLY_EXPR} complicates the flow graph, since the cleanup needs to appear on every edge out of the controlled block; this reduces the freedom to move code across these edges. Therefore, the diff --git a/gcc/except.c b/gcc/except.c index edaeeb4..29f3339 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -27,14 +27,14 @@ along with GCC; see the file COPYING3. If not see the compilation process: In the beginning, in the front end, we have the GENERIC trees - TRY_CATCH_EXPR, TRY_FINALLY_EXPR, WITH_CLEANUP_EXPR, + TRY_CATCH_EXPR, TRY_FINALLY_EXPR, EH_ELSE_EXPR, WITH_CLEANUP_EXPR, CLEANUP_POINT_EXPR, CATCH_EXPR, and EH_FILTER_EXPR. - During initial gimplification (gimplify.c) these are lowered - to the GIMPLE_TRY, GIMPLE_CATCH, and GIMPLE_EH_FILTER nodes. - The WITH_CLEANUP_EXPR and CLEANUP_POINT_EXPR nodes are converted - into GIMPLE_TRY_FINALLY nodes; the others are a more direct 1-1 - conversion. + During initial gimplification (gimplify.c) these are lowered to the + GIMPLE_TRY, GIMPLE_CATCH, GIMPLE_EH_ELSE, and GIMPLE_EH_FILTER + nodes. The WITH_CLEANUP_EXPR and CLEANUP_POINT_EXPR nodes are + converted into GIMPLE_TRY_FINALLY nodes; the others are a more + direct 1-1 conversion. During pass_lower_eh (tree-eh.c) we record the nested structure of the TRY nodes in EH_REGION nodes in CFUN->EH->REGION_TREE. diff --git a/gcc/expr.c b/gcc/expr.c index 4acf250..c922aaa 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -11292,6 +11292,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, case CATCH_EXPR: case EH_FILTER_EXPR: case TRY_FINALLY_EXPR: + case EH_ELSE_EXPR: /* Lowered by tree-eh.c. */ gcc_unreachable (); diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 45e7260..ce339ee 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1232,6 +1232,8 @@ dump_gimple_try (pretty_printer *buffer, gtry *gs, int spc, newline_and_indent (buffer, spc + 2); pp_right_brace (buffer); + gimple_seq seq = gimple_try_cleanup (gs); + if (gimple_try_kind (gs) == GIMPLE_TRY_CATCH) { newline_and_indent (buffer, spc); @@ -1245,12 +1247,28 @@ dump_gimple_try (pretty_printer *buffer, gtry *gs, int spc, pp_string (buffer, "finally"); newline_and_indent (buffer, spc + 2); pp_left_brace (buffer); + + if (seq && is_a (gimple_seq_first_stmt (seq)) + && gimple_seq_nondebug_singleton_p (seq)) + { + geh_else *stmt = as_a (gimple_seq_first_stmt (seq)); + seq = gimple_eh_else_n_body (stmt); + pp_newline (buffer); + dump_gimple_seq (buffer, seq, spc + 4, flags); + newline_and_indent (buffer, spc + 2); + pp_right_brace (buffer); + seq = gimple_eh_else_e_body (stmt); + newline_and_indent (buffer, spc); + pp_string (buffer, "else"); + newline_and_indent (buffer, spc + 2); + pp_left_brace (buffer); + } } else pp_string (buffer, " {"); pp_newline (buffer); - dump_gimple_seq (buffer, gimple_try_cleanup (gs), spc + 4, flags); + dump_gimple_seq (buffer, seq, spc + 4, flags); newline_and_indent (buffer, spc + 2); pp_right_brace (buffer); } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9e5e423..a3792d1 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -13079,7 +13079,22 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, input_location = UNKNOWN_LOCATION; eval = cleanup = NULL; gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval); - gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup); + if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR + && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR) + { + gimple_seq n = NULL, e = NULL; + gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1), + 0), &n); + gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1), + 1), &e); + if (!gimple_seq_empty_p (n) && !gimple_seq_empty_p (e)) + { + geh_else *stmt = gimple_build_eh_else (n, e); + gimple_seq_add_stmt (&cleanup, stmt); + } + } + else + gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup); /* Don't create bogus GIMPLE_TRY with empty cleanup. */ if (gimple_seq_empty_p (cleanup)) { @@ -13637,6 +13652,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && code != LOOP_EXPR && code != SWITCH_EXPR && code != TRY_FINALLY_EXPR + && code != EH_ELSE_EXPR && code != OACC_PARALLEL && code != OACC_KERNELS && code != OACC_DATA diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index 58cb1ee..51c0965 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -604,6 +604,7 @@ dequeue_and_dump (dump_info_p di) break; case TRY_FINALLY_EXPR: + case EH_ELSE_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index dacda7b..742c284 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -2815,12 +2815,34 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, newline_and_indent (pp, spc+2); pp_right_brace (pp); newline_and_indent (pp, spc); - pp_string (pp, - (TREE_CODE (node) == TRY_CATCH_EXPR) ? "catch" : "finally"); + if (TREE_CODE (node) == TRY_CATCH_EXPR) + { + node = TREE_OPERAND (node, 1); + pp_string (pp, "catch"); + } + else + { + gcc_assert (TREE_CODE (node) == TRY_FINALLY_EXPR); + node = TREE_OPERAND (node, 1); + pp_string (pp, "finally"); + if (TREE_CODE (node) == EH_ELSE_EXPR) + { + newline_and_indent (pp, spc+2); + pp_left_brace (pp); + newline_and_indent (pp, spc+4); + dump_generic_node (pp, TREE_OPERAND (node, 0), spc+4, + flags, true); + newline_and_indent (pp, spc+2); + pp_right_brace (pp); + newline_and_indent (pp, spc); + node = TREE_OPERAND (node, 1); + pp_string (pp, "else"); + } + } newline_and_indent (pp, spc+2); pp_left_brace (pp); newline_and_indent (pp, spc+4); - dump_generic_node (pp, TREE_OPERAND (node, 1), spc+4, flags, true); + dump_generic_node (pp, node, spc+4, flags, true); newline_and_indent (pp, spc+2); pp_right_brace (pp); is_expr = false; diff --git a/gcc/tree.c b/gcc/tree.c index 76d94c6..563af6f 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -13415,6 +13415,9 @@ block_may_fallthru (const_tree block) return (block_may_fallthru (TREE_OPERAND (stmt, 0)) && block_may_fallthru (TREE_OPERAND (stmt, 1))); + case EH_ELSE_EXPR: + return block_may_fallthru (TREE_OPERAND (stmt, 0)); + case MODIFY_EXPR: if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR) stmt = TREE_OPERAND (stmt, 1); diff --git a/gcc/tree.def b/gcc/tree.def index 10a14fc..d2e6938 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -908,7 +908,14 @@ DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", tcc_statement, 2) /* Evaluate the first operand. The second operand is a cleanup expression which is evaluated on any exit (normal, exception, or jump out) from this expression. */ -DEFTREECODE (TRY_FINALLY_EXPR, "try_finally", tcc_statement, 2) +DEFTREECODE (TRY_FINALLY_EXPR, "try_finally_expr", tcc_statement, 2) + +/* Evaluate either the normal or the exceptional cleanup. This must + only be present as the cleanup expression in a TRY_FINALLY_EXPR. + If the TRY_FINALLY_EXPR completes normally, the first operand of + EH_ELSE_EXPR is used as a cleanup, otherwise the second operand is + used. */ +DEFTREECODE (EH_ELSE_EXPR, "eh_else_expr", tcc_statement, 2) /* These types of expressions have no useful value, and always have side effects. */ -- cgit v1.1 From ee118c14f71f43a4b82c439cd4381e034bd2786a Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Thu, 4 Jul 2019 15:46:00 +0000 Subject: introduce gcc_jit_context_new_bitfield gcc/jit/ChangeLog: 2019-07-04 Andrea Corallo * docs/topics/compatibility.rst (LIBGCCJIT_ABI_12): New ABI tag. * docs/topics/types.rst: Add gcc_jit_context_new_bitfield. * jit-common.h (namespace recording): Add class bitfield. * jit-playback.c: (DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): Add macros. (playback::context::new_bitfield): New method. (playback::compound_type::set_fields): Add bitfield support. (playback::lvalue::mark_addressable): Was jit_mark_addressable make this a method of lvalue plus return a bool to communicate success. (playback::lvalue::get_address): Check for jit_mark_addressable return value. * jit-playback.h (new_bitfield): New method. (class bitfield): New class. (class lvalue): Add jit_mark_addressable method. * jit-recording.c (recording::context::new_bitfield): New method. (recording::bitfield::replay_into): New method. (recording::bitfield::write_to_dump): Likewise. (recording::bitfield::make_debug_string): Likewise. (recording::bitfield::write_reproducer): Likewise. * jit-recording.h (class context): Add new_bitfield method. (class field): Make it derivable by class bitfield. (class bitfield): Add new class. * libgccjit++.h (class context): Add new_bitfield method. * libgccjit.c (struct gcc_jit_bitfield): New structure. (gcc_jit_context_new_bitfield): New function. * libgccjit.h (LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield) New macro. (gcc_jit_context_new_bitfield): New function. * libgccjit.map (LIBGCCJIT_ABI_12) New ABI tag. gcc/testsuite/ChangeLog: 2019-07-04 Andrea Corallo * jit.dg/all-non-failing-tests.h: Add test-accessing-bitfield.c. * jit.dg/test-accessing-bitfield.c: New testcase. * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c: Likewise. * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c: Likewise. * jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c: Likewise. From-SVN: r273086 --- gcc/jit/ChangeLog | 32 +++++ gcc/jit/docs/topics/compatibility.rst | 5 + gcc/jit/docs/topics/types.rst | 24 ++++ gcc/jit/jit-common.h | 1 + gcc/jit/jit-playback.c | 91 +++++++++++++-- gcc/jit/jit-playback.h | 11 +- gcc/jit/jit-recording.c | 80 ++++++++++++- gcc/jit/jit-recording.h | 41 ++++++- gcc/jit/libgccjit++.h | 14 +++ gcc/jit/libgccjit.c | 40 +++++++ gcc/jit/libgccjit.h | 15 +++ gcc/jit/libgccjit.map | 7 +- gcc/testsuite/ChangeLog | 13 ++- gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 ++ gcc/testsuite/jit.dg/test-accessing-bitfield.c | 130 +++++++++++++++++++++ ...ror-gcc_jit_context_new_bitfield-invalid-type.c | 53 +++++++++ ...or-gcc_jit_context_new_bitfield-invalid-width.c | 44 +++++++ ...est-error-gcc_jit_lvalue_get_address-bitfield.c | 66 +++++++++++ 18 files changed, 656 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-accessing-bitfield.c create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c (limited to 'gcc') diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 9958db1..8323e2f 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,35 @@ +2019-07-04 Andrea Corallo + + * docs/topics/compatibility.rst (LIBGCCJIT_ABI_12): New ABI tag. + * docs/topics/types.rst: Add gcc_jit_context_new_bitfield. + * jit-common.h (namespace recording): Add class bitfield. + * jit-playback.c: + (DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): Add macros. + (playback::context::new_bitfield): New method. + (playback::compound_type::set_fields): Add bitfield support. + (playback::lvalue::mark_addressable): Was jit_mark_addressable make this + a method of lvalue plus return a bool to communicate success. + (playback::lvalue::get_address): Check for jit_mark_addressable return + value. + * jit-playback.h (new_bitfield): New method. + (class bitfield): New class. + (class lvalue): Add jit_mark_addressable method. + * jit-recording.c (recording::context::new_bitfield): New method. + (recording::bitfield::replay_into): New method. + (recording::bitfield::write_to_dump): Likewise. + (recording::bitfield::make_debug_string): Likewise. + (recording::bitfield::write_reproducer): Likewise. + * jit-recording.h (class context): Add new_bitfield method. + (class field): Make it derivable by class bitfield. + (class bitfield): Add new class. + * libgccjit++.h (class context): Add new_bitfield method. + * libgccjit.c (struct gcc_jit_bitfield): New structure. + (gcc_jit_context_new_bitfield): New function. + * libgccjit.h + (LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield) New macro. + (gcc_jit_context_new_bitfield): New function. + * libgccjit.map (LIBGCCJIT_ABI_12) New ABI tag. + 2019-03-21 Jakub Jelinek * jit-recording.c (reproducer::m_set_identifiers): Use false as Lazy diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index abefa56..da64920 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -177,3 +177,8 @@ entrypoints: -------------------- ``LIBGCCJIT_ABI_11`` covers the addition of :func:`gcc_jit_context_add_driver_option` + +``LIBGCCJIT_ABI_12`` +-------------------- +``LIBGCCJIT_ABI_12`` covers the addition of +:func:`gcc_jit_context_new_bitfield` diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst index 1d2dcd4..37d9d01 100644 --- a/gcc/jit/docs/topics/types.rst +++ b/gcc/jit/docs/topics/types.rst @@ -247,6 +247,30 @@ You can model C `struct` types by creating :c:type:`gcc_jit_struct *` and underlying string, so it is valid to pass in a pointer to an on-stack buffer. +.. function:: gcc_jit_field *\ + gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + int width,\ + const char *name) + + Construct a new bit field, with the given type width and name. + + The parameter ``name`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + + The parameter ``type`` must be an integer type. + + The parameter ``width`` must be a positive integer that does not exceed the + size of ``type``. + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_12`; you can test + for its presence using + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield + .. function:: gcc_jit_object *\ gcc_jit_field_as_object (gcc_jit_field *field) diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h index 1d96cc3..e747d96 100644 --- a/gcc/jit/jit-common.h +++ b/gcc/jit/jit-common.h @@ -119,6 +119,7 @@ namespace recording { class union_; class vector_type; class field; + class bitfield; class fields; class function; class block; diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index b74495c..942c730 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -47,6 +47,13 @@ along with GCC; see the file COPYING3. If not see #include "jit-builtins.h" #include "jit-tempdir.h" +/* Compare with gcc/c-family/c-common.h: DECL_C_BIT_FIELD, + SET_DECL_C_BIT_FIELD. + These are redefined here to avoid depending from the C frontend. */ +#define DECL_JIT_BIT_FIELD(NODE) \ + (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1) +#define SET_DECL_JIT_BIT_FIELD(NODE) \ + (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 1) /* gcc::jit::playback::context::build_cast uses the convert.h API, which in turn requires the frontend to provide a "convert" @@ -263,6 +270,46 @@ new_field (location *loc, return new field (decl); } +/* Construct a playback::bitfield instance (wrapping a tree). */ + +playback::field * +playback::context:: +new_bitfield (location *loc, + type *type, + int width, + const char *name) +{ + gcc_assert (type); + gcc_assert (name); + gcc_assert (width); + + /* compare with c/c-decl.c:grokfield, grokdeclarator and + check_bitfield_type_and_width. */ + + tree tree_type = type->as_tree (); + gcc_assert (INTEGRAL_TYPE_P (tree_type)); + tree tree_width = build_int_cst (integer_type_node, width); + if (compare_tree_int (tree_width, TYPE_PRECISION (tree_type)) > 0) + { + add_error ( + loc, + "width of bit-field %s (width: %i) is wider than its type (width: %i)", + name, width, TYPE_PRECISION (tree_type)); + return NULL; + } + + tree decl = build_decl (UNKNOWN_LOCATION, FIELD_DECL, + get_identifier (name), type->as_tree ()); + DECL_NONADDRESSABLE_P (decl) = true; + DECL_INITIAL (decl) = tree_width; + SET_DECL_JIT_BIT_FIELD (decl); + + if (loc) + set_tree_location (decl, loc); + + return new field (decl); +} + /* Construct a playback::compound_type instance (wrapping a tree). */ playback::compound_type * @@ -295,8 +342,15 @@ playback::compound_type::set_fields (const auto_vec *fields) for (unsigned i = 0; i < fields->length (); i++) { field *f = (*fields)[i]; - DECL_CONTEXT (f->as_tree ()) = t; - fieldlist = chainon (f->as_tree (), fieldlist); + tree x = f->as_tree (); + DECL_CONTEXT (x) = t; + if (DECL_JIT_BIT_FIELD (x)) + { + unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x)); + DECL_SIZE (x) = bitsize_int (width); + DECL_BIT_FIELD (x) = 1; + } + fieldlist = chainon (x, fieldlist); } fieldlist = nreverse (fieldlist); TYPE_FIELDS (t) = fieldlist; @@ -1197,20 +1251,31 @@ dereference (location *loc) return new lvalue (get_context (), datum); } -/* Mark EXP saying that we need to be able to take the +/* Mark the lvalue saying that we need to be able to take the address of it; it should not be allocated in a register. - Compare with e.g. c/c-typeck.c: c_mark_addressable. */ + Compare with e.g. c/c-typeck.c: c_mark_addressable really_atomic_lvalue. + Returns false if a failure occurred (an error will already have been + added to the active context for this case). */ -static void -jit_mark_addressable (tree exp) +bool +playback::lvalue:: +mark_addressable (location *loc) { - tree x = exp; + tree x = as_tree ();; while (1) switch (TREE_CODE (x)) { case COMPONENT_REF: - /* (we don't yet support bitfields) */ + if (DECL_JIT_BIT_FIELD (TREE_OPERAND (x, 1))) + { + gcc_assert (gcc::jit::active_playback_ctxt); + gcc::jit:: + active_playback_ctxt->add_error (loc, + "cannot take address of " + "bit-field"); + return false; + } /* fallthrough */ case ADDR_EXPR: case ARRAY_REF: @@ -1222,7 +1287,7 @@ jit_mark_addressable (tree exp) case COMPOUND_LITERAL_EXPR: case CONSTRUCTOR: TREE_ADDRESSABLE (x) = 1; - return; + return true; case VAR_DECL: case CONST_DECL: @@ -1234,7 +1299,7 @@ jit_mark_addressable (tree exp) TREE_ADDRESSABLE (x) = 1; /* fallthrough */ default: - return; + return true; } } @@ -1251,8 +1316,10 @@ get_address (location *loc) tree ptr = build1 (ADDR_EXPR, t_ptrtype, t_lvalue); if (loc) get_context ()->set_tree_location (ptr, loc); - jit_mark_addressable (t_lvalue); - return new rvalue (get_context (), ptr); + if (mark_addressable (loc)) + return new rvalue (get_context (), ptr); + else + return NULL; } /* The wrapper subclasses are GC-managed, but can own non-GC memory. diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index bc4de9c..d4b148e 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -75,6 +75,12 @@ public: type *type, const char *name); + field * + new_bitfield (location *loc, + type *type, + int width, + const char *name); + compound_type * new_compound_type (location *loc, const char *name, @@ -426,6 +432,8 @@ private: tree m_inner; }; +class bitfield : public field {}; + class function : public wrapper { public: @@ -614,6 +622,8 @@ public: rvalue * get_address (location *loc); +private: + bool mark_addressable (location *loc); }; class param : public lvalue @@ -703,4 +713,3 @@ extern playback::context *active_playback_ctxt; } // namespace gcc #endif /* JIT_PLAYBACK_H */ - diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index a332fe8..495ac7f 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -872,6 +872,24 @@ recording::context::new_field (recording::location *loc, return result; } +/* Create a recording::bitfield instance and add it to this context's list + of mementos. + + Implements the post-error-checking part of + gcc_jit_context_new_bitfield. */ + +recording::field * +recording::context::new_bitfield (recording::location *loc, + recording::type *type, + int width, + const char *name) +{ + recording::field *result = + new recording::bitfield (this, loc, type, width, new_string (name)); + record (result); + return result; +} + /* Create a recording::struct_ instance and add it to this context's list of mementos and list of compound types. @@ -2962,7 +2980,7 @@ recording::field::replay_into (replayer *r) recording::memento::write_to_dump. Dump each field by dumping a line of the form: TYPE NAME; - so that we can build up a struct/union field-byfield. */ + so that we can build up a struct/union field by field. */ void recording::field::write_to_dump (dump &d) @@ -2999,6 +3017,66 @@ recording::field::write_reproducer (reproducer &r) m_name->get_debug_string ()); } +/* The implementation of class gcc::jit::recording::bitfield. */ + +/* Implementation of pure virtual hook recording::memento::replay_into + for recording::bitfield. */ + +void +recording::bitfield::replay_into (replayer *r) +{ + set_playback_obj (r->new_bitfield (playback_location (r, m_loc), + m_type->playback_type (), + m_width, + playback_string (m_name))); +} + +/* Override the default implementation of + recording::memento::write_to_dump. Dump each bit field + by dumping a line of the form: + TYPE NAME:WIDTH; + so that we can build up a struct/union field by field. */ + +void +recording::bitfield::write_to_dump (dump &d) +{ + d.write (" %s %s:%d;\n", + m_type->get_debug_string (), + m_name->c_str (), + m_width); +} + +/* Implementation of recording::memento::make_debug_string for + results of new_bitfield. */ + +recording::string * +recording::bitfield::make_debug_string () +{ + return string::from_printf (m_ctxt, + "%s:%d", + m_name->c_str (), m_width); +} + +/* Implementation of recording::memento::write_reproducer for bitfields. */ + +void +recording::bitfield::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "bitfield"); + r.write (" gcc_jit_field *%s =\n" + " gcc_jit_context_new_bitfield (%s,\n" + " %s, /* gcc_jit_location *loc */\n" + " %s, /* gcc_jit_type *type, */\n" + " %d, /* int width, */\n" + " %s); /* const char *name */\n", + id, + r.get_identifier (get_context ()), + r.get_identifier (m_loc), + r.get_identifier_as_type (m_type), + m_width, + m_name->get_debug_string ()); +} + /* The implementation of class gcc::jit::recording::compound_type */ /* The constructor for gcc::jit::recording::compound_type. */ diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index b9f2250..13ec7ea 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -95,6 +95,12 @@ public: type *type, const char *name); + field * + new_bitfield (location *loc, + type *type, + int width, + const char *name); + struct_ * new_struct_type (location *loc, const char *name); @@ -822,9 +828,9 @@ public: compound_type * get_container () const { return m_container; } void set_container (compound_type *c) { m_container = c; } - void replay_into (replayer *) FINAL OVERRIDE; + void replay_into (replayer *) OVERRIDE; - void write_to_dump (dump &d) FINAL OVERRIDE; + void write_to_dump (dump &d) OVERRIDE; playback::field * playback_field () const @@ -833,16 +839,41 @@ public: } private: - string * make_debug_string () FINAL OVERRIDE; - void write_reproducer (reproducer &r) FINAL OVERRIDE; + string * make_debug_string () OVERRIDE; + void write_reproducer (reproducer &r) OVERRIDE; -private: +protected: location *m_loc; type *m_type; string *m_name; compound_type *m_container; }; + +class bitfield : public field +{ +public: + bitfield (context *ctxt, + location *loc, + type *type, + int width, + string *name) + : field (ctxt, loc, type, name), + m_width (width) + {} + + void replay_into (replayer *) FINAL OVERRIDE; + + void write_to_dump (dump &d) FINAL OVERRIDE; + +private: + string * make_debug_string () FINAL OVERRIDE; + void write_reproducer (reproducer &r) FINAL OVERRIDE; + +private: + int m_width; +}; + /* Base class for struct_ and union_ */ class compound_type : public type { diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index 55aebca..0c5be5a 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -152,6 +152,9 @@ namespace gccjit field new_field (type type_, const std::string &name, location loc = location ()); + field new_bitfield (type type_, int width, const std::string &name, + location loc = location ()); + struct_ new_struct_type (const std::string &name, std::vector &fields, location loc = location ()); @@ -757,6 +760,17 @@ context::new_field (type type_, const std::string &name, location loc) name.c_str ())); } +inline field +context::new_bitfield (type type_, int width, const std::string &name, + location loc) +{ + return field (gcc_jit_context_new_bitfield (m_inner_ctxt, + loc.get_inner_location (), + type_.get_inner_type (), + width, + name.c_str ())); +} + inline struct_ context::new_struct_type (const std::string &name, std::vector &fields, diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index e4f17f8..abf7019 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -62,6 +62,10 @@ struct gcc_jit_field : public gcc::jit::recording::field { }; +struct gcc_jit_bitfield : public gcc::jit::recording::bitfield +{ +}; + struct gcc_jit_function : public gcc::jit::recording::function { }; @@ -556,6 +560,42 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt, /* Public entrypoint. See description in libgccjit.h. + After error-checking, the real work is done by the + gcc::jit::recording::context::new_bitfield method, in + jit-recording.c. */ + +gcc_jit_field * +gcc_jit_context_new_bitfield (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_type *type, + int width, + const char *name) +{ + RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + JIT_LOG_FUNC (ctxt->get_logger ()); + /* LOC can be NULL. */ + RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name"); + RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type"); + RETURN_NULL_IF_FAIL_PRINTF2 (type->is_int () || type->is_bool (), + ctxt, loc, + "bit-field %s has non integral type %s", + name, type->get_debug_string ()); + RETURN_NULL_IF_FAIL_PRINTF2 ( + width > 0, ctxt, loc, + "invalid width %d for bitfield \"%s\" (must be > 0)", + width, name); + RETURN_NULL_IF_FAIL_PRINTF2 ( + type->has_known_size (), + ctxt, loc, + "unknown size for field \"%s\" (type: %s)", + name, + type->get_debug_string ()); + + return (gcc_jit_field *)ctxt->new_bitfield (loc, type, width, name); +} + +/* Public entrypoint. See description in libgccjit.h. + After error-checking, this calls the trivial gcc::jit::recording::memento::as_object method (a field is a memento), in jit-recording.h. */ diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index beeb747..9c5f23b 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -602,6 +602,21 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt, gcc_jit_type *type, const char *name); +#define LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield + +/* Create a bit field, for use within a struct or union. + + This API entrypoint was added in LIBGCCJIT_ABI_12; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield +*/ +extern gcc_jit_field * +gcc_jit_context_new_bitfield (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_type *type, + int width, + const char *name); + /* Upcasting from field to object. */ extern gcc_jit_object * gcc_jit_field_as_object (gcc_jit_field *field); diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 16f5253..40e1c78 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -174,4 +174,9 @@ LIBGCCJIT_ABI_10 { LIBGCCJIT_ABI_11 { global: gcc_jit_context_add_driver_option; -} LIBGCCJIT_ABI_10; \ No newline at end of file +} LIBGCCJIT_ABI_10; + +LIBGCCJIT_ABI_12 { + global: + gcc_jit_context_new_bitfield; +} LIBGCCJIT_ABI_11; \ No newline at end of file diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a89a218..e7db610 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2019-07-04 Andrea Corallo + + * jit.dg/all-non-failing-tests.h: Add test-accessing-bitfield.c. + * jit.dg/test-accessing-bitfield.c: New testcase. + * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c: + Likewise. + * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c: + Likewise. + * jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c: + Likewise. + 2019-07-04 Jan Hubicka * gcc.dg/tree-ssa/alias-access-path-3.c: New testcase. @@ -122,7 +133,7 @@ PR tree-optimization/91033 * gcc.target/i386/pr91033.c: New test. - + 2019-07-03 Bob Duff * gnat.dg/task2.adb, gnat.dg/task2_pkg.adb, diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 9a10418..0272e6f8 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -8,6 +8,13 @@ hooks provided by each test case. */ #define COMBINED_TEST +/* test-accessing-bitfield.c */ +#define create_code create_code_accessing_bitfield +#define verify_code verify_code_accessing_bitfield +#include "test-accessing-bitfield.c" +#undef create_code +#undef verify_code + /* test-accessing-struct.c */ #define create_code create_code_accessing_struct #define verify_code verify_code_accessing_struct @@ -266,6 +273,9 @@ struct testcase }; const struct testcase testcases[] = { + {"accessing_bitfield", + create_code_accessing_bitfield, + verify_code_accessing_bitfield}, {"accessing_struct", create_code_accessing_struct, verify_code_accessing_struct}, diff --git a/gcc/testsuite/jit.dg/test-accessing-bitfield.c b/gcc/testsuite/jit.dg/test-accessing-bitfield.c new file mode 100644 index 0000000..5e80351 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-accessing-bitfield.c @@ -0,0 +1,130 @@ +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +struct bit_foo +{ + int i:3; + int x:5; + int y:5; + int z:10; + int j:3; +}; + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + void + test_bitfield_access (struct bit_foo *f) + { + f->z = f->x + f->y; + } + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_field *i = + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 3, + "i"); + gcc_jit_field *x = + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 5, + "x"); + gcc_jit_field *y = + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 5, + "y"); + gcc_jit_field *z = + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 10, + "z"); + gcc_jit_field *j = + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 3, + "j"); + gcc_jit_field *fields[] = {i, x, y, z, j}; + gcc_jit_struct *struct_type = + gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 5, fields); + gcc_jit_type *ptr_type = + gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type)); + + /* Build the test function. */ + gcc_jit_param *param_f = + gcc_jit_context_new_param (ctxt, NULL, ptr_type, "f"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_bitfield_access", + 1, ¶m_f, + 0); + + /* f->x + f->y */ + gcc_jit_rvalue *sum = + gcc_jit_context_new_binary_op ( + ctxt, NULL, + GCC_JIT_BINARY_OP_PLUS, + int_type, + gcc_jit_lvalue_as_rvalue ( + gcc_jit_rvalue_dereference_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + x)), + gcc_jit_lvalue_as_rvalue ( + gcc_jit_rvalue_dereference_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + y))); + + /* f->z = ... */ + gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); + gcc_jit_block_add_assignment ( + block, + NULL, + gcc_jit_rvalue_dereference_field ( + gcc_jit_param_as_rvalue (param_f), + NULL, + z), + sum); + gcc_jit_block_end_with_void_return (block, NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef void (*fn_type) (struct bit_foo *); + CHECK_NON_NULL (result); + + fn_type test_bitfield_access = + (fn_type)gcc_jit_result_get_code (result, "test_bitfield_access"); + CHECK_NON_NULL (test_bitfield_access); + + struct bit_foo tmp; + tmp.i = 3; + tmp.x = 5; + tmp.y = 7; + tmp.z = 0; + tmp.j = 3; + + /* Call the JIT-generated function. */ + test_bitfield_access (&tmp); + + /* Verify that the code correctly modified the field "z". */ + CHECK_VALUE (tmp.z, 12); +} diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c new file mode 100644 index 0000000..d2ef5a8 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c @@ -0,0 +1,53 @@ +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +/* Try to declare a bit-field with invalid type. */ + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + gcc_jit_type *bool_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL); + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *long_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG); + gcc_jit_type *float_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT); + + gcc_jit_context_new_bitfield (ctxt, + NULL, + bool_type, + 3, + "b"); + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 3, + "i"); + gcc_jit_context_new_bitfield (ctxt, + NULL, + long_type, + 3, + "l"); + gcc_jit_context_new_bitfield (ctxt, + NULL, + float_type, + 5, + "f"); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + + /* Verify that the correct error message was emitted. */ + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + "gcc_jit_context_new_bitfield: bit-field f has non " + "integral type float"); +} diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c new file mode 100644 index 0000000..67db120 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c @@ -0,0 +1,44 @@ +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +/* Try to declare a bit-field with invalid width. */ + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + gcc_jit_type *short_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SHORT); + gcc_jit_field *i = + gcc_jit_context_new_bitfield (ctxt, + NULL, + short_type, + 3, + "i"); + gcc_jit_field *j = + gcc_jit_context_new_bitfield (ctxt, + NULL, + short_type, + 157, + "j"); + gcc_jit_field *fields[] = {i, j}; + gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 2, fields); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + char error_str[256]; + snprintf (error_str, sizeof (error_str), + "width of bit-field j (width: 157) is wider than its type " + "(width: %zu)", 8 * sizeof (short)); + + /* Verify that the correct error message was emitted. */ + + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + error_str); +} diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c new file mode 100644 index 0000000..f102a6a --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c @@ -0,0 +1,66 @@ +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +/* Try to dereference a bit-field. */ + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + + struct bit_foo + { + int i:3; + int j:3; + }; + + struct bit_foo f; + &(f.j) + */ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_field *i = + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 3, + "i"); + gcc_jit_field *j = + gcc_jit_context_new_bitfield (ctxt, + NULL, + int_type, + 3, + "j"); + gcc_jit_field *fields[] = {i, j}; + gcc_jit_type *struct_type = + gcc_jit_struct_as_type ( + gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 2, fields)); + + gcc_jit_lvalue *f_struct = + gcc_jit_context_new_global (ctxt, + NULL, + GCC_JIT_GLOBAL_INTERNAL, + struct_type, + "f"); + + gcc_jit_lvalue_get_address ( + gcc_jit_lvalue_access_field ( + f_struct, + NULL, + j), + NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + + /* Verify that the correct error message was emitted. */ + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + "cannot take address of bit-field"); +} -- cgit v1.1 From c80ab4a34c3c3761a91459755e9f632f64c99259 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 4 Jul 2019 17:59:19 +0200 Subject: Support __builtin_expect_with_probability for analysis of # of loop iterations. 2019-07-04 Martin Liska * tree-ssa-loop-niter.c (get_upper_bound_based_on_builtin_expr_with_prob): New function. (estimate_numbers_of_iterations): Support __builtin_expect_with_probability for analysis of # of loop iterations. From-SVN: r273087 --- gcc/ChangeLog | 8 ++++++ gcc/tree-ssa-loop-niter.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41b8b14..d4e9991 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-04 Martin Liska + + * tree-ssa-loop-niter.c (get_upper_bound_based_on_builtin_expr_with_prob): + New function. + (estimate_numbers_of_iterations): + Support __builtin_expect_with_probability for analysis + of # of loop iterations. + 2019-07-04 Alexandre Oliva * doc/generic.texi (Cleanups): Document EH_ELSE_EXPR. diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index f513859..5e75a41 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -4183,6 +4183,55 @@ maybe_lower_iteration_bound (struct loop *loop) delete not_executed_last_iteration; } +/* Get expected upper bound for number of loop iterations for + BUILT_IN_EXPECT_WITH_PROBABILITY for a condition COND. */ + +static tree +get_upper_bound_based_on_builtin_expr_with_prob (gcond *cond) +{ + if (cond == NULL) + return NULL_TREE; + + tree lhs = gimple_cond_lhs (cond); + if (TREE_CODE (lhs) != SSA_NAME) + return NULL_TREE; + + gimple *stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (cond)); + gcall *def = dyn_cast (stmt); + if (def == NULL) + return NULL_TREE; + + tree decl = gimple_call_fndecl (def); + if (!decl + || !fndecl_built_in_p (decl, BUILT_IN_EXPECT_WITH_PROBABILITY) + || gimple_call_num_args (stmt) != 3) + return NULL_TREE; + + tree c = gimple_call_arg (def, 1); + tree condt = TREE_TYPE (lhs); + tree res = fold_build2 (gimple_cond_code (cond), + condt, c, + gimple_cond_rhs (cond)); + if (TREE_CODE (res) != INTEGER_CST) + return NULL_TREE; + + + tree prob = gimple_call_arg (def, 2); + tree t = TREE_TYPE (prob); + tree one + = build_real_from_int_cst (t, + integer_one_node); + if (integer_zerop (res)) + prob = fold_build2 (MINUS_EXPR, t, one, prob); + tree r = fold_build2 (RDIV_EXPR, t, one, prob); + if (TREE_CODE (r) != REAL_CST) + return NULL_TREE; + + HOST_WIDE_INT probi + = real_to_integer (TREE_REAL_CST_PTR (r)); + return build_int_cst (condt, probi); +} + /* Records estimates on numbers of iterations of LOOP. If USE_UNDEFINED_P is true also use estimates derived from undefined behavior. */ @@ -4231,6 +4280,23 @@ estimate_numbers_of_iterations (struct loop *loop) likely_exit = single_likely_exit (loop); FOR_EACH_VEC_ELT (exits, i, ex) { + if (ex == likely_exit) + { + gimple *stmt = last_stmt (ex->src); + if (stmt != NULL) + { + gcond *cond = dyn_cast (stmt); + tree niter_bound + = get_upper_bound_based_on_builtin_expr_with_prob (cond); + if (niter_bound != NULL_TREE) + { + widest_int max = derive_constant_upper_bound (niter_bound); + record_estimate (loop, niter_bound, max, cond, + true, true, false); + } + } + } + if (!number_of_iterations_exit (loop, ex, &niter_desc, false, false)) continue; -- cgit v1.1 From e2c3bbbf905a8010729d35df8eda2792755107c4 Mon Sep 17 00:00:00 2001 From: Wilco Dijkstra Date: Thu, 4 Jul 2019 16:00:26 +0000 Subject: Fix arm XFAIL in cunroll-15.c Remove the XFAIL on arm in cunroll-15.c since the test passes on trunk. Committed as obvious. testsuite/ * gcc.dg/tree-ssa/cunroll-15.c: Remove XFAIL on arm. From-SVN: r273088 --- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/tree-ssa/cunroll-15.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e7db610..77949d9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-04 Wilco Dijkstra + + * gcc.dg/tree-ssa/cunroll-15.c: Remove XFAIL on arm. + 2019-07-04 Andrea Corallo * jit.dg/all-non-failing-tests.h: Add test-accessing-bitfield.c. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-15.c b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-15.c index 55cdcff..a681450 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-15.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-15.c @@ -20,4 +20,4 @@ int Test(void) /* When SLP vectorization is enabled the following will fail because DOM doesn't know how to deal with the vectorized initializer of in. */ /* DOM also doesn't know to CSE in[1] with in = *.LC0 thus the list of targets this fails. */ -/* { dg-final { scan-tree-dump "return 1;" "optimized" { xfail { arm*-*-* powerpc-*-* } } } } */ +/* { dg-final { scan-tree-dump "return 1;" "optimized" { xfail { powerpc-*-* } } } } */ -- cgit v1.1 From 2b442504a0a4073992da8985ebcf1998ef4aff5e Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Thu, 4 Jul 2019 16:25:06 +0000 Subject: jit: gcc_jit_context_new_binary_op check res type gcc/jit/ChangeLog: 2019-07-04 Andrea Corallo * libgccjit.c (gcc_jit_context_new_binary_op): Check result_type to be a numeric type. gcc/testsuite/ChangeLog: 2019-07-04 Andrea Corallo * jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c: New testcase. From-SVN: r273089 --- gcc/jit/ChangeLog | 5 +++ gcc/jit/libgccjit.c | 6 ++++ gcc/testsuite/ChangeLog | 5 +++ ...or-gcc_jit_context_new_binary_op-bad-res-type.c | 41 ++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c (limited to 'gcc') diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 8323e2f..41cb60f 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,5 +1,10 @@ 2019-07-04 Andrea Corallo + * libgccjit.c (gcc_jit_context_new_binary_op): Check result_type to be a + numeric type. + +2019-07-04 Andrea Corallo + * docs/topics/compatibility.rst (LIBGCCJIT_ABI_12): New ABI tag. * docs/topics/types.rst: Add gcc_jit_context_new_bitfield. * jit-common.h (namespace recording): Add class bitfield. diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index abf7019..23e83e2 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -1385,6 +1385,12 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, a->get_type ()->get_debug_string (), b->get_debug_string (), b->get_type ()->get_debug_string ()); + RETURN_NULL_IF_FAIL_PRINTF4 ( + result_type->is_numeric (), ctxt, loc, + "gcc_jit_binary_op %i with operands a: %s b: %s " + "has non numeric result_type: %s", + op, a->get_debug_string (), b->get_debug_string (), + result_type->get_debug_string ()); return (gcc_jit_rvalue *)ctxt->new_binary_op (loc, op, result_type, a, b); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 77949d9..73847a9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Andrea Corallo + + * jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c: + New testcase. + 2019-07-04 Wilco Dijkstra * gcc.dg/tree-ssa/cunroll-15.c: Remove XFAIL on arm. diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c new file mode 100644 index 0000000..abadc9f --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c @@ -0,0 +1,41 @@ +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +/* Try to create a binary operator with invalid result type. */ + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *void_ptr_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR); + + gcc_jit_context_new_binary_op ( + ctxt, + NULL, + GCC_JIT_BINARY_OP_MINUS, + void_ptr_type, + gcc_jit_context_new_rvalue_from_int (ctxt, + int_type, + 1), + gcc_jit_context_new_rvalue_from_int (ctxt, + int_type, + 2)); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + + /* Verify that the correct error message was emitted. */ + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + "gcc_jit_context_new_binary_op: gcc_jit_binary_op 1 with" + " operands a: (int)1 b: (int)2 has non numeric " + "result_type: void *"); +} -- cgit v1.1 From 532bb2f908e6a14eda50ebd4debda9d063e4f8e7 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 4 Jul 2019 18:30:53 +0200 Subject: tree-ssa-alias.c (nonoverlapping_component_refs_since_match_p): Fix check for match in the ref walk. * tree-ssa-alias.c (nonoverlapping_component_refs_since_match_p): Fix check for match in the ref walk. From-SVN: r273090 --- gcc/ChangeLog | 5 +++++ gcc/tree-ssa-alias.c | 8 ++------ 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d4e9991..3517011 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Jan Hubicka + + * tree-ssa-alias.c (nonoverlapping_component_refs_since_match_p): + Fix check for match in the ref walk. + 2019-07-04 Martin Liska * tree-ssa-loop-niter.c (get_upper_bound_based_on_builtin_expr_with_prob): diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index d76656e..5c5cbe4 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1153,15 +1153,13 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, auto_vec component_refs2; /* Create the stack of handled components for REF1. */ - while (handled_component_p (ref1)) + while (handled_component_p (ref1) && ref1 != match1) { if (TREE_CODE (ref1) == VIEW_CONVERT_EXPR || TREE_CODE (ref1) == BIT_FIELD_REF) component_refs1.truncate (0); else component_refs1.safe_push (ref1); - if (ref1 == match1) - break; ref1 = TREE_OPERAND (ref1, 0); } if (TREE_CODE (ref1) == MEM_REF && ref1 != match1) @@ -1180,15 +1178,13 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, } /* Create the stack of handled components for REF2. */ - while (handled_component_p (ref2)) + while (handled_component_p (ref2) && ref2 != match2) { if (TREE_CODE (ref2) == VIEW_CONVERT_EXPR || TREE_CODE (ref2) == BIT_FIELD_REF) component_refs2.truncate (0); else component_refs2.safe_push (ref2); - if (ref2 == match2) - break; ref2 = TREE_OPERAND (ref2, 0); } if (TREE_CODE (ref2) == MEM_REF && ref2 != match2) -- cgit v1.1 From 2f03073ff24bbb005d52db7e2b7a5ea32bb01140 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Jul 2019 23:40:56 +0200 Subject: omp-expand.c (expand_omp_for_static_nochunk): Don't emit GOMP_loop_start at the start of second worksharing loop in a scan. * omp-expand.c (expand_omp_for_static_nochunk): Don't emit GOMP_loop_start at the start of second worksharing loop in a scan. For nowait, don't emit GOMP_loop_end_nowait at the end of first worksharing loop in a scan even if there are conditional lastprivates, and do emit GOMP_loop_end_nowait at the end of second worksharing loop. * testsuite/libgomp.c/scan-9.c: New test. * testsuite/libgomp.c/scan-10.c: New test. From-SVN: r273095 --- gcc/ChangeLog | 8 ++++++++ gcc/omp-expand.c | 7 +++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3517011..c51ba75 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-04 Jakub Jelinek + + * omp-expand.c (expand_omp_for_static_nochunk): Don't emit + GOMP_loop_start at the start of second worksharing loop in a scan. + For nowait, don't emit GOMP_loop_end_nowait at the end of first + worksharing loop in a scan even if there are conditional lastprivates, + and do emit GOMP_loop_end_nowait at the end of second worksharing loop. + 2019-07-04 Jan Hubicka * tree-ssa-alias.c (nonoverlapping_component_refs_since_match_p): diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c index 9236b36..1de445b 100644 --- a/gcc/omp-expand.c +++ b/gcc/omp-expand.c @@ -3744,7 +3744,9 @@ expand_omp_for_static_nochunk (struct omp_region *region, cond_var = OMP_CLAUSE_DECL (c); } if (fd->have_reductemp - || fd->have_pointer_condtemp + /* For scan, we don't want to reinitialize condtemp before the + second loop. */ + || (fd->have_pointer_condtemp && !fd->have_scantemp) || fd->have_nonctrl_scantemp) { tree t1 = build_int_cst (long_integer_type_node, 0); @@ -4235,7 +4237,8 @@ expand_omp_for_static_nochunk (struct omp_region *region, else gsi_insert_after (&gsi, omp_build_barrier (t), GSI_SAME_STMT); } - else if (fd->have_pointer_condtemp) + else if ((fd->have_pointer_condtemp || fd->have_scantemp) + && !fd->have_nonctrl_scantemp) { tree fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT); gcall *g = gimple_build_call (fn, 0); -- cgit v1.1 From ec03bc90e5bdb772e2f19ec352fc4b2e985e4c91 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 4 Jul 2019 23:41:49 +0200 Subject: re PR middle-end/78884 ([7/8] ICE when gimplifying VLA in OpenMP SIMD region) PR middle-end/78884 * gimplify.c (struct gimplify_omp_ctx): Add add_safelen1 member. (gimplify_bind_expr): If seeing TREE_ADDRESSABLE VLA inside of simd loop body, set ctx->add_safelen1 instead of making it GOVD_PRIVATE. (gimplify_adjust_omp_clauses): Add safelen (1) clause if ctx->add_safelen1 is set. * gcc.dg/gomp/pr78884.c: New test. From-SVN: r273096 --- gcc/ChangeLog | 7 +++++++ gcc/gimplify.c | 24 +++++++++++++++++++++--- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/gomp/pr78884.c | 16 ++++++++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/gomp/pr78884.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c51ba75..5145487 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2019-07-04 Jakub Jelinek + PR middle-end/78884 + * gimplify.c (struct gimplify_omp_ctx): Add add_safelen1 member. + (gimplify_bind_expr): If seeing TREE_ADDRESSABLE VLA inside of simd + loop body, set ctx->add_safelen1 instead of making it GOVD_PRIVATE. + (gimplify_adjust_omp_clauses): Add safelen (1) clause if + ctx->add_safelen1 is set. + * omp-expand.c (expand_omp_for_static_nochunk): Don't emit GOMP_loop_start at the start of second worksharing loop in a scan. For nowait, don't emit GOMP_loop_end_nowait at the end of first diff --git a/gcc/gimplify.c b/gcc/gimplify.c index a3792d1..239988b 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -221,6 +221,7 @@ struct gimplify_omp_ctx bool combined_loop; bool distribute; bool target_firstprivatize_array_bases; + bool add_safelen1; int defaultmap[4]; }; @@ -1331,12 +1332,17 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) || splay_tree_lookup (ctx->variables, (splay_tree_key) t) == NULL) { + int flag = GOVD_LOCAL; if (ctx->region_type == ORT_SIMD && TREE_ADDRESSABLE (t) && !TREE_STATIC (t)) - omp_add_variable (ctx, t, GOVD_PRIVATE | GOVD_SEEN); - else - omp_add_variable (ctx, t, GOVD_LOCAL | GOVD_SEEN); + { + if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST) + ctx->add_safelen1 = true; + else + flag = GOVD_PRIVATE; + } + omp_add_variable (ctx, t, flag | GOVD_SEEN); } /* Static locals inside of target construct or offloaded routines need to be "omp declare target". */ @@ -9801,6 +9807,18 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, } } + if (ctx->add_safelen1) + { + /* If there are VLAs in the body of simd loop, prevent + vectorization. */ + gcc_assert (ctx->region_type == ORT_SIMD); + c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN); + OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node; + OMP_CLAUSE_CHAIN (c) = *list_p; + *list_p = c; + list_p = &OMP_CLAUSE_CHAIN (c); + } + if (ctx->region_type == ORT_WORKSHARE && ctx->outer_context && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 73847a9..30b2d1f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-04 Jakub Jelinek + + PR middle-end/78884 + * gcc.dg/gomp/pr78884.c: New test. + 2019-07-04 Andrea Corallo * jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c: diff --git a/gcc/testsuite/gcc.dg/gomp/pr78884.c b/gcc/testsuite/gcc.dg/gomp/pr78884.c new file mode 100644 index 0000000..3e03df5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr78884.c @@ -0,0 +1,16 @@ +/* PR middle-end/78884 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fopenmp" } */ + +void bar (int *); + +void +foo (int n) +{ +#pragma omp simd + for (int i = 0; i < 1024; i++) + { + int vla[n]; + bar (vla); + } +} -- cgit v1.1 From 0f146681aec81cb862049765619f7102a9c2ecf5 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 5 Jul 2019 00:16:23 +0000 Subject: Daily bump. From-SVN: r273100 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c881b7b..3b646d6 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190704 +20190705 -- cgit v1.1 From 9328056ba3cbc5cddef1d7ef6b57ae97bbefb808 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Fri, 5 Jul 2019 07:01:40 +0000 Subject: [Ada] GNAT.Traceback: add a Call_Chain function 2019-07-05 Dmitriy Anisimkov gcc/ada/ * libgnat/g-traceb.ads, libgnat/g-traceb.adb (Call_Chain): New function. From-SVN: r273101 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/libgnat/g-traceb.adb | 14 ++++++++++++-- gcc/ada/libgnat/g-traceb.ads | 9 +++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index bc6f2e0..aac81ea 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Dmitriy Anisimkov + + * libgnat/g-traceb.ads, libgnat/g-traceb.adb (Call_Chain): New + function. + 2019-07-04 James Clarke * libgnarl/s-osinte__kfreebsd-gnu.ads (clockid_t): Make type diff --git a/gcc/ada/libgnat/g-traceb.adb b/gcc/ada/libgnat/g-traceb.adb index cc52e57..f40d84e 100644 --- a/gcc/ada/libgnat/g-traceb.adb +++ b/gcc/ada/libgnat/g-traceb.adb @@ -41,10 +41,20 @@ package body GNAT.Traceback is procedure Call_Chain (Traceback : out Tracebacks_Array; - Len : out Natural) - is + Len : out Natural) is begin System.Traceback.Call_Chain (Traceback, Traceback'Length, Len); end Call_Chain; + function Call_Chain + (Max_Len : Positive; Skip_Frames : Natural := 1) return Tracebacks_Array + is + Traceback : Tracebacks_Array (1 .. Max_Len); + Len : Natural; + begin + System.Traceback.Call_Chain + (Traceback, Max_Len, Len, Skip_Frames => Skip_Frames + 1); + return Traceback (1 .. Len); + end Call_Chain; + end GNAT.Traceback; diff --git a/gcc/ada/libgnat/g-traceb.ads b/gcc/ada/libgnat/g-traceb.ads index aeb3b0a..bdd46b2 100644 --- a/gcc/ada/libgnat/g-traceb.ads +++ b/gcc/ada/libgnat/g-traceb.ads @@ -98,4 +98,13 @@ package GNAT.Traceback is -- shorter, in which case positions in Traceback past the Len position -- are undefined on return. + function Call_Chain + (Max_Len : Positive; Skip_Frames : Natural := 1) return Tracebacks_Array; + -- Returns up to Max_Len tracebacks corresponding to the current call + -- chain. Result array order is the same as in above procedure Call_Chain + -- except that Skip_Frames says how many of the most recent calls should be + -- excluded from the result, starting with this procedure itself: 1 means + -- exclude the frame for this procedure, 2 means 1 + exclude the frame for + -- this procedure's caller, ... + end GNAT.Traceback; -- cgit v1.1 From 584b52902b4b1bbcabc0e5bdd4196bd223d2f5a8 Mon Sep 17 00:00:00 2001 From: Claire Dross Date: Fri, 5 Jul 2019 07:01:45 +0000 Subject: [Ada] Ada.Containers.Formal_Vectors: make vectors always bounded 2019-07-05 Claire Dross gcc/ada/ * libgnat/a-cofove.ads, libgnat/a-cofove.adb: Definite formal vectors are now always bounded so that they do not need to be limited anymore. From-SVN: r273102 --- gcc/ada/ChangeLog | 6 ++ gcc/ada/libgnat/a-cofove.adb | 183 +++++++------------------------------------ gcc/ada/libgnat/a-cofove.ads | 59 +++----------- 3 files changed, 44 insertions(+), 204 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index aac81ea..42fa71b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-05 Claire Dross + + * libgnat/a-cofove.ads, libgnat/a-cofove.adb: Definite formal + vectors are now always bounded so that they do not need to be + limited anymore. + 2019-07-05 Dmitriy Anisimkov * libgnat/g-traceb.ads, libgnat/g-traceb.adb (Call_Chain): New diff --git a/gcc/ada/libgnat/a-cofove.adb b/gcc/ada/libgnat/a-cofove.adb index f9675ab..c848ad8 100644 --- a/gcc/ada/libgnat/a-cofove.adb +++ b/gcc/ada/libgnat/a-cofove.adb @@ -26,7 +26,6 @@ ------------------------------------------------------------------------------ with Ada.Containers.Generic_Array_Sort; -with Ada.Unchecked_Deallocation; with System; use type System.Address; @@ -34,41 +33,10 @@ package body Ada.Containers.Formal_Vectors with SPARK_Mode => Off is - Growth_Factor : constant := 2; - -- When growing a container, multiply current capacity by this. Doubling - -- leads to amortized linear-time copying. - type Int is range System.Min_Int .. System.Max_Int; - procedure Free is - new Ada.Unchecked_Deallocation (Elements_Array, Elements_Array_Ptr); - - type Maximal_Array_Ptr is access all Elements_Array (Array_Index) - with Storage_Size => 0; - type Maximal_Array_Ptr_Const is access constant Elements_Array (Array_Index) - with Storage_Size => 0; - - function Elems (Container : in out Vector) return Maximal_Array_Ptr; - function Elemsc - (Container : Vector) return Maximal_Array_Ptr_Const; - -- Returns a pointer to the Elements array currently in use -- either - -- Container.Elements_Ptr or a pointer to Container.Elements. We work with - -- pointers to a bogus array subtype that is constrained with the maximum - -- possible bounds. This means that the pointer is a thin pointer. This is - -- necessary because 'Unrestricted_Access doesn't work when it produces - -- access-to-unconstrained and is returned from a function. - -- - -- Note that this is dangerous: make sure calls to this use an indexed - -- component or slice that is within the bounds 1 .. Length (Container). - - function Get_Element - (Container : Vector; - Position : Capacity_Range) return Element_Type; - function To_Array_Index (Index : Index_Type'Base) return Count_Type'Base; - function Current_Capacity (Container : Vector) return Capacity_Range; - procedure Insert_Space (Container : in out Vector; Before : Extended_Index; @@ -89,7 +57,7 @@ is end if; for J in 1 .. Length (Left) loop - if Get_Element (Left, J) /= Get_Element (Right, J) then + if Left.Elements (J) /= Right.Elements (J) then return False; end if; end loop; @@ -148,7 +116,7 @@ is return; end if; - if Bounded and then Target.Capacity < LS then + if Target.Capacity < LS then raise Constraint_Error; end if; @@ -162,11 +130,7 @@ is function Capacity (Container : Vector) return Capacity_Range is begin - return - (if Bounded then - Container.Capacity - else - Capacity_Range'Last); + return Container.Capacity; end Capacity; ----------- @@ -176,10 +140,6 @@ is procedure Clear (Container : in out Vector) is begin Container.Last := No_Index; - - -- Free element, note that this is OK if Elements_Ptr is null - - Free (Container.Elements_Ptr); end Clear; -------------- @@ -215,24 +175,11 @@ is end if; return Target : Vector (C) do - Elems (Target) (1 .. LS) := Elemsc (Source) (1 .. LS); + Target.Elements (1 .. LS) := Source.Elements (1 .. LS); Target.Last := Source.Last; end return; end Copy; - ---------------------- - -- Current_Capacity -- - ---------------------- - - function Current_Capacity (Container : Vector) return Capacity_Range is - begin - return - (if Container.Elements_Ptr = null then - Container.Elements'Length - else - Container.Elements_Ptr.all'Length); - end Current_Capacity; - ------------ -- Delete -- ------------ @@ -333,7 +280,7 @@ is -- so we just slide down to Index the elements that weren't deleted. declare - EA : Maximal_Array_Ptr renames Elems (Container); + EA : Elements_Array renames Container.Elements; Idx : constant Count_Type := EA'First + Off; begin EA (Idx .. Old_Len - Count) := EA (Idx + Count .. Old_Len); @@ -418,32 +365,10 @@ is II : constant Int'Base := Int (Index) - Int (No_Index); I : constant Capacity_Range := Capacity_Range (II); begin - return Get_Element (Container, I); + return Container.Elements (I); end; end Element; - ----------- - -- Elems -- - ----------- - - function Elems (Container : in out Vector) return Maximal_Array_Ptr is - begin - return - (if Container.Elements_Ptr = null then - Container.Elements'Unrestricted_Access - else - Container.Elements_Ptr.all'Unrestricted_Access); - end Elems; - - function Elemsc (Container : Vector) return Maximal_Array_Ptr_Const is - begin - return - (if Container.Elements_Ptr = null then - Container.Elements'Unrestricted_Access - else - Container.Elements_Ptr.all'Unrestricted_Access); - end Elemsc; - ---------------- -- Find_Index -- ---------------- @@ -459,7 +384,7 @@ is begin K := Capacity_Range (Int (Index) - Int (No_Index)); for Indx in Index .. Last loop - if Get_Element (Container, K) = Item then + if Container.Elements (K) = Item then return Indx; end if; @@ -478,7 +403,7 @@ is if Is_Empty (Container) then raise Constraint_Error with "Container is empty"; else - return Get_Element (Container, 1); + return Container.Elements (1); end if; end First_Element; @@ -622,7 +547,7 @@ is begin for Position in 1 .. Length (Container) loop - R := M.Add (R, Elemsc (Container) (Position)); + R := M.Add (R, Container.Elements (Position)); end loop; return R; @@ -684,8 +609,8 @@ is begin for J in 1 .. L - 1 loop - if Get_Element (Container, J + 1) < - Get_Element (Container, J) + if Container.Elements (J + 1) < + Container.Elements (J) then return False; end if; @@ -712,7 +637,7 @@ is if Container.Last <= Index_Type'First then return; else - Sort (Elems (Container) (1 .. Len)); + Sort (Container.Elements (1 .. Len)); end if; end Sort; @@ -744,16 +669,6 @@ is New_Length : constant Count_Type := I + Length (Source); begin - if not Bounded - and then Current_Capacity (Target) < Capacity_Range (New_Length) - then - Reserve_Capacity - (Target, - Capacity_Range'Max - (Current_Capacity (Target) * Growth_Factor, - Capacity_Range (New_Length))); - end if; - if Index_Type'Base'Last >= Count_Type'Pos (Count_Type'Last) then Target.Last := No_Index + Index_Type'Base (New_Length); @@ -764,8 +679,8 @@ is end; declare - TA : Maximal_Array_Ptr renames Elems (Target); - SA : Maximal_Array_Ptr renames Elems (Source); + TA : Elements_Array renames Target.Elements; + SA : Elements_Array renames Source.Elements; begin J := Length (Target); @@ -793,18 +708,6 @@ is end Generic_Sorting; ----------------- - -- Get_Element -- - ----------------- - - function Get_Element - (Container : Vector; - Position : Capacity_Range) return Element_Type - is - begin - return Elemsc (Container) (Position); - end Get_Element; - - ----------------- -- Has_Element -- ----------------- @@ -844,7 +747,7 @@ is J := To_Array_Index (Before); - Elems (Container) (J .. J - 1 + Count) := (others => New_Item); + Container.Elements (J .. J - 1 + Count) := (others => New_Item); end Insert; procedure Insert @@ -876,7 +779,7 @@ is B := To_Array_Index (Before); - Elems (Container) (B .. B + N - 1) := Elemsc (New_Item) (1 .. N); + Container.Elements (B .. B + N - 1) := New_Item.Elements (1 .. N); end Insert; ------------------ @@ -1053,19 +956,8 @@ is J := To_Array_Index (Before); - -- Increase the capacity of container if needed - - if not Bounded - and then Current_Capacity (Container) < Capacity_Range (New_Length) - then - Reserve_Capacity - (Container, - Capacity_Range'Max (Current_Capacity (Container) * Growth_Factor, - Capacity_Range (New_Length))); - end if; - declare - EA : Maximal_Array_Ptr renames Elems (Container); + EA : Elements_Array renames Container.Elements; begin if Before <= Container.Last then @@ -1105,7 +997,7 @@ is if Is_Empty (Container) then raise Constraint_Error with "Container is empty"; else - return Get_Element (Container, Length (Container)); + return Container.Elements (Length (Container)); end if; end Last_Element; @@ -1143,7 +1035,7 @@ is return; end if; - if Bounded and then Target.Capacity < LS then + if Target.Capacity < LS then raise Constraint_Error; end if; @@ -1194,7 +1086,7 @@ is I : constant Capacity_Range := Capacity_Range (II); begin - Elems (Container) (I) := New_Item; + Container.Elements (I) := New_Item; end; end Replace_Element; @@ -1207,24 +1099,8 @@ is Capacity : Capacity_Range) is begin - if Bounded then - if Capacity > Container.Capacity then - raise Constraint_Error with "Capacity is out of range"; - end if; - - else - if Capacity > Formal_Vectors.Current_Capacity (Container) then - declare - New_Elements : constant Elements_Array_Ptr := - new Elements_Array (1 .. Capacity); - L : constant Capacity_Range := Length (Container); - - begin - New_Elements (1 .. L) := Elemsc (Container) (1 .. L); - Free (Container.Elements_Ptr); - Container.Elements_Ptr := New_Elements; - end; - end if; + if Capacity > Container.Capacity then + raise Constraint_Error with "Capacity is out of range"; end if; end Reserve_Capacity; @@ -1241,7 +1117,7 @@ is declare I, J : Capacity_Range; E : Elements_Array renames - Elems (Container) (1 .. Length (Container)); + Container.Elements (1 .. Length (Container)); begin I := 1; @@ -1282,7 +1158,7 @@ is K := Capacity_Range (Int (Last) - Int (No_Index)); for Indx in reverse Index_Type'First .. Last loop - if Get_Element (Container, K) = Item then + if Container.Elements (K) = Item then return Indx; end if; @@ -1318,8 +1194,8 @@ is II : constant Int'Base := Int (I) - Int (No_Index); JJ : constant Int'Base := Int (J) - Int (No_Index); - EI : Element_Type renames Elems (Container) (Capacity_Range (II)); - EJ : Element_Type renames Elems (Container) (Capacity_Range (JJ)); + EI : Element_Type renames Container.Elements (Capacity_Range (II)); + EJ : Element_Type renames Container.Elements (Capacity_Range (JJ)); EI_Copy : constant Element_Type := EI; @@ -1388,10 +1264,9 @@ is Last := Index_Type (Last_As_Int); return - (Capacity => Length, - Last => Last, - Elements_Ptr => <>, - Elements => (others => New_Item)); + (Capacity => Length, + Last => Last, + Elements => (others => New_Item)); end; end To_Vector; diff --git a/gcc/ada/libgnat/a-cofove.ads b/gcc/ada/libgnat/a-cofove.ads index 635ef48..5b62664 100644 --- a/gcc/ada/libgnat/a-cofove.ads +++ b/gcc/ada/libgnat/a-cofove.ads @@ -40,12 +40,6 @@ with Ada.Containers.Functional_Vectors; generic type Index_Type is range <>; type Element_Type is private; - - Bounded : Boolean := True; - -- If True, the containers are bounded; the initial capacity is the maximum - -- size, and heap allocation will be avoided. If False, the containers can - -- grow via heap allocation. - package Ada.Containers.Formal_Vectors with SPARK_Mode is @@ -73,17 +67,8 @@ is subtype Capacity_Range is Count_Type range 0 .. Last_Count; - type Vector (Capacity : Capacity_Range) is limited private with + type Vector (Capacity : Capacity_Range) is private with Default_Initial_Condition => Is_Empty (Vector); - -- In the bounded case, Capacity is the capacity of the container, which - -- never changes. In the unbounded case, Capacity is the initial capacity - -- of the container, and operations such as Reserve_Capacity and Append can - -- increase the capacity. The capacity never shrinks, except in the case of - -- Clear. - -- - -- Note that all objects of type Vector are constrained, including in the - -- unbounded case; you can't assign from one object to another if the - -- Capacity is different. function Length (Container : Vector) return Capacity_Range with Global => null, @@ -220,11 +205,7 @@ is function Capacity (Container : Vector) return Capacity_Range with Global => null, Post => - Capacity'Result = - (if Bounded then - Container.Capacity - else - Capacity_Range'Last); + Capacity'Result = Container.Capacity; pragma Annotate (GNATprove, Inline_For_Proof, Capacity); procedure Reserve_Capacity @@ -232,7 +213,7 @@ is Capacity : Capacity_Range) with Global => null, - Pre => (if Bounded then Capacity <= Container.Capacity), + Pre => Capacity <= Container.Capacity, Post => Model (Container) = Model (Container)'Old; function Is_Empty (Container : Vector) return Boolean with @@ -242,13 +223,10 @@ is procedure Clear (Container : in out Vector) with Global => null, Post => Length (Container) = 0; - -- Note that this reclaims storage in the unbounded case. You need to call - -- this before a container goes out of scope in order to avoid storage - -- leaks. In addition, "X := ..." can leak unless you Clear(X) first. procedure Assign (Target : in out Vector; Source : Vector) with Global => null, - Pre => (if Bounded then Length (Source) <= Target.Capacity), + Pre => Length (Source) <= Target.Capacity, Post => Model (Target) = Model (Source); function Copy @@ -256,7 +234,7 @@ is Capacity : Capacity_Range := 0) return Vector with Global => null, - Pre => (if Bounded then (Capacity = 0 or Length (Source) <= Capacity)), + Pre => (Capacity = 0 or Length (Source) <= Capacity), Post => Model (Copy'Result) = Model (Source) and (if Capacity = 0 then @@ -267,7 +245,7 @@ is procedure Move (Target : in out Vector; Source : in out Vector) with Global => null, - Pre => (if Bounded then Length (Source) <= Capacity (Target)), + Pre => Length (Source) <= Capacity (Target), Post => Model (Target) = Model (Source)'Old and Length (Source) = 0; function Element @@ -894,30 +872,11 @@ private type Elements_Array is array (Array_Index range <>) of Element_Type; function "=" (L, R : Elements_Array) return Boolean is abstract; - type Elements_Array_Ptr is access all Elements_Array; - - type Vector (Capacity : Capacity_Range) is limited record - - -- In the bounded case, the elements are stored in Elements. In the - -- unbounded case, the elements are initially stored in Elements, until - -- we run out of room, then we switch to Elements_Ptr. - - Last : Extended_Index := No_Index; - Elements_Ptr : Elements_Array_Ptr := null; - Elements : aliased Elements_Array (1 .. Capacity); + type Vector (Capacity : Capacity_Range) is record + Last : Extended_Index := No_Index; + Elements : Elements_Array (1 .. Capacity); end record; - -- The primary reason Vector is limited is that in the unbounded case, once - -- Elements_Ptr is in use, assignment statements won't work. "X := Y;" will - -- cause X and Y to share state; that is, X.Elements_Ptr = Y.Elements_Ptr, - -- so for example "Append (X, ...);" will modify BOTH X and Y. That would - -- allow SPARK to "prove" things that are false. We could fix that by - -- making Vector a controlled type, and override Adjust to make a deep - -- copy, but finalization is not allowed in SPARK. - -- - -- Note that (unfortunately) this means that 'Old and 'Loop_Entry are not - -- allowed on Vectors. - function Empty_Vector return Vector is ((Capacity => 0, others => <>)); -- cgit v1.1 From 8e28429a9395c3c9ed58e4aaa7f6d8b32931f18e Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Fri, 5 Jul 2019 07:01:49 +0000 Subject: [Ada] No_Stream_Optimizations ignored for 'Class'Input This patch fixes a bug in which if pragma Restrictions (No_Stream_Optimizations) is in effect, it is ignored for T'Class'Input. Revision 251886 was causing the compiler to bypass No_Stream_Optimizations. 2019-07-05 Bob Duff gcc/ada/ * exp_attr.adb (Input): Take the No_Stream_Optimizations restriction into account. From-SVN: r273103 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_attr.adb | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 42fa71b..9f7ee9d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Bob Duff + + * exp_attr.adb (Input): Take the No_Stream_Optimizations + restriction into account. + 2019-07-05 Claire Dross * libgnat/a-cofove.ads, libgnat/a-cofove.adb: Definite formal diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 1e1b2f9..a4350ca 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -3997,11 +3997,13 @@ package body Exp_Attr is declare Rtyp : constant Entity_Id := Root_Type (P_Type); - Expr : Node_Id; + Get_Tag : Node_Id; -- expression to read the 'Tag + Expr : Node_Id; -- call to Descendant_Tag begin -- Read the internal tag (RM 13.13.2(34)) and use it to - -- initialize a dummy tag value. We used to generate: + -- initialize a dummy tag value. We used to unconditionally + -- generate: -- -- Descendant_Tag (String'Input (Strm), P_Type); -- @@ -4012,6 +4014,11 @@ package body Exp_Attr is -- String_Input_Blk_IO, except that if the String is -- absurdly long, it raises an exception. -- + -- However, if the No_Stream_Optimizations restriction + -- is active, we disable this unnecessary attempt at + -- robustness; we really need to read the string + -- character-by-character. + -- -- This value is used only to provide a controlling -- argument for the eventual _Input call. Descendant_Tag is -- called rather than Internal_Tag to ensure that we have a @@ -4026,18 +4033,30 @@ package body Exp_Attr is -- this constant in Cntrl, but this caused a secondary stack -- leak. + if Restriction_Active (No_Stream_Optimizations) then + Get_Tag := + Make_Attribute_Reference (Loc, + Prefix => + New_Occurrence_Of (Standard_String, Loc), + Attribute_Name => Name_Input, + Expressions => New_List ( + Relocate_Node (Duplicate_Subexpr (Strm)))); + else + Get_Tag := + Make_Function_Call (Loc, + Name => + New_Occurrence_Of + (RTE (RE_String_Input_Tag), Loc), + Parameter_Associations => New_List ( + Relocate_Node (Duplicate_Subexpr (Strm)))); + end if; + Expr := Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_Descendant_Tag), Loc), Parameter_Associations => New_List ( - Make_Function_Call (Loc, - Name => - New_Occurrence_Of - (RTE (RE_String_Input_Tag), Loc), - Parameter_Associations => New_List ( - Relocate_Node (Duplicate_Subexpr (Strm)))), - + Get_Tag, Make_Attribute_Reference (Loc, Prefix => New_Occurrence_Of (P_Type, Loc), Attribute_Name => Name_Tag))); -- cgit v1.1 From 8518042a54fde0880fabc3e380e9549ad13de601 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Fri, 5 Jul 2019 07:01:54 +0000 Subject: [Ada] Fix typo in GNAT RM 2019-07-05 Bob Duff gcc/ada/ * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst: Fix typo. * gnat_rm.texi: Regenerate. From-SVN: r273104 --- gcc/ada/ChangeLog | 6 ++++++ .../gnat_rm/standard_and_implementation_defined_restrictions.rst | 2 +- gcc/ada/gnat_rm.texi | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9f7ee9d..eacc5f2 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,11 @@ 2019-07-05 Bob Duff + * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst: + Fix typo. + * gnat_rm.texi: Regenerate. + +2019-07-05 Bob Duff + * exp_attr.adb (Input): Take the No_Stream_Optimizations restriction into account. diff --git a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst index 7b599be..cfa6356 100644 --- a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst +++ b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst @@ -633,7 +633,7 @@ No_Stream_Optimizations [GNAT] This restriction affects the performance of stream operations on types ``String``, ``Wide_String`` and ``Wide_Wide_String``. By default, the compiler uses block reads and writes when manipulating ``String`` objects -due to their supperior performance. When this restriction is in effect, the +due to their superior performance. When this restriction is in effect, the compiler performs all IO operations on a per-character basis. No_Streams diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 268ae30..e67fb7b 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -12838,7 +12838,7 @@ user-defined storage pool. [GNAT] This restriction affects the performance of stream operations on types @code{String}, @code{Wide_String} and @code{Wide_Wide_String}. By default, the compiler uses block reads and writes when manipulating @code{String} objects -due to their supperior performance. When this restriction is in effect, the +due to their superior performance. When this restriction is in effect, the compiler performs all IO operations on a per-character basis. @node No_Streams,No_Task_Allocators,No_Stream_Optimizations,Partition-Wide Restrictions -- cgit v1.1 From 85ee7b4903e320b8f22ac0350afcd07263d2a5d6 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Fri, 5 Jul 2019 07:01:58 +0000 Subject: [Ada] Fix inlining in GNATprove inside quantified expressions Calls to local subprograms in GNATprove may be inlined in some case, but it should not be the case inside quantified expressions which are handled as expressions inside GNATprove. Because quantified expressions are only preanalayzed, the detection of the impossible inlining was not performed. Now fixed. There is no impact on compilation. 2019-07-05 Yannick Moy gcc/ada/ * sem_res.adb (Resolve_Call): Cannot inline in quantified expressions. * sem_util.adb, sem_util.ads (In_Quantified_Expression): New function. From-SVN: r273105 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_res.adb | 9 +++++++++ gcc/ada/sem_util.adb | 19 +++++++++++++++++++ gcc/ada/sem_util.ads | 3 +++ 4 files changed, 38 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index eacc5f2..6f22a1a 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Yannick Moy + + * sem_res.adb (Resolve_Call): Cannot inline in quantified + expressions. + * sem_util.adb, sem_util.ads (In_Quantified_Expression): New + function. + 2019-07-05 Bob Duff * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst: diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 8521478..9c22635 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -6768,6 +6768,15 @@ package body Sem_Res is Cannot_Inline ("cannot inline & (in default expression)?", N, Nam_UA); + -- Calls cannot be inlined inside quantified expressions, which + -- are left in expression form for GNATprove. Since these + -- expressions are only preanalyzed, we need to detect the failure + -- to inline outside of the case for Full_Analysis below. + + elsif In_Quantified_Expression (N) then + Cannot_Inline + ("cannot inline & (in quantified expression)?", N, Nam_UA); + -- Inlining should not be performed during preanalysis elsif Full_Analysis then diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 868e93e..55e6443 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -12305,6 +12305,25 @@ package body Sem_Util is end if; end In_Pre_Post_Condition; + ------------------------------ + -- In_Quantified_Expression -- + ------------------------------ + + function In_Quantified_Expression (N : Node_Id) return Boolean is + P : Node_Id; + begin + P := Parent (N); + loop + if No (P) then + return False; + elsif Nkind (P) = N_Quantified_Expression then + return True; + else + P := Parent (P); + end if; + end loop; + end In_Quantified_Expression; + ------------------------------------- -- In_Reverse_Storage_Order_Object -- ------------------------------------- diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 3f8d2e7..43c0bc5 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -1410,6 +1410,9 @@ package Sem_Util is -- Returns True if node N appears within a pre/postcondition pragma. Note -- the pragma Check equivalents are NOT considered. + function In_Quantified_Expression (N : Node_Id) return Boolean; + -- Returns true if the expression N occurs within a quantified expression + function In_Reverse_Storage_Order_Object (N : Node_Id) return Boolean; -- Returns True if N denotes a component or subcomponent in a record or -- array that has Reverse_Storage_Order. -- cgit v1.1 From db6261488e4e53e4ac09ec9db50ea2e4a1859377 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Fri, 5 Jul 2019 07:02:03 +0000 Subject: [Ada] Compiler abort on a dynamic predicate used in a precondition This patch suppresses the generation of a predicate check when the expression is a formal IN parameter of a subprogram S. If the check is being applied to the actual in a call, the call is either in the body of S, or in an aspect specfication for S, e.g. a precondition, In both cases the check is redundant bevause it will be applied on any call to S. In the second case the expansion of the predicate check may lead to out-of-scope references the the formal. 2019-07-05 Ed Schonberg gcc/ada/ * checks.adb (Apply_Predicate_Check): Except within the subprogram body that defines the formal, do not apply predicate check on a formal IN parameter: such a check is redundant and its expansion can lead to out-of-scope references when it is originates in a function call in a precondition, gcc/testsuite/ * gnat.dg/predicate7.adb, gnat.dg/predicate7.ads, gnat.dg/predicate7_pkg.ads: New testcase. From-SVN: r273106 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/checks.adb | 35 ++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/predicate7.adb | 6 ++++++ gcc/testsuite/gnat.dg/predicate7.ads | 13 ++++++++++++ gcc/testsuite/gnat.dg/predicate7_pkg.ads | 3 +++ 6 files changed, 70 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/predicate7.adb create mode 100644 gcc/testsuite/gnat.dg/predicate7.ads create mode 100644 gcc/testsuite/gnat.dg/predicate7_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6f22a1a..b1b98f2 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-05 Ed Schonberg + + * checks.adb (Apply_Predicate_Check): Except within the + subprogram body that defines the formal, do not apply predicate + check on a formal IN parameter: such a check is redundant and + its expansion can lead to out-of-scope references when it is + originates in a function call in a precondition, + 2019-07-05 Yannick Moy * sem_res.adb (Resolve_Call): Cannot inline in quantified diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 33fb27e..8176f85 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -2707,6 +2707,41 @@ package body Checks is -- Here for normal case of predicate active else + -- If the expression is an IN parameter, the predicate will have + -- been applied at the point of call. An additional check would + -- be redundant, or will lead to out-of-scope references if the + -- call appears within an aspect specification for a precondition. + + -- However, if the reference is within the body of the subprogram + -- that declares the formal, the predicate can safely be applied, + -- which may be necessary for a nested call whose formal has a + -- different predicate. + + if Is_Entity_Name (N) + and then Ekind (Entity (N)) = E_In_Parameter + then + declare + In_Body : Boolean := False; + P : Node_Id := Parent (N); + + begin + while Present (P) loop + if Nkind (P) = N_Subprogram_Body + and then Corresponding_Spec (P) = Scope (Entity (N)) + then + In_Body := True; + exit; + end if; + + P := Parent (P); + end loop; + + if not In_Body then + return; + end if; + end; + end if; + -- If the type has a static predicate and the expression is known -- at compile time, see if the expression satisfies the predicate. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 30b2d1f..d5905f0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Ed Schonberg + + * gnat.dg/predicate7.adb, gnat.dg/predicate7.ads, + gnat.dg/predicate7_pkg.ads: New testcase. + 2019-07-04 Jakub Jelinek PR middle-end/78884 diff --git a/gcc/testsuite/gnat.dg/predicate7.adb b/gcc/testsuite/gnat.dg/predicate7.adb new file mode 100644 index 0000000..119c190 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate7.adb @@ -0,0 +1,6 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +package body Predicate7 is + procedure Foo is null; +end; diff --git a/gcc/testsuite/gnat.dg/predicate7.ads b/gcc/testsuite/gnat.dg/predicate7.ads new file mode 100644 index 0000000..598e2b0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate7.ads @@ -0,0 +1,13 @@ +with Predicate7_Pkg; use Predicate7_Pkg; + +package Predicate7 is + function Always_True (I : My_Int) return Boolean; + + function Identity (I : My_Int ) return Integer with Pre => Always_True (I); + + procedure Foo; + +private + function Identity (I : My_Int ) return Integer is (I); + function Always_True (I : My_Int) return Boolean is (True); +end; diff --git a/gcc/testsuite/gnat.dg/predicate7_pkg.ads b/gcc/testsuite/gnat.dg/predicate7_pkg.ads new file mode 100644 index 0000000..b90419e --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate7_pkg.ads @@ -0,0 +1,3 @@ +package Predicate7_Pkg is + subtype My_Int is Integer with Dynamic_Predicate => My_Int /= 0; +end Predicate7_Pkg; -- cgit v1.1 From 9795b20366362d63be058f1e4f3009d6bad79310 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Fri, 5 Jul 2019 07:02:08 +0000 Subject: [Ada] Diagnostics in Elaboration order v4.0 This patch introduces several changes to the new elaboration order mechanism: * The library graph can now discover, store, and organize the various cycles it contains. * The elaboration order mechanism can now diagnose one or all cycles within the library graph. Diagnostics consist of describing the reason for the cycle, listing all units comprising the circuit, and offering suggestions on how to break the cycle. The patch also modifies unit ALI to hide all invocation-related data structures and several implementation-specific types by relocating them in the body of the unit. The patch cleans up most children of Bindo by using better names of routines and formal parameters. ------------ -- Source -- ------------ -- a.ads with B; pragma Elaborate_All (B); with C; pragma Elaborate_All (C); package A is end A; -- b.ads package B is procedure Force_Body; end B; -- b.adb with D; package body B is procedure Force_Body is null; Elab : constant Integer := D.Func; end B; -- c.ads package C is procedure Force_Body; end C; -- c.adb with E; package body C is procedure Force_Body is null; end C; -- d.ads package D is function Func return Integer; end D; -- d.adb with A; package body D is Local : Integer := 123; function Func return Integer is begin return Local; end Func; end D; -- e.ads with A; package E is end E; -- main.adb with B; -- Elaborate_All Elaborate_All with -- C spec <--------------- A spec ---------------------> B spec <------ Main -- ^ ^ ^ ^ -- | | | | -- sbb | | | | sbb -- | | | | -- C body -----------> E spec | D spec <--------- B body -- with | ^ with | -- | | | -- | sbb | | -- | | | -- +------ D body <------------+ -- with Invocation -- -- The cycles are -- -- A spec --> C spec --> E spec --> A spec -- C body -- -- A spec --> B spec --> D body --> A spec -- B body procedure Main is begin null; end Main; ---------------------------- -- Compilation and output -- ---------------------------- $ gnatmake -q main.adb -bargs -d_C -d_N error: Elaboration circularity detected info: info: Reason: info: info: unit "a (spec)" depends on its own elaboration info: info: Circularity: info: info: unit "a (spec)" has with clause and pragma Elaborate_All for unit "b (spec)" info: unit "b (body)" is in the closure of pragma Elaborate_All info: unit "b (body)" has with clause for unit "d (spec)" info: unit "d (body)" is in the closure of pragma Elaborate_All info: unit "d (body)" has with clause for unit "a (spec)" info: info: Suggestions: info: info: change pragma Elaborate_All for unit "b (spec)" to Elaborate in unit "a (spec)" info: remove pragma Elaborate_All for unit "b (spec)" in unit "a (spec)" info: error: Elaboration circularity detected info: info: Reason: info: info: unit "a (spec)" depends on its own elaboration info: info: Circularity: info: info: unit "a (spec)" has with clause and pragma Elaborate_All for unit "c (spec)" info: unit "c (body)" is in the closure of pragma Elaborate_All info: unit "c (body)" has with clause for unit "e (spec)" info: unit "e (spec)" has with clause for unit "a (spec)" info: info: Suggestions: info: info: change pragma Elaborate_All for unit "c (spec)" to Elaborate in unit "a (spec)" info: remove pragma Elaborate_All for unit "c (spec)" in unit "a (spec)" info: gnatmake: *** bind failed. 2019-07-05 Hristian Kirtchev gcc/ada/ * ali.adb: Relocate types Invocation_Construct_Record, Invocation_Relation_Record, and Invocation_Signature_Record to the body of ALI. Relocate tables Invocation_Constructs, Invocation_Relations, and Invocation_Signatures to the body of ALI. Remove type Body_Placement_Codes. Add new types Declaration_Placement_Codes, and Invocation_Graph_Encoding_Codes. Update the literals of type Invocation_Graph_Line_Codes. (Add_Invocation_Construct): Update the parameter profile. Add an invocation construct built from all attributes provided. (Add_Invocation_Relation): Update the parameter profile. Add an invocation relation built from all attributes provided. (Body_Placement): New routine. (Body_Placement_Kind_To_Code, Code_To_Body_Placement_Kind): Removed. (Code_To_Declaration_Placement_Kind, Code_To_Invocation_Graph_Encoding_Kind, Column, Declaration_Placement_Kind_To_Code, Extra, For_Each_Invocation_Construct, For_Each_Invocation_Relation, Invocation_Graph_Encoding, Invocation_Graph_Encoding_Kind_To_Code, Invoker, Kind, Line, Locations, Name): New routine. (Scan_Invocation_Construct_Line): Reimplement the scanning mechanism. (Scan_Invocation_Graph_Attributes_Line): New routine. (Scan_Invocation_Graph_Line): Use a case statement to dispatch. (Scan_Invocation_Relation_Line): Reimplement the scanning mechanism. (Scope): New routine. (Set_Invocation_Graph_Encoding, Signature, Spec_Placement, Target): New routine. * ali.ads: Add new type Invocation_Graph_Encoding_Kind. Add component Invocation_Graph_Encoding to type Unit_Record. Relocate various types and data structures to the body of ALI. (Add_Invocation_Construct, Add_Invocation_Relation): Update the parameter profile. (Body_Placement): New routine. (Body_Placement_Kind_To_Code, Code_To_Body_Placement_Kind): Removed. (Code_To_Declaration_Placement_Kind, Code_To_Invocation_Graph_Encoding_Kind, Column, Declaration_Placement_Kind_To_Code, Extra, For_Each_Invocation_Construct, For_Each_Invocation_Relation, Invocation_Graph_Encoding, Invocation_Graph_Encoding_Kind_To_Code, Invoker, Kind, Line, Locations, Name, Scope, Set_Invocation_Graph_Encoding, Signature, Spec_Placement, Target): New routine. * bindo.adb: Add with clause for Binde. Add with and use clauses for Debug. Update the documentation. Add new switches. (Find_Elaboration_Order): Dispatch to the proper elaboration mechanism. * bindo-augmentors.adb: Remove with and use clauses for GNAT and GNAT.Sets. Remove membership set VS. Update the parameter profiles of most routines to use better parameter names. Update the implementation of most routine to use the new parameter names. Remove various redundant assertions. * bindo-builders.adb: Use better names for instantiated data structures. Update all references to these names. Update the parameter profiles of most routines to use better parameter names. Update the implementation of most routine to use the new parameter names. (Build_Library_Graph): Update the parameter profile. Update the call to Create. (Create_Vertex): Reimplemented. (Declaration_Placement_Vertex): New routine. * bindo-builders.ads (Build_Library_Graph): Update the parameter profile and comment on usage. * bindo-diagnostics.adb: Almost a new unit. * bindo-diagnostics.ads: Add a use clause for Bindo.Graphs.Invocation_Graphs. Remove package Cycle_Diagnostics. (Diagnose_Circularities): New routine. * bindo-elaborators.adb: Remove the with and use clauses for Binderr and GNAT.Sets. Remove the use clause for Bindo.Diagnostics.Cycle_Diagnostics. Remove membership set VS. Update the parameter profiles of most routines to use better parameter names. Update the implementation of most routine to use the new parameter names. (Elaborate_Units_Common): Update the parameter profile. Pass an infication to the library graph builder whether the dynamic model is in effect. (Elaborate_Units_Dynamic, Elaborate_Units_Static): Use Diagnose_Circularities to provide diagnostics. (Update_Successor): Use routine In_Same_Component to determine whether the predecessor and successor reside in different components. * bindo-graphs.adb: Add with and use clauses for Butil, Debug, Output, and Bindo.Writers. Remove with and use clauses for GNAT.Lists. Update the parameter profiles of most routines to use better parameter names. Update the implementation of most routine to use the new parameter names. Remove various redundant assertions. Remove doubly linked list EL. Add new type Precedence_Kind. (Add_Cycle): New routine. (Add_Vertex): Update the parameter profile. Update the creation of vertex attributes. (Add_Vertex_And_Complement, Body_Vertex, Column, Complementary_Vertex, Copy_Cycle_Path, Cycle_Kind_Of): New routines. (Destroy_Invocation_Graph_Edge, Destroy_Library_Graph_Cycle, Destroy_Library_Graph_Edge, Extra, File_Name, Find_All_Cycles_Through_Vertex, Find_All_Cycles_With_Edge, Find_Cycles, Find_First_Lower_Precedence_Cycle, Get_LGC_Attributes, Has_Next, Hash_Library_Graph_Cycle, Hash_Library_Graph_Cycle_Attributes, Highest_Precedence_Cycle, Highest_Precedence_Edge, In_Same_Component, Insert_And_Sort, Invocation_Edge_Count, Invocation_Graph_Encoding, Is_Cycle_Initiating_Edge, Is_Cyclic_Edge, Is_Cyclic_Elaborate_All_Edge, Is_Cyclic_Elaborate_Body_Edge, Is_Cyclic_Elaborate_Edge, Is_Cyclic_Forced_Edge, Is_Cyclic_Invocation_Edge, Is_Cyclic_With_Edge, Is_Dynamically_Elaborated, Is_Elaborate_All_Edge, Is_Elaborate_Body_Edge, Is_Elaborate_Edge: New routines. (Is_Existing_Predecessor_Successor_Relation): Removed. (Is_Forced_Edge, Is_Invocation_Edge, Is_Recorded_Cycle, Is_Recorded_Edge, Is_With_Edge, Iterate_Edges_Of_Cycle, Kind, Length): New routine. (Lib_Vertex): Removed. (Line, Links_Vertices_In_Same_Component, Maximum_Invocation_Edge_Count, Next, Normalize_And_Add_Cycle, Normalize_Cycle_Path, Number_Of_Cycles, Path, Precedence, Remove_Vertex_And_Complement, Sequence_Next_Cycle): New routines. (Sequence_Next_IGE_Id): Renamed to Sequence_Next_Edge. (Sequence_Next_IGV_Id): Renamed to Sequence_Next_Vertex. (Sequence_Next_LGE_Id): Renamed to Sequence_Next_Edge. (Sequence_Next_LGV_Id): Renamed to Sequence_Next_Vertex. (Set_Is_Existing_Predecessor_Successor_Relation): Removed. (Set_Is_Recorded_Cycle, Set_Is_Recorded_Edge, Set_LGC_Attributes, Spec_Vertex, Trace_Cycle, Trace_Edge, Trace_Eol, Trace_Vertex): New routines. * bindo-graphs.ads: Add with and use clauses for Types and GNAT.Lists. Update the parameter profiles of most routines to use better parameter names. Update the implementation of most routine to use the new parameter names. Add the new instantiated data structures IGE_Lists, IGV_Sets, LGC_Lists, LGE_Lists, LGE_Sets, LGV_Sets, and RC_Sets. Add new type Library_Graph_Cycle_Id along with an empty and initial value. Remove component Lib_Vertex and add new components Body_Vertex and Spec_Vertex to type Invocation_Graph_Vertex_Attributes. Add new type Library_Graph_Cycle_Kind. Add new iterators All_Cycle_Iterator and Edges_Of_Cycle_Iterator. Add new type Library_Graph_Cycle_Attributes. Add new components Cycle_Attributes, Cycles, and Dynamically_Elaborated to type Library_Graph_Attributes. (Body_Vertex, Column, Destroy_Invocation_Graph_Edge, Destroy_Library_Graph_Cycle_Attributes, Destroy_Library_Graph_Edge, Extra, File_Name, Find_Cycles, Has_Elaborate_All_Cycle, Has_Next, Hash_Library_Graph_Cycle, Hash_Library_Graph_Cycle_Attributes, Highest_Precedence_Cycle, In_Same_Component, Invocation_Edge_Count, Invocation_Graph_Encoding, Is_Dynamically_Elaborated, Is_Elaborate_All_Edge, Is_Elaborate_Body_Edge, Is_Elaborate_Edge, Is_Forced_Edge, Is_Invocation_Edge, Is_With_Edge, Iterate_All_Cycles, Iterate_Edges_Of_Cycle, Kind): New routines. (Length, Lib_Vertex, (Line, Next, Number_Of_Cycles, Present, Same_Library_Graph_Cycle_Attributes, Spec_Vertex): New routines. * bindo-units.adb (File_Name, Invocation_Graph_Encoding): New routines. * bindo-units.ads: Add new instantiated data structure Unit_Sets. (File_Name, Invocation_Graph_Encoding): New routine. * bindo-validators.adb: Remove with and use clauses for GNAT and GNAT.Sets. Remove membership set US. Update the parameter profiles of most routines to use better parameter names. Update the implementation of most routine to use the new parameter names. (Validate_Cycle, Validate_Cycle_Path, Validate_Cycles, Validate_Invocation_Graph_Vertex): Remove the validation of component Lib_Vertex. Add the validation of components Body_Vertex and Spec_Vertex. (Write_Error): New routine. * bindo-validators.ads (Validate_Cycles): New routine. * bindo-writers.adb: Update the parameter profiles of most routines to use better parameter names. Update the implementation of most routine to use the new parameter names. (Write_Cycle, Write_Cyclic_Edge, Write_Cycles): New routines. (Write_Invocation_Graph_Vertex): Remove the output of component Lib_Vertex. Add the output of components Body_Vertex and Spec_Vertex. * bindo-writers.ads (Write_Cycles): New routine. * debug.adb: Use binder switches -d_C and -d_P, add documentation on their usage. * gnatbind.adb: Remove with and use clauses for Binde. Delegate the choice of elaboration mechanism to Bindo. * lib-writ.adb (Column, Extra, Invoker, Kind, Line, Locations, Name, Placement, Scope, Signature, Target): Removed. (Write_Invocation_Graph): Moved at the top level. (Write_Invocation_Graph_Attributes): New routine. (Write_Invocation_Relation, Write_Invocation_Signature): Moved at the top level. * lib-writ.ads: Add a documentation section on invocation graph attributes. * sem_elab.adb (Body_Placement_Of): New routine. (Declare_Invocation_Construct): Update the call to Add_Invocation_Construct. (Declaration_Placement_Of_Node): New routine. (Get_Invocation_Attributes): Correct the retrieval of the enclosing subprogram where the postcondition procedure lives. (Placement_Of, Placement_Of_Node): Removed. (Record_Invocation_Graph): Record the encoding format used. (Record_Invocation_Graph_Encoding): New routine. (Record_Invocation_Relation): Update the call to Add_Invocation_Relation. (Spec_Placement_Of): Removed. * libgnat/g-lists.ads, libgnat/g-lists.adb (Equal): New routine. From-SVN: r273107 --- gcc/ada/ChangeLog | 209 +++ gcc/ada/ali.adb | 551 ++++++- gcc/ada/ali.ads | 315 ++-- gcc/ada/bindo-augmentors.adb | 153 +- gcc/ada/bindo-builders.adb | 229 ++- gcc/ada/bindo-builders.ads | 6 +- gcc/ada/bindo-diagnostics.adb | 1469 ++++++++++++++++++- gcc/ada/bindo-diagnostics.ads | 20 +- gcc/ada/bindo-elaborators.adb | 447 +++--- gcc/ada/bindo-graphs.adb | 3171 +++++++++++++++++++++++++++++++++-------- gcc/ada/bindo-graphs.ads | 680 ++++++--- gcc/ada/bindo-units.adb | 66 +- gcc/ada/bindo-units.ads | 32 +- gcc/ada/bindo-validators.adb | 460 +++--- gcc/ada/bindo-validators.ads | 20 + gcc/ada/bindo-writers.adb | 369 +++-- gcc/ada/bindo-writers.ads | 10 + gcc/ada/bindo.adb | 125 +- gcc/ada/debug.adb | 33 +- gcc/ada/gnatbind.adb | 10 +- gcc/ada/lib-writ.adb | 544 +++---- gcc/ada/lib-writ.ads | 20 +- gcc/ada/libgnat/g-lists.adb | 51 + gcc/ada/libgnat/g-lists.ads | 6 + gcc/ada/sem_elab.adb | 172 ++- 25 files changed, 6939 insertions(+), 2229 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b1b98f2..279eac5 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,212 @@ +2019-07-05 Hristian Kirtchev + + * ali.adb: Relocate types Invocation_Construct_Record, + Invocation_Relation_Record, and Invocation_Signature_Record to + the body of ALI. Relocate tables Invocation_Constructs, + Invocation_Relations, and Invocation_Signatures to the body of + ALI. Remove type Body_Placement_Codes. Add new types + Declaration_Placement_Codes, and + Invocation_Graph_Encoding_Codes. Update the literals of type + Invocation_Graph_Line_Codes. + (Add_Invocation_Construct): Update the parameter profile. Add an + invocation construct built from all attributes provided. + (Add_Invocation_Relation): Update the parameter profile. Add an + invocation relation built from all attributes provided. + (Body_Placement): New routine. + (Body_Placement_Kind_To_Code, Code_To_Body_Placement_Kind): + Removed. + (Code_To_Declaration_Placement_Kind, + Code_To_Invocation_Graph_Encoding_Kind, Column, + Declaration_Placement_Kind_To_Code, Extra, + For_Each_Invocation_Construct, For_Each_Invocation_Relation, + Invocation_Graph_Encoding, + Invocation_Graph_Encoding_Kind_To_Code, Invoker, Kind, Line, + Locations, Name): New routine. + (Scan_Invocation_Construct_Line): Reimplement the scanning + mechanism. + (Scan_Invocation_Graph_Attributes_Line): New routine. + (Scan_Invocation_Graph_Line): Use a case statement to dispatch. + (Scan_Invocation_Relation_Line): Reimplement the scanning + mechanism. + (Scope): New routine. + (Set_Invocation_Graph_Encoding, Signature, Spec_Placement, + Target): New routine. + * ali.ads: Add new type Invocation_Graph_Encoding_Kind. Add + component Invocation_Graph_Encoding to type Unit_Record. + Relocate various types and data structures to the body of ALI. + (Add_Invocation_Construct, Add_Invocation_Relation): Update the + parameter profile. + (Body_Placement): New routine. + (Body_Placement_Kind_To_Code, Code_To_Body_Placement_Kind): + Removed. + (Code_To_Declaration_Placement_Kind, + Code_To_Invocation_Graph_Encoding_Kind, Column, + Declaration_Placement_Kind_To_Code, Extra, + For_Each_Invocation_Construct, For_Each_Invocation_Relation, + Invocation_Graph_Encoding, + Invocation_Graph_Encoding_Kind_To_Code, Invoker, Kind, Line, + Locations, Name, Scope, Set_Invocation_Graph_Encoding, + Signature, Spec_Placement, Target): New routine. + * bindo.adb: Add with clause for Binde. Add with and use + clauses for Debug. Update the documentation. Add new switches. + (Find_Elaboration_Order): Dispatch to the proper elaboration + mechanism. + * bindo-augmentors.adb: + Remove with and use clauses for GNAT and GNAT.Sets. Remove + membership set VS. Update the parameter profiles of most + routines to use better parameter names. Update the + implementation of most routine to use the new parameter names. + Remove various redundant assertions. + * bindo-builders.adb: Use better names for instantiated data + structures. Update all references to these names. Update the + parameter profiles of most routines to use better parameter + names. Update the implementation of most routine to use the new + parameter names. + (Build_Library_Graph): Update the parameter profile. Update the + call to Create. + (Create_Vertex): Reimplemented. + (Declaration_Placement_Vertex): New routine. + * bindo-builders.ads (Build_Library_Graph): Update the parameter + profile and comment on usage. + * bindo-diagnostics.adb: Almost a new unit. + * bindo-diagnostics.ads: Add a use clause for + Bindo.Graphs.Invocation_Graphs. Remove package + Cycle_Diagnostics. + (Diagnose_Circularities): New routine. + * bindo-elaborators.adb: Remove the with and use clauses for + Binderr and GNAT.Sets. Remove the use clause for + Bindo.Diagnostics.Cycle_Diagnostics. Remove membership set VS. + Update the parameter profiles of most routines to use better + parameter names. Update the implementation of most routine to + use the new parameter names. (Elaborate_Units_Common): Update + the parameter profile. Pass an infication to the library graph + builder whether the dynamic model is in effect. + (Elaborate_Units_Dynamic, Elaborate_Units_Static): Use + Diagnose_Circularities to provide diagnostics. + (Update_Successor): Use routine In_Same_Component to determine + whether the predecessor and successor reside in different + components. + * bindo-graphs.adb: Add with and use clauses for Butil, Debug, + Output, and Bindo.Writers. Remove with and use clauses for + GNAT.Lists. Update the parameter profiles of most routines to + use better parameter names. Update the implementation of most + routine to use the new parameter names. Remove various + redundant assertions. Remove doubly linked list EL. Add new + type Precedence_Kind. + (Add_Cycle): New routine. + (Add_Vertex): Update the parameter profile. Update the creation + of vertex attributes. + (Add_Vertex_And_Complement, Body_Vertex, Column, + Complementary_Vertex, Copy_Cycle_Path, Cycle_Kind_Of): New + routines. + (Destroy_Invocation_Graph_Edge, Destroy_Library_Graph_Cycle, + Destroy_Library_Graph_Edge, Extra, File_Name, + Find_All_Cycles_Through_Vertex, Find_All_Cycles_With_Edge, + Find_Cycles, Find_First_Lower_Precedence_Cycle, + Get_LGC_Attributes, Has_Next, Hash_Library_Graph_Cycle, + Hash_Library_Graph_Cycle_Attributes, Highest_Precedence_Cycle, + Highest_Precedence_Edge, In_Same_Component, Insert_And_Sort, + Invocation_Edge_Count, Invocation_Graph_Encoding, + Is_Cycle_Initiating_Edge, Is_Cyclic_Edge, + Is_Cyclic_Elaborate_All_Edge, Is_Cyclic_Elaborate_Body_Edge, + Is_Cyclic_Elaborate_Edge, Is_Cyclic_Forced_Edge, + Is_Cyclic_Invocation_Edge, Is_Cyclic_With_Edge, + Is_Dynamically_Elaborated, Is_Elaborate_All_Edge, + Is_Elaborate_Body_Edge, Is_Elaborate_Edge: New routines. + (Is_Existing_Predecessor_Successor_Relation): Removed. + (Is_Forced_Edge, Is_Invocation_Edge, Is_Recorded_Cycle, + Is_Recorded_Edge, Is_With_Edge, Iterate_Edges_Of_Cycle, Kind, + Length): New routine. + (Lib_Vertex): Removed. + (Line, Links_Vertices_In_Same_Component, + Maximum_Invocation_Edge_Count, Next, Normalize_And_Add_Cycle, + Normalize_Cycle_Path, Number_Of_Cycles, Path, Precedence, + Remove_Vertex_And_Complement, Sequence_Next_Cycle): New routines. + (Sequence_Next_IGE_Id): Renamed to Sequence_Next_Edge. + (Sequence_Next_IGV_Id): Renamed to Sequence_Next_Vertex. + (Sequence_Next_LGE_Id): Renamed to Sequence_Next_Edge. + (Sequence_Next_LGV_Id): Renamed to Sequence_Next_Vertex. + (Set_Is_Existing_Predecessor_Successor_Relation): Removed. + (Set_Is_Recorded_Cycle, Set_Is_Recorded_Edge, + Set_LGC_Attributes, Spec_Vertex, Trace_Cycle, Trace_Edge, + Trace_Eol, Trace_Vertex): New routines. + * bindo-graphs.ads: Add with and use clauses for Types and + GNAT.Lists. Update the parameter profiles of most routines to + use better parameter names. Update the implementation of most + routine to use the new parameter names. Add the new + instantiated data structures IGE_Lists, IGV_Sets, LGC_Lists, + LGE_Lists, LGE_Sets, LGV_Sets, and RC_Sets. Add new type + Library_Graph_Cycle_Id along with an empty and initial value. + Remove component Lib_Vertex and add new components Body_Vertex + and Spec_Vertex to type Invocation_Graph_Vertex_Attributes. Add + new type Library_Graph_Cycle_Kind. Add new iterators + All_Cycle_Iterator and Edges_Of_Cycle_Iterator. Add new type + Library_Graph_Cycle_Attributes. Add new components + Cycle_Attributes, Cycles, and Dynamically_Elaborated to type + Library_Graph_Attributes. + (Body_Vertex, Column, Destroy_Invocation_Graph_Edge, + Destroy_Library_Graph_Cycle_Attributes, + Destroy_Library_Graph_Edge, Extra, File_Name, Find_Cycles, + Has_Elaborate_All_Cycle, Has_Next, Hash_Library_Graph_Cycle, + Hash_Library_Graph_Cycle_Attributes, Highest_Precedence_Cycle, + In_Same_Component, Invocation_Edge_Count, + Invocation_Graph_Encoding, Is_Dynamically_Elaborated, + Is_Elaborate_All_Edge, Is_Elaborate_Body_Edge, + Is_Elaborate_Edge, Is_Forced_Edge, Is_Invocation_Edge, + Is_With_Edge, Iterate_All_Cycles, Iterate_Edges_Of_Cycle, Kind): + New routines. + (Length, Lib_Vertex, (Line, Next, Number_Of_Cycles, Present, + Same_Library_Graph_Cycle_Attributes, Spec_Vertex): New routines. + * bindo-units.adb (File_Name, Invocation_Graph_Encoding): New + routines. + * bindo-units.ads: Add new instantiated data structure + Unit_Sets. + (File_Name, Invocation_Graph_Encoding): New routine. + * bindo-validators.adb: Remove with and use clauses for GNAT and + GNAT.Sets. Remove membership set US. Update the parameter + profiles of most routines to use better parameter names. Update + the implementation of most routine to use the new parameter + names. + (Validate_Cycle, Validate_Cycle_Path, Validate_Cycles, + Validate_Invocation_Graph_Vertex): Remove the validation of + component Lib_Vertex. Add the validation of components + Body_Vertex and Spec_Vertex. + (Write_Error): New routine. + * bindo-validators.ads (Validate_Cycles): New routine. + * bindo-writers.adb: Update the parameter profiles of most + routines to use better parameter names. Update the + implementation of most routine to use the new parameter names. + (Write_Cycle, Write_Cyclic_Edge, Write_Cycles): New routines. + (Write_Invocation_Graph_Vertex): Remove the output of component + Lib_Vertex. Add the output of components Body_Vertex and + Spec_Vertex. + * bindo-writers.ads (Write_Cycles): New routine. + * debug.adb: Use binder switches -d_C and -d_P, add + documentation on their usage. + * gnatbind.adb: Remove with and use clauses for Binde. Delegate + the choice of elaboration mechanism to Bindo. + * lib-writ.adb (Column, Extra, Invoker, Kind, Line, Locations, + Name, Placement, Scope, Signature, Target): Removed. + (Write_Invocation_Graph): Moved at the top level. + (Write_Invocation_Graph_Attributes): New routine. + (Write_Invocation_Relation, Write_Invocation_Signature): Moved + at the top level. + * lib-writ.ads: Add a documentation section on invocation graph + attributes. + * sem_elab.adb (Body_Placement_Of): New routine. + (Declare_Invocation_Construct): Update the call to + Add_Invocation_Construct. + (Declaration_Placement_Of_Node): New routine. + (Get_Invocation_Attributes): Correct the retrieval of the + enclosing subprogram where the postcondition procedure lives. + (Placement_Of, Placement_Of_Node): Removed. + (Record_Invocation_Graph): Record the encoding format used. + (Record_Invocation_Graph_Encoding): New routine. + (Record_Invocation_Relation): Update the call to + Add_Invocation_Relation. + (Spec_Placement_Of): Removed. + * libgnat/g-lists.ads, libgnat/g-lists.adb (Equal): New routine. + 2019-07-05 Ed Schonberg * checks.adb (Apply_Predicate_Check): Except within the diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb index 978fb3d..aa8b242 100644 --- a/gcc/ada/ali.adb +++ b/gcc/ada/ali.adb @@ -39,10 +39,115 @@ package body ALI is use ASCII; -- Make control characters visible + ----------- + -- Types -- + ----------- + + -- The following type represents an invocation construct + + type Invocation_Construct_Record is record + Body_Placement : Declaration_Placement_Kind := No_Declaration_Placement; + -- The location of the invocation construct's body with respect to the + -- unit where it is declared. + + Kind : Invocation_Construct_Kind := Regular_Construct; + -- The nature of the invocation construct + + Signature : Invocation_Signature_Id := No_Invocation_Signature; + -- The invocation signature that uniquely identifies the invocation + -- construct in the ALI space. + + Spec_Placement : Declaration_Placement_Kind := No_Declaration_Placement; + -- The location of the invocation construct's spec with respect to the + -- unit where it is declared. + end record; + + -- The following type represents an invocation relation. It associates an + -- invoker that activates/calls/instantiates with a target. + + type Invocation_Relation_Record is record + Extra : Name_Id := No_Name; + -- The name of an additional entity used in error diagnostics + + Invoker : Invocation_Signature_Id := No_Invocation_Signature; + -- The invocation signature that uniquely identifies the invoker within + -- the ALI space. + + Kind : Invocation_Kind := No_Invocation; + -- The nature of the invocation + + Target : Invocation_Signature_Id := No_Invocation_Signature; + -- The invocation signature that uniquely identifies the target within + -- the ALI space. + end record; + + -- The following type represents an invocation signature. Its purpose is + -- to uniquely identify an invocation construct within the ALI space. The + -- signature comprises several pieces, some of which are used in error + -- diagnostics by the binder. Identification issues are resolved as + -- follows: + -- + -- * The Column, Line, and Locations attributes together differentiate + -- between homonyms. In most cases, the Column and Line are sufficient + -- except when generic instantiations are involved. Together, the three + -- attributes offer a sequence of column-line pairs that eventually + -- reflect the location within the generic template. + -- + -- * The Name attribute differentiates between invocation constructs at + -- the scope level. Since it is illegal for two entities with the same + -- name to coexist in the same scope, the Name attribute is sufficient + -- to distinguish them. Overloaded entities are already handled by the + -- Column, Line, and Locations attributes. + -- + -- * The Scope attribute differentiates between invocation constructs at + -- various levels of nesting. + + type Invocation_Signature_Record is record + Column : Nat := 0; + -- The column number where the invocation construct is declared + + Line : Nat := 0; + -- The line number where the invocation construct is declared + + Locations : Name_Id := No_Name; + -- Sequence of column and line numbers within nested instantiations + + Name : Name_Id := No_Name; + -- The name of the invocation construct + + Scope : Name_Id := No_Name; + -- The qualified name of the scope where the invocation construct is + -- declared. + end record; + --------------------- -- Data structures -- --------------------- + package Invocation_Constructs is new Table.Table + (Table_Index_Type => Invocation_Construct_Id, + Table_Component_Type => Invocation_Construct_Record, + Table_Low_Bound => First_Invocation_Construct, + Table_Initial => 2500, + Table_Increment => 200, + Table_Name => "Invocation_Constructs"); + + package Invocation_Relations is new Table.Table + (Table_Index_Type => Invocation_Relation_Id, + Table_Component_Type => Invocation_Relation_Record, + Table_Low_Bound => First_Invocation_Relation, + Table_Initial => 2500, + Table_Increment => 200, + Table_Name => "Invocation_Relation"); + + package Invocation_Signatures is new Table.Table + (Table_Index_Type => Invocation_Signature_Id, + Table_Component_Type => Invocation_Signature_Record, + Table_Low_Bound => First_Invocation_Signature, + Table_Initial => 2500, + Table_Increment => 200, + Table_Name => "Invocation_Signatures"); + procedure Destroy (IS_Id : in out Invocation_Signature_Id); -- Destroy an invocation signature with id IS_Id @@ -68,14 +173,19 @@ package body ALI is Sig_To_Sig_Map : constant Sig_Map.Dynamic_Hash_Table := Sig_Map.Create (500); - -- The folowing table maps body placement kinds to character codes for - -- invocation construct encoding in ALI files. + -- The folowing table maps declaration placement kinds to character codes + -- for invocation construct encoding in ALI files. - Body_Placement_Codes : - constant array (Body_Placement_Kind) of Character := - (In_Body => 'b', - In_Spec => 's', - No_Body_Placement => 'Z'); + Declaration_Placement_Codes : + constant array (Declaration_Placement_Kind) of Character := + (In_Body => 'b', + In_Spec => 's', + No_Declaration_Placement => 'Z'); + + Compile_Time_Invocation_Graph_Encoding : Invocation_Graph_Encoding_Kind := + No_Encoding; + -- The invocation-graph encoding format as specified at compile time. Do + -- not manipulate this value directly. -- The following table maps invocation kinds to character codes for -- invocation relation encoding in ALI files. @@ -112,13 +222,23 @@ package body ALI is Elaborate_Spec_Procedure => 's', Regular_Construct => 'Z'); - -- The following table maps invocation graph line kinds to character codes + -- The following table maps invocation-graph encoding kinds to character + -- codes for invocation-graph encoding in ALI files. + + Invocation_Graph_Encoding_Codes : + constant array (Invocation_Graph_Encoding_Kind) of Character := + (Full_Path_Encoding => 'f', + Endpoints_Encoding => 'e', + No_Encoding => 'Z'); + + -- The following table maps invocation-graph line kinds to character codes -- used in ALI files. Invocation_Graph_Line_Codes : constant array (Invocation_Graph_Line_Kind) of Character := - (Invocation_Construct_Line => 'c', - Invocation_Relation_Line => 'r'); + (Invocation_Construct_Line => 'c', + Invocation_Graph_Attributes_Line => 'a', + Invocation_Relation_Line => 'r'); -- The following variable records which characters currently are used as -- line type markers in the ALI file. This is used in Scan_ALI to detect @@ -153,18 +273,22 @@ package body ALI is ------------------------------ procedure Add_Invocation_Construct - (IC_Rec : Invocation_Construct_Record; - Update_Units : Boolean := True) + (Body_Placement : Declaration_Placement_Kind; + Kind : Invocation_Construct_Kind; + Signature : Invocation_Signature_Id; + Spec_Placement : Declaration_Placement_Kind; + Update_Units : Boolean := True) is - IC_Id : Invocation_Construct_Id; - begin - pragma Assert (Present (IC_Rec.Signature)); + pragma Assert (Present (Signature)); -- Create a invocation construct from the scanned attributes - Invocation_Constructs.Append (IC_Rec); - IC_Id := Invocation_Constructs.Last; + Invocation_Constructs.Append + ((Body_Placement => Body_Placement, + Kind => Kind, + Signature => Signature, + Spec_Placement => Spec_Placement)); -- Update the invocation construct counter of the current unit only when -- requested by the caller. @@ -174,7 +298,7 @@ package body ALI is Curr_Unit : Unit_Record renames Units.Table (Units.Last); begin - Curr_Unit.Last_Invocation_Construct := IC_Id; + Curr_Unit.Last_Invocation_Construct := Invocation_Constructs.Last; end; end if; end Add_Invocation_Construct; @@ -184,20 +308,24 @@ package body ALI is ----------------------------- procedure Add_Invocation_Relation - (IR_Rec : Invocation_Relation_Record; + (Extra : Name_Id; + Invoker : Invocation_Signature_Id; + Kind : Invocation_Kind; + Target : Invocation_Signature_Id; Update_Units : Boolean := True) is - IR_Id : Invocation_Relation_Id; - begin - pragma Assert (Present (IR_Rec.Invoker)); - pragma Assert (Present (IR_Rec.Target)); - pragma Assert (IR_Rec.Kind /= No_Invocation); + pragma Assert (Present (Invoker)); + pragma Assert (Kind /= No_Invocation); + pragma Assert (Present (Target)); -- Create an invocation relation from the scanned attributes - Invocation_Relations.Append (IR_Rec); - IR_Id := Invocation_Relations.Last; + Invocation_Relations.Append + ((Extra => Extra, + Invoker => Invoker, + Kind => Kind, + Target => Target)); -- Update the invocation relation counter of the current unit only when -- requested by the caller. @@ -207,41 +335,42 @@ package body ALI is Curr_Unit : Unit_Record renames Units.Table (Units.Last); begin - Curr_Unit.Last_Invocation_Relation := IR_Id; + Curr_Unit.Last_Invocation_Relation := Invocation_Relations.Last; end; end if; end Add_Invocation_Relation; - --------------------------------- - -- Body_Placement_Kind_To_Code -- - --------------------------------- + -------------------- + -- Body_Placement -- + -------------------- - function Body_Placement_Kind_To_Code - (Kind : Body_Placement_Kind) return Character + function Body_Placement + (IC_Id : Invocation_Construct_Id) return Declaration_Placement_Kind is begin - return Body_Placement_Codes (Kind); - end Body_Placement_Kind_To_Code; + pragma Assert (Present (IC_Id)); + return Invocation_Constructs.Table (IC_Id).Body_Placement; + end Body_Placement; - --------------------------------- - -- Code_To_Body_Placement_Kind -- - --------------------------------- + ---------------------------------------- + -- Code_To_Declaration_Placement_Kind -- + ---------------------------------------- - function Code_To_Body_Placement_Kind - (Code : Character) return Body_Placement_Kind + function Code_To_Declaration_Placement_Kind + (Code : Character) return Declaration_Placement_Kind is begin - -- Determine which body placement kind corresponds to the character code - -- by traversing the contents of the mapping table. + -- Determine which placement kind corresponds to the character code by + -- traversing the contents of the mapping table. - for Kind in Body_Placement_Kind loop - if Body_Placement_Codes (Kind) = Code then + for Kind in Declaration_Placement_Kind loop + if Declaration_Placement_Codes (Kind) = Code then return Kind; end if; end loop; raise Program_Error; - end Code_To_Body_Placement_Kind; + end Code_To_Declaration_Placement_Kind; --------------------------------------- -- Code_To_Invocation_Construct_Kind -- @@ -263,6 +392,26 @@ package body ALI is raise Program_Error; end Code_To_Invocation_Construct_Kind; + -------------------------------------------- + -- Code_To_Invocation_Graph_Encoding_Kind -- + -------------------------------------------- + + function Code_To_Invocation_Graph_Encoding_Kind + (Code : Character) return Invocation_Graph_Encoding_Kind + is + begin + -- Determine which invocation-graph encoding kind matches the character + -- code by traversing the contents of the mapping table. + + for Kind in Invocation_Graph_Encoding_Kind loop + if Invocation_Graph_Encoding_Codes (Kind) = Code then + return Kind; + end if; + end loop; + + raise Program_Error; + end Code_To_Invocation_Graph_Encoding_Kind; + ----------------------------- -- Code_To_Invocation_Kind -- ----------------------------- @@ -291,7 +440,7 @@ package body ALI is (Code : Character) return Invocation_Graph_Line_Kind is begin - -- Determine which invocation graph line kind matches the character + -- Determine which invocation-graph line kind matches the character -- code by traversing the contents of the mapping table. for Kind in Invocation_Graph_Line_Kind loop @@ -303,6 +452,27 @@ package body ALI is raise Program_Error; end Code_To_Invocation_Graph_Line_Kind; + ------------ + -- Column -- + ------------ + + function Column (IS_Id : Invocation_Signature_Id) return Nat is + begin + pragma Assert (Present (IS_Id)); + return Invocation_Signatures.Table (IS_Id).Column; + end Column; + + ---------------------------------------- + -- Declaration_Placement_Kind_To_Code -- + ---------------------------------------- + + function Declaration_Placement_Kind_To_Code + (Kind : Declaration_Placement_Kind) return Character + is + begin + return Declaration_Placement_Codes (Kind); + end Declaration_Placement_Kind_To_Code; + ------------- -- Destroy -- ------------- @@ -313,6 +483,50 @@ package body ALI is null; end Destroy; + ----------- + -- Extra -- + ----------- + + function Extra (IR_Id : Invocation_Relation_Id) return Name_Id is + begin + pragma Assert (Present (IR_Id)); + return Invocation_Relations.Table (IR_Id).Extra; + end Extra; + + ----------------------------------- + -- For_Each_Invocation_Construct -- + ----------------------------------- + + procedure For_Each_Invocation_Construct + (Processor : Invocation_Construct_Processor_Ptr) + is + begin + pragma Assert (Processor /= null); + + for IC_Id in Invocation_Constructs.First .. + Invocation_Constructs.Last + loop + Processor.all (IC_Id); + end loop; + end For_Each_Invocation_Construct; + + ---------------------------------- + -- For_Each_Invocation_Relation -- + ---------------------------------- + + procedure For_Each_Invocation_Relation + (Processor : Invocation_Relation_Processor_Ptr) + is + begin + pragma Assert (Processor /= null); + + for IR_Id in Invocation_Relations.First .. + Invocation_Relations.Last + loop + Processor.all (IR_Id); + end loop; + end For_Each_Invocation_Relation; + ---------- -- Hash -- ---------- @@ -428,6 +642,26 @@ package body ALI is return Invocation_Construct_Codes (Kind); end Invocation_Construct_Kind_To_Code; + ------------------------------- + -- Invocation_Graph_Encoding -- + ------------------------------- + + function Invocation_Graph_Encoding return Invocation_Graph_Encoding_Kind is + begin + return Compile_Time_Invocation_Graph_Encoding; + end Invocation_Graph_Encoding; + + -------------------------------------------- + -- Invocation_Graph_Encoding_Kind_To_Code -- + -------------------------------------------- + + function Invocation_Graph_Encoding_Kind_To_Code + (Kind : Invocation_Graph_Encoding_Kind) return Character + is + begin + return Invocation_Graph_Encoding_Codes (Kind); + end Invocation_Graph_Encoding_Kind_To_Code; + ---------------------------------------- -- Invocation_Graph_Line_Kind_To_Code -- ---------------------------------------- @@ -489,6 +723,70 @@ package body ALI is end Invocation_Signature_Of; ------------- + -- Invoker -- + ------------- + + function Invoker + (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id + is + begin + pragma Assert (Present (IR_Id)); + return Invocation_Relations.Table (IR_Id).Invoker; + end Invoker; + + ---------- + -- Kind -- + ---------- + + function Kind + (IC_Id : Invocation_Construct_Id) return Invocation_Construct_Kind + is + begin + pragma Assert (Present (IC_Id)); + return Invocation_Constructs.Table (IC_Id).Kind; + end Kind; + + ---------- + -- Kind -- + ---------- + + function Kind (IR_Id : Invocation_Relation_Id) return Invocation_Kind is + begin + pragma Assert (Present (IR_Id)); + return Invocation_Relations.Table (IR_Id).Kind; + end Kind; + + ---------- + -- Line -- + ---------- + + function Line (IS_Id : Invocation_Signature_Id) return Nat is + begin + pragma Assert (Present (IS_Id)); + return Invocation_Signatures.Table (IS_Id).Line; + end Line; + + --------------- + -- Locations -- + --------------- + + function Locations (IS_Id : Invocation_Signature_Id) return Name_Id is + begin + pragma Assert (Present (IS_Id)); + return Invocation_Signatures.Table (IS_Id).Locations; + end Locations; + + ---------- + -- Name -- + ---------- + + function Name (IS_Id : Invocation_Signature_Id) return Name_Id is + begin + pragma Assert (Present (IS_Id)); + return Invocation_Signatures.Table (IS_Id).Name; + end Name; + + ------------- -- Present -- ------------- @@ -638,7 +936,7 @@ package body ALI is -- -- If Ignore_Special is False (normal case), the scan is terminated by -- a typeref bracket or an equal sign except for the special case of - -- an operator name starting with a double quote which is terminated + -- an operator name starting with a double quote that is terminated -- by another double quote. -- -- If May_Be_Quoted is True and the first non blank character is '"' @@ -674,7 +972,7 @@ package body ALI is -- Parse the definition of a typeref (<...>, {...} or (...)) procedure Scan_Invocation_Graph_Line; - -- Parse a single line which encodes a piece of the invocation graph + -- Parse a single line that encodes a piece of the invocation graph procedure Skip_Eol; -- Skip past spaces, then skip past end of line (fatal error if not @@ -1204,6 +1502,13 @@ package body ALI is -- * Invocation_Constructs -- * Units + procedure Scan_Invocation_Graph_Attributes_Line; + pragma Inline (Scan_Invocation_Graph_Attributes_Line); + -- Parse an invocation-graph attributes line. The following data + -- structures are updated: + -- + -- * Units + procedure Scan_Invocation_Relation_Line; pragma Inline (Scan_Invocation_Relation_Line); -- Parse an invocation relation line and construct the corresponding @@ -1225,51 +1530,78 @@ package body ALI is ------------------------------------ procedure Scan_Invocation_Construct_Line is - IC_Rec : Invocation_Construct_Record; + Body_Placement : Declaration_Placement_Kind; + Kind : Invocation_Construct_Kind; + Signature : Invocation_Signature_Id; + Spec_Placement : Declaration_Placement_Kind; begin -- construct-kind - IC_Rec.Kind := Code_To_Invocation_Construct_Kind (Getc); + Kind := Code_To_Invocation_Construct_Kind (Getc); + Checkc (' '); + Skip_Space; + + -- construct-spec-placement + + Spec_Placement := Code_To_Declaration_Placement_Kind (Getc); Checkc (' '); Skip_Space; -- construct-body-placement - IC_Rec.Placement := Code_To_Body_Placement_Kind (Getc); + Body_Placement := Code_To_Declaration_Placement_Kind (Getc); Checkc (' '); Skip_Space; -- construct-signature - IC_Rec.Signature := Scan_Invocation_Signature; - pragma Assert (Present (IC_Rec.Signature)); - + Signature := Scan_Invocation_Signature; Skip_Eol; - Add_Invocation_Construct (IC_Rec); + Add_Invocation_Construct + (Body_Placement => Body_Placement, + Kind => Kind, + Signature => Signature, + Spec_Placement => Spec_Placement); end Scan_Invocation_Construct_Line; + ------------------------------------------- + -- Scan_Invocation_Graph_Attributes_Line -- + ------------------------------------------- + + procedure Scan_Invocation_Graph_Attributes_Line is + begin + -- encoding-kind + + Set_Invocation_Graph_Encoding + (Code_To_Invocation_Graph_Encoding_Kind (Getc)); + Skip_Eol; + end Scan_Invocation_Graph_Attributes_Line; + ----------------------------------- -- Scan_Invocation_Relation_Line -- ----------------------------------- procedure Scan_Invocation_Relation_Line is - IR_Rec : Invocation_Relation_Record; + Extra : Name_Id; + Invoker : Invocation_Signature_Id; + Kind : Invocation_Kind; + Target : Invocation_Signature_Id; begin -- relation-kind - IR_Rec.Kind := Code_To_Invocation_Kind (Getc); + Kind := Code_To_Invocation_Kind (Getc); Checkc (' '); Skip_Space; -- (extra-name | "none") - IR_Rec.Extra := Get_Name; + Extra := Get_Name; - if IR_Rec.Extra = Name_None then - IR_Rec.Extra := No_Name; + if Extra = Name_None then + Extra := No_Name; end if; Checkc (' '); @@ -1277,20 +1609,20 @@ package body ALI is -- invoker-signature - IR_Rec.Invoker := Scan_Invocation_Signature; - pragma Assert (Present (IR_Rec.Invoker)); - + Invoker := Scan_Invocation_Signature; Checkc (' '); Skip_Space; -- target-signature - IR_Rec.Target := Scan_Invocation_Signature; - pragma Assert (Present (IR_Rec.Target)); - + Target := Scan_Invocation_Signature; Skip_Eol; - Add_Invocation_Relation (IR_Rec); + Add_Invocation_Relation + (Extra => Extra, + Invoker => Invoker, + Kind => Kind, + Target => Target); end Scan_Invocation_Relation_Line; ------------------------------- @@ -1378,13 +1710,16 @@ package body ALI is -- line-attributes - if Line = Invocation_Construct_Line then - Scan_Invocation_Construct_Line; + case Line is + when Invocation_Construct_Line => + Scan_Invocation_Construct_Line; - else - pragma Assert (Line = Invocation_Relation_Line); - Scan_Invocation_Relation_Line; - end if; + when Invocation_Graph_Attributes_Line => + Scan_Invocation_Graph_Attributes_Line; + + when Invocation_Relation_Line => + Scan_Invocation_Relation_Line; + end case; end Scan_Invocation_Graph_Line; -------------- @@ -3064,7 +3399,7 @@ package body ALI is ALIs.Table (Id).Last_Sdep := Sdep.Last; - -- Loop through invocation graph lines + -- Loop through invocation-graph lines G_Loop : loop Check_Unknown_Line; @@ -3436,6 +3771,16 @@ package body ALI is return No_ALI_Id; end Scan_ALI; + ----------- + -- Scope -- + ----------- + + function Scope (IS_Id : Invocation_Signature_Id) return Name_Id is + begin + pragma Assert (Present (IS_Id)); + return Invocation_Signatures.Table (IS_Id).Scope; + end Scope; + --------- -- SEq -- --------- @@ -3445,6 +3790,30 @@ package body ALI is return F1.all = F2.all; end SEq; + ----------------------------------- + -- Set_Invocation_Graph_Encoding -- + ----------------------------------- + + procedure Set_Invocation_Graph_Encoding + (Kind : Invocation_Graph_Encoding_Kind; + Update_Units : Boolean := True) + is + begin + Compile_Time_Invocation_Graph_Encoding := Kind; + + -- Update the invocation-graph encoding of the current unit only when + -- requested by the caller. + + if Update_Units then + declare + Curr_Unit : Unit_Record renames Units.Table (Units.Last); + + begin + Curr_Unit.Invocation_Graph_Encoding := Kind; + end; + end if; + end Set_Invocation_Graph_Encoding; + ----------- -- SHash -- ----------- @@ -3461,4 +3830,40 @@ package body ALI is return Vindex (Vindex'First + Vindex (H mod Vindex'Range_Length)); end SHash; + --------------- + -- Signature -- + --------------- + + function Signature + (IC_Id : Invocation_Construct_Id) return Invocation_Signature_Id + is + begin + pragma Assert (Present (IC_Id)); + return Invocation_Constructs.Table (IC_Id).Signature; + end Signature; + + -------------------- + -- Spec_Placement -- + -------------------- + + function Spec_Placement + (IC_Id : Invocation_Construct_Id) return Declaration_Placement_Kind + is + begin + pragma Assert (Present (IC_Id)); + return Invocation_Constructs.Table (IC_Id).Spec_Placement; + end Spec_Placement; + + ------------ + -- Target -- + ------------ + + function Target + (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id + is + begin + pragma Assert (Present (IR_Id)); + return Invocation_Relations.Table (IR_Id).Target; + end Target; + end ALI; diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads index 79eabb1..6db9e49 100644 --- a/gcc/ada/ali.ads +++ b/gcc/ada/ali.ads @@ -112,6 +112,20 @@ package ALI is First_ALI_Entry : constant ALI_Id := No_ALI_Id + 1; -- Id of first actual entry in table + -- The following type enumerates all possible invocation-graph encoding + -- kinds. + + type Invocation_Graph_Encoding_Kind is + (Endpoints_Encoding, + -- The invocation construct and relation lines contain information for + -- the start construct and end target found on an invocation-graph path. + + Full_Path_Encoding, + -- The invocation construct and relation lines contain information for + -- all constructs and targets found on a invocation-graph path. + + No_Encoding); + type Main_Program_Type is (None, Proc, Func); -- Indicator of whether unit can be used as main program @@ -368,6 +382,11 @@ package ALI is Last_Arg : Arg_Id; -- Id of last args table entry for this file + Invocation_Graph_Encoding : Invocation_Graph_Encoding_Kind; + -- The encoding format used to capture information about the invocation + -- constructs and relations within the corresponding ALI file of this + -- unit. + First_Invocation_Construct : Invocation_Construct_Id; -- Id of the first invocation construct for this unit @@ -1087,6 +1106,20 @@ package ALI is -- Invocation Graph Types -- ---------------------------- + -- The following type identifies an invocation construct + + No_Invocation_Construct : constant Invocation_Construct_Id := + Invocation_Construct_Id'First; + First_Invocation_Construct : constant Invocation_Construct_Id := + No_Invocation_Construct + 1; + + -- The following type identifies an invocation relation + + No_Invocation_Relation : constant Invocation_Relation_Id := + Invocation_Relation_Id'First; + First_Invocation_Relation : constant Invocation_Relation_Id := + No_Invocation_Relation + 1; + -- The following type identifies an invocation signature No_Invocation_Signature : constant Invocation_Signature_Id := @@ -1094,59 +1127,20 @@ package ALI is First_Invocation_Signature : constant Invocation_Signature_Id := No_Invocation_Signature + 1; - -- The following type represents an invocation signature. Its purpose is - -- to uniquely identify an invocation construct within the ALI space. The - -- signature is comprised out of several pieces, some of which are used in - -- error diagnostics by the binder. Identification issues are resolved as - -- follows: - -- - -- * The Column, Line, and Locations attributes together differentiate - -- between homonyms. In most cases, the Column and Line are sufficient - -- except when generic instantiations are involved. Together, the three - -- attributes offer a sequence of column-line pairs which eventually - -- reflect the location within the generic template. - -- - -- * The Name attribute differentiates between invocation constructs at - -- the scope level. Since it is illegal for two entities with the same - -- name to coexist in the same scope, the Name attribute is sufficient - -- to distinguish them. Overloaded entities are already handled by the - -- Column, Line, and Locations attributes. - -- - -- * The Scope attribute differentiates between invocation constructs at - -- various levels of nesting. - - type Invocation_Signature_Record is record - Column : Nat := 0; - -- The column number where the invocation construct is declared - - Line : Nat := 0; - -- The line number where the invocation construct is declared - - Locations : Name_Id := No_Name; - -- Sequence of column and line numbers within nested instantiations - - Name : Name_Id := No_Name; - -- The name of the invocation construct - - Scope : Name_Id := No_Name; - -- The qualified name of the scope where the invocation construct is - -- declared. - end record; - -- The following type enumerates all possible placements of an invocation - -- construct's body body with respect to the unit it is declared in. + -- construct's spec and body with respect to the unit it is declared in. - type Body_Placement_Kind is + type Declaration_Placement_Kind is (In_Body, - -- The body of the invocation construct is within the body of the unit - -- it is declared in. + -- The declaration of the invocation construct is within the body of the + -- unit it is declared in. In_Spec, - -- The body of the invocation construct is within the spec of the unit - -- it is declared in. + -- The declaration of the invocation construct is within the spec of the + -- unit it is declared in. - No_Body_Placement); - -- The invocation construct does not have a body + No_Declaration_Placement); + -- The invocation construct does not have a declaration -- The following type enumerates all possible invocation construct kinds @@ -1162,35 +1156,6 @@ package ALI is Regular_Construct); -- The invocation construct is a normal invocation construct - -- The following type identifies an invocation construct - - No_Invocation_Construct : constant Invocation_Construct_Id := - Invocation_Construct_Id'First; - First_Invocation_Construct : constant Invocation_Construct_Id := - No_Invocation_Construct + 1; - - -- The following type represents an invocation construct - - type Invocation_Construct_Record is record - Kind : Invocation_Construct_Kind := Regular_Construct; - -- The nature of the invocation construct - - Placement : Body_Placement_Kind := No_Body_Placement; - -- The location of the invocation construct's body with respect to the - -- body of the unit it is declared in. - - Signature : Invocation_Signature_Id := No_Invocation_Signature; - -- The invocation signature which uniquely identifies the invocation - -- construct in the ALI space. - end record; - - -- The following type identifies an invocation relation - - No_Invocation_Relation : constant Invocation_Relation_Id := - Invocation_Relation_Id'First; - First_Invocation_Relation : constant Invocation_Relation_Id := - No_Invocation_Relation + 1; - -- The following type enumerates all possible invocation kinds type Invocation_Kind is @@ -1220,94 +1185,60 @@ package ALI is -- Internal_Controlled_Finalization Internal_Controlled_Initialization; - -- The following type represents an invocation relation. It associates an - -- invoker which activates/calls/instantiates with a target. - - type Invocation_Relation_Record is record - Extra : Name_Id := No_Name; - -- The name of an additional entity used in error diagnostics - - Invoker : Invocation_Signature_Id := No_Invocation_Signature; - -- The invocation signature which uniquely identifies the invoker within - -- the ALI space. - - Kind : Invocation_Kind := No_Invocation; - -- The nature of the invocation - - Target : Invocation_Signature_Id := No_Invocation_Signature; - -- The invocation signature which uniquely identifies the target within - -- the ALI space. - end record; - - -- The following type enumerates all possible invocation graph ALI lines + -- The following type enumerates all possible invocation-graph ALI lines type Invocation_Graph_Line_Kind is (Invocation_Construct_Line, + Invocation_Graph_Attributes_Line, Invocation_Relation_Line); - -------------------------------------- - -- Invocation Graph Data Structures -- - -------------------------------------- - - package Invocation_Constructs is new Table.Table - (Table_Index_Type => Invocation_Construct_Id, - Table_Component_Type => Invocation_Construct_Record, - Table_Low_Bound => First_Invocation_Construct, - Table_Initial => 2500, - Table_Increment => 200, - Table_Name => "Invocation_Constructs"); - - package Invocation_Relations is new Table.Table - (Table_Index_Type => Invocation_Relation_Id, - Table_Component_Type => Invocation_Relation_Record, - Table_Low_Bound => First_Invocation_Relation, - Table_Initial => 2500, - Table_Increment => 200, - Table_Name => "Invocation_Relation"); - - package Invocation_Signatures is new Table.Table - (Table_Index_Type => Invocation_Signature_Id, - Table_Component_Type => Invocation_Signature_Record, - Table_Low_Bound => First_Invocation_Signature, - Table_Initial => 2500, - Table_Increment => 200, - Table_Name => "Invocation_Signatures"); - ---------------------------------- -- Invocation Graph Subprograms -- ---------------------------------- procedure Add_Invocation_Construct - (IC_Rec : Invocation_Construct_Record; - Update_Units : Boolean := True); + (Body_Placement : Declaration_Placement_Kind; + Kind : Invocation_Construct_Kind; + Signature : Invocation_Signature_Id; + Spec_Placement : Declaration_Placement_Kind; + Update_Units : Boolean := True); pragma Inline (Add_Invocation_Construct); - -- Add invocation construct attributes IC_Rec to internal data structures. - -- Flag Undate_Units should be set when this addition must be reflected in - -- the attributes of the current unit. + -- Add a new invocation construct described by its attributes. Update_Units + -- should be set when this addition must be reflected in the attributes of + -- the current unit. procedure Add_Invocation_Relation - (IR_Rec : Invocation_Relation_Record; + (Extra : Name_Id; + Invoker : Invocation_Signature_Id; + Kind : Invocation_Kind; + Target : Invocation_Signature_Id; Update_Units : Boolean := True); pragma Inline (Add_Invocation_Relation); - -- Add invocation relation attributes IR_Rec to internal data structures. - -- Flag Undate_Units should be set when this addition must be reflected in - -- the attributes of the current unit. + -- Add a new invocation relation described by its attributes. Update_Units + -- should be set when this addition must be reflected in the attributes of + -- the current unit. - function Body_Placement_Kind_To_Code - (Kind : Body_Placement_Kind) return Character; - pragma Inline (Body_Placement_Kind_To_Code); - -- Obtain the character encoding of body placement kind Kind + function Body_Placement + (IC_Id : Invocation_Construct_Id) return Declaration_Placement_Kind; + pragma Inline (Body_Placement); + -- Obtain the location of invocation construct IC_Id's body with respect to + -- the unit where it is declared. - function Code_To_Body_Placement_Kind - (Code : Character) return Body_Placement_Kind; - pragma Inline (Code_To_Body_Placement_Kind); - -- Obtain the body placement kind of character encoding Code + function Code_To_Declaration_Placement_Kind + (Code : Character) return Declaration_Placement_Kind; + pragma Inline (Code_To_Declaration_Placement_Kind); + -- Obtain the declaration placement kind of character encoding Code function Code_To_Invocation_Construct_Kind (Code : Character) return Invocation_Construct_Kind; pragma Inline (Code_To_Invocation_Construct_Kind); -- Obtain the invocation construct kind of character encoding Code + function Code_To_Invocation_Graph_Encoding_Kind + (Code : Character) return Invocation_Graph_Encoding_Kind; + pragma Inline (Code_To_Invocation_Graph_Encoding_Kind); + -- Obtain the invocation-graph encoding kind of character encoding Code + function Code_To_Invocation_Kind (Code : Character) return Invocation_Kind; pragma Inline (Code_To_Invocation_Kind); @@ -1316,17 +1247,58 @@ package ALI is function Code_To_Invocation_Graph_Line_Kind (Code : Character) return Invocation_Graph_Line_Kind; pragma Inline (Code_To_Invocation_Graph_Line_Kind); - -- Obtain the invocation graph line kind of character encoding Code + -- Obtain the invocation-graph line kind of character encoding Code + + function Column (IS_Id : Invocation_Signature_Id) return Nat; + pragma Inline (Column); + -- Obtain the column number of invocation signature IS_Id + + function Declaration_Placement_Kind_To_Code + (Kind : Declaration_Placement_Kind) return Character; + pragma Inline (Declaration_Placement_Kind_To_Code); + -- Obtain the character encoding of declaration placement kind Kind + + function Extra (IR_Id : Invocation_Relation_Id) return Name_Id; + pragma Inline (Extra); + -- Obtain the name of the additional entity used in error diagnostics for + -- invocation relation IR_Id. + + type Invocation_Construct_Processor_Ptr is + access procedure (IC_Id : Invocation_Construct_Id); + + procedure For_Each_Invocation_Construct + (Processor : Invocation_Construct_Processor_Ptr); + pragma Inline (For_Each_Invocation_Construct); + -- Invoke Processor on each invocation construct + + type Invocation_Relation_Processor_Ptr is + access procedure (IR_Id : Invocation_Relation_Id); + + procedure For_Each_Invocation_Relation + (Processor : Invocation_Relation_Processor_Ptr); + pragma Inline (For_Each_Invocation_Relation); + -- Invoker Processor on each invocation relation function Invocation_Construct_Kind_To_Code (Kind : Invocation_Construct_Kind) return Character; pragma Inline (Invocation_Construct_Kind_To_Code); -- Obtain the character encoding of invocation kind Kind + function Invocation_Graph_Encoding return Invocation_Graph_Encoding_Kind; + pragma Inline (Invocation_Graph_Encoding); + -- Obtain the encoding format used to capture information about the + -- invocation constructs and relations within the ALI file of the main + -- unit. + + function Invocation_Graph_Encoding_Kind_To_Code + (Kind : Invocation_Graph_Encoding_Kind) return Character; + pragma Inline (Invocation_Graph_Encoding_Kind_To_Code); + -- Obtain the character encoding for invocation-graph encoding kind Kind + function Invocation_Graph_Line_Kind_To_Code (Kind : Invocation_Graph_Line_Kind) return Character; pragma Inline (Invocation_Graph_Line_Kind_To_Code); - -- Obtain the character encoding for invocation like kind Kind + -- Obtain the character encoding for invocation line kind Kind function Invocation_Kind_To_Code (Kind : Invocation_Kind) return Character; @@ -1342,6 +1314,63 @@ package ALI is pragma Inline (Invocation_Signature_Of); -- Obtain the invocation signature that corresponds to the input attributes + function Invoker + (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id; + pragma Inline (Invoker); + -- Obtain the signature of the invocation relation IR_Id's invoker + + function Kind + (IC_Id : Invocation_Construct_Id) return Invocation_Construct_Kind; + pragma Inline (Kind); + -- Obtain the nature of invocation construct IC_Id + + function Kind + (IR_Id : Invocation_Relation_Id) return Invocation_Kind; + pragma Inline (Kind); + -- Obtain the nature of invocation relation IR_Id + + function Line (IS_Id : Invocation_Signature_Id) return Nat; + pragma Inline (Line); + -- Obtain the line number of invocation signature IS_Id + + function Locations (IS_Id : Invocation_Signature_Id) return Name_Id; + pragma Inline (Locations); + -- Obtain the sequence of column and line numbers within nested instances + -- of invocation signature IS_Id + + function Name (IS_Id : Invocation_Signature_Id) return Name_Id; + pragma Inline (Name); + -- Obtain the name of invocation signature IS_Id + + function Scope (IS_Id : Invocation_Signature_Id) return Name_Id; + pragma Inline (Scope); + -- Obtain the scope of invocation signature IS_Id + + procedure Set_Invocation_Graph_Encoding + (Kind : Invocation_Graph_Encoding_Kind; + Update_Units : Boolean := True); + pragma Inline (Set_Invocation_Graph_Encoding); + -- Set the encoding format used to capture information about the invocation + -- constructs and relations within the ALI file of the main unit to Kind. + -- Update_Units should be set when this action must be reflected in the + -- attributes of the current unit. + + function Signature + (IC_Id : Invocation_Construct_Id) return Invocation_Signature_Id; + pragma Inline (Signature); + -- Obtain the signature of invocation construct IC_Id + + function Spec_Placement + (IC_Id : Invocation_Construct_Id) return Declaration_Placement_Kind; + pragma Inline (Spec_Placement); + -- Obtain the location of invocation construct IC_Id's spec with respect to + -- the unit where it is declared. + + function Target + (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id; + pragma Inline (Target); + -- Obtain the signature of the invocation relation IR_Id's target + -------------------------------------- -- Subprograms for Reading ALI File -- -------------------------------------- diff --git a/gcc/ada/bindo-augmentors.adb b/gcc/ada/bindo-augmentors.adb index f97f0d0..af39464 100644 --- a/gcc/ada/bindo-augmentors.adb +++ b/gcc/ada/bindo-augmentors.adb @@ -29,9 +29,6 @@ with Types; use Types; with Bindo.Writers; use Bindo.Writers; -with GNAT; use GNAT; -with GNAT.Sets; use GNAT.Sets; - package body Bindo.Augmentors is ------------------------------ @@ -41,22 +38,12 @@ package body Bindo.Augmentors is package body Library_Graph_Augmentors is ----------------- - -- Visited set -- - ----------------- - - package VS is new Membership_Sets - (Element_Type => Invocation_Graph_Vertex_Id, - "=" => "=", - Hash => Hash_Invocation_Graph_Vertex); - use VS; - - ----------------- -- Global data -- ----------------- - Inv_Graph : Invocation_Graph := Invocation_Graphs.Nil; - Lib_Graph : Library_Graph := Library_Graphs.Nil; - Visited : Membership_Set := VS.Nil; + Inv_Graph : Invocation_Graph := Invocation_Graphs.Nil; + Lib_Graph : Library_Graph := Library_Graphs.Nil; + Visited : IGV_Sets.Membership_Set := IGV_Sets.Nil; ---------------- -- Statistics -- @@ -75,16 +62,16 @@ package body Bindo.Augmentors is ----------------------- function Is_Visited - (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean; + (Vertex : Invocation_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Visited); - -- Determine whether invocation graph vertex IGV_Id has been visited + -- Determine whether invocation graph vertex Vertex has been visited -- during the traversal. procedure Set_Is_Visited - (IGV_Id : Invocation_Graph_Vertex_Id; + (Vertex : Invocation_Graph_Vertex_Id; Val : Boolean := True); pragma Inline (Set_Is_Visited); - -- Mark invocation graph vertex IGV_Id as visited during the traversal + -- Mark invocation graph vertex Vertex as visited during the traversal -- depending on value Val. procedure Visit_Elaboration_Root (Root : Invocation_Graph_Vertex_Id); @@ -106,26 +93,26 @@ package body Bindo.Augmentors is -- successor is the current root. procedure Visit_Vertex - (Curr_IGV_Id : Invocation_Graph_Vertex_Id; - Last_LGV_Id : Library_Graph_Vertex_Id; - Root_LGV_Id : Library_Graph_Vertex_Id; - Internal_Ctrl : Boolean; - Path : Natural); + (Invoker : Invocation_Graph_Vertex_Id; + Last_Vertex : Library_Graph_Vertex_Id; + Root_Vertex : Library_Graph_Vertex_Id; + Internal_Controlled_Action : Boolean; + Path : Natural); pragma Inline (Visit_Vertex); - -- Visit invocation graph vertex Curr_IGV_Id to: + -- Visit invocation graph vertex Invoker to: -- -- * Detect a transition from the last library graph vertex denoted by - -- Last_LGV_Id to the library graph vertex of Curr_IGV_Id. + -- Last_Vertex to the library graph vertex of Invoker. -- -- * Create an invocation edge in library graph Lib_Graph to reflect -- the transition, where the predecessor is the library graph vertex - -- or Curr_IGV_Id, and the successor is Root_LGV_Id. + -- or Invoker, and the successor is Root_Vertex. -- - -- * Visit the neighbours of Curr_IGV_Id. + -- * Visit the neighbours of Invoker. -- - -- Flag Internal_Ctrl should be set when the DFS traversal visited an - -- internal controlled invocation edge. Path denotes the length of the - -- path. + -- Flag Internal_Controlled_Action should be set when the DFS traversal + -- visited an internal controlled invocation edge. Path is the length of + -- the path. procedure Write_Statistics; pragma Inline (Write_Statistics); @@ -166,13 +153,13 @@ package body Bindo.Augmentors is ---------------- function Is_Visited - (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean + (Vertex : Invocation_Graph_Vertex_Id) return Boolean is begin - pragma Assert (Present (Visited)); - pragma Assert (Present (IGV_Id)); + pragma Assert (IGV_Sets.Present (Visited)); + pragma Assert (Present (Vertex)); - return Contains (Visited, IGV_Id); + return IGV_Sets.Contains (Visited, Vertex); end Is_Visited; -------------------- @@ -180,17 +167,17 @@ package body Bindo.Augmentors is -------------------- procedure Set_Is_Visited - (IGV_Id : Invocation_Graph_Vertex_Id; + (Vertex : Invocation_Graph_Vertex_Id; Val : Boolean := True) is begin - pragma Assert (Present (Visited)); - pragma Assert (Present (IGV_Id)); + pragma Assert (IGV_Sets.Present (Visited)); + pragma Assert (Present (Vertex)); if Val then - Insert (Visited, IGV_Id); + IGV_Sets.Insert (Visited, Vertex); else - Delete (Visited, IGV_Id); + IGV_Sets.Delete (Visited, Vertex); end if; end Set_Is_Visited; @@ -203,24 +190,24 @@ package body Bindo.Augmentors is pragma Assert (Present (Root)); pragma Assert (Present (Lib_Graph)); - Root_LGV_Id : constant Library_Graph_Vertex_Id := - Lib_Vertex (Inv_Graph, Root); + Root_Vertex : constant Library_Graph_Vertex_Id := + Body_Vertex (Inv_Graph, Root); - pragma Assert (Present (Root_LGV_Id)); + pragma Assert (Present (Root_Vertex)); begin -- Prepare the global data - Visited := Create (Number_Of_Vertices (Inv_Graph)); + Visited := IGV_Sets.Create (Number_Of_Vertices (Inv_Graph)); Visit_Vertex - (Curr_IGV_Id => Root, - Last_LGV_Id => Root_LGV_Id, - Root_LGV_Id => Root_LGV_Id, - Internal_Ctrl => False, - Path => 0); + (Invoker => Root, + Last_Vertex => Root_Vertex, + Root_Vertex => Root_Vertex, + Internal_Controlled_Action => False, + Path => 0); - Destroy (Visited); + IGV_Sets.Destroy (Visited); end Visit_Elaboration_Root; ----------------------------- @@ -237,7 +224,6 @@ package body Bindo.Augmentors is Iter := Iterate_Elaboration_Roots (Inv_Graph); while Has_Next (Iter) loop Next (Iter, Root); - pragma Assert (Present (Root)); Visit_Elaboration_Root (Root); end loop; @@ -248,34 +234,33 @@ package body Bindo.Augmentors is ------------------ procedure Visit_Vertex - (Curr_IGV_Id : Invocation_Graph_Vertex_Id; - Last_LGV_Id : Library_Graph_Vertex_Id; - Root_LGV_Id : Library_Graph_Vertex_Id; - Internal_Ctrl : Boolean; - Path : Natural) + (Invoker : Invocation_Graph_Vertex_Id; + Last_Vertex : Library_Graph_Vertex_Id; + Root_Vertex : Library_Graph_Vertex_Id; + Internal_Controlled_Action : Boolean; + Path : Natural) is New_Path : constant Natural := Path + 1; - Curr_LGV_Id : Library_Graph_Vertex_Id; - IGE_Id : Invocation_Graph_Edge_Id; - Iter : Edges_To_Targets_Iterator; - Targ : Invocation_Graph_Vertex_Id; + Edge : Invocation_Graph_Edge_Id; + Invoker_Vertex : Library_Graph_Vertex_Id; + Iter : Edges_To_Targets_Iterator; begin pragma Assert (Present (Inv_Graph)); - pragma Assert (Present (Curr_IGV_Id)); pragma Assert (Present (Lib_Graph)); - pragma Assert (Present (Last_LGV_Id)); - pragma Assert (Present (Root_LGV_Id)); + pragma Assert (Present (Invoker)); + pragma Assert (Present (Last_Vertex)); + pragma Assert (Present (Root_Vertex)); -- Nothing to do when the current invocation graph vertex has already -- been visited. - if Is_Visited (Curr_IGV_Id) then + if Is_Visited (Invoker) then return; end if; - Set_Is_Visited (Curr_IGV_Id); + Set_Is_Visited (Invoker); -- Update the statistics @@ -287,10 +272,10 @@ package body Bindo.Augmentors is -- indicates that elaboration is transitioning from one unit to -- another. Add a library graph edge to capture this dependency. - Curr_LGV_Id := Lib_Vertex (Inv_Graph, Curr_IGV_Id); - pragma Assert (Present (Curr_LGV_Id)); + Invoker_Vertex := Body_Vertex (Inv_Graph, Invoker); + pragma Assert (Present (Invoker_Vertex)); - if Curr_LGV_Id /= Last_LGV_Id then + if Invoker_Vertex /= Last_Vertex then -- The path ultimately reaches back into the unit where the root -- resides, resulting in a self dependency. In most cases this is @@ -299,7 +284,9 @@ package body Bindo.Augmentors is -- library graph edge because the circularity is the result of -- expansion and thus spurious. - if Curr_LGV_Id = Root_LGV_Id and then Internal_Ctrl then + if Invoker_Vertex = Root_Vertex + and then Internal_Controlled_Action + then null; -- Otherwise create the library graph edge, even if this results @@ -308,8 +295,8 @@ package body Bindo.Augmentors is else Add_Edge (G => Lib_Graph, - Pred => Curr_LGV_Id, - Succ => Root_LGV_Id, + Pred => Invoker_Vertex, + Succ => Root_Vertex, Kind => Invocation_Edge); end if; end if; @@ -317,23 +304,19 @@ package body Bindo.Augmentors is -- Extend the DFS traversal to all targets of the invocation graph -- vertex. - Iter := Iterate_Edges_To_Targets (Inv_Graph, Curr_IGV_Id); + Iter := Iterate_Edges_To_Targets (Inv_Graph, Invoker); while Has_Next (Iter) loop - Next (Iter, IGE_Id); - pragma Assert (Present (IGE_Id)); - - Targ := Target (Inv_Graph, IGE_Id); - pragma Assert (Present (Targ)); + Next (Iter, Edge); Visit_Vertex - (Curr_IGV_Id => Targ, - Last_LGV_Id => Curr_LGV_Id, - Root_LGV_Id => Root_LGV_Id, - Internal_Ctrl => - Internal_Ctrl - or else Kind (Inv_Graph, IGE_Id) in + (Invoker => Target (Inv_Graph, Edge), + Last_Vertex => Invoker_Vertex, + Root_Vertex => Root_Vertex, + Internal_Controlled_Action => + Internal_Controlled_Action + or else Kind (Inv_Graph, Edge) in Internal_Controlled_Invocation_Kind, - Path => New_Path); + Path => New_Path); end loop; end Visit_Vertex; diff --git a/gcc/ada/bindo-builders.adb b/gcc/ada/bindo-builders.adb index c0340c0..f4b8e42 100644 --- a/gcc/ada/bindo-builders.adb +++ b/gcc/ada/bindo-builders.adb @@ -64,10 +64,10 @@ package body Bindo.Builders is procedure Create_Vertex (IC_Id : Invocation_Construct_Id; - LGV_Id : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id); pragma Inline (Create_Vertex); -- Create a new vertex for invocation construct IC_Id in invocation - -- graph Inv_Graph. The vertex is linked to vertex LGV_Id of library + -- graph Inv_Graph. The vertex is linked to vertex Vertex of library -- graph Lib_Graph. procedure Create_Vertices (U_Id : Unit_Id); @@ -75,6 +75,14 @@ package body Bindo.Builders is -- Create new vertices for all invocation constructs of unit U_Id in -- invocation graph Inv_Graph. + function Declaration_Placement_Vertex + (Vertex : Library_Graph_Vertex_Id; + Placement : Declaration_Placement_Kind) + return Library_Graph_Vertex_Id; + pragma Inline (Declaration_Placement_Vertex); + -- Obtain the spec or body of vertex Vertex depending on the requested + -- placement in Placement. + ---------------------------- -- Build_Invocation_Graph -- ---------------------------- @@ -88,8 +96,9 @@ package body Bindo.Builders is -- Prepare the global data Inv_Graph := - Create (Initial_Vertices => Number_Of_Elaborable_Units, - Initial_Edges => Number_Of_Elaborable_Units); + Create + (Initial_Vertices => Number_Of_Elaborable_Units, + Initial_Edges => Number_Of_Elaborable_Units); Lib_Graph := Lib_G; For_Each_Elaborable_Unit (Create_Vertices'Access); @@ -107,33 +116,24 @@ package body Bindo.Builders is pragma Assert (Present (Lib_Graph)); pragma Assert (Present (IR_Id)); - IR_Rec : Invocation_Relation_Record renames - Invocation_Relations.Table (IR_Id); - - pragma Assert (Present (IR_Rec.Invoker)); - pragma Assert (Present (IR_Rec.Target)); + Invoker_Sig : constant Invocation_Signature_Id := Invoker (IR_Id); + Target_Sig : constant Invocation_Signature_Id := Target (IR_Id); - Invoker : Invocation_Graph_Vertex_Id; - Target : Invocation_Graph_Vertex_Id; + pragma Assert (Present (Invoker_Sig)); + pragma Assert (Present (Target_Sig)); begin -- Nothing to do when the target denotes an invocation construct that -- resides in a unit which will never be elaborated. - if not Needs_Elaboration (IR_Rec.Target) then + if not Needs_Elaboration (Target_Sig) then return; end if; - Invoker := Corresponding_Vertex (Inv_Graph, IR_Rec.Invoker); - Target := Corresponding_Vertex (Inv_Graph, IR_Rec.Target); - - pragma Assert (Present (Invoker)); - pragma Assert (Present (Target)); - Add_Edge (G => Inv_Graph, - Source => Invoker, - Target => Target, + Source => Corresponding_Vertex (Inv_Graph, Invoker_Sig), + Target => Corresponding_Vertex (Inv_Graph, Target_Sig), IR_Id => IR_Id); end Create_Edge; @@ -162,35 +162,25 @@ package body Bindo.Builders is procedure Create_Vertex (IC_Id : Invocation_Construct_Id; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) is + begin pragma Assert (Present (Inv_Graph)); pragma Assert (Present (Lib_Graph)); pragma Assert (Present (IC_Id)); - pragma Assert (Present (LGV_Id)); - - IC_Rec : Invocation_Construct_Record renames - Invocation_Constructs.Table (IC_Id); - - Body_LGV_Id : Library_Graph_Vertex_Id; - - begin - -- Determine the proper library graph vertex which holds the body of - -- the invocation construct. - - if IC_Rec.Placement = In_Body then - Body_LGV_Id := Proper_Body (Lib_Graph, LGV_Id); - else - pragma Assert (IC_Rec.Placement = In_Spec); - Body_LGV_Id := Proper_Spec (Lib_Graph, LGV_Id); - end if; - - pragma Assert (Present (Body_LGV_Id)); + pragma Assert (Present (Vertex)); Add_Vertex - (G => Inv_Graph, - IC_Id => IC_Id, - LGV_Id => Body_LGV_Id); + (G => Inv_Graph, + IC_Id => IC_Id, + Body_Vertex => + Declaration_Placement_Vertex + (Vertex => Vertex, + Placement => Body_Placement (IC_Id)), + Spec_Vertex => + Declaration_Placement_Vertex + (Vertex => Vertex, + Placement => Spec_Placement (IC_Id))); end Create_Vertex; --------------------- @@ -203,18 +193,37 @@ package body Bindo.Builders is pragma Assert (Present (U_Id)); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); - LGV_Id : constant Library_Graph_Vertex_Id := + Vertex : constant Library_Graph_Vertex_Id := Corresponding_Vertex (Lib_Graph, U_Id); - pragma Assert (Present (LGV_Id)); - begin for IC_Id in U_Rec.First_Invocation_Construct .. U_Rec.Last_Invocation_Construct loop - Create_Vertex (IC_Id, LGV_Id); + Create_Vertex (IC_Id, Vertex); end loop; end Create_Vertices; + + ---------------------------------- + -- Declaration_Placement_Vertex -- + ---------------------------------- + + function Declaration_Placement_Vertex + (Vertex : Library_Graph_Vertex_Id; + Placement : Declaration_Placement_Kind) + return Library_Graph_Vertex_Id + is + begin + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Vertex)); + + if Placement = In_Body then + return Proper_Body (Lib_Graph, Vertex); + else + pragma Assert (Placement = In_Spec); + return Proper_Spec (Lib_Graph, Vertex); + end if; + end Declaration_Placement_Vertex; end Invocation_Graph_Builders; ---------------------------- @@ -235,7 +244,7 @@ package body Bindo.Builders is pragma Inline (Hash_Unit); -- Obtain the hash value of key U_Id - package UL is new Dynamic_Hash_Tables + package Unit_Line_Tables is new Dynamic_Hash_Tables (Key_Type => Unit_Id, Value_Type => Logical_Line_Number, No_Value => No_Line_Number, @@ -253,9 +262,10 @@ package body Bindo.Builders is Lib_Graph : Library_Graph := Library_Graphs.Nil; - Unit_To_Line : UL.Dynamic_Hash_Table := UL.Nil; + Unit_To_Line : Unit_Line_Tables.Dynamic_Hash_Table := + Unit_Line_Tables.Nil; -- The map of unit name -> line number, used to detect duplicate unit - -- names and report errors. + -- names in the forced-elaboration-order file and report errors. ----------------------- -- Local subprograms -- @@ -348,20 +358,24 @@ package body Bindo.Builders is begin pragma Assert (Present (U_Id)); - UL.Put (Unit_To_Line, U_Id, Line); + Unit_Line_Tables.Put (Unit_To_Line, U_Id, Line); end Add_Unit; ------------------------- -- Build_Library_Graph -- ------------------------- - function Build_Library_Graph return Library_Graph is + function Build_Library_Graph + (Dynamically_Elaborated : Boolean) return Library_Graph + is begin -- Prepare the global data Lib_Graph := - Create (Initial_Vertices => Number_Of_Elaborable_Units, - Initial_Edges => Number_Of_Elaborable_Units); + Create + (Initial_Vertices => Number_Of_Elaborable_Units, + Initial_Edges => Number_Of_Elaborable_Units, + Dynamically_Elaborated => Dynamically_Elaborated); For_Each_Elaborable_Unit (Create_Vertex'Access); For_Each_Elaborable_Unit (Create_Spec_And_Body_Edge'Access); @@ -383,14 +397,11 @@ package body Bindo.Builders is pragma Assert (Present (Pred)); pragma Assert (Present (Succ)); - Pred_LGV_Id : constant Library_Graph_Vertex_Id := + Pred_Vertex : constant Library_Graph_Vertex_Id := Corresponding_Vertex (Lib_Graph, Pred); - Succ_LGV_Id : constant Library_Graph_Vertex_Id := + Succ_Vertex : constant Library_Graph_Vertex_Id := Corresponding_Vertex (Lib_Graph, Succ); - pragma Assert (Present (Pred_LGV_Id)); - pragma Assert (Present (Succ_LGV_Id)); - begin Write_Unit_Name (Name (Pred)); Write_Str (" <-- "); @@ -399,8 +410,8 @@ package body Bindo.Builders is Add_Edge (G => Lib_Graph, - Pred => Pred_LGV_Id, - Succ => Succ_LGV_Id, + Pred => Pred_Vertex, + Succ => Succ_Vertex, Kind => Forced_Edge); end Create_Forced_Edge; @@ -409,15 +420,15 @@ package body Bindo.Builders is ------------------------- procedure Create_Forced_Edges is - Curr_Unit : Unit_Id; - Iter : Forced_Units_Iterator; - Prev_Unit : Unit_Id; - Unit_Line : Logical_Line_Number; - Unit_Name : Unit_Name_Type; + Current_Unit : Unit_Id; + Iter : Forced_Units_Iterator; + Previous_Unit : Unit_Id; + Unit_Line : Logical_Line_Number; + Unit_Name : Unit_Name_Type; begin - Prev_Unit := No_Unit_Id; - Unit_To_Line := UL.Create (20); + Previous_Unit := No_Unit_Id; + Unit_To_Line := Unit_Line_Tables.Create (20); -- Inspect the contents of the forced-elaboration-order file supplied -- to the binder using switch -f, and diagnose each unit accordingly. @@ -425,36 +436,35 @@ package body Bindo.Builders is Iter := Iterate_Forced_Units; while Has_Next (Iter) loop Next (Iter, Unit_Name, Unit_Line); - pragma Assert (Present (Unit_Name)); - Curr_Unit := Corresponding_Unit (Unit_Name); + Current_Unit := Corresponding_Unit (Unit_Name); - if not Present (Curr_Unit) then + if not Present (Current_Unit) then Missing_Unit_Info (Unit_Name); - elsif Is_Internal_Unit (Curr_Unit) then + elsif Is_Internal_Unit (Current_Unit) then Internal_Unit_Info (Unit_Name); - elsif Is_Duplicate_Unit (Curr_Unit) then - Duplicate_Unit_Error (Curr_Unit, Unit_Name, Unit_Line); + elsif Is_Duplicate_Unit (Current_Unit) then + Duplicate_Unit_Error (Current_Unit, Unit_Name, Unit_Line); -- Otherwise the unit is a valid candidate for a vertex. Create a -- forced edge between each pair of units. else - Add_Unit (Curr_Unit, Unit_Line); + Add_Unit (Current_Unit, Unit_Line); - if Present (Prev_Unit) then + if Present (Previous_Unit) then Create_Forced_Edge - (Pred => Prev_Unit, - Succ => Curr_Unit); + (Pred => Previous_Unit, + Succ => Current_Unit); end if; - Prev_Unit := Curr_Unit; + Previous_Unit := Current_Unit; end if; end loop; - UL.Destroy (Unit_To_Line); + Unit_Line_Tables.Destroy (Unit_To_Line); end Create_Forced_Edges; ------------------------------- @@ -462,42 +472,37 @@ package body Bindo.Builders is ------------------------------- procedure Create_Spec_And_Body_Edge (U_Id : Unit_Id) is - Aux_LGV_Id : Library_Graph_Vertex_Id; - LGV_Id : Library_Graph_Vertex_Id; + Extra_Vertex : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (Lib_Graph)); pragma Assert (Present (U_Id)); - LGV_Id := Corresponding_Vertex (Lib_Graph, U_Id); - pragma Assert (Present (LGV_Id)); + Vertex := Corresponding_Vertex (Lib_Graph, U_Id); -- The unit denotes a body that completes a previous spec. Link the -- spec and body. Add an edge between the predecessor spec and the -- successor body. - if Is_Body_With_Spec (Lib_Graph, LGV_Id) then - Aux_LGV_Id := + if Is_Body_With_Spec (Lib_Graph, Vertex) then + Extra_Vertex := Corresponding_Vertex (Lib_Graph, Corresponding_Spec (U_Id)); - pragma Assert (Present (Aux_LGV_Id)); - - Set_Corresponding_Item (Lib_Graph, LGV_Id, Aux_LGV_Id); + Set_Corresponding_Item (Lib_Graph, Vertex, Extra_Vertex); Add_Edge (G => Lib_Graph, - Pred => Aux_LGV_Id, - Succ => LGV_Id, + Pred => Extra_Vertex, + Succ => Vertex, Kind => Spec_Before_Body_Edge); -- The unit denotes a spec with a completing body. Link the spec and -- body. - elsif Is_Spec_With_Body (Lib_Graph, LGV_Id) then - Aux_LGV_Id := + elsif Is_Spec_With_Body (Lib_Graph, Vertex) then + Extra_Vertex := Corresponding_Vertex (Lib_Graph, Corresponding_Body (U_Id)); - pragma Assert (Present (Aux_LGV_Id)); - - Set_Corresponding_Item (Lib_Graph, LGV_Id, Aux_LGV_Id); + Set_Corresponding_Item (Lib_Graph, Vertex, Extra_Vertex); end if; end Create_Spec_And_Body_Edge; @@ -531,11 +536,8 @@ package body Bindo.Builders is Withed_U_Id : constant Unit_Id := Corresponding_Unit (Withed_Rec.Uname); - pragma Assert (Present (Withed_U_Id)); - - Aux_LGV_Id : Library_Graph_Vertex_Id; Kind : Library_Graph_Edge_Kind; - Withed_LGV_Id : Library_Graph_Vertex_Id; + Withed_Vertex : Library_Graph_Vertex_Id; begin -- Nothing to do when the withed unit does not need to be elaborated. @@ -545,8 +547,7 @@ package body Bindo.Builders is return; end if; - Withed_LGV_Id := Corresponding_Vertex (Lib_Graph, Withed_U_Id); - pragma Assert (Present (Withed_LGV_Id)); + Withed_Vertex := Corresponding_Vertex (Lib_Graph, Withed_U_Id); -- The with comes with pragma Elaborate @@ -557,15 +558,12 @@ package body Bindo.Builders is -- between the body of the withed predecessor and the withing -- successor. - if Is_Spec_With_Body (Lib_Graph, Withed_LGV_Id) then - Aux_LGV_Id := - Corresponding_Vertex - (Lib_Graph, Corresponding_Body (Withed_U_Id)); - pragma Assert (Present (Aux_LGV_Id)); - + if Is_Spec_With_Body (Lib_Graph, Withed_Vertex) then Add_Edge (G => Lib_Graph, - Pred => Aux_LGV_Id, + Pred => + Corresponding_Vertex + (Lib_Graph, Corresponding_Body (Withed_U_Id)), Succ => Succ, Kind => Kind); end if; @@ -586,7 +584,7 @@ package body Bindo.Builders is Add_Edge (G => Lib_Graph, - Pred => Withed_LGV_Id, + Pred => Withed_Vertex, Succ => Succ, Kind => Kind); end Create_With_Edge; @@ -596,18 +594,13 @@ package body Bindo.Builders is ----------------------- procedure Create_With_Edges (U_Id : Unit_Id) is - LGV_Id : Library_Graph_Vertex_Id; - begin pragma Assert (Present (Lib_Graph)); pragma Assert (Present (U_Id)); - LGV_Id := Corresponding_Vertex (Lib_Graph, U_Id); - pragma Assert (Present (LGV_Id)); - Create_With_Edges (U_Id => U_Id, - Succ => LGV_Id); + Succ => Corresponding_Vertex (Lib_Graph, U_Id)); end Create_With_Edges; ----------------------- @@ -655,7 +648,7 @@ package body Bindo.Builders is pragma Assert (Present (Nam)); Prev_Line : constant Logical_Line_Number := - UL.Get (Unit_To_Line, U_Id); + Unit_Line_Tables.Get (Unit_To_Line, U_Id); begin Error_Msg_Nat_1 := Nat (Line); @@ -698,7 +691,7 @@ package body Bindo.Builders is begin pragma Assert (Present (U_Id)); - return UL.Contains (Unit_To_Line, U_Id); + return Unit_Line_Tables.Contains (Unit_To_Line, U_Id); end Is_Duplicate_Unit; ------------------------- diff --git a/gcc/ada/bindo-builders.ads b/gcc/ada/bindo-builders.ads index 54c39e4..0e8519f 100644 --- a/gcc/ada/bindo-builders.ads +++ b/gcc/ada/bindo-builders.ads @@ -56,9 +56,11 @@ package Bindo.Builders is ---------------------------- package Library_Graph_Builders is - function Build_Library_Graph return Library_Graph; + function Build_Library_Graph + (Dynamically_Elaborated : Boolean) return Library_Graph; -- Return a new library graph that reflects the dependencies between - -- all units of the bind. + -- all units of the bind. Flag Dynamically_Elaborated must be set when + -- the main library unit was compiled using the dynamic model. end Library_Graph_Builders; diff --git a/gcc/ada/bindo-diagnostics.adb b/gcc/ada/bindo-diagnostics.adb index bf11d39..a4b031d 100644 --- a/gcc/ada/bindo-diagnostics.adb +++ b/gcc/ada/bindo-diagnostics.adb @@ -23,50 +23,1457 @@ -- -- ------------------------------------------------------------------------------ +with Binderr; use Binderr; +with Debug; use Debug; +with Types; use Types; + +with Bindo.Validators; +use Bindo.Validators; +use Bindo.Validators.Cycle_Validators; + +with Bindo.Writers; +use Bindo.Writers; +use Bindo.Writers.Cycle_Writers; + package body Bindo.Diagnostics is ----------------------- - -- Cycle_Diagnostics -- + -- Local subprograms -- + ----------------------- + + procedure Diagnose_All_Cycles + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph); + pragma Inline (Diagnose_All_Cycles); + -- Emit diagnostics for all cycles of library graph G + + procedure Diagnose_Cycle + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Diagnose_Cycle); + -- Emit diagnostics for cycle Cycle of library graph G + + procedure Find_And_Output_Invocation_Paths + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Source : Library_Graph_Vertex_Id; + Destination : Library_Graph_Vertex_Id); + pragma Inline (Find_And_Output_Invocation_Paths); + -- Find all paths in invocation graph Inv_Graph that originate from vertex + -- Source and reach vertex Destination of library graph Lib_Graph. Output + -- the transitions of each such path. + + function Find_Elaboration_Root + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Invocation_Graph_Vertex_Id; + pragma Inline (Find_Elaboration_Root); + -- Find the elaboration root in invocation graph Inv_Graph that corresponds + -- to vertex Vertex of library graph Lib_Graph. + + procedure Output_All_Cycles_Suggestions (G : Library_Graph); + pragma Inline (Output_All_Cycles_Suggestions); + -- Suggest the diagnostic of all cycles in library graph G if circumstances + -- allow it. + + procedure Output_Dynamic_Model_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Output_Dynamic_Model_Suggestions); + -- Suggest the use of the dynamic elaboration model to break cycle Cycle of + -- library graph G if circumstances allow it. + + procedure Output_Elaborate_All_Suggestions + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id); + pragma Inline (Output_Elaborate_All_Suggestions); + -- Suggest ways to break a cycle that involves an Elaborate_All edge that + -- links predecessor Pred and successor Succ of library graph G. + + procedure Output_Elaborate_All_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id); + pragma Inline (Output_Elaborate_All_Transition); + -- Output a transition through an Elaborate_All edge of library graph G + -- with successor Source and predecessor Actual_Destination. Parameter + -- Expected_Destination denotes the predecessor as specified by the next + -- edge in a cycle. + + procedure Output_Elaborate_Body_Suggestions + (G : Library_Graph; + Succ : Library_Graph_Vertex_Id); + pragma Inline (Output_Elaborate_Body_Suggestions); + -- Suggest ways to break a cycle that involves an edge where successor Succ + -- is either a spec subject to pragma Elaborate_Body or the body of such a + -- spec. + + procedure Output_Elaborate_Body_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id); + pragma Inline (Output_Elaborate_Body_Transition); + -- Output a transition through an edge of library graph G with successor + -- Source and predecessor Actual_Destination. Vertex Source is either a + -- spec subject to pragma Elaborate_Body or denotes the body of such a + -- spec. Expected_Destination denotes the predecessor as specified by the + -- next edge in a cycle. + + procedure Output_Elaborate_Suggestions + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id); + pragma Inline (Output_Elaborate_Suggestions); + -- Suggest ways to break a cycle that involves an Elaborate edge that links + -- predecessor Pred and successor Succ of library graph G. + + procedure Output_Elaborate_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id); + pragma Inline (Output_Elaborate_Transition); + -- Output a transition through an Elaborate edge of library graph G + -- with successor Source and predecessor Actual_Destination. Parameter + -- Expected_Destination denotes the predecessor as specified by the next + -- edge in a cycle. + + procedure Output_Forced_Suggestions + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id); + pragma Inline (Output_Forced_Suggestions); + -- Suggest ways to break a cycle that involves a Forced edge that links + -- predecessor Pred with successor Succ of library graph G. + + procedure Output_Forced_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean); + pragma Inline (Output_Forced_Transition); + -- Output a transition through a Forced edge of library graph G with + -- successor Source and predecessor Actual_Destination. Parameter + -- Expected_Destination denotes the predecessor as specified by the + -- next edge in a cycle. + + procedure Output_Full_Encoding_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + First_Edge : Library_Graph_Edge_Id); + pragma Inline (Output_Full_Encoding_Suggestions); + -- Suggest the use of the full path invocation graph encoding to break + -- cycle Cycle with initial edge First_Edge of library graph G. + + procedure Output_Invocation_Path + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Elaborated_Vertex : Library_Graph_Vertex_Id; + Path : IGE_Lists.Doubly_Linked_List; + Path_Id : in out Nat); + pragma Inline (Output_Invocation_Path); + -- Output path Path, which consists of invocation graph Inv_Graph edges. + -- Elaborated_Vertex is the vertex of library graph Lib_Graph whose + -- elaboration initiated the path. Path_Id is the unique id of the path. + + procedure Output_Invocation_Path_Transition + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Edge : Invocation_Graph_Edge_Id); + pragma Inline (Output_Invocation_Path_Transition); + -- Output a transition through edge Edge of invocation graph G, which is + -- part of an invocation path. Lib_Graph is the related library graph. + + procedure Output_Invocation_Transition + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Source : Library_Graph_Vertex_Id; + Destination : Library_Graph_Vertex_Id); + pragma Inline (Output_Invocation_Transition); + -- Output a transition through an invocation edge of library graph G with + -- successor Source and predecessor Destination. Inv_Graph is the related + -- invocation graph. + + procedure Output_Reason_And_Circularity_Header + (G : Library_Graph; + First_Edge : Library_Graph_Edge_Id); + pragma Inline (Output_Reason_And_Circularity_Header); + -- Output the reason and circularity header for a circularity of library + -- graph G with initial edge First_Edge. + + procedure Output_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + First_Edge : Library_Graph_Edge_Id); + pragma Inline (Output_Suggestions); + -- Suggest various ways to break cycle Cycle with initial edge First_Edge + -- of library graph G. + + procedure Output_Transition + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Current_Edge : Library_Graph_Edge_Id; + Next_Edge : Library_Graph_Edge_Id; + Elaborate_All_Active : Boolean); + pragma Inline (Output_Transition); + -- Output a transition described by edge Current_Edge, which is followed by + -- edge Next_Edge of library graph Lib_Graph. Inv_Graph denotes the related + -- invocation graph. Elaborate_All_Active should be set when the transition + -- occurs within a cycle that involves an Elaborate_All edge. + + procedure Output_With_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean); + pragma Inline (Output_With_Transition); + -- Output a transition through a regular with edge of library graph G + -- with successor Source and predecessor Actual_Destination. Parameter + -- Expected_Destination denotes the predecessor as specified by the next + -- edge in a cycle. Elaborate_All_Active should be set when the transition + -- occurs within a cycle that involves an Elaborate_All edge. + + procedure Visit_Vertex + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Invoker : Invocation_Graph_Vertex_Id; + Invoker_Vertex : Library_Graph_Vertex_Id; + Last_Vertex : Library_Graph_Vertex_Id; + Elaborated_Vertex : Library_Graph_Vertex_Id; + End_Vertex : Library_Graph_Vertex_Id; + Path : IGE_Lists.Doubly_Linked_List; + Path_Id : in out Nat); + pragma Inline (Visit_Vertex); + -- Visit invocation graph vertex Invoker that resides in library graph + -- vertex Invoker_Vertex as part of a DFS traversal. Last_Vertex denotes + -- the previous vertex in the traversal. Elaborated_Vertex is the vertex + -- whose elaboration started the traversal. End_Vertex is the vertex that + -- terminates the traversal. All edges along the path are recorded in Path. + -- Path_Id is the id of the path. + + ------------------------- + -- Diagnose_All_Cycles -- + ------------------------- + + procedure Diagnose_All_Cycles + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph) + is + Cycle : Library_Graph_Cycle_Id; + Iter : All_Cycle_Iterator; + + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + + Iter := Iterate_All_Cycles (Lib_Graph); + while Has_Next (Iter) loop + Next (Iter, Cycle); + + Diagnose_Cycle + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Cycle => Cycle); + end loop; + end Diagnose_All_Cycles; + + -------------------------- + -- Diagnose_Circularities -- + -------------------------- + + procedure Diagnose_Circularities + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph) + is + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + + -- Find, validate, and output all cycles of the library graph + + Find_Cycles (Lib_Graph); + Validate_Cycles (Lib_Graph); + Write_Cycles (Lib_Graph); + + -- Diagnose all cycles in the graph regardless of their importance when + -- switch -d_C (diagnose all cycles) is in effect. + + if Debug_Flag_Underscore_CC then + Diagnose_All_Cycles (Inv_Graph, Lib_Graph); + + -- Otherwise diagnose the most important cycle in the graph + + else + Diagnose_Cycle + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Cycle => Highest_Precedence_Cycle (Lib_Graph)); + end if; + end Diagnose_Circularities; + + -------------------- + -- Diagnose_Cycle -- + -------------------- + + procedure Diagnose_Cycle + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + Current_Edge : Library_Graph_Edge_Id; + Elaborate_All_Active : Boolean; + First_Edge : Library_Graph_Edge_Id; + Iter : Edges_Of_Cycle_Iterator; + Next_Edge : Library_Graph_Edge_Id; + + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Cycle)); + + Elaborate_All_Active := False; + First_Edge := No_Library_Graph_Edge; + + -- Inspect the edges of the cycle in pairs, emitting diagnostics based + -- on their successors and predecessors. + + Iter := Iterate_Edges_Of_Cycle (Lib_Graph, Cycle); + while Has_Next (Iter) loop + + -- Emit the reason for the cycle using the initial edge, which is the + -- most important edge in the cycle. + + if not Present (First_Edge) then + Next (Iter, Current_Edge); + + First_Edge := Current_Edge; + Elaborate_All_Active := + Is_Elaborate_All_Edge + (G => Lib_Graph, + Edge => First_Edge); + + Output_Reason_And_Circularity_Header + (G => Lib_Graph, + First_Edge => First_Edge); + end if; + + -- Obtain the other edge of the pair + + exit when not Has_Next (Iter); + Next (Iter, Next_Edge); + + -- Describe the transition from the current edge to the next edge by + -- taking into account the predecessors and successors involved, as + -- well as the nature of the edge. + + Output_Transition + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Current_Edge => Current_Edge, + Next_Edge => Next_Edge, + Elaborate_All_Active => Elaborate_All_Active); + + Current_Edge := Next_Edge; + end loop; + + -- Describe the transition from the last edge to the first edge + + Output_Transition + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Current_Edge => Current_Edge, + Next_Edge => First_Edge, + Elaborate_All_Active => Elaborate_All_Active); + + -- Suggest various alternatives for breaking the cycle + + Output_Suggestions + (G => Lib_Graph, + Cycle => Cycle, + First_Edge => First_Edge); + end Diagnose_Cycle; + + -------------------------------------- + -- Find_And_Output_Invocation_Paths -- + -------------------------------------- + + procedure Find_And_Output_Invocation_Paths + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Source : Library_Graph_Vertex_Id; + Destination : Library_Graph_Vertex_Id) + is + Path : IGE_Lists.Doubly_Linked_List; + Path_Id : Nat; + + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Source)); + pragma Assert (Present (Destination)); + + -- Nothing to do when the invocation graph encoding format of the source + -- vertex does not contain detailed information about invocation paths. + + if Invocation_Graph_Encoding (Lib_Graph, Source) /= + Full_Path_Encoding + then + return; + end if; + + Path := IGE_Lists.Create; + Path_Id := 1; + + -- Start a DFS traversal over the invocation graph, in an attempt to + -- reach Destination from Source. The actual start of the path is the + -- elaboration root invocation vertex that corresponds to the Source. + -- Each unique path is emitted as part of the current cycle diagnostic. + + Visit_Vertex + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Invoker => + Find_Elaboration_Root + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Vertex => Source), + Invoker_Vertex => Source, + Last_Vertex => Source, + Elaborated_Vertex => Source, + End_Vertex => Destination, + Path => Path, + Path_Id => Path_Id); + + IGE_Lists.Destroy (Path); + end Find_And_Output_Invocation_Paths; + + --------------------------- + -- Find_Elaboration_Root -- + --------------------------- + + function Find_Elaboration_Root + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Invocation_Graph_Vertex_Id + is + Current_Vertex : Invocation_Graph_Vertex_Id; + Iter : Elaboration_Root_Iterator; + Root_Vertex : Invocation_Graph_Vertex_Id; + + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Vertex)); + + -- Assume that the vertex does not have a corresponding elaboration root + + Root_Vertex := No_Invocation_Graph_Vertex; + + -- Inspect all elaboration roots trying to find the one that resides in + -- the input vertex. + -- + -- IMPORTANT: + -- + -- * The iterator must run to completion in order to unlock the + -- invocation graph. + + Iter := Iterate_Elaboration_Roots (Inv_Graph); + while Has_Next (Iter) loop + Next (Iter, Current_Vertex); + + if not Present (Root_Vertex) + and then Body_Vertex (Inv_Graph, Current_Vertex) = Vertex + then + Root_Vertex := Current_Vertex; + end if; + end loop; + + return Root_Vertex; + end Find_Elaboration_Root; + + ----------------------------------- + -- Output_All_Cycles_Suggestions -- + ----------------------------------- + + procedure Output_All_Cycles_Suggestions (G : Library_Graph) is + begin + pragma Assert (Present (G)); + + -- The library graph contains at least one cycle and only the highest + -- priority cycle was diagnosed. Diagnosing all cycles may yield extra + -- information for decision making. + + if Number_Of_Cycles (G) > 1 and then not Debug_Flag_Underscore_CC then + Error_Msg_Info + (" diagnose all circularities (-d_C)"); + end if; + end Output_All_Cycles_Suggestions; + + -------------------------------------- + -- Output_Dynamic_Model_Suggestions -- + -------------------------------------- + + procedure Output_Dynamic_Model_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- The cycle contains at least one invocation edge and the main library + -- unit was compiled with the static model. Using the dynamic model may + -- eliminate the invocation edge, and thus the cycle. + + if Invocation_Edge_Count (G, Cycle) > 0 + and then not Is_Dynamically_Elaborated (G) + then + Error_Msg_Info + (" use the dynamic elaboration model (-gnatE)"); + end if; + end Output_Dynamic_Model_Suggestions; + + -------------------------------------- + -- Output_Elaborate_All_Suggestions -- + -------------------------------------- + + procedure Output_Elaborate_All_Suggestions + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Pred)); + pragma Assert (Present (Succ)); + + Error_Msg_Unit_1 := Name (G, Pred); + Error_Msg_Unit_2 := Name (G, Succ); + Error_Msg_Info + (" change pragma Elaborate_All for unit $ to Elaborate in unit $"); + Error_Msg_Info + (" remove pragma Elaborate_All for unit $ in unit $"); + end Output_Elaborate_All_Suggestions; + + ------------------------------------- + -- Output_Elaborate_All_Transition -- + ------------------------------------- + + procedure Output_Elaborate_All_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Source)); + pragma Assert (Present (Actual_Destination)); + pragma Assert (Present (Expected_Destination)); + + -- The actual and expected destination vertices match, and denote the + -- spec of a unit. + -- + -- Elaborate_All Actual_Destination + -- Source ---------------> spec --> + -- Expected_Destination + -- + -- Elaborate_All Actual_Destination + -- Source ---------------> stand-alone body --> + -- Expected_Destination + + if Actual_Destination = Expected_Destination then + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause and pragma Elaborate_All for unit $"); + + -- Otherwise the actual destination vertex denotes the spec of a unit, + -- while the expected destination is the corresponding body. + -- + -- Elaborate_All Actual_Destination + -- Source ---------------> spec + -- + -- body --> + -- Expected_Destination + + else + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause and pragma Elaborate_All for unit $"); + + Error_Msg_Unit_1 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate_All"); + end if; + end Output_Elaborate_All_Transition; + + --------------------------------------- + -- Output_Elaborate_Body_Suggestions -- + --------------------------------------- + + procedure Output_Elaborate_Body_Suggestions + (G : Library_Graph; + Succ : Library_Graph_Vertex_Id) + is + Spec : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Succ)); + + -- Find the initial declaration of the unit because it is the one + -- subject to pragma Elaborate_Body. + + if Is_Body_With_Spec (G, Succ) then + Spec := Proper_Spec (G, Succ); + else + Spec := Succ; + end if; + + Error_Msg_Unit_1 := Name (G, Spec); + Error_Msg_Info + (" remove pragma Elaborate_Body in unit $"); + end Output_Elaborate_Body_Suggestions; + + -------------------------------------- + -- Output_Elaborate_Body_Transition -- + -------------------------------------- + + procedure Output_Elaborate_Body_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Source)); + pragma Assert (Present (Actual_Destination)); + pragma Assert (Present (Expected_Destination)); + + -- The actual and expected destination vertices match, and denote the + -- spec of a unit subject to pragma Elaborate_Body. There is no need to + -- mention the pragma because it does not affect the path of the cycle. + -- Treat the edge as a regular with edge. + -- + -- Actual_Destination + -- Source --> spec Elaborate_Body --> + -- Expected_Destination + + if Actual_Destination = Expected_Destination then + pragma Assert (Is_Spec (G, Actual_Destination)); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause for unit $"); + + -- Otherwise the actual destination vertex is the spec of a unit subject + -- to pragma Elaborate_Body and the expected destination vertex is the + -- completion body. The pragma must be mentioned because it directs the + -- path of the cycle from the spec to the body. + -- + -- Actual_Destination + -- Source --> spec Elaborate_Body + -- + -- body --> + -- Expected_Destination + + else + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ is subject to pragma Elaborate_Body"); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ has with clause for unit $"); + end if; + end Output_Elaborate_Body_Transition; + + ---------------------------------- + -- Output_Elaborate_Suggestions -- + ---------------------------------- + + procedure Output_Elaborate_Suggestions + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Pred)); + pragma Assert (Present (Succ)); + + Error_Msg_Unit_1 := Name (G, Pred); + Error_Msg_Unit_2 := Name (G, Succ); + Error_Msg_Info + (" remove pragma Elaborate for unit $ in unit $"); + end Output_Elaborate_Suggestions; + + --------------------------------- + -- Output_Elaborate_Transition -- + --------------------------------- + + procedure Output_Elaborate_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id) + is + Spec : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Source)); + pragma Assert (Present (Actual_Destination)); + pragma Assert (Present (Expected_Destination)); + + -- The actual and expected destination vertices match, and denote the + -- spec of a unit. + -- + -- Elaborate Actual_Destination + -- Source -----------> spec --> + -- Expected_Destination + -- + -- Elaborate Actual_Destination + -- Source -----------> stand-alone body --> + -- Expected_Destination + -- + -- The processing of pragma Elaborate body generates an edge between a + -- successor and predecessor body. + -- + -- spec + -- + -- Elaborate Actual_Destination + -- Source -----------> body --> + -- Expected_Destination + + if Actual_Destination = Expected_Destination then + + -- Find the initial declaration of the unit because it is the one + -- subject to pragma Elaborate. + + if Is_Body_With_Spec (G, Actual_Destination) then + Spec := Proper_Spec (G, Actual_Destination); + else + Spec := Actual_Destination; + end if; + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Spec); + Error_Msg_Info + (" unit $ has with clause and pragma Elaborate for unit $"); + + if Actual_Destination /= Spec then + Error_Msg_Unit_1 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate"); + end if; + + -- Otherwise the actual destination vertex denotes the spec of a unit + -- while the expected destination vertex is the corresponding body. + -- + -- Elaborate Actual_Destination + -- Source -----------> spec + -- + -- body --> + -- Expected_Destination + + else + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause and pragma Elaborate for unit $"); + + Error_Msg_Unit_1 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate"); + end if; + end Output_Elaborate_Transition; + + ------------------------------- + -- Output_Forced_Suggestions -- + ------------------------------- + + procedure Output_Forced_Suggestions + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Pred)); + pragma Assert (Present (Succ)); + + Error_Msg_Unit_1 := Name (G, Succ); + Error_Msg_Unit_2 := Name (G, Pred); + Error_Msg_Info + (" remove the dependency of unit $ on unit $ from argument of -f " + & "switch"); + end Output_Forced_Suggestions; + + ------------------------------ + -- Output_Forced_Transition -- + ------------------------------ + + procedure Output_Forced_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Source)); + pragma Assert (Present (Actual_Destination)); + pragma Assert (Present (Expected_Destination)); + + -- The actual and expected destination vertices match, and denote the + -- spec of a unit. + -- + -- Forced Actual_Destination + -- Source --------> spec --> + -- Expected_Destination + -- + -- Forced Actual_Destination + -- Source --------> body --> + -- Expected_Destination + + if Actual_Destination = Expected_Destination then + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has a dependency on unit $ forced by -f switch"); + + -- The actual destination vertex denotes the spec of a unit while the + -- expected destination is the corresponding body, and the unit is in + -- the closure of an earlier Elaborate_All pragma. + -- + -- Forced Actual_Destination + -- Source --------> spec + -- + -- body --> + -- Expected_Destination + + elsif Elaborate_All_Active then + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has a dependency on unit $ forced by -f switch"); + + Error_Msg_Unit_1 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate_All"); + + -- Otherwise the actual destination vertex denotes a spec subject to + -- pragma Elaborate_Body while the expected destination denotes the + -- corresponding body. + -- + -- Forced Actual_Destination + -- Source --------> spec Elaborate_Body + -- + -- body --> + -- Expected_Destination + + else + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Spec_With_Elaborate_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Is_Body_Of_Spec_With_Elaborate_Body (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has a dependency on unit $ forced by -f switch"); + + Error_Msg_Unit_1 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ is subject to pragma Elaborate_Body"); + + Error_Msg_Unit_1 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate_Body"); + end if; + end Output_Forced_Transition; + + -------------------------------------- + -- Output_Full_Encoding_Suggestions -- + -------------------------------------- + + procedure Output_Full_Encoding_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + First_Edge : Library_Graph_Edge_Id) + is + Succ : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + pragma Assert (Present (First_Edge)); + + if Is_Invocation_Edge (G, First_Edge) then + Succ := Successor (G, First_Edge); + + if Invocation_Graph_Encoding (G, Succ) /= Full_Path_Encoding then + Error_Msg_Info + (" use detailed invocation information (-gnatd_F)"); + end if; + end if; + end Output_Full_Encoding_Suggestions; + + ---------------------------- + -- Output_Invocation_Path -- + ----------------------------- + + procedure Output_Invocation_Path + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Elaborated_Vertex : Library_Graph_Vertex_Id; + Path : IGE_Lists.Doubly_Linked_List; + Path_Id : in out Nat) + is + Edge : Invocation_Graph_Edge_Id; + Iter : IGE_Lists.Iterator; + + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Elaborated_Vertex)); + pragma Assert (IGE_Lists.Present (Path)); + + Error_Msg_Nat_1 := Path_Id; + Error_Msg_Info (" path #:"); + + Error_Msg_Unit_1 := Name (Lib_Graph, Elaborated_Vertex); + Error_Msg_Info (" elaboration of unit $"); + + Iter := IGE_Lists.Iterate (Path); + while IGE_Lists.Has_Next (Iter) loop + IGE_Lists.Next (Iter, Edge); + + Output_Invocation_Path_Transition + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Edge => Edge); + end loop; + + Path_Id := Path_Id + 1; + end Output_Invocation_Path; + + --------------------------------------- + -- Output_Invocation_Path_Transition -- + --------------------------------------- + + procedure Output_Invocation_Path_Transition + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Edge : Invocation_Graph_Edge_Id) + is + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Edge)); + + Declared : constant String := "declared at {:#:#"; + + Targ : constant Invocation_Graph_Vertex_Id := + Target (Inv_Graph, Edge); + Targ_Extra : constant Name_Id := + Extra (Inv_Graph, Edge); + Targ_Vertex : constant Library_Graph_Vertex_Id := + Spec_Vertex (Inv_Graph, Targ); + + begin + Error_Msg_Name_1 := Name (Inv_Graph, Targ); + Error_Msg_Nat_1 := Line (Inv_Graph, Targ); + Error_Msg_Nat_2 := Column (Inv_Graph, Targ); + Error_Msg_File_1 := File_Name (Lib_Graph, Targ_Vertex); + + case Kind (Inv_Graph, Edge) is + when Accept_Alternative => + Error_Msg_Info + (" selection of entry % " + & Declared); + + when Access_Taken => + Error_Msg_Info + (" aliasing of subprogram % " + & Declared); + + when Call => + Error_Msg_Info + (" call to subprogram % " + & Declared); + + when Controlled_Adjustment + | Internal_Controlled_Adjustment + => + Error_Msg_Name_1 := Targ_Extra; + Error_Msg_Info + (" adjustment actions for type % " + & Declared); + + when Controlled_Finalization + | Internal_Controlled_Finalization + => + Error_Msg_Name_1 := Targ_Extra; + Error_Msg_Info + (" finalization actions for type % " + & Declared); + + when Controlled_Initialization + | Internal_Controlled_Initialization + | Type_Initialization + => + Error_Msg_Name_1 := Targ_Extra; + Error_Msg_Info + (" initialization actions for type % " + & Declared); + + when Default_Initial_Condition_Verification => + Error_Msg_Name_1 := Targ_Extra; + Error_Msg_Info + (" verification of Default_Initial_Condition for type % " + & Declared); + + when Initial_Condition_Verification => + Error_Msg_Info + (" verification of Initial_Condition " + & Declared); + + when Instantiation => + Error_Msg_Info + (" instantiation % " + & Declared); + + when Invariant_Verification => + Error_Msg_Name_1 := Targ_Extra; + Error_Msg_Info + (" verification of invariant for type % " + & Declared); + + when Postcondition_Verification => + Error_Msg_Name_1 := Targ_Extra; + Error_Msg_Info + (" verification of postcondition for subprogram % " + & Declared); + + when Protected_Entry_Call => + Error_Msg_Info + (" call to protected entry % " + & Declared); + + when Protected_Subprogram_Call => + Error_Msg_Info + (" call to protected subprogram % " + & Declared); + + when Task_Activation => + Error_Msg_Info + (" activation of local task " + & Declared); + + when Task_Entry_Call => + Error_Msg_Info + (" call to task entry % " + & Declared); + + when others => + pragma Assert (False); + null; + end case; + end Output_Invocation_Path_Transition; + + ---------------------------------- + -- Output_Invocation_Transition -- + ---------------------------------- + + procedure Output_Invocation_Transition + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Source : Library_Graph_Vertex_Id; + Destination : Library_Graph_Vertex_Id) + is + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Source)); + pragma Assert (Present (Destination)); + + Error_Msg_Unit_1 := Name (Lib_Graph, Source); + Error_Msg_Unit_2 := Name (Lib_Graph, Destination); + Error_Msg_Info + (" unit $ invokes a construct of unit $ at elaboration time"); + + Find_And_Output_Invocation_Paths + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Source => Source, + Destination => Destination); + end Output_Invocation_Transition; + + ------------------------------------------ + -- Output_Reason_And_Circularity_Header -- + ------------------------------------------ + + procedure Output_Reason_And_Circularity_Header + (G : Library_Graph; + First_Edge : Library_Graph_Edge_Id) + is + pragma Assert (Present (G)); + pragma Assert (Present (First_Edge)); + + Succ : constant Library_Graph_Vertex_Id := Successor (G, First_Edge); + + begin + Error_Msg_Unit_1 := Name (G, Succ); + Error_Msg ("Elaboration circularity detected"); + Error_Msg_Info (""); + Error_Msg_Info (" Reason:"); + Error_Msg_Info (""); + Error_Msg_Info (" unit $ depends on its own elaboration"); + Error_Msg_Info (""); + Error_Msg_Info (" Circularity:"); + Error_Msg_Info (""); + end Output_Reason_And_Circularity_Header; + + ------------------------ + -- Output_Suggestions -- + ------------------------ + + procedure Output_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + First_Edge : Library_Graph_Edge_Id) + is + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + pragma Assert (Present (First_Edge)); + + Pred : constant Library_Graph_Vertex_Id := Predecessor (G, First_Edge); + Succ : constant Library_Graph_Vertex_Id := Successor (G, First_Edge); + + begin + Error_Msg_Info (""); + Error_Msg_Info (" Suggestions:"); + Error_Msg_Info (""); + + -- Output edge-specific suggestions + + if Is_Elaborate_All_Edge (G, First_Edge) then + Output_Elaborate_All_Suggestions + (G => G, + Pred => Pred, + Succ => Succ); + + elsif Is_Elaborate_Body_Edge (G, First_Edge) then + Output_Elaborate_Body_Suggestions + (G => G, + Succ => Succ); + + elsif Is_Elaborate_Edge (G, First_Edge) then + Output_Elaborate_Suggestions + (G => G, + Pred => Pred, + Succ => Succ); + + elsif Is_Forced_Edge (G, First_Edge) then + Output_Forced_Suggestions + (G => G, + Pred => Pred, + Succ => Succ); + end if; + + -- Output general purpose suggestions + + Output_Dynamic_Model_Suggestions + (G => G, + Cycle => Cycle); + + Output_Full_Encoding_Suggestions + (G => G, + Cycle => Cycle, + First_Edge => First_Edge); + + Output_All_Cycles_Suggestions (G); + + Error_Msg_Info (""); + end Output_Suggestions; + + ----------------------- + -- Output_Transition -- ----------------------- - package body Cycle_Diagnostics is + procedure Output_Transition + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Current_Edge : Library_Graph_Edge_Id; + Next_Edge : Library_Graph_Edge_Id; + Elaborate_All_Active : Boolean) + is + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Current_Edge)); + pragma Assert (Present (Next_Edge)); + + Actual_Destination : constant Library_Graph_Vertex_Id := + Predecessor (Lib_Graph, Current_Edge); + Expected_Destination : constant Library_Graph_Vertex_Id := + Successor (Lib_Graph, Next_Edge); + Source : constant Library_Graph_Vertex_Id := + Successor (Lib_Graph, Current_Edge); - ----------------------------- - -- Has_Elaborate_All_Cycle -- - ----------------------------- + begin + if Is_Elaborate_All_Edge (Lib_Graph, Current_Edge) then + Output_Elaborate_All_Transition + (G => Lib_Graph, + Source => Source, + Actual_Destination => Actual_Destination, + Expected_Destination => Expected_Destination); - function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean is - Has_Cycle : Boolean; - Iter : All_Edge_Iterator; - LGE_Id : Library_Graph_Edge_Id; + elsif Is_Elaborate_Body_Edge (Lib_Graph, Current_Edge) then + Output_Elaborate_Body_Transition + (G => Lib_Graph, + Source => Source, + Actual_Destination => Actual_Destination, + Expected_Destination => Expected_Destination); - begin - pragma Assert (Present (G)); + elsif Is_Elaborate_Edge (Lib_Graph, Current_Edge) then + Output_Elaborate_Transition + (G => Lib_Graph, + Source => Source, + Actual_Destination => Actual_Destination, + Expected_Destination => Expected_Destination); - -- Assume that the graph lacks a cycle + elsif Is_Forced_Edge (Lib_Graph, Current_Edge) then + Output_Forced_Transition + (G => Lib_Graph, + Source => Source, + Actual_Destination => Actual_Destination, + Expected_Destination => Expected_Destination, + Elaborate_All_Active => Elaborate_All_Active); - Has_Cycle := False; + elsif Is_Invocation_Edge (Lib_Graph, Current_Edge) then + Output_Invocation_Transition + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Source => Source, + Destination => Expected_Destination); - -- The library graph has an Elaborate_All cycle when one of its edges - -- represents a with clause for a unit with pragma Elaborate_All, and - -- both the predecessor and successor reside in the same component. - -- Note that the iteration must run to completion in order to unlock - -- the graph. + else + pragma Assert (Is_With_Edge (Lib_Graph, Current_Edge)); - Iter := Iterate_All_Edges (G); + Output_With_Transition + (G => Lib_Graph, + Source => Source, + Actual_Destination => Actual_Destination, + Expected_Destination => Expected_Destination, + Elaborate_All_Active => Elaborate_All_Active); + end if; + end Output_Transition; + + ---------------------------- + -- Output_With_Transition -- + ---------------------------- + + procedure Output_With_Transition + (G : Library_Graph; + Source : Library_Graph_Vertex_Id; + Actual_Destination : Library_Graph_Vertex_Id; + Expected_Destination : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Source)); + pragma Assert (Present (Actual_Destination)); + pragma Assert (Present (Expected_Destination)); + + -- The actual and expected destination vertices match, and denote the + -- spec of a unit. + -- + -- with Actual_Destination + -- Source ------> spec --> + -- Expected_Destination + -- + -- with Actual_Destination + -- Source ------> stand-alone body --> + -- Expected_Destination + + if Actual_Destination = Expected_Destination then + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause for unit $"); + + -- The actual destination vertex denotes the spec of a unit while the + -- expected destination is the corresponding body, and the unit is in + -- the closure of an earlier Elaborate_All pragma. + -- + -- with Actual_Destination + -- Source ------> spec + -- + -- body --> + -- Expected_Destination + + elsif Elaborate_All_Active then + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause for unit $"); + + Error_Msg_Unit_1 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate_All"); + + -- Otherwise the actual destination vertex denotes a spec subject to + -- pragma Elaborate_Body while the expected destination denotes the + -- corresponding body. + -- + -- with Actual_Destination + -- Source ------> spec Elaborate_Body + -- + -- body --> + -- Expected_Destination + + else + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Spec_With_Elaborate_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Is_Body_Of_Spec_With_Elaborate_Body (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause for unit $"); + + Error_Msg_Unit_1 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ is subject to pragma Elaborate_Body"); + + Error_Msg_Unit_1 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate_Body"); + end if; + end Output_With_Transition; + + ------------------ + -- Visit_Vertex -- + ------------------ + + procedure Visit_Vertex + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Invoker : Invocation_Graph_Vertex_Id; + Invoker_Vertex : Library_Graph_Vertex_Id; + Last_Vertex : Library_Graph_Vertex_Id; + Elaborated_Vertex : Library_Graph_Vertex_Id; + End_Vertex : Library_Graph_Vertex_Id; + Path : IGE_Lists.Doubly_Linked_List; + Path_Id : in out Nat) + is + Edge : Invocation_Graph_Edge_Id; + Iter : Edges_To_Targets_Iterator; + Targ : Invocation_Graph_Vertex_Id; + + begin + pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Invoker)); + pragma Assert (Present (Invoker_Vertex)); + pragma Assert (Present (Last_Vertex)); + pragma Assert (Present (Elaborated_Vertex)); + pragma Assert (Present (End_Vertex)); + pragma Assert (IGE_Lists.Present (Path)); + + -- The current invocation vertex resides within the end library vertex. + -- Emit the path that started from some elaboration root and ultimately + -- reached the desired library vertex. + + if Body_Vertex (Inv_Graph, Invoker) = End_Vertex + and then Invoker_Vertex /= Last_Vertex + then + Output_Invocation_Path + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Elaborated_Vertex => Elaborated_Vertex, + Path => Path, + Path_Id => Path_Id); + + -- Otherwise extend the search for the end library vertex via all edges + -- to targets. + + else + Iter := Iterate_Edges_To_Targets (Inv_Graph, Invoker); while Has_Next (Iter) loop - Next (Iter, LGE_Id); - pragma Assert (Present (LGE_Id)); - - if Kind (G, LGE_Id) = Elaborate_All_Edge - and then Links_Vertices_In_Same_Component (G, LGE_Id) - then - Has_Cycle := True; - end if; - end loop; + Next (Iter, Edge); - return Has_Cycle; - end Has_Elaborate_All_Cycle; - end Cycle_Diagnostics; + -- Prepare for edge backtracking + + IGE_Lists.Append (Path, Edge); + + -- The traversal proceeds through the library vertex that houses + -- the body of the target. + + Targ := Target (Inv_Graph, Edge); + + Visit_Vertex + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Invoker => Targ, + Invoker_Vertex => Body_Vertex (Inv_Graph, Targ), + Last_Vertex => Invoker_Vertex, + Elaborated_Vertex => Elaborated_Vertex, + End_Vertex => End_Vertex, + Path => Path, + Path_Id => Path_Id); + + -- Backtrack the edge + + IGE_Lists.Delete_Last (Path); + end loop; + end if; + end Visit_Vertex; end Bindo.Diagnostics; diff --git a/gcc/ada/bindo-diagnostics.ads b/gcc/ada/bindo-diagnostics.ads index 3b1d01c..3835a68 100644 --- a/gcc/ada/bindo-diagnostics.ads +++ b/gcc/ada/bindo-diagnostics.ads @@ -30,6 +30,7 @@ with Bindo.Graphs; use Bindo.Graphs; +use Bindo.Graphs.Invocation_Graphs; use Bindo.Graphs.Library_Graphs; package Bindo.Diagnostics is @@ -46,16 +47,15 @@ package Bindo.Diagnostics is Order_Has_Elaborate_All_Circularity, Order_OK); - ----------------------- - -- Cycle_Diagnostics -- - ----------------------- + --------- + -- API -- + --------- - package Cycle_Diagnostics is - function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean; - pragma Inline (Has_Elaborate_All_Cycle); - -- Determine whether library graph G contains a cycle where pragma - -- Elaborate_All appears within a component. - - end Cycle_Diagnostics; + procedure Diagnose_Circularities + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph); + pragma Inline (Diagnose_Circularities); + -- Diagnose all cycles of library graph Lib_Graph with matching invocation + -- graph Inv_Graph. end Bindo.Diagnostics; diff --git a/gcc/ada/bindo-elaborators.adb b/gcc/ada/bindo-elaborators.adb index b11598c..d26101a 100644 --- a/gcc/ada/bindo-elaborators.adb +++ b/gcc/ada/bindo-elaborators.adb @@ -23,11 +23,10 @@ -- -- ------------------------------------------------------------------------------ -with Binderr; use Binderr; -with Butil; use Butil; -with Debug; use Debug; -with Output; use Output; -with Types; use Types; +with Butil; use Butil; +with Debug; use Debug; +with Output; use Output; +with Types; use Types; with Bindo.Augmentors; use Bindo.Augmentors; @@ -40,7 +39,6 @@ use Bindo.Builders.Library_Graph_Builders; with Bindo.Diagnostics; use Bindo.Diagnostics; -use Bindo.Diagnostics.Cycle_Diagnostics; with Bindo.Units; use Bindo.Units; @@ -61,7 +59,6 @@ use Bindo.Writers.Unit_Closure_Writers; with GNAT; use GNAT; with GNAT.Graphs; use GNAT.Graphs; -with GNAT.Sets; use GNAT.Sets; package body Bindo.Elaborators is @@ -89,49 +86,39 @@ package body Bindo.Elaborators is type String_Ptr is access all String; - ----------------- - -- Visited set -- - ----------------- - - package VS is new Membership_Sets - (Element_Type => Library_Graph_Vertex_Id, - "=" => "=", - Hash => Hash_Library_Graph_Vertex); - use VS; - ----------------------- -- Local subprograms -- ----------------------- procedure Add_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - Set : Membership_Set; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Add_Vertex); - -- Add vertex LGV_Id of library graph G to membership set Set. Msg is + -- Add vertex Vertex of library graph G to membership set Set. Msg is -- a message emitted for tracing purposes. Step is the current step in -- the elaboration order. Indent is the desired indentation level for -- tracing. procedure Add_Vertex_If_Elaborable (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - Set : Membership_Set; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Add_Vertex_If_Elaborable); - -- Add vertex LGV_Id of library graph G to membership set Set if it can + -- Add vertex Vertex of library graph G to membership set Set if it can -- be elaborated. Msg is a message emitted for tracing purposes. Step is -- the current step in the elaboration order. Indent is the desired -- indentation level for tracing. function Create_All_Candidates_Set (G : Library_Graph; - Step : Elaboration_Order_Step) return Membership_Set; + Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set; pragma Inline (Create_All_Candidates_Set); -- Collect all elaborable candidate vertices of library graph G in a -- set. Step is the current step in the elaboration order. @@ -139,7 +126,7 @@ package body Bindo.Elaborators is function Create_Component_Candidates_Set (G : Library_Graph; Comp : Component_Id; - Step : Elaboration_Order_Step) return Membership_Set; + Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set; pragma Inline (Create_Component_Candidates_Set); -- Collect all elaborable candidate vertices that appear in component -- Comp of library graph G in a set. Step is the current step in the @@ -148,7 +135,7 @@ package body Bindo.Elaborators is procedure Elaborate_Component (G : Library_Graph; Comp : Component_Id; - All_Candidates : Membership_Set; + All_Candidates : LGV_Sets.Membership_Set; Remaining_Vertices : in out Natural; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step); @@ -170,6 +157,7 @@ package body Bindo.Elaborators is procedure Elaborate_Units_Common (Use_Inv_Graph : Boolean; + Is_Dyn_Elab : Boolean; Inv_Graph : out Invocation_Graph; Lib_Graph : out Library_Graph; Order : out Unit_Id_Table; @@ -177,8 +165,10 @@ package body Bindo.Elaborators is pragma Inline (Elaborate_Units_Common); -- Find the elaboration order of all units in the bind. Use_Inv_Graph -- should be set when library graph Lib_Graph is to be augmented with - -- information from invocation graph Inv_Graph. Order is the elaboration - -- order. Status is the condition of the elaboration order. + -- information from invocation graph Inv_Graph. Is_Dyn_Elab should be + -- set when the main library unit was compiled using the dynamic model. + -- Order is the elaboration order. Status is the condition of the + -- elaboration order. procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table); pragma Inline (Elaborate_Units_Dynamic); @@ -196,26 +186,26 @@ package body Bindo.Elaborators is procedure Elaborate_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - All_Candidates : Membership_Set; - Comp_Candidates : Membership_Set; + Vertex : Library_Graph_Vertex_Id; + All_Candidates : LGV_Sets.Membership_Set; + Comp_Candidates : LGV_Sets.Membership_Set; Remaining_Vertices : in out Natural; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Elaborate_Vertex); - -- Elaborate vertex LGV_Id of library graph G by adding its unit to + -- Elaborate vertex Vertex of library graph G by adding its unit to -- elaboration order Order. The routine updates awaiting successors -- where applicable. All_Candidates denotes the set of all elaborable -- vertices across the whole library graph. Comp_Candidates is the set - -- of all elaborable vertices in the component of LGV_Id. Parameter + -- of all elaborable vertices in the component of Vertex. Parameter -- Remaining_Vertices denotes the number of vertices that remain to -- be elaborated. Step is the current step in the elaboration order. -- Indent is the desired indentation level for tracing. function Find_Best_Candidate (G : Library_Graph; - Set : Membership_Set; + Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id; pragma Inline (Find_Best_Candidate); @@ -224,17 +214,17 @@ package body Bindo.Elaborators is -- order. Indent is the desired indentation level for tracing. function Is_Better_Candidate - (G : Library_Graph; - Best_Candid : Library_Graph_Vertex_Id; - New_Candid : Library_Graph_Vertex_Id) return Boolean; + (G : Library_Graph; + Best_Candidate : Library_Graph_Vertex_Id; + New_Candidate : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Better_Candidate); - -- Determine whether new candidate vertex New_Candid of library graph + -- Determine whether new candidate vertex New_Candidate of library graph -- G is a more suitable choice for elaboration compared to the current - -- best candidate Best_Candid. + -- best candidate Best_Candidate. procedure Trace_Candidate_Vertices (G : Library_Graph; - Set : Membership_Set; + Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step); pragma Inline (Trace_Candidate_Vertices); -- Write the candidate vertices of library graph G present in membership @@ -266,12 +256,12 @@ package body Bindo.Elaborators is procedure Trace_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Trace_Vertex); - -- Write elaboration-related information for vertex LGV_Id of library + -- Write elaboration-related information for vertex Vertex of library -- graph G to standard output, starting with message Msg. Step is the -- current step in the elaboration order. Indent denotes the desired -- indentation level for tracing. @@ -280,8 +270,8 @@ package body Bindo.Elaborators is (G : Library_Graph; Pred : Library_Graph_Vertex_Id; Succ : Library_Graph_Vertex_Id; - All_Candidates : Membership_Set; - Comp_Candidates : Membership_Set; + All_Candidates : LGV_Sets.Membership_Set; + Comp_Candidates : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Update_Successor); @@ -297,8 +287,8 @@ package body Bindo.Elaborators is procedure Update_Successors (G : Library_Graph; Pred : Library_Graph_Vertex_Id; - All_Candidates : Membership_Set; - Comp_Candidates : Membership_Set; + All_Candidates : LGV_Sets.Membership_Set; + Comp_Candidates : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level); pragma Inline (Update_Successors); @@ -317,30 +307,30 @@ package body Bindo.Elaborators is procedure Add_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - Set : Membership_Set; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) is begin - pragma Assert (Present (LGV_Id)); - pragma Assert (Needs_Elaboration (G, LGV_Id)); - pragma Assert (Present (Set)); + pragma Assert (Present (Vertex)); + pragma Assert (Needs_Elaboration (G, Vertex)); + pragma Assert (LGV_Sets.Present (Set)); -- Add vertex only when it is not present in the set. This is not -- strictly necessary because the set implementation handles this -- case, however the check eliminates spurious traces. - if not Contains (Set, LGV_Id) then + if not LGV_Sets.Contains (Set, Vertex) then Trace_Vertex (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Msg => Msg, Step => Step, Indent => Indent); - Insert (Set, LGV_Id); + LGV_Sets.Insert (Set, Vertex); end if; end Add_Vertex; @@ -350,24 +340,24 @@ package body Bindo.Elaborators is procedure Add_Vertex_If_Elaborable (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - Set : Membership_Set; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) is - Aux_LGV_Id : Library_Graph_Vertex_Id; + Extra_Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - pragma Assert (Needs_Elaboration (G, LGV_Id)); - pragma Assert (Present (Set)); + pragma Assert (Present (Vertex)); + pragma Assert (Needs_Elaboration (G, Vertex)); + pragma Assert (LGV_Sets.Present (Set)); - if Is_Elaborable_Vertex (G, LGV_Id) then + if Is_Elaborable_Vertex (G, Vertex) then Add_Vertex (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Set => Set, Msg => Msg, Step => Step, @@ -375,28 +365,28 @@ package body Bindo.Elaborators is -- Assume that there is no extra vertex that needs to be added - Aux_LGV_Id := No_Library_Graph_Vertex; + Extra_Vertex := No_Library_Graph_Vertex; -- A spec-body pair where the spec carries pragma Elaborate_Body -- must be treated as one vertex for elaboration purposes. If one -- of them is elaborable, then the other is also elaborable. This -- property is guaranteed by predicate Is_Elaborable_Vertex. - if Is_Body_Of_Spec_With_Elaborate_Body (G, LGV_Id) then - Aux_LGV_Id := Proper_Spec (G, LGV_Id); - pragma Assert (Present (Aux_LGV_Id)); + if Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then + Extra_Vertex := Proper_Spec (G, Vertex); + pragma Assert (Present (Extra_Vertex)); - elsif Is_Spec_With_Elaborate_Body (G, LGV_Id) then - Aux_LGV_Id := Proper_Body (G, LGV_Id); - pragma Assert (Present (Aux_LGV_Id)); + elsif Is_Spec_With_Elaborate_Body (G, Vertex) then + Extra_Vertex := Proper_Body (G, Vertex); + pragma Assert (Present (Extra_Vertex)); end if; - if Present (Aux_LGV_Id) then - pragma Assert (Needs_Elaboration (G, Aux_LGV_Id)); + if Present (Extra_Vertex) then + pragma Assert (Needs_Elaboration (G, Extra_Vertex)); Add_Vertex (G => G, - LGV_Id => Aux_LGV_Id, + Vertex => Extra_Vertex, Set => Set, Msg => Msg, Step => Step, @@ -411,24 +401,23 @@ package body Bindo.Elaborators is function Create_All_Candidates_Set (G : Library_Graph; - Step : Elaboration_Order_Step) return Membership_Set + Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set is Iter : Library_Graphs.All_Vertex_Iterator; - LGV_Id : Library_Graph_Vertex_Id; - Set : Membership_Set; + Set : LGV_Sets.Membership_Set; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); - Set := Create (Number_Of_Vertices (G)); + Set := LGV_Sets.Create (Number_Of_Vertices (G)); Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop - Next (Iter, LGV_Id); - pragma Assert (Present (LGV_Id)); + Next (Iter, Vertex); Add_Vertex_If_Elaborable (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Set => Set, Msg => Add_To_All_Candidates_Msg, Step => Step, @@ -445,25 +434,24 @@ package body Bindo.Elaborators is function Create_Component_Candidates_Set (G : Library_Graph; Comp : Component_Id; - Step : Elaboration_Order_Step) return Membership_Set + Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set is Iter : Component_Vertex_Iterator; - LGV_Id : Library_Graph_Vertex_Id; - Set : Membership_Set; + Set : LGV_Sets.Membership_Set; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); pragma Assert (Present (Comp)); - Set := Create (Number_Of_Component_Vertices (G, Comp)); + Set := LGV_Sets.Create (Number_Of_Component_Vertices (G, Comp)); Iter := Iterate_Component_Vertices (G, Comp); while Has_Next (Iter) loop - Next (Iter, LGV_Id); - pragma Assert (Present (LGV_Id)); + Next (Iter, Vertex); Add_Vertex_If_Elaborable (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Set => Set, Msg => Add_To_Comp_Candidates_Msg, Step => Step, @@ -480,18 +468,18 @@ package body Bindo.Elaborators is procedure Elaborate_Component (G : Library_Graph; Comp : Component_Id; - All_Candidates : Membership_Set; + All_Candidates : LGV_Sets.Membership_Set; Remaining_Vertices : in out Natural; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step) is Candidate : Library_Graph_Vertex_Id; - Comp_Candidates : Membership_Set; + Comp_Candidates : LGV_Sets.Membership_Set; begin pragma Assert (Present (G)); pragma Assert (Present (Comp)); - pragma Assert (Present (All_Candidates)); + pragma Assert (LGV_Sets.Present (All_Candidates)); Trace_Component (G => G, @@ -518,7 +506,7 @@ package body Bindo.Elaborators is Elaborate_Vertex (G => G, - LGV_Id => Candidate, + Vertex => Candidate, All_Candidates => All_Candidates, Comp_Candidates => Comp_Candidates, Remaining_Vertices => Remaining_Vertices, @@ -527,7 +515,7 @@ package body Bindo.Elaborators is Indent => Nested_Indentation); end loop; - Destroy (Comp_Candidates); + LGV_Sets.Destroy (Comp_Candidates); end Elaborate_Component; ----------------------------- @@ -539,9 +527,8 @@ package body Bindo.Elaborators is Order : out Unit_Id_Table; Status : out Elaboration_Order_Status) is - All_Candidates : Membership_Set; + All_Candidates : LGV_Sets.Membership_Set; Candidate : Library_Graph_Vertex_Id; - Comp : Component_Id; Remaining_Vertices : Natural; Step : Elaboration_Order_Step; @@ -585,19 +572,16 @@ package body Bindo.Elaborators is -- and their components that they have one less predecessor to -- wait on. This may add new candidates to set All_Candidates. - Comp := Component (G, Candidate); - pragma Assert (Present (Comp)); - Elaborate_Component (G => G, - Comp => Comp, + Comp => Component (G, Candidate), All_Candidates => All_Candidates, Remaining_Vertices => Remaining_Vertices, Order => Order, Step => Step); end loop; - Destroy (All_Candidates); + LGV_Sets.Destroy (All_Candidates); -- The library graph contains an Elaborate_All circularity when -- at least one edge subject to the related pragma appears in a @@ -642,7 +626,7 @@ package body Bindo.Elaborators is Write_ALI_Tables; -- Choose the proper elaboration strategy based on whether the main - -- library unit was compiled with dynamic elaboration checks. + -- library unit was compiled using the dynamic model. if Is_Dynamically_Elaborated (Main_Lib_Unit) then Elaborate_Units_Dynamic (Order); @@ -673,6 +657,7 @@ package body Bindo.Elaborators is procedure Elaborate_Units_Common (Use_Inv_Graph : Boolean; + Is_Dyn_Elab : Boolean; Inv_Graph : out Invocation_Graph; Lib_Graph : out Library_Graph; Order : out Unit_Id_Table; @@ -682,7 +667,7 @@ package body Bindo.Elaborators is -- Create, validate, and output the library graph that captures the -- dependencies between library items. - Lib_Graph := Build_Library_Graph; + Lib_Graph := Build_Library_Graph (Is_Dyn_Elab); Validate_Library_Graph (Lib_Graph); Write_Library_Graph (Lib_Graph); @@ -746,6 +731,7 @@ package body Bindo.Elaborators is Elaborate_Units_Common (Use_Inv_Graph => True, + Is_Dyn_Elab => True, Inv_Graph => Mix_Inv_Graph, Lib_Graph => Mix_Lib_Graph, Order => Mix_Order, @@ -761,9 +747,9 @@ package body Bindo.Elaborators is -- the invocation graph because the circularity will persist. elsif Status = Order_Has_Elaborate_All_Circularity then - Error_Msg ("elaboration circularity detected"); - - -- Report error here + Diagnose_Circularities + (Inv_Graph => Mix_Inv_Graph, + Lib_Graph => Mix_Lib_Graph); -- Otherwise the library graph contains a circularity, or the extra -- information provided by the invocation graph caused a circularity. @@ -776,6 +762,7 @@ package body Bindo.Elaborators is Elaborate_Units_Common (Use_Inv_Graph => False, + Is_Dyn_Elab => True, Inv_Graph => Dyn_Inv_Graph, Lib_Graph => Dyn_Lib_Graph, Order => Dyn_Order, @@ -792,9 +779,9 @@ package body Bindo.Elaborators is -- the circularity. else - Error_Msg ("elaboration circularity detected"); - - -- Report error here + Diagnose_Circularities + (Inv_Graph => Dyn_Inv_Graph, + Lib_Graph => Dyn_Lib_Graph); end if; Destroy (Dyn_Inv_Graph); @@ -827,6 +814,7 @@ package body Bindo.Elaborators is Elaborate_Units_Common (Use_Inv_Graph => True, + Is_Dyn_Elab => False, Inv_Graph => Inv_Graph, Lib_Graph => Lib_Graph, Order => Order, @@ -835,9 +823,9 @@ package body Bindo.Elaborators is -- The augmented library graph contains a circularity if Status /= Order_OK then - Error_Msg ("elaboration circularity detected"); - - -- Report error here + Diagnose_Circularities + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph); end if; Destroy (Inv_Graph); @@ -856,27 +844,24 @@ package body Bindo.Elaborators is procedure Elaborate_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - All_Candidates : Membership_Set; - Comp_Candidates : Membership_Set; + Vertex : Library_Graph_Vertex_Id; + All_Candidates : LGV_Sets.Membership_Set; + Comp_Candidates : LGV_Sets.Membership_Set; Remaining_Vertices : in out Natural; Order : in out Unit_Id_Table; Step : Elaboration_Order_Step; Indent : Indentation_Level) is - Body_LGV_Id : Library_Graph_Vertex_Id; - U_Id : Unit_Id; - begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - pragma Assert (Needs_Elaboration (G, LGV_Id)); - pragma Assert (Present (All_Candidates)); - pragma Assert (Present (Comp_Candidates)); + pragma Assert (Present (Vertex)); + pragma Assert (Needs_Elaboration (G, Vertex)); + pragma Assert (LGV_Sets.Present (All_Candidates)); + pragma Assert (LGV_Sets.Present (Comp_Candidates)); Trace_Vertex (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Msg => "elaborating vertex", Step => Step, Indent => Indent); @@ -887,20 +872,17 @@ package body Bindo.Elaborators is -- check that the vertex is present in either set because the set -- implementation handles this case. - Delete (All_Candidates, LGV_Id); - Delete (Comp_Candidates, LGV_Id); + LGV_Sets.Delete (All_Candidates, Vertex); + LGV_Sets.Delete (Comp_Candidates, Vertex); -- Mark the vertex as elaborated in order to prevent further attempts -- to re-elaborate it. - Set_In_Elaboration_Order (G, LGV_Id); + Set_In_Elaboration_Order (G, Vertex); -- Add the unit represented by the vertex to the elaboration order - U_Id := Unit (G, LGV_Id); - pragma Assert (Present (U_Id)); - - Unit_Id_Tables.Append (Order, U_Id); + Unit_Id_Tables.Append (Order, Unit (G, Vertex)); -- There is now one fewer vertex to elaborate @@ -912,7 +894,7 @@ package body Bindo.Elaborators is Update_Successors (G => G, - Pred => LGV_Id, + Pred => Vertex, All_Candidates => All_Candidates, Comp_Candidates => Comp_Candidates, Step => Step, @@ -922,13 +904,10 @@ package body Bindo.Elaborators is -- to pragma Elaborate_Body. Elaborate the body in order to satisfy -- the semantics of the pragma. - if Is_Spec_With_Elaborate_Body (G, LGV_Id) then - Body_LGV_Id := Proper_Body (G, LGV_Id); - pragma Assert (Present (Body_LGV_Id)); - + if Is_Spec_With_Elaborate_Body (G, Vertex) then Elaborate_Vertex (G => G, - LGV_Id => Body_LGV_Id, + Vertex => Proper_Body (G, Vertex), All_Candidates => All_Candidates, Comp_Candidates => Comp_Candidates, Remaining_Vertices => Remaining_Vertices, @@ -944,17 +923,17 @@ package body Bindo.Elaborators is function Find_Best_Candidate (G : Library_Graph; - Set : Membership_Set; + Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id is - Best : Library_Graph_Vertex_Id; - Curr : Library_Graph_Vertex_Id; - Iter : Iterator; + Best : Library_Graph_Vertex_Id; + Current : Library_Graph_Vertex_Id; + Iter : LGV_Sets.Iterator; begin pragma Assert (Present (G)); - pragma Assert (Present (Set)); + pragma Assert (LGV_Sets.Present (Set)); -- Assume that there is no candidate @@ -963,21 +942,19 @@ package body Bindo.Elaborators is -- Inspect all vertices in the set, looking for the best candidate to -- elaborate. - Iter := Iterate (Set); - while Has_Next (Iter) loop - Next (Iter, Curr); - - pragma Assert (Present (Curr)); - pragma Assert (Needs_Elaboration (G, Curr)); + Iter := LGV_Sets.Iterate (Set); + while LGV_Sets.Has_Next (Iter) loop + LGV_Sets.Next (Iter, Current); + pragma Assert (Needs_Elaboration (G, Current)); -- Update the best candidate when there is no such candidate if not Present (Best) then - Best := Curr; + Best := Current; Trace_Vertex (G => G, - LGV_Id => Best, + Vertex => Best, Msg => "initial best candidate vertex", Step => Step, Indent => Indent); @@ -987,14 +964,14 @@ package body Bindo.Elaborators is elsif Is_Better_Candidate (G => G, - Best_Candid => Best, - New_Candid => Curr) + Best_Candidate => Best, + New_Candidate => Current) then - Best := Curr; + Best := Current; Trace_Vertex (G => G, - LGV_Id => Best, + Vertex => Best, Msg => "best candidate vertex", Step => Step, Indent => Indent); @@ -1009,48 +986,48 @@ package body Bindo.Elaborators is ------------------------- function Is_Better_Candidate - (G : Library_Graph; - Best_Candid : Library_Graph_Vertex_Id; - New_Candid : Library_Graph_Vertex_Id) return Boolean + (G : Library_Graph; + Best_Candidate : Library_Graph_Vertex_Id; + New_Candidate : Library_Graph_Vertex_Id) return Boolean is begin pragma Assert (Present (G)); - pragma Assert (Present (Best_Candid)); - pragma Assert (Present (New_Candid)); + pragma Assert (Present (Best_Candidate)); + pragma Assert (Present (New_Candidate)); -- Prefer a predefined unit over a non-predefined unit - if Is_Predefined_Unit (G, Best_Candid) - and then not Is_Predefined_Unit (G, New_Candid) + if Is_Predefined_Unit (G, Best_Candidate) + and then not Is_Predefined_Unit (G, New_Candidate) then return False; - elsif not Is_Predefined_Unit (G, Best_Candid) - and then Is_Predefined_Unit (G, New_Candid) + elsif not Is_Predefined_Unit (G, Best_Candidate) + and then Is_Predefined_Unit (G, New_Candidate) then return True; -- Prefer an internal unit over a non-iternal unit - elsif Is_Internal_Unit (G, Best_Candid) - and then not Is_Internal_Unit (G, New_Candid) + elsif Is_Internal_Unit (G, Best_Candidate) + and then not Is_Internal_Unit (G, New_Candidate) then return False; - elsif not Is_Internal_Unit (G, Best_Candid) - and then Is_Internal_Unit (G, New_Candid) + elsif not Is_Internal_Unit (G, Best_Candidate) + and then Is_Internal_Unit (G, New_Candidate) then return True; -- Prefer a preelaborated unit over a non-preelaborated unit - elsif Is_Preelaborated_Unit (G, Best_Candid) - and then not Is_Preelaborated_Unit (G, New_Candid) + elsif Is_Preelaborated_Unit (G, Best_Candidate) + and then not Is_Preelaborated_Unit (G, New_Candidate) then return False; - elsif not Is_Preelaborated_Unit (G, Best_Candid) - and then Is_Preelaborated_Unit (G, New_Candid) + elsif not Is_Preelaborated_Unit (G, Best_Candidate) + and then Is_Preelaborated_Unit (G, New_Candidate) then return True; @@ -1058,7 +1035,8 @@ package body Bindo.Elaborators is -- behavior. else - return Uname_Less (Name (G, Best_Candid), Name (G, New_Candid)); + return + Uname_Less (Name (G, Best_Candidate), Name (G, New_Candidate)); end if; end Is_Better_Candidate; @@ -1068,18 +1046,18 @@ package body Bindo.Elaborators is procedure Trace_Candidate_Vertices (G : Library_Graph; - Set : Membership_Set; + Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step) is - Iter : Iterator; - LGV_Id : Library_Graph_Vertex_Id; + Iter : LGV_Sets.Iterator; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); - pragma Assert (Present (Set)); + pragma Assert (LGV_Sets.Present (Set)); - -- Nothing to do when switch -d_T (output elaboration order trace - -- information) is not in effect. + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; @@ -1087,17 +1065,16 @@ package body Bindo.Elaborators is Trace_Step (Step); Write_Str ("candidate vertices: "); - Write_Int (Int (Size (Set))); + Write_Int (Int (LGV_Sets.Size (Set))); Write_Eol; - Iter := Iterate (Set); - while Has_Next (Iter) loop - Next (Iter, LGV_Id); - pragma Assert (Present (LGV_Id)); + Iter := LGV_Sets.Iterate (Set); + while LGV_Sets.Has_Next (Iter) loop + LGV_Sets.Next (Iter, Vertex); Trace_Vertex (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Msg => "candidate vertex", Step => Step, Indent => Nested_Indentation); @@ -1118,8 +1095,8 @@ package body Bindo.Elaborators is pragma Assert (Present (G)); pragma Assert (Present (Comp)); - -- Nothing to do when switch -d_T (output elaboration order trace - -- information) is not in effect. + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; @@ -1145,8 +1122,8 @@ package body Bindo.Elaborators is procedure Trace_Step (Step : Elaboration_Order_Step) is begin - -- Nothing to do when switch -d_T (output elaboration order trace - -- information) is not in effect. + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; @@ -1168,13 +1145,13 @@ package body Bindo.Elaborators is Step : Elaboration_Order_Step) is Iter : Library_Graphs.All_Vertex_Iterator; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); - -- Nothing to do when switch -d_T (output elaboration order trace - -- information) is not in effect. + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; @@ -1187,15 +1164,14 @@ package body Bindo.Elaborators is Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop - Next (Iter, LGV_Id); - pragma Assert (Present (LGV_Id)); + Next (Iter, Vertex); - if Needs_Elaboration (G, LGV_Id) - and then not In_Elaboration_Order (G, LGV_Id) + if Needs_Elaboration (G, Vertex) + and then not In_Elaboration_Order (G, Vertex) then Trace_Vertex (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Msg => "remaining vertex", Step => Step, Indent => Nested_Indentation); @@ -1209,21 +1185,21 @@ package body Bindo.Elaborators is procedure Trace_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Msg : String; Step : Elaboration_Order_Step; Indent : Indentation_Level) is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - Comp : constant Component_Id := Component (G, LGV_Id); - - pragma Assert (Present (Comp)); + Attr_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + Comp : constant Component_Id := Component (G, Vertex); begin - -- Nothing to do when switch -d_T (output elaboration order trace - -- information) is not in effect. + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. if not Debug_Flag_Underscore_TT then return; @@ -1233,31 +1209,31 @@ package body Bindo.Elaborators is Indent_By (Indent); Write_Str (Msg); Write_Str (" (LGV_Id_"); - Write_Int (Int (LGV_Id)); + Write_Int (Int (Vertex)); Write_Str (")"); Write_Eol; Trace_Step (Step); - Indent_By (Indent + Nested_Indentation); + Indent_By (Attr_Indent); Write_Str ("name = "); - Write_Name (Name (G, LGV_Id)); + Write_Name (Name (G, Vertex)); Write_Eol; Trace_Step (Step); - Indent_By (Indent + Nested_Indentation); + Indent_By (Attr_Indent); Write_Str ("Component (Comp_Id_"); Write_Int (Int (Comp)); Write_Str (")"); Write_Eol; Trace_Step (Step); - Indent_By (Indent + Nested_Indentation); + Indent_By (Attr_Indent); Write_Str ("pending predecessors: "); - Write_Num (Int (Pending_Predecessors (G, LGV_Id))); + Write_Num (Int (Pending_Predecessors (G, Vertex))); Write_Eol; Trace_Step (Step); - Indent_By (Indent + Nested_Indentation); + Indent_By (Attr_Indent); Write_Str ("pending components : "); Write_Num (Int (Pending_Predecessors (G, Comp))); Write_Eol; @@ -1271,8 +1247,8 @@ package body Bindo.Elaborators is (G : Library_Graph; Pred : Library_Graph_Vertex_Id; Succ : Library_Graph_Vertex_Id; - All_Candidates : Membership_Set; - Comp_Candidates : Membership_Set; + All_Candidates : LGV_Sets.Membership_Set; + Comp_Candidates : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) is @@ -1281,26 +1257,28 @@ package body Bindo.Elaborators is pragma Assert (Needs_Elaboration (G, Pred)); pragma Assert (Present (Succ)); pragma Assert (Needs_Elaboration (G, Succ)); - pragma Assert (Present (All_Candidates)); - pragma Assert (Present (Comp_Candidates)); - - Pred_Comp : constant Component_Id := Component (G, Pred); - Succ_Comp : constant Component_Id := Component (G, Succ); + pragma Assert (LGV_Sets.Present (All_Candidates)); + pragma Assert (LGV_Sets.Present (Comp_Candidates)); - pragma Assert (Present (Pred_Comp)); - pragma Assert (Present (Succ_Comp)); + In_Different_Components : constant Boolean := + not In_Same_Component + (G => G, + Left => Pred, + Right => Succ); - In_Different_Components : constant Boolean := Pred_Comp /= Succ_Comp; + Succ_Comp : constant Component_Id := Component (G, Succ); + Vertex_Indent : constant Indentation_Level := + Indent + Nested_Indentation; Candidate : Library_Graph_Vertex_Id; Iter : Component_Vertex_Iterator; Msg : String_Ptr; - Set : Membership_Set; + Set : LGV_Sets.Membership_Set; begin Trace_Vertex (G => G, - LGV_Id => Succ, + Vertex => Succ, Msg => "updating successor", Step => Step, Indent => Indent); @@ -1341,11 +1319,11 @@ package body Bindo.Elaborators is Add_Vertex_If_Elaborable (G => G, - LGV_Id => Succ, + Vertex => Succ, Set => Set, Msg => Msg.all, Step => Step, - Indent => Indent + Nested_Indentation); + Indent => Vertex_Indent); -- At this point the successor component may become elaborable when -- its final predecessor component is elaborated. This in turn may @@ -1357,15 +1335,14 @@ package body Bindo.Elaborators is Iter := Iterate_Component_Vertices (G, Succ_Comp); while Has_Next (Iter) loop Next (Iter, Candidate); - pragma Assert (Present (Candidate)); Add_Vertex_If_Elaborable (G => G, - LGV_Id => Candidate, + Vertex => Candidate, Set => All_Candidates, Msg => Add_To_All_Candidates_Msg, Step => Step, - Indent => Indent + Nested_Indentation); + Indent => Vertex_Indent); end loop; end if; end Update_Successor; @@ -1377,36 +1354,30 @@ package body Bindo.Elaborators is procedure Update_Successors (G : Library_Graph; Pred : Library_Graph_Vertex_Id; - All_Candidates : Membership_Set; - Comp_Candidates : Membership_Set; + All_Candidates : LGV_Sets.Membership_Set; + Comp_Candidates : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) is - Iter : Edges_To_Successors_Iterator; - LGE_Id : Library_Graph_Edge_Id; - Succ : Library_Graph_Vertex_Id; + Edge : Library_Graph_Edge_Id; + Iter : Edges_To_Successors_Iterator; begin pragma Assert (Present (G)); pragma Assert (Present (Pred)); pragma Assert (Needs_Elaboration (G, Pred)); - pragma Assert (Present (All_Candidates)); - pragma Assert (Present (Comp_Candidates)); + pragma Assert (LGV_Sets.Present (All_Candidates)); + pragma Assert (LGV_Sets.Present (Comp_Candidates)); Iter := Iterate_Edges_To_Successors (G, Pred); while Has_Next (Iter) loop - Next (Iter, LGE_Id); - - pragma Assert (Present (LGE_Id)); - pragma Assert (Predecessor (G, LGE_Id) = Pred); - - Succ := Successor (G, LGE_Id); - pragma Assert (Present (Succ)); + Next (Iter, Edge); + pragma Assert (Predecessor (G, Edge) = Pred); Update_Successor (G => G, Pred => Pred, - Succ => Succ, + Succ => Successor (G, Edge), All_Candidates => All_Candidates, Comp_Candidates => Comp_Candidates, Step => Step, diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index b2f458c..c68e367 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -25,7 +25,12 @@ with Ada.Unchecked_Deallocation; -with GNAT.Lists; use GNAT.Lists; +with Butil; use Butil; +with Debug; use Debug; +with Output; use Output; + +with Bindo.Writers; +use Bindo.Writers; package body Bindo.Graphs is @@ -33,33 +38,73 @@ package body Bindo.Graphs is -- Local subprograms -- ----------------------- - function Sequence_Next_IGE_Id return Invocation_Graph_Edge_Id; - pragma Inline (Sequence_Next_IGE_Id); - -- Generate a new unique invocation graph edge handle + function Sequence_Next_Cycle return Library_Graph_Cycle_Id; + pragma Inline (Sequence_Next_Cycle); + -- Generate a new unique library graph cycle handle - function Sequence_Next_IGV_Id return Invocation_Graph_Vertex_Id; - pragma Inline (Sequence_Next_IGV_Id); - -- Generate a new unique invocation graph vertex handle + function Sequence_Next_Edge return Invocation_Graph_Edge_Id; + pragma Inline (Sequence_Next_Edge); + -- Generate a new unique invocation graph edge handle - function Sequence_Next_LGE_Id return Library_Graph_Edge_Id; - pragma Inline (Sequence_Next_LGE_Id); + function Sequence_Next_Edge return Library_Graph_Edge_Id; + pragma Inline (Sequence_Next_Edge); -- Generate a new unique library graph edge handle - function Sequence_Next_LGV_Id return Library_Graph_Vertex_Id; - pragma Inline (Sequence_Next_LGV_Id); + function Sequence_Next_Vertex return Invocation_Graph_Vertex_Id; + pragma Inline (Sequence_Next_Vertex); + -- Generate a new unique invocation graph vertex handle + + function Sequence_Next_Vertex return Library_Graph_Vertex_Id; + pragma Inline (Sequence_Next_Vertex); -- Generate a new unique library graph vertex handle + ----------------------------------- + -- Destroy_Invocation_Graph_Edge -- + ----------------------------------- + + procedure Destroy_Invocation_Graph_Edge + (Edge : in out Invocation_Graph_Edge_Id) + is + pragma Unreferenced (Edge); + begin + null; + end Destroy_Invocation_Graph_Edge; + + --------------------------------- + -- Destroy_Library_Graph_Cycle -- + --------------------------------- + + procedure Destroy_Library_Graph_Cycle + (Cycle : in out Library_Graph_Cycle_Id) + is + pragma Unreferenced (Cycle); + begin + null; + end Destroy_Library_Graph_Cycle; + + -------------------------------- + -- Destroy_Library_Graph_Edge -- + -------------------------------- + + procedure Destroy_Library_Graph_Edge + (Edge : in out Library_Graph_Edge_Id) + is + pragma Unreferenced (Edge); + begin + null; + end Destroy_Library_Graph_Edge; + -------------------------------- -- Hash_Invocation_Graph_Edge -- -------------------------------- function Hash_Invocation_Graph_Edge - (IGE_Id : Invocation_Graph_Edge_Id) return Bucket_Range_Type + (Edge : Invocation_Graph_Edge_Id) return Bucket_Range_Type is begin - pragma Assert (Present (IGE_Id)); + pragma Assert (Present (Edge)); - return Bucket_Range_Type (IGE_Id); + return Bucket_Range_Type (Edge); end Hash_Invocation_Graph_Edge; ---------------------------------- @@ -67,25 +112,38 @@ package body Bindo.Graphs is ---------------------------------- function Hash_Invocation_Graph_Vertex - (IGV_Id : Invocation_Graph_Vertex_Id) return Bucket_Range_Type + (Vertex : Invocation_Graph_Vertex_Id) return Bucket_Range_Type is begin - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); - return Bucket_Range_Type (IGV_Id); + return Bucket_Range_Type (Vertex); end Hash_Invocation_Graph_Vertex; + ------------------------------ + -- Hash_Library_Graph_Cycle -- + ------------------------------ + + function Hash_Library_Graph_Cycle + (Cycle : Library_Graph_Cycle_Id) return Bucket_Range_Type + is + begin + pragma Assert (Present (Cycle)); + + return Bucket_Range_Type (Cycle); + end Hash_Library_Graph_Cycle; + ----------------------------- -- Hash_Library_Graph_Edge -- ----------------------------- function Hash_Library_Graph_Edge - (LGE_Id : Library_Graph_Edge_Id) return Bucket_Range_Type + (Edge : Library_Graph_Edge_Id) return Bucket_Range_Type is begin - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Edge)); - return Bucket_Range_Type (LGE_Id); + return Bucket_Range_Type (Edge); end Hash_Library_Graph_Edge; ------------------------------- @@ -93,12 +151,12 @@ package body Bindo.Graphs is ------------------------------- function Hash_Library_Graph_Vertex - (LGV_Id : Library_Graph_Vertex_Id) return Bucket_Range_Type + (Vertex : Library_Graph_Vertex_Id) return Bucket_Range_Type is begin - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - return Bucket_Range_Type (LGV_Id); + return Bucket_Range_Type (Vertex); end Hash_Library_Graph_Vertex; ----------------------- @@ -116,18 +174,18 @@ package body Bindo.Graphs is (Invocation_Graph_Attributes, Invocation_Graph); function Get_IGE_Attributes - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Invocation_Graph_Edge_Attributes; pragma Inline (Get_IGE_Attributes); - -- Obtain the attributes of edge IGE_Id of invocation graph G + -- Obtain the attributes of edge Edge of invocation graph G function Get_IGV_Attributes (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) + Vertex : Invocation_Graph_Vertex_Id) return Invocation_Graph_Vertex_Attributes; pragma Inline (Get_IGV_Attributes); - -- Obtain the attributes of vertex IGV_Id of invocation graph G + -- Obtain the attributes of vertex Vertex of invocation graph G procedure Increment_Invocation_Graph_Edge_Count (G : Invocation_Graph; @@ -138,9 +196,9 @@ package body Bindo.Graphs is function Is_Elaboration_Root (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Boolean; + Vertex : Invocation_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Elaboration_Root); - -- Determine whether vertex IGV_Id of invocation graph denotes the + -- Determine whether vertex Vertex of invocation graph denotes the -- elaboration procedure of a spec or a body. function Is_Existing_Source_Target_Relation @@ -159,9 +217,9 @@ package body Bindo.Graphs is procedure Set_Corresponding_Vertex (G : Invocation_Graph; IS_Id : Invocation_Signature_Id; - IGV_Id : Invocation_Graph_Vertex_Id); + Vertex : Invocation_Graph_Vertex_Id); pragma Inline (Set_Corresponding_Vertex); - -- Associate vertex IGV_Id of invocation graph G with signature IS_Id + -- Associate vertex Vertex of invocation graph G with signature IS_Id procedure Set_Is_Existing_Source_Target_Relation (G : Invocation_Graph; @@ -172,18 +230,18 @@ package body Bindo.Graphs is -- already related in invocation graph G depending on value Val. procedure Set_IGE_Attributes - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id; - Val : Invocation_Graph_Edge_Attributes); + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id; + Val : Invocation_Graph_Edge_Attributes); pragma Inline (Set_IGE_Attributes); - -- Set the attributes of edge IGE_Id of invocation graph G to value Val + -- Set the attributes of edge Edge of invocation graph G to value Val procedure Set_IGV_Attributes (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id; + Vertex : Invocation_Graph_Vertex_Id; Val : Invocation_Graph_Vertex_Attributes); pragma Inline (Set_IGV_Attributes); - -- Set the attributes of vertex IGV_Id of invocation graph G to value + -- Set the attributes of vertex Vertex of invocation graph G to value -- Val. -------------- @@ -205,10 +263,7 @@ package body Bindo.Graphs is (Source => Source, Target => Target); - IR_Rec : Invocation_Relation_Record renames - Invocation_Relations.Table (IR_Id); - - IGE_Id : Invocation_Graph_Edge_Id; + Edge : Invocation_Graph_Edge_Id; begin -- Nothing to do when the source and target are already related by an @@ -218,22 +273,22 @@ package body Bindo.Graphs is return; end if; - IGE_Id := Sequence_Next_IGE_Id; + Edge := Sequence_Next_Edge; -- Add the edge to the underlying graph DG.Add_Edge (G => G.Graph, - E => IGE_Id, + E => Edge, Source => Source, Destination => Target); -- Build and save the attributes of the edge Set_IGE_Attributes - (G => G, - IGE_Id => IGE_Id, - Val => (Relation => IR_Id)); + (G => G, + Edge => Edge, + Val => (Relation => IR_Id)); -- Mark the source and target as related by the new edge. This -- prevents all further attempts to link the same source and target. @@ -242,7 +297,7 @@ package body Bindo.Graphs is -- Update the edge statistics - Increment_Invocation_Graph_Edge_Count (G, IR_Rec.Kind); + Increment_Invocation_Graph_Edge_Count (G, Kind (IR_Id)); end Add_Edge; ---------------- @@ -250,67 +305,97 @@ package body Bindo.Graphs is ---------------- procedure Add_Vertex - (G : Invocation_Graph; - IC_Id : Invocation_Construct_Id; - LGV_Id : Library_Graph_Vertex_Id) + (G : Invocation_Graph; + IC_Id : Invocation_Construct_Id; + Body_Vertex : Library_Graph_Vertex_Id; + Spec_Vertex : Library_Graph_Vertex_Id) is pragma Assert (Present (G)); pragma Assert (Present (IC_Id)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Body_Vertex)); + pragma Assert (Present (Spec_Vertex)); - IC_Rec : Invocation_Construct_Record renames - Invocation_Constructs.Table (IC_Id); - - pragma Assert (Present (IC_Rec.Signature)); - - IGV_Id : Invocation_Graph_Vertex_Id; + Construct_Signature : constant Invocation_Signature_Id := + Signature (IC_Id); + Vertex : Invocation_Graph_Vertex_Id; begin -- Nothing to do when the construct already has a vertex - if Present (Corresponding_Vertex (G, IC_Rec.Signature)) then + if Present (Corresponding_Vertex (G, Construct_Signature)) then return; end if; - IGV_Id := Sequence_Next_IGV_Id; + Vertex := Sequence_Next_Vertex; -- Add the vertex to the underlying graph - DG.Add_Vertex (G.Graph, IGV_Id); + DG.Add_Vertex (G.Graph, Vertex); -- Build and save the attributes of the vertex Set_IGV_Attributes (G => G, - IGV_Id => IGV_Id, - Val => (Construct => IC_Id, - Lib_Vertex => LGV_Id)); + Vertex => Vertex, + Val => (Body_Vertex => Body_Vertex, + Construct => IC_Id, + Spec_Vertex => Spec_Vertex)); -- Associate the construct with its corresponding vertex - Set_Corresponding_Vertex (G, IC_Rec.Signature, IGV_Id); + Set_Corresponding_Vertex (G, Construct_Signature, Vertex); -- Save the vertex for later processing when it denotes a spec or -- body elaboration procedure. - if Is_Elaboration_Root (G, IGV_Id) then - Save_Elaboration_Root (G, IGV_Id); + if Is_Elaboration_Root (G, Vertex) then + Save_Elaboration_Root (G, Vertex); end if; end Add_Vertex; + ----------------- + -- Body_Vertex -- + ----------------- + + function Body_Vertex + (G : Invocation_Graph; + Vertex : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + return Get_IGV_Attributes (G, Vertex).Body_Vertex; + end Body_Vertex; + + ------------ + -- Column -- + ------------ + + function Column + (G : Invocation_Graph; + Vertex : Invocation_Graph_Vertex_Id) return Nat + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + return Column (Signature (Construct (G, Vertex))); + end Column; + --------------- -- Construct -- --------------- function Construct (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Invocation_Construct_Id + Vertex : Invocation_Graph_Vertex_Id) return Invocation_Construct_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); - return Get_IGV_Attributes (G, IGV_Id).Construct; + return Get_IGV_Attributes (G, Vertex).Construct; end Construct; -------------------------- @@ -325,7 +410,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (IS_Id)); - return SV.Get (G.Signature_To_Vertex, IS_Id); + return Signature_Tables.Get (G.Signature_To_Vertex, IS_Id); end Corresponding_Vertex; ------------ @@ -339,15 +424,15 @@ package body Bindo.Graphs is G : constant Invocation_Graph := new Invocation_Graph_Attributes; begin - G.Edge_Attributes := EA.Create (Initial_Edges); + G.Edge_Attributes := IGE_Tables.Create (Initial_Edges); G.Graph := DG.Create (Initial_Vertices => Initial_Vertices, Initial_Edges => Initial_Edges); - G.Relations := ST.Create (Initial_Edges); - G.Roots := ER.Create (Initial_Vertices); - G.Signature_To_Vertex := SV.Create (Initial_Vertices); - G.Vertex_Attributes := VA.Create (Initial_Vertices); + G.Relations := Relation_Sets.Create (Initial_Edges); + G.Roots := IGV_Sets.Create (Initial_Vertices); + G.Signature_To_Vertex := Signature_Tables.Create (Initial_Vertices); + G.Vertex_Attributes := IGV_Tables.Create (Initial_Vertices); return G; end Create; @@ -360,12 +445,12 @@ package body Bindo.Graphs is begin pragma Assert (Present (G)); - EA.Destroy (G.Edge_Attributes); - DG.Destroy (G.Graph); - ST.Destroy (G.Relations); - ER.Destroy (G.Roots); - SV.Destroy (G.Signature_To_Vertex); - VA.Destroy (G.Vertex_Attributes); + IGE_Tables.Destroy (G.Edge_Attributes); + DG.Destroy (G.Graph); + Relation_Sets.Destroy (G.Relations); + IGV_Sets.Destroy (G.Roots); + Signature_Tables.Destroy (G.Signature_To_Vertex); + IGV_Tables.Destroy (G.Vertex_Attributes); Free (G); end Destroy; @@ -375,9 +460,9 @@ package body Bindo.Graphs is ----------------------------------- procedure Destroy_Invocation_Graph_Edge - (IGE_Id : in out Invocation_Graph_Edge_Id) + (Edge : in out Invocation_Graph_Edge_Id) is - pragma Unreferenced (IGE_Id); + pragma Unreferenced (Edge); begin null; end Destroy_Invocation_Graph_Edge; @@ -399,9 +484,9 @@ package body Bindo.Graphs is ------------------------------------- procedure Destroy_Invocation_Graph_Vertex - (IGV_Id : in out Invocation_Graph_Vertex_Id) + (Vertex : in out Invocation_Graph_Vertex_Id) is - pragma Unreferenced (IGV_Id); + pragma Unreferenced (Vertex); begin null; end Destroy_Invocation_Graph_Vertex; @@ -418,20 +503,35 @@ package body Bindo.Graphs is null; end Destroy_Invocation_Graph_Vertex_Attributes; + ----------- + -- Extra -- + ----------- + + function Extra + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Name_Id + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return Extra (Relation (G, Edge)); + end Extra; + ------------------------ -- Get_IGE_Attributes -- ------------------------ function Get_IGE_Attributes - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Invocation_Graph_Edge_Attributes is begin pragma Assert (Present (G)); - pragma Assert (Present (IGE_Id)); + pragma Assert (Present (Edge)); - return EA.Get (G.Edge_Attributes, IGE_Id); + return IGE_Tables.Get (G.Edge_Attributes, Edge); end Get_IGE_Attributes; ------------------------ @@ -440,14 +540,14 @@ package body Bindo.Graphs is function Get_IGV_Attributes (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) + Vertex : Invocation_Graph_Vertex_Id) return Invocation_Graph_Vertex_Attributes is begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); - return VA.Get (G.Vertex_Attributes, IGV_Id); + return IGV_Tables.Get (G.Vertex_Attributes, Vertex); end Get_IGV_Attributes; -------------- @@ -483,7 +583,7 @@ package body Bindo.Graphs is function Has_Next (Iter : Elaboration_Root_Iterator) return Boolean is begin - return ER.Has_Next (ER.Iterator (Iter)); + return IGV_Sets.Has_Next (IGV_Sets.Iterator (Iter)); end Has_Next; ------------------------------- @@ -552,23 +652,19 @@ package body Bindo.Graphs is function Is_Elaboration_Root (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Boolean + Vertex : Invocation_Graph_Vertex_Id) return Boolean is pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); - - IC_Id : constant Invocation_Construct_Id := Construct (G, IGV_Id); - - pragma Assert (Present (IC_Id)); + pragma Assert (Present (Vertex)); - IC_Rec : Invocation_Construct_Record renames - Invocation_Constructs.Table (IC_Id); + Vertex_Kind : constant Invocation_Construct_Kind := + Kind (Construct (G, Vertex)); begin return - IC_Rec.Kind = Elaborate_Body_Procedure + Vertex_Kind = Elaborate_Body_Procedure or else - IC_Rec.Kind = Elaborate_Spec_Procedure; + Vertex_Kind = Elaborate_Spec_Procedure; end Is_Elaboration_Root; ---------------------------------------- @@ -582,7 +678,7 @@ package body Bindo.Graphs is begin pragma Assert (Present (G)); - return ST.Contains (G.Relations, Rel); + return Relation_Sets.Contains (G.Relations, Rel); end Is_Existing_Source_Target_Relation; ----------------------- @@ -617,15 +713,15 @@ package body Bindo.Graphs is function Iterate_Edges_To_Targets (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Edges_To_Targets_Iterator + Vertex : Invocation_Graph_Vertex_Id) return Edges_To_Targets_Iterator is begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); return Edges_To_Targets_Iterator - (DG.Iterate_Outgoing_Edges (G.Graph, IGV_Id)); + (DG.Iterate_Outgoing_Edges (G.Graph, Vertex)); end Iterate_Edges_To_Targets; ------------------------------- @@ -638,7 +734,7 @@ package body Bindo.Graphs is begin pragma Assert (Present (G)); - return Elaboration_Root_Iterator (ER.Iterate (G.Roots)); + return Elaboration_Root_Iterator (IGV_Sets.Iterate (G.Roots)); end Iterate_Elaboration_Roots; ---------- @@ -646,37 +742,30 @@ package body Bindo.Graphs is ---------- function Kind - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Kind + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Invocation_Kind is + begin pragma Assert (Present (G)); - pragma Assert (Present (IGE_Id)); - - IR_Id : constant Invocation_Relation_Id := Relation (G, IGE_Id); + pragma Assert (Present (Edge)); - pragma Assert (Present (IR_Id)); - - IR_Rec : Invocation_Relation_Record renames - Invocation_Relations.Table (IR_Id); - - begin - return IR_Rec.Kind; + return Kind (Relation (G, Edge)); end Kind; - ---------------- - -- Lib_Vertex -- - ---------------- + ---------- + -- Line -- + ---------- - function Lib_Vertex + function Line (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id + Vertex : Invocation_Graph_Vertex_Id) return Nat is begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); - return Get_IGV_Attributes (G, IGV_Id).Lib_Vertex; - end Lib_Vertex; + return Line (Signature (Construct (G, Vertex))); + end Line; ---------- -- Name -- @@ -684,25 +773,13 @@ package body Bindo.Graphs is function Name (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Name_Id + Vertex : Invocation_Graph_Vertex_Id) return Name_Id is + begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); - - IC_Id : constant Invocation_Construct_Id := Construct (G, IGV_Id); - - pragma Assert (Present (IC_Id)); + pragma Assert (Present (Vertex)); - IC_Rec : Invocation_Construct_Record renames - Invocation_Constructs.Table (IC_Id); - - pragma Assert (Present (IC_Rec.Signature)); - - IS_Rec : Invocation_Signature_Record renames - Invocation_Signatures.Table (IC_Rec.Signature); - - begin - return IS_Rec.Name; + return Name (Signature (Construct (G, Vertex))); end Name; ---------- @@ -710,11 +787,11 @@ package body Bindo.Graphs is ---------- procedure Next - (Iter : in out All_Edge_Iterator; - IGE_Id : out Invocation_Graph_Edge_Id) + (Iter : in out All_Edge_Iterator; + Edge : out Invocation_Graph_Edge_Id) is begin - DG.Next (DG.All_Edge_Iterator (Iter), IGE_Id); + DG.Next (DG.All_Edge_Iterator (Iter), Edge); end Next; ---------- @@ -723,10 +800,10 @@ package body Bindo.Graphs is procedure Next (Iter : in out All_Vertex_Iterator; - IGV_Id : out Invocation_Graph_Vertex_Id) + Vertex : out Invocation_Graph_Vertex_Id) is begin - DG.Next (DG.All_Vertex_Iterator (Iter), IGV_Id); + DG.Next (DG.All_Vertex_Iterator (Iter), Vertex); end Next; ---------- @@ -734,11 +811,11 @@ package body Bindo.Graphs is ---------- procedure Next - (Iter : in out Edges_To_Targets_Iterator; - IGE_Id : out Invocation_Graph_Edge_Id) + (Iter : in out Edges_To_Targets_Iterator; + Edge : out Invocation_Graph_Edge_Id) is begin - DG.Next (DG.Outgoing_Edge_Iterator (Iter), IGE_Id); + DG.Next (DG.Outgoing_Edge_Iterator (Iter), Edge); end Next; ---------- @@ -750,7 +827,7 @@ package body Bindo.Graphs is Root : out Invocation_Graph_Vertex_Id) is begin - ER.Next (ER.Iterator (Iter), Root); + IGV_Sets.Next (IGV_Sets.Iterator (Iter), Root); end Next; --------------------- @@ -770,13 +847,13 @@ package body Bindo.Graphs is function Number_Of_Edges_To_Targets (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Natural + Vertex : Invocation_Graph_Vertex_Id) return Natural is begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); - return DG.Number_Of_Outgoing_Edges (G.Graph, IGV_Id); + return DG.Number_Of_Outgoing_Edges (G.Graph, Vertex); end Number_Of_Edges_To_Targets; --------------------------------- @@ -789,7 +866,7 @@ package body Bindo.Graphs is begin pragma Assert (Present (G)); - return ER.Size (G.Roots); + return IGV_Sets.Size (G.Roots); end Number_Of_Elaboration_Roots; ------------------------ @@ -817,14 +894,14 @@ package body Bindo.Graphs is -------------- function Relation - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Relation_Id + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Invocation_Relation_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (IGE_Id)); + pragma Assert (Present (Edge)); - return Get_IGE_Attributes (G, IGE_Id).Relation; + return Get_IGE_Attributes (G, Edge).Relation; end Relation; --------------------------- @@ -839,7 +916,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Root)); - ER.Insert (G.Roots, Root); + IGV_Sets.Insert (G.Roots, Root); end Save_Elaboration_Root; ------------------------------ @@ -849,14 +926,14 @@ package body Bindo.Graphs is procedure Set_Corresponding_Vertex (G : Invocation_Graph; IS_Id : Invocation_Signature_Id; - IGV_Id : Invocation_Graph_Vertex_Id) + Vertex : Invocation_Graph_Vertex_Id) is begin pragma Assert (Present (G)); pragma Assert (Present (IS_Id)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); - SV.Put (G.Signature_To_Vertex, IS_Id, IGV_Id); + Signature_Tables.Put (G.Signature_To_Vertex, IS_Id, Vertex); end Set_Corresponding_Vertex; -------------------------------------------- @@ -874,9 +951,9 @@ package body Bindo.Graphs is pragma Assert (Present (Rel.Target)); if Val then - ST.Insert (G.Relations, Rel); + Relation_Sets.Insert (G.Relations, Rel); else - ST.Delete (G.Relations, Rel); + Relation_Sets.Delete (G.Relations, Rel); end if; end Set_Is_Existing_Source_Target_Relation; @@ -885,15 +962,15 @@ package body Bindo.Graphs is ------------------------ procedure Set_IGE_Attributes - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id; - Val : Invocation_Graph_Edge_Attributes) + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id; + Val : Invocation_Graph_Edge_Attributes) is begin pragma Assert (Present (G)); - pragma Assert (Present (IGE_Id)); + pragma Assert (Present (Edge)); - EA.Put (G.Edge_Attributes, IGE_Id, Val); + IGE_Tables.Put (G.Edge_Attributes, Edge, Val); end Set_IGE_Attributes; ------------------------ @@ -902,29 +979,44 @@ package body Bindo.Graphs is procedure Set_IGV_Attributes (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id; + Vertex : Invocation_Graph_Vertex_Id; Val : Invocation_Graph_Vertex_Attributes) is begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); - VA.Put (G.Vertex_Attributes, IGV_Id, Val); + IGV_Tables.Put (G.Vertex_Attributes, Vertex, Val); end Set_IGV_Attributes; + ----------------- + -- Spec_Vertex -- + ----------------- + + function Spec_Vertex + (G : Invocation_Graph; + Vertex : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + return Get_IGV_Attributes (G, Vertex).Spec_Vertex; + end Spec_Vertex; + ------------ -- Target -- ------------ function Target (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Graph_Vertex_Id + Edge : Invocation_Graph_Edge_Id) return Invocation_Graph_Vertex_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (IGE_Id)); + pragma Assert (Present (Edge)); - return DG.Destination_Vertex (G.Graph, IGE_Id); + return DG.Destination_Vertex (G.Graph, Edge); end Target; end Invocation_Graphs; @@ -934,14 +1026,17 @@ package body Bindo.Graphs is package body Library_Graphs is - --------------- - -- Edge list -- - --------------- + ----------- + -- Types -- + ----------- + + -- The following type represents the various kinds of precedence between + -- two items. - package EL is new Doubly_Linked_Lists - (Element_Type => Library_Graph_Edge_Id, - "=" => "=", - Destroy_Element => Destroy_Library_Graph_Edge); + type Precedence_Kind is + (Lower_Precedence, + Equal_Precedence, + Higher_Precedence); ----------------------- -- Local subprograms -- @@ -949,21 +1044,31 @@ package body Bindo.Graphs is procedure Add_Body_Before_Spec_Edge (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - Edges : EL.Doubly_Linked_List); + Vertex : Library_Graph_Vertex_Id; + Edges : LGE_Lists.Doubly_Linked_List); pragma Inline (Add_Body_Before_Spec_Edge); - -- Create a new edge in library graph G between vertex LGV_Id and its + -- Create a new edge in library graph G between vertex Vertex and its -- corresponding spec or body, where the body is a predecessor and the -- spec a successor. Add the edge to list Edges. procedure Add_Body_Before_Spec_Edges (G : Library_Graph; - Edges : EL.Doubly_Linked_List); + Edges : LGE_Lists.Doubly_Linked_List); pragma Inline (Add_Body_Before_Spec_Edges); -- Create new edges in library graph G for all vertices and their -- corresponding specs or bodies, where the body is a predecessor -- and the spec is a successor. Add all edges to list Edges. + procedure Add_Cycle + (G : Library_Graph; + Attrs : Library_Graph_Cycle_Attributes; + Indent : Indentation_Level); + pragma Inline (Add_Cycle); + -- Store a cycle described by attribytes Attrs in library graph G, + -- unless a prior rotation of it already exists. The edges of the cycle + -- must be in normalized form. Indent is the desired indentation level + -- for tracing. + function Add_Edge_With_Return (G : Library_Graph; Pred : Library_Graph_Vertex_Id; @@ -975,6 +1080,38 @@ package body Bindo.Graphs is -- nature of the edge. If Pred and Succ are already related, no edge -- is created and No_Library_Graph_Edge is returned. + procedure Add_Vertex_And_Complement + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; + Do_Complement : Boolean); + pragma Inline (Add_Vertex_And_Complement); + -- Add vertex Vertex of library graph G to set Set. If the vertex is + -- part of an Elaborate_Body pair, or flag Do_Complement is set, add + -- the complementary vertex to the set. + + function Complementary_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Do_Complement : Boolean) return Library_Graph_Vertex_Id; + pragma Inline (Complementary_Vertex); + -- If vertex Vertex of library graph G is part of an Elaborate_Body + -- pair, or flag Do_Complement is set, return the spec when Vertex is + -- a body, the body when Vertex is a spec, or No_Library_Graph_Vertex. + + function Copy_Cycle_Path + (Cycle_Path : LGE_Lists.Doubly_Linked_List) + return LGE_Lists.Doubly_Linked_List; + pragma Inline (Copy_Cycle_Path); + -- Create a deep copy of list Cycle_Path + + function Cycle_Kind_Of + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Cycle_Kind; + pragma Inline (Cycle_Kind_Of); + -- Determine the cycle kind of edge Edge of library graph G if the edge + -- participated in a circuit. + procedure Decrement_Library_Graph_Edge_Count (G : Library_Graph; Kind : Library_Graph_Edge_Kind); @@ -983,7 +1120,7 @@ package body Bindo.Graphs is procedure Delete_Body_Before_Spec_Edges (G : Library_Graph; - Edges : EL.Doubly_Linked_List); + Edges : LGE_Lists.Doubly_Linked_List); pragma Inline (Delete_Body_Before_Spec_Edges); -- Delete all edges in list Edges from library graph G, that link spec -- and bodies, where the body acts as the predecessor and the spec as a @@ -991,9 +1128,52 @@ package body Bindo.Graphs is procedure Delete_Edge (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id); + Edge : Library_Graph_Edge_Id); pragma Inline (Delete_Edge); - -- Delete edge LGE_Id from library graph G + -- Delete edge Edge from library graph G + + procedure Find_All_Cycles_Through_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + End_Vertices : LGV_Sets.Membership_Set; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Spec_And_Body_Together : Boolean; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Visited_Vertices : LGV_Sets.Membership_Set; + Indent : Indentation_Level); + pragma Inline (Find_All_Cycles_Through_Vertex); + -- Explore all edges to successors of vertex Vertex of library graph G + -- in an attempt to find a cycle. A cycle is considered closed when the + -- Vertex appears in set End_Vertices. Most_Significant_Edge denotes the + -- edge with the highest significance along the candidate cycle path. + -- Invocation_Edge_Count denotes the number of invocation edges along + -- the candidate cycle path. Spec_And_Body_Together should be set when + -- spec and body vertices must be treated as one vertex. Cycle_Path is + -- the candidate cycle path. Visited_Vertices denotes the set of visited + -- vertices so far. Indent is the desired indentation level for tracing. + + procedure Find_All_Cycles_With_Edge + (G : Library_Graph; + Initial_Edge : Library_Graph_Edge_Id; + Spec_And_Body_Together : Boolean; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Visited_Vertices : LGV_Sets.Membership_Set; + Indent : Indentation_Level); + pragma Inline (Find_All_Cycles_With_Edge); + -- Find all cycles which contain edge Initial_Edge of library graph G. + -- Spec_And_Body_Together should be set when spec and body vertices must + -- be treated as one vertex. Cycle_Path is the candidate cycle path. + -- Visited_Vertices is the set of visited vertices so far. Indent is + -- the desired indentation level for tracing. + + function Find_First_Lower_Precedence_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Library_Graph_Cycle_Id; + pragma Inline (Find_First_Lower_Precedence_Cycle); + -- Inspect the list of cycles of library graph G and return the first + -- cycle whose precedence is lower than that of cycle Cycle. If there + -- is no such cycle, return No_Library_Graph_Cycle. procedure Free is new Ada.Unchecked_Deallocation @@ -1005,27 +1185,41 @@ package body Bindo.Graphs is pragma Inline (Get_Component_Attributes); -- Obtain the attributes of component Comp of library graph G + function Get_LGC_Attributes + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Library_Graph_Cycle_Attributes; + pragma Inline (Get_LGC_Attributes); + -- Obtain the attributes of cycle Cycle of library graph G + function Get_LGE_Attributes - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Edge_Attributes; pragma Inline (Get_LGE_Attributes); - -- Obtain the attributes of edge LGE_Id of library graph G + -- Obtain the attributes of edge Edge of library graph G function Get_LGV_Attributes (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Attributes; pragma Inline (Get_LGV_Attributes); - -- Obtain the attributes of vertex LGE_Id of library graph G + -- Obtain the attributes of vertex Edge of library graph G function Has_Elaborate_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Has_Elaborate_Body); - -- Determine whether vertex LGV_Id of library graph G is subject to + -- Determine whether vertex Vertex of library graph G is subject to -- pragma Elaborate_Body. + function Highest_Precedence_Edge + (G : Library_Graph; + Left : Library_Graph_Edge_Id; + Right : Library_Graph_Edge_Id) return Library_Graph_Edge_Id; + pragma Inline (Highest_Precedence_Edge); + -- Return the edge with highest precedence among edges Left and Right of + -- library graph G. + procedure Increment_Library_Graph_Edge_Count (G : Library_Graph; Kind : Library_Graph_Edge_Kind); @@ -1041,9 +1235,9 @@ package body Bindo.Graphs is procedure Increment_Pending_Predecessors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id); pragma Inline (Increment_Pending_Predecessors); - -- Increment the number of pending precedessors vertex LGV_Id of library + -- Increment the number of pending precedessors vertex Vertex of library -- graph G must wait on before it can be elaborated by one. procedure Initialize_Components (G : Library_Graph); @@ -1051,20 +1245,174 @@ package body Bindo.Graphs is -- Initialize on the initial call or re-initialize on subsequent calls -- all components of library graph G. + procedure Insert_And_Sort + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Insert_And_Sort); + -- Insert cycle Cycle in library graph G and sort it based on its + -- precedence relative to all recorded cycles. + + function Is_Cycle_Initiating_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cycle_Initiating_Edge); + -- Determine whether edge Edge of library graph G starts a cycle + + function Is_Cyclic_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cyclic_Edge); + -- Determine whether edge Edge of library graph G participates in a + -- cycle. + + function Is_Cyclic_Elaborate_All_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cyclic_Elaborate_All_Edge); + -- Determine whether edge Edge of library graph G participates in a + -- cycle and has a predecessor that is subject to pragma Elaborate_All. + + function Is_Cyclic_Elaborate_Body_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cyclic_Elaborate_Body_Edge); + -- Determine whether edge Edge of library graph G participates in a + -- cycle and has a successor that is either a spec subject to pragma + -- Elaborate_Body, or a body that completes such a spec. + + function Is_Cyclic_Elaborate_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cyclic_Elaborate_Edge); + -- Determine whether edge Edge of library graph G participates in a + -- cycle and has a predecessor that is subject to pragma Elaborate. + + function Is_Cyclic_Forced_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cyclic_Forced_Edge); + -- Determine whether edge Edge of library graph G participates in a + -- cycle and came from the forced-elaboration-order file. + + function Is_Cyclic_Invocation_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cyclic_Invocation_Edge); + -- Determine whether edge Edge of library graph G participates in a + -- cycle and came from the traversal of the invocation graph. + + function Is_Cyclic_With_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Cyclic_With_Edge); + -- Determine whether edge Edge of library graph G participates in a + -- cycle and is the result of awith dependency between its successor + -- and predecessor. + function Is_Elaborable_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Predecessors : Natural) return Boolean; pragma Inline (Is_Elaborable_Vertex); - -- Determine whether vertex LGV_Id of library graph G can be elaborated + -- Determine whether vertex Vertex of library graph G can be elaborated -- given that it meets number of predecessors Predecessors. - function Is_Existing_Predecessor_Successor_Relation + function Is_Recorded_Cycle + (G : Library_Graph; + Attrs : Library_Graph_Cycle_Attributes) return Boolean; + pragma Inline (Is_Recorded_Cycle); + -- Determine whether a cycle desctibed by its attributes Attrs has + -- has already been recorded in library graph G. + + function Is_Recorded_Edge (G : Library_Graph; Rel : Predecessor_Successor_Relation) return Boolean; - pragma Inline (Is_Existing_Predecessor_Successor_Relation); + pragma Inline (Is_Recorded_Edge); -- Determine whether a predecessor vertex and a successor vertex - -- desctibed by relation Rel are already related in library graph G. + -- desctibed by relation Rel are already linked in library graph G. + + function Links_Vertices_In_Same_Component + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Links_Vertices_In_Same_Component); + -- Determine whether edge Edge of library graph G links a predecessor + -- and successor that reside in the same component. + + function Maximum_Invocation_Edge_Count + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Count : Natural) return Natural; + pragma Inline (Maximum_Invocation_Edge_Count); + -- Determine whether edge Edge of library graph G is an invocation edge, + -- and if it is return Count + 1, otherwise return Count. + + procedure Normalize_And_Add_Cycle + (G : Library_Graph; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Indent : Indentation_Level); + pragma Inline (Normalize_And_Add_Cycle); + -- Normalize a cycle described by its path Cycle_Path and add it to + -- library graph G. Most_Significant_Edge denotes the edge with the + -- highest significance along the cycle path. Invocation_Edge_Count + -- denotes the number of invocation edges along the cycle path. Indent + -- is the desired indentation level for tracing. + + procedure Normalize_Cycle_Path + (Cycle_Path : LGE_Lists.Doubly_Linked_List; + Most_Significant_Edge : Library_Graph_Edge_Id); + pragma Inline (Normalize_Cycle_Path); + -- Normalize cycle path Path by rotating it until its starting edge is + -- Sig_Edge. + + function Path + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return LGE_Lists.Doubly_Linked_List; + pragma Inline (Path); + -- Obtain the path of edges which comprises cycle Cycle of library + -- graph G. + + function Precedence + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Compared_To : Library_Graph_Cycle_Id) return Precedence_Kind; + pragma Inline (Precedence); + -- Determine the precedence of cycle Cycle of library graph G compared + -- to cycle Compared_To. + + function Precedence + (Kind : Library_Graph_Cycle_Kind; + Compared_To : Library_Graph_Cycle_Kind) return Precedence_Kind; + pragma Inline (Precedence); + -- Determine the precedence of cycle kind Kind compared to cycle kind + -- Compared_To. + + function Precedence + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Compared_To : Library_Graph_Edge_Id) return Precedence_Kind; + pragma Inline (Precedence); + -- Determine the precedence of edge Edge of library graph G compared to + -- edge Compared_To. + + function Precedence + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; + pragma Inline (Precedence); + -- Determine the precedence of vertex Vertex of library graph G compared + -- to vertex Compared_To. + + procedure Remove_Vertex_And_Complement + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; + Do_Complement : Boolean); + pragma Inline (Remove_Vertex_And_Complement); + -- Remove vertex Vertex of library graph G from set Set. If the vertex + -- is part of an Elaborate_Body pair, or Do_Complement is set, remove + -- the complementary vertex from the set. procedure Set_Component_Attributes (G : Library_Graph; @@ -1080,27 +1428,70 @@ package body Bindo.Graphs is pragma Inline (Set_Corresponding_Vertex); -- Associate vertex Val of library graph G with unit U_Id - procedure Set_Is_Existing_Predecessor_Successor_Relation + procedure Set_Is_Recorded_Cycle + (G : Library_Graph; + Attrs : Library_Graph_Cycle_Attributes; + Val : Boolean := True); + pragma Inline (Set_Is_Recorded_Cycle); + -- Mark a cycle described by its attributes Attrs as recorded in library + -- graph G depending on value Val. + + procedure Set_Is_Recorded_Edge (G : Library_Graph; Rel : Predecessor_Successor_Relation; Val : Boolean := True); - pragma Inline (Set_Is_Existing_Predecessor_Successor_Relation); - -- Mark a a predecessor vertex and a successor vertex desctibed by - -- relation Rel as already related depending on value Val. + pragma Inline (Set_Is_Recorded_Edge); + -- Mark a predecessor vertex and a successor vertex desctibed by + -- relation Rel as already linked depending on value Val. + + procedure Set_LGC_Attributes + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Val : Library_Graph_Cycle_Attributes); + pragma Inline (Set_LGC_Attributes); + -- Set the attributes of cycle Cycle of library graph G to value Val procedure Set_LGE_Attributes - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id; - Val : Library_Graph_Edge_Attributes); + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Val : Library_Graph_Edge_Attributes); pragma Inline (Set_LGE_Attributes); - -- Set the attributes of edge LGE_Id of library graph G to value Val + -- Set the attributes of edge Edge of library graph G to value Val procedure Set_LGV_Attributes (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Val : Library_Graph_Vertex_Attributes); pragma Inline (Set_LGV_Attributes); - -- Set the attributes of vertex LGV_Id of library graph G to value Val + -- Set the attributes of vertex Vertex of library graph G to value Val + + procedure Trace_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Indent : Indentation_Level); + pragma Inline (Trace_Cycle); + -- Write the contents of cycle Cycle of library graph G to standard + -- output. Indent is the desired indentation level for tracing. + + procedure Trace_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Indent : Indentation_Level); + pragma Inline (Trace_Edge); + -- Write the contents of edge Edge of library graph G to standard + -- output. Indent is the desired indentation level for tracing. + + procedure Trace_Eol; + pragma Inline (Trace_Eol); + -- Write an end-of-line to standard output + + procedure Trace_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Indent : Indentation_Level); + pragma Inline (Trace_Vertex); + -- Write the contents of vertex Vertex of library graph G to standard + -- output. Indent is the desired indentation level for tracing. procedure Update_Pending_Predecessors_Of_Components (G : Library_Graph); pragma Inline (Update_Pending_Predecessors_Of_Components); @@ -1108,8 +1499,8 @@ package body Bindo.Graphs is -- graph G must wait on before they can be elaborated. procedure Update_Pending_Predecessors_Of_Components - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id); + (G : Library_Graph; + Edge : Library_Graph_Edge_Id); pragma Inline (Update_Pending_Predecessors_Of_Components); -- Update the number of pending predecessors the component of edge -- LGE_Is's successor vertex of library graph G must wait on before @@ -1121,15 +1512,15 @@ package body Bindo.Graphs is procedure Add_Body_Before_Spec_Edge (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; - Edges : EL.Doubly_Linked_List) + Vertex : Library_Graph_Vertex_Id; + Edges : LGE_Lists.Doubly_Linked_List) is - LGE_Id : Library_Graph_Edge_Id; + Edge : Library_Graph_Edge_Id; begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - pragma Assert (EL.Present (Edges)); + pragma Assert (Present (Vertex)); + pragma Assert (LGE_Lists.Present (Edges)); -- A vertex requires a special Body_Before_Spec edge to its -- Corresponging_Item when it either denotes a @@ -1150,31 +1541,31 @@ package body Bindo.Graphs is -- Assume that that no Body_Before_Spec is necessary - LGE_Id := No_Library_Graph_Edge; + Edge := No_Library_Graph_Edge; -- A body that completes a previous spec - if Is_Body_With_Spec (G, LGV_Id) then - LGE_Id := + if Is_Body_With_Spec (G, Vertex) then + Edge := Add_Edge_With_Return (G => G, - Pred => LGV_Id, -- body - Succ => Corresponding_Item (G, LGV_Id), -- spec + Pred => Vertex, -- body + Succ => Corresponding_Item (G, Vertex), -- spec Kind => Body_Before_Spec_Edge); -- A spec with a completing body - elsif Is_Spec_With_Body (G, LGV_Id) then - LGE_Id := + elsif Is_Spec_With_Body (G, Vertex) then + Edge := Add_Edge_With_Return (G => G, - Pred => Corresponding_Item (G, LGV_Id), -- body - Succ => LGV_Id, -- spec + Pred => Corresponding_Item (G, Vertex), -- body + Succ => Vertex, -- spec Kind => Body_Before_Spec_Edge); end if; - if Present (LGE_Id) then - EL.Append (Edges, LGE_Id); + if Present (Edge) then + LGE_Lists.Append (Edges, Edge); end if; end Add_Body_Before_Spec_Edge; @@ -1184,27 +1575,64 @@ package body Bindo.Graphs is procedure Add_Body_Before_Spec_Edges (G : Library_Graph; - Edges : EL.Doubly_Linked_List) + Edges : LGE_Lists.Doubly_Linked_List) is - Iter : Elaborable_Units_Iterator; - LGV_Id : Library_Graph_Vertex_Id; - U_Id : Unit_Id; + Iter : Elaborable_Units_Iterator; + U_Id : Unit_Id; begin pragma Assert (Present (G)); - pragma Assert (EL.Present (Edges)); + pragma Assert (LGE_Lists.Present (Edges)); Iter := Iterate_Elaborable_Units; while Has_Next (Iter) loop Next (Iter, U_Id); - LGV_Id := Corresponding_Vertex (G, U_Id); - pragma Assert (Present (LGV_Id)); - - Add_Body_Before_Spec_Edge (G, LGV_Id, Edges); + Add_Body_Before_Spec_Edge + (G => G, + Vertex => Corresponding_Vertex (G, U_Id), + Edges => Edges); end loop; end Add_Body_Before_Spec_Edges; + --------------- + -- Add_Cycle -- + --------------- + + procedure Add_Cycle + (G : Library_Graph; + Attrs : Library_Graph_Cycle_Attributes; + Indent : Indentation_Level) + is + Cycle : Library_Graph_Cycle_Id; + + begin + pragma Assert (Present (G)); + + -- Nothing to do when the cycle has already been recorded, possibly + -- in a rotated form. + + if Is_Recorded_Cycle (G, Attrs) then + return; + end if; + + -- Mark the cycle as recorded. This prevents further attempts to add + -- rotations of the same cycle. + + Set_Is_Recorded_Cycle (G, Attrs); + + -- Save the attributes of the cycle + + Cycle := Sequence_Next_Cycle; + Set_LGC_Attributes (G, Cycle, Attrs); + + Trace_Cycle (G, Cycle, Indent); + + -- Insert the cycle in the list of all cycle based on its precedence + + Insert_And_Sort (G, Cycle); + end Add_Cycle; + -------------- -- Add_Edge -- -------------- @@ -1215,8 +1643,8 @@ package body Bindo.Graphs is Succ : Library_Graph_Vertex_Id; Kind : Library_Graph_Edge_Kind) is - LGE_Id : Library_Graph_Edge_Id; - pragma Unreferenced (LGE_Id); + Edge : Library_Graph_Edge_Id; + pragma Unreferenced (Edge); begin pragma Assert (Present (G)); @@ -1224,7 +1652,7 @@ package body Bindo.Graphs is pragma Assert (Present (Succ)); pragma Assert (Kind /= No_Edge); - LGE_Id := + Edge := Add_Edge_With_Return (G => G, Pred => Pred, @@ -1251,17 +1679,17 @@ package body Bindo.Graphs is (Predecessor => Pred, Successor => Succ); - LGE_Id : Library_Graph_Edge_Id; + Edge : Library_Graph_Edge_Id; begin -- Nothing to do when the predecessor and successor are already -- related by an edge. - if Is_Existing_Predecessor_Successor_Relation (G, Rel) then + if Is_Recorded_Edge (G, Rel) then return No_Library_Graph_Edge; end if; - LGE_Id := Sequence_Next_LGE_Id; + Edge := Sequence_Next_Edge; -- Add the edge to the underlying graph. Note that the predecessor -- is the source of the edge because it will later need to notify @@ -1269,22 +1697,22 @@ package body Bindo.Graphs is DG.Add_Edge (G => G.Graph, - E => LGE_Id, + E => Edge, Source => Pred, Destination => Succ); -- Construct and save the attributes of the edge Set_LGE_Attributes - (G => G, - LGE_Id => LGE_Id, - Val => (Kind => Kind)); + (G => G, + Edge => Edge, + Val => (Kind => Kind)); -- Mark the predecessor and successor as related by the new edge. -- This prevents all further attempts to link the same predecessor -- and successor. - Set_Is_Existing_Predecessor_Successor_Relation (G, Rel); + Set_Is_Recorded_Edge (G, Rel); -- Update the number of pending predecessors the successor must wait -- on before it is elaborated. @@ -1295,7 +1723,7 @@ package body Bindo.Graphs is Increment_Library_Graph_Edge_Count (G, Kind); - return LGE_Id; + return Edge; end Add_Edge_With_Return; ---------------- @@ -1306,7 +1734,7 @@ package body Bindo.Graphs is (G : Library_Graph; U_Id : Unit_Id) is - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); @@ -1318,17 +1746,17 @@ package body Bindo.Graphs is return; end if; - LGV_Id := Sequence_Next_LGV_Id; + Vertex := Sequence_Next_Vertex; -- Add the vertex to the underlying graph - DG.Add_Vertex (G.Graph, LGV_Id); + DG.Add_Vertex (G.Graph, Vertex); -- Construct and save the attributes of the vertex Set_LGV_Attributes (G => G, - LGV_Id => LGV_Id, + Vertex => Vertex, Val => (Corresponding_Item => No_Library_Graph_Vertex, In_Elaboration_Order => False, Pending_Predecessors => 0, @@ -1336,37 +1764,131 @@ package body Bindo.Graphs is -- Associate the unit with its corresponding vertex - Set_Corresponding_Vertex (G, U_Id, LGV_Id); + Set_Corresponding_Vertex (G, U_Id, Vertex); end Add_Vertex; + ------------------------------- + -- Add_Vertex_And_Complement -- + ------------------------------- + + procedure Add_Vertex_And_Complement + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; + Do_Complement : Boolean) + is + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + pragma Assert (LGV_Sets.Present (Set)); + + Complement : constant Library_Graph_Vertex_Id := + Complementary_Vertex + (G => G, + Vertex => Vertex, + Do_Complement => Do_Complement); + + begin + LGV_Sets.Insert (Set, Vertex); + + if Present (Complement) then + LGV_Sets.Insert (Set, Complement); + end if; + end Add_Vertex_And_Complement; + + -------------------------- + -- Complementary_Vertex -- + -------------------------- + + function Complementary_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Do_Complement : Boolean) return Library_Graph_Vertex_Id + is + Complement : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + -- Assume that there is no complementary vertex + + Complement := No_Library_Graph_Vertex; + + -- The caller requests the complement explicitly + + if Do_Complement then + Complement := Corresponding_Item (G, Vertex); + + -- The vertex is a completing body of a spec subject to pragma + -- Elaborate_Body. The complementary vertex is the spec. + + elsif Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then + Complement := Proper_Spec (G, Vertex); + + -- The vertex is a spec subject to pragma Elaborate_Body. The + -- complementary vertex is the body. + + elsif Is_Spec_With_Elaborate_Body (G, Vertex) then + Complement := Proper_Body (G, Vertex); + end if; + + return Complement; + end Complementary_Vertex; + --------------- -- Component -- --------------- function Component (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Component_Id + Vertex : Library_Graph_Vertex_Id) return Component_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - return DG.Component (G.Graph, LGV_Id); + return DG.Component (G.Graph, Vertex); end Component; + --------------------- + -- Copy_Cycle_Path -- + --------------------- + + function Copy_Cycle_Path + (Cycle_Path : LGE_Lists.Doubly_Linked_List) + return LGE_Lists.Doubly_Linked_List + is + Edge : Library_Graph_Edge_Id; + Iter : LGE_Lists.Iterator; + Path : LGE_Lists.Doubly_Linked_List; + + begin + pragma Assert (LGE_Lists.Present (Cycle_Path)); + + Path := LGE_Lists.Create; + Iter := LGE_Lists.Iterate (Cycle_Path); + while LGE_Lists.Has_Next (Iter) loop + LGE_Lists.Next (Iter, Edge); + + LGE_Lists.Append (Path, Edge); + end loop; + + return Path; + end Copy_Cycle_Path; + ------------------------ -- Corresponding_Item -- ------------------------ function Corresponding_Item (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - return Get_LGV_Attributes (G, LGV_Id).Corresponding_Item; + return Get_LGV_Attributes (G, Vertex).Corresponding_Item; end Corresponding_Item; -------------------------- @@ -1381,7 +1903,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (U_Id)); - return UV.Get (G.Unit_To_Vertex, U_Id); + return Unit_Tables.Get (G.Unit_To_Vertex, U_Id); end Corresponding_Vertex; ------------ @@ -1389,25 +1911,63 @@ package body Bindo.Graphs is ------------ function Create - (Initial_Vertices : Positive; - Initial_Edges : Positive) return Library_Graph + (Initial_Vertices : Positive; + Initial_Edges : Positive; + Dynamically_Elaborated : Boolean) return Library_Graph is G : constant Library_Graph := new Library_Graph_Attributes; begin - G.Component_Attributes := CA.Create (Initial_Vertices); - G.Edge_Attributes := EA.Create (Initial_Edges); + G.Dynamically_Elaborated := Dynamically_Elaborated; + + G.Component_Attributes := Component_Tables.Create (Initial_Vertices); + G.Cycle_Attributes := LGC_Tables.Create (Initial_Vertices); + G.Cycles := LGC_Lists.Create; + G.Edge_Attributes := LGE_Tables.Create (Initial_Edges); G.Graph := DG.Create (Initial_Vertices => Initial_Vertices, Initial_Edges => Initial_Edges); - G.Relations := PS.Create (Initial_Edges); - G.Unit_To_Vertex := UV.Create (Initial_Vertices); - G.Vertex_Attributes := VA.Create (Initial_Vertices); + G.Recorded_Cycles := RC_Sets.Create (Initial_Vertices); + G.Recorded_Edges := RE_Sets.Create (Initial_Edges); + G.Unit_To_Vertex := Unit_Tables.Create (Initial_Vertices); + G.Vertex_Attributes := LGV_Tables.Create (Initial_Vertices); return G; end Create; + ------------------- + -- Cycle_Kind_Of -- + ------------------- + + function Cycle_Kind_Of + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Cycle_Kind + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + begin + if Is_Cyclic_Elaborate_All_Edge (G, Edge) then + return Elaborate_All_Cycle; + + elsif Is_Cyclic_Elaborate_Body_Edge (G, Edge) then + return Elaborate_Body_Cycle; + + elsif Is_Cyclic_Elaborate_Edge (G, Edge) then + return Elaborate_Cycle; + + elsif Is_Cyclic_Forced_Edge (G, Edge) then + return Forced_Cycle; + + elsif Is_Cyclic_Invocation_Edge (G, Edge) then + return Invocation_Cycle; + + else + return No_Cycle_Kind; + end if; + end Cycle_Kind_Of; + ---------------------------------------- -- Decrement_Library_Graph_Edge_Count -- ---------------------------------------- @@ -1449,17 +2009,17 @@ package body Bindo.Graphs is procedure Decrement_Pending_Predecessors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) is Attrs : Library_Graph_Vertex_Attributes; begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - Attrs := Get_LGV_Attributes (G, LGV_Id); + Attrs := Get_LGV_Attributes (G, Vertex); Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1; - Set_LGV_Attributes (G, LGV_Id, Attrs); + Set_LGV_Attributes (G, Vertex, Attrs); end Decrement_Pending_Predecessors; ----------------------------------- @@ -1468,22 +2028,21 @@ package body Bindo.Graphs is procedure Delete_Body_Before_Spec_Edges (G : Library_Graph; - Edges : EL.Doubly_Linked_List) + Edges : LGE_Lists.Doubly_Linked_List) is - Iter : EL.Iterator; - LGE_Id : Library_Graph_Edge_Id; + Edge : Library_Graph_Edge_Id; + Iter : LGE_Lists.Iterator; begin pragma Assert (Present (G)); - pragma Assert (EL.Present (Edges)); + pragma Assert (LGE_Lists.Present (Edges)); - Iter := EL.Iterate (Edges); - while EL.Has_Next (Iter) loop - EL.Next (Iter, LGE_Id); - pragma Assert (Present (LGE_Id)); - pragma Assert (Kind (G, LGE_Id) = Body_Before_Spec_Edge); + Iter := LGE_Lists.Iterate (Edges); + while LGE_Lists.Has_Next (Iter) loop + LGE_Lists.Next (Iter, Edge); + pragma Assert (Kind (G, Edge) = Body_Before_Spec_Edge); - Delete_Edge (G, LGE_Id); + Delete_Edge (G, Edge); end loop; end Delete_Body_Before_Spec_Edges; @@ -1492,26 +2051,22 @@ package body Bindo.Graphs is ----------------- procedure Delete_Edge - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) is pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); - - Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id); - Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id); - - pragma Assert (Present (Pred)); - pragma Assert (Present (Succ)); + pragma Assert (Present (Edge)); - Rel : constant Predecessor_Successor_Relation := - (Predecessor => Pred, - Successor => Succ); + Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge); + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); + Rel : constant Predecessor_Successor_Relation := + (Predecessor => Pred, + Successor => Succ); begin -- Update the edge statistics - Decrement_Library_Graph_Edge_Count (G, Kind (G, LGE_Id)); + Decrement_Library_Graph_Edge_Count (G, Kind (G, Edge)); -- Update the number of pending predecessors the successor must wait -- on before it is elaborated. @@ -1521,15 +2076,15 @@ package body Bindo.Graphs is -- Delete the link between the predecessor and successor. This allows -- for further attempts to link the same predecessor and successor. - PS.Delete (G.Relations, Rel); + RE_Sets.Delete (G.Recorded_Edges, Rel); -- Delete the attributes of the edge - EA.Delete (G.Edge_Attributes, LGE_Id); + LGE_Tables.Delete (G.Edge_Attributes, Edge); -- Delete the edge from the underlying graph - DG.Delete_Edge (G.Graph, LGE_Id); + DG.Delete_Edge (G.Graph, Edge); end Delete_Edge; ------------- @@ -1540,12 +2095,15 @@ package body Bindo.Graphs is begin pragma Assert (Present (G)); - CA.Destroy (G.Component_Attributes); - EA.Destroy (G.Edge_Attributes); - DG.Destroy (G.Graph); - PS.Destroy (G.Relations); - UV.Destroy (G.Unit_To_Vertex); - VA.Destroy (G.Vertex_Attributes); + Component_Tables.Destroy (G.Component_Attributes); + LGC_Tables.Destroy (G.Cycle_Attributes); + LGC_Lists.Destroy (G.Cycles); + LGE_Tables.Destroy (G.Edge_Attributes); + DG.Destroy (G.Graph); + RC_Sets.Destroy (G.Recorded_Cycles); + RE_Sets.Destroy (G.Recorded_Edges); + Unit_Tables.Destroy (G.Unit_To_Vertex); + LGV_Tables.Destroy (G.Vertex_Attributes); Free (G); end Destroy; @@ -1562,17 +2120,16 @@ package body Bindo.Graphs is null; end Destroy_Component_Attributes; - -------------------------------- - -- Destroy_Library_Graph_Edge -- - -------------------------------- + -------------------------------------------- + -- Destroy_Library_Graph_Cycle_Attributes -- + -------------------------------------------- - procedure Destroy_Library_Graph_Edge - (LGE_Id : in out Library_Graph_Edge_Id) + procedure Destroy_Library_Graph_Cycle_Attributes + (Attrs : in out Library_Graph_Cycle_Attributes) is - pragma Unreferenced (LGE_Id); begin - null; - end Destroy_Library_Graph_Edge; + LGE_Lists.Destroy (Attrs.Path); + end Destroy_Library_Graph_Cycle_Attributes; ------------------------------------------- -- Destroy_Library_Graph_Edge_Attributes -- @@ -1591,9 +2148,9 @@ package body Bindo.Graphs is ---------------------------------- procedure Destroy_Library_Graph_Vertex - (LGV_Id : in out Library_Graph_Vertex_Id) + (Vertex : in out Library_Graph_Vertex_Id) is - pragma Unreferenced (LGV_Id); + pragma Unreferenced (Vertex); begin null; end Destroy_Library_Graph_Vertex; @@ -1610,26 +2167,270 @@ package body Bindo.Graphs is null; end Destroy_Library_Graph_Vertex_Attributes; - --------------------- - -- Find_Components -- - --------------------- - - procedure Find_Components (G : Library_Graph) is - Edges : EL.Doubly_Linked_List; + --------------- + -- File_Name -- + --------------- + function File_Name + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return File_Name_Type + is begin pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); - -- Initialize or reinitialize the components of the graph + return File_Name (Unit (G, Vertex)); + end File_Name; - Initialize_Components (G); + ------------------------------------ + -- Find_All_Cycles_Through_Vertex -- + ------------------------------------ + + procedure Find_All_Cycles_Through_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + End_Vertices : LGV_Sets.Membership_Set; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Spec_And_Body_Together : Boolean; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Visited_Vertices : LGV_Sets.Membership_Set; + Indent : Indentation_Level) + is + Edge_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + + Iter : Edges_To_Successors_Iterator; + Next_Edge : Library_Graph_Edge_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (LGV_Sets.Present (End_Vertices)); + pragma Assert (Present (Most_Significant_Edge)); + pragma Assert (LGE_Lists.Present (Cycle_Path)); + pragma Assert (LGV_Sets.Present (Visited_Vertices)); + + -- Nothing to do when there is no vertex + + if not Present (Vertex) then + return; + end if; + + Trace_Vertex (G, Vertex, Indent); + + -- The current vertex denotes the end vertex of the cycle and closes + -- the circuit. Normalize the cycle such that it is rotated with its + -- most significant edge first, and record it for diagnostics. + + if LGV_Sets.Contains (End_Vertices, Vertex) then + Normalize_And_Add_Cycle + (G => G, + Most_Significant_Edge => Most_Significant_Edge, + Invocation_Edge_Count => Invocation_Edge_Count, + Cycle_Path => Cycle_Path, + Indent => Indent + Nested_Indentation); + + -- Otherwise extend the search for a cycle only when the vertex has + -- not been visited yet. + + elsif not LGV_Sets.Contains (Visited_Vertices, Vertex) then + + -- Prepare for vertex backtracking + + LGV_Sets.Insert (Visited_Vertices, Vertex); + + -- Extend the search via all edges to successors of the vertex + + Iter := Iterate_Edges_To_Successors (G, Vertex); + while Has_Next (Iter) loop + Next (Iter, Next_Edge); + + if Is_Cyclic_Edge (G, Next_Edge) then + Trace_Edge (G, Next_Edge, Edge_Indent); + + -- Prepare for edge backtracking. Prepending ensures that + -- final ordering of edges can be traversed from successor + -- to predecessor. + + LGE_Lists.Prepend (Cycle_Path, Next_Edge); + + -- Extend the search via the successor of the next edge + + Find_All_Cycles_Through_Vertex + (G => G, + Vertex => Successor (G, Next_Edge), + End_Vertices => End_Vertices, + + -- The next edge may be more important than the current + -- most important edge, thus "upgrading" the nature of + -- the cycle, and shifting its point of normalization. + + Most_Significant_Edge => + Highest_Precedence_Edge + (G => G, + Left => Next_Edge, + Right => Most_Significant_Edge), + + -- The next edge may be an invocation edge, in which case + -- the count of invocation edges increases by one. + + Invocation_Edge_Count => + Maximum_Invocation_Edge_Count + (G => G, + Edge => Next_Edge, + Count => Invocation_Edge_Count), + Spec_And_Body_Together => Spec_And_Body_Together, + Cycle_Path => Cycle_Path, + Visited_Vertices => Visited_Vertices, + Indent => Indent); + + -- Backtrack the edge + + LGE_Lists.Delete_First (Cycle_Path); + end if; + end loop; + + -- Extend the search via the complementary vertex when the current + -- vertex is part of an Elaborate_Body pair, or the initial edge + -- is an Elaborate_All edge. + + Find_All_Cycles_Through_Vertex + (G => G, + Vertex => + Complementary_Vertex + (G => G, + Vertex => Vertex, + Do_Complement => Spec_And_Body_Together), + End_Vertices => End_Vertices, + Most_Significant_Edge => Most_Significant_Edge, + Invocation_Edge_Count => Invocation_Edge_Count, + Spec_And_Body_Together => Spec_And_Body_Together, + Cycle_Path => Cycle_Path, + Visited_Vertices => Visited_Vertices, + Indent => Indent); + + -- Backtrack the vertex + + LGV_Sets.Delete (Visited_Vertices, Vertex); + end if; + end Find_All_Cycles_Through_Vertex; + + ------------------------------- + -- Find_All_Cycles_With_Edge -- + ------------------------------- + + procedure Find_All_Cycles_With_Edge + (G : Library_Graph; + Initial_Edge : Library_Graph_Edge_Id; + Spec_And_Body_Together : Boolean; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Visited_Vertices : LGV_Sets.Membership_Set; + Indent : Indentation_Level) + is + pragma Assert (Present (G)); + pragma Assert (Present (Initial_Edge)); + pragma Assert (LGE_Lists.Present (Cycle_Path)); + pragma Assert (LGV_Sets.Present (Visited_Vertices)); + + Pred : constant Library_Graph_Vertex_Id := + Predecessor (G, Initial_Edge); + Succ : constant Library_Graph_Vertex_Id := + Successor (G, Initial_Edge); + + End_Vertices : LGV_Sets.Membership_Set; + + begin + Trace_Edge (G, Initial_Edge, Indent); + + -- Use a set to represent the end vertices of the cycle. The set is + -- needed to accomodate the Elaborate_All and Elaborate_Body cases + -- where a cycle may terminate on either a spec or a body vertex. + + End_Vertices := LGV_Sets.Create (2); + Add_Vertex_And_Complement + (G => G, + Vertex => Pred, + Set => End_Vertices, + Do_Complement => Spec_And_Body_Together); + + -- Prepare for edge backtracking + -- + -- The initial edge starts the path. During the traversal, edges with + -- higher precedence may be discovered, in which case they supersede + -- the initial edge in terms of significance. Prepending to the cycle + -- path ensures that the vertices can be visited in the proper order + -- for diagnostics. + + LGE_Lists.Prepend (Cycle_Path, Initial_Edge); + + -- Prepare for vertex backtracking + -- + -- The predecessor is considered the terminator of the path. Add it + -- to the set of visited vertices along with its complement vertex + -- in the Elaborate_All and Elaborate_Body cases to prevent infinite + -- recursion. + + Add_Vertex_And_Complement + (G => G, + Vertex => Pred, + Set => Visited_Vertices, + Do_Complement => Spec_And_Body_Together); + + -- Traverse a potential cycle by continuously visiting successors + -- until either the predecessor of the initial edge is reached, or + -- no more successors are available. + + Find_All_Cycles_Through_Vertex + (G => G, + Vertex => Succ, + End_Vertices => End_Vertices, + Most_Significant_Edge => Initial_Edge, + Invocation_Edge_Count => + Maximum_Invocation_Edge_Count + (G => G, + Edge => Initial_Edge, + Count => 0), + Spec_And_Body_Together => Spec_And_Body_Together, + Cycle_Path => Cycle_Path, + Visited_Vertices => Visited_Vertices, + Indent => Indent + Nested_Indentation); + + -- Backtrack the edge + + LGE_Lists.Delete_First (Cycle_Path); + + -- Backtrack the predecessor, along with the complement vertex in the + -- Elaborate_All and Elaborate_Body cases. + + Remove_Vertex_And_Complement + (G => G, + Vertex => Pred, + Set => Visited_Vertices, + Do_Complement => Spec_And_Body_Together); + + LGV_Sets.Destroy (End_Vertices); + end Find_All_Cycles_With_Edge; + + --------------------- + -- Find_Components -- + --------------------- + + procedure Find_Components (G : Library_Graph) is + Edges : LGE_Lists.Doubly_Linked_List; + + begin + pragma Assert (Present (G)); + + -- Initialize or reinitialize the components of the graph + + Initialize_Components (G); -- Create a set of special edges that link a predecessor body with a -- successor spec. This is an illegal dependency, however using such -- edges eliminates the need to create yet another graph, where both -- spec and body are collapsed into a single vertex. - Edges := EL.Create; + Edges := LGE_Lists.Create; Add_Body_Before_Spec_Edges (G, Edges); DG.Find_Components (G.Graph); @@ -1638,7 +2439,7 @@ package body Bindo.Graphs is -- successor spec because they cause unresolvable circularities. Delete_Body_Before_Spec_Edges (G, Edges); - EL.Destroy (Edges); + LGE_Lists.Destroy (Edges); -- Update the number of predecessors various components must wait on -- before they can be elaborated. @@ -1646,6 +2447,100 @@ package body Bindo.Graphs is Update_Pending_Predecessors_Of_Components (G); end Find_Components; + ----------------- + -- Find_Cycles -- + ----------------- + + procedure Find_Cycles (G : Library_Graph) is + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Edge : Library_Graph_Edge_Id; + Iter : All_Edge_Iterator; + Visited_Vertices : LGV_Sets.Membership_Set; + + begin + pragma Assert (Present (G)); + + -- Use a list of edges to describe the path of a cycle + + Cycle_Path := LGE_Lists.Create; + + -- Use a set of visited vertices to prevent infinite traversal of the + -- graph. + + Visited_Vertices := LGV_Sets.Create (Number_Of_Vertices (G)); + + -- Inspect all edges, trying to find an edge that links two vertices + -- in the same component. + + Iter := Iterate_All_Edges (G); + while Has_Next (Iter) loop + Next (Iter, Edge); + + -- Find all cycles involving the current edge. Duplicate cycles in + -- the forms of rotations are not saved for diagnostic purposes. + + if Is_Cycle_Initiating_Edge (G, Edge) then + Find_All_Cycles_With_Edge + (G => G, + Initial_Edge => Edge, + Spec_And_Body_Together => Is_Elaborate_All_Edge (G, Edge), + Cycle_Path => Cycle_Path, + Visited_Vertices => Visited_Vertices, + Indent => No_Indentation); + + Trace_Eol; + end if; + end loop; + + LGE_Lists.Destroy (Cycle_Path); + LGV_Sets.Destroy (Visited_Vertices); + end Find_Cycles; + + --------------------------------------- + -- Find_First_Lower_Precedence_Cycle -- + --------------------------------------- + + function Find_First_Lower_Precedence_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Library_Graph_Cycle_Id + is + Current_Cycle : Library_Graph_Cycle_Id; + Iter : All_Cycle_Iterator; + Lesser_Cycle : Library_Graph_Cycle_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- Assume that there is no lesser cycle + + Lesser_Cycle := No_Library_Graph_Cycle; + + -- Find a cycle with a slightly lower precedence than the input + -- cycle. + -- + -- IMPORTANT: + -- + -- * The iterator must run to completion in order to unlock the + -- list of all cycles. + + Iter := Iterate_All_Cycles (G); + while Has_Next (Iter) loop + Next (Iter, Current_Cycle); + + if not Present (Lesser_Cycle) + and then Precedence + (G => G, + Cycle => Cycle, + Compared_To => Current_Cycle) = Higher_Precedence + then + Lesser_Cycle := Current_Cycle; + end if; + end loop; + + return Lesser_Cycle; + end Find_First_Lower_Precedence_Cycle; + ------------------------------ -- Get_Component_Attributes -- ------------------------------ @@ -1658,23 +2553,37 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Comp)); - return CA.Get (G.Component_Attributes, Comp); + return Component_Tables.Get (G.Component_Attributes, Comp); end Get_Component_Attributes; ------------------------ + -- Get_LGC_Attributes -- + ------------------------ + + function Get_LGC_Attributes + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Library_Graph_Cycle_Attributes + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + return LGC_Tables.Get (G.Cycle_Attributes, Cycle); + end Get_LGC_Attributes; + + ------------------------ -- Get_LGE_Attributes -- ------------------------ function Get_LGE_Attributes - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) - return Library_Graph_Edge_Attributes + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Edge_Attributes is begin pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Edge)); - return EA.Get (G.Edge_Attributes, LGE_Id); + return LGE_Tables.Get (G.Edge_Attributes, Edge); end Get_LGE_Attributes; ------------------------ @@ -1683,31 +2592,61 @@ package body Bindo.Graphs is function Get_LGV_Attributes (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Attributes is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - return VA.Get (G.Vertex_Attributes, LGV_Id); + return LGV_Tables.Get (G.Vertex_Attributes, Vertex); end Get_LGV_Attributes; + ----------------------------- + -- Has_Elaborate_All_Cycle -- + ----------------------------- + + function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean is + Edge : Library_Graph_Edge_Id; + Iter : All_Edge_Iterator; + Seen : Boolean; + + begin + pragma Assert (Present (G)); + + -- Assume that no cyclic Elaborate_All edge has been seen + + Seen := False; + + -- IMPORTANT: + -- + -- * The iteration must run to completion in order to unlock the + -- graph. + + Iter := Iterate_All_Edges (G); + while Has_Next (Iter) loop + Next (Iter, Edge); + + if not Seen and then Is_Cyclic_Elaborate_All_Edge (G, Edge) then + Seen := True; + end if; + end loop; + + return Seen; + end Has_Elaborate_All_Cycle; + ------------------------ -- Has_Elaborate_Body -- ------------------------ function Has_Elaborate_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); + pragma Assert (Present (Vertex)); + U_Id : constant Unit_Id := Unit (G, Vertex); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); begin @@ -1718,6 +2657,15 @@ package body Bindo.Graphs is -- Has_Next -- -------------- + function Has_Next (Iter : All_Cycle_Iterator) return Boolean is + begin + return LGC_Lists.Has_Next (LGC_Lists.Iterator (Iter)); + end Has_Next; + + -------------- + -- Has_Next -- + -------------- + function Has_Next (Iter : All_Edge_Iterator) return Boolean is begin return DG.Has_Next (DG.All_Edge_Iterator (Iter)); @@ -1754,12 +2702,50 @@ package body Bindo.Graphs is -- Has_Next -- -------------- + function Has_Next (Iter : Edges_Of_Cycle_Iterator) return Boolean is + begin + return LGE_Lists.Has_Next (LGE_Lists.Iterator (Iter)); + end Has_Next; + + -------------- + -- Has_Next -- + -------------- + function Has_Next (Iter : Edges_To_Successors_Iterator) return Boolean is begin return DG.Has_Next (DG.Outgoing_Edge_Iterator (Iter)); end Has_Next; ----------------------------------------- + -- Hash_Library_Graph_Cycle_Attributes -- + ----------------------------------------- + + function Hash_Library_Graph_Cycle_Attributes + (Attrs : Library_Graph_Cycle_Attributes) return Bucket_Range_Type + is + Edge : Library_Graph_Edge_Id; + Hash : Bucket_Range_Type; + Iter : LGE_Lists.Iterator; + + begin + pragma Assert (LGE_Lists.Present (Attrs.Path)); + + -- The hash is obtained in the following manner: + -- + -- (((edge1 * 31) + edge2) * 31) + edgeN + + Hash := 0; + Iter := LGE_Lists.Iterate (Attrs.Path); + while LGE_Lists.Has_Next (Iter) loop + LGE_Lists.Next (Iter, Edge); + + Hash := (Hash * 31) + Bucket_Range_Type (Edge); + end loop; + + return Hash; + end Hash_Library_Graph_Cycle_Attributes; + + ----------------------------------------- -- Hash_Predecessor_Successor_Relation -- ----------------------------------------- @@ -1776,21 +2762,106 @@ package body Bindo.Graphs is Bucket_Range_Type (Rel.Successor)); end Hash_Predecessor_Successor_Relation; + ------------------------------ + -- Highest_Precedence_Cycle -- + ------------------------------ + + function Highest_Precedence_Cycle + (G : Library_Graph) return Library_Graph_Cycle_Id + is + begin + pragma Assert (Present (G)); + pragma Assert (LGC_Lists.Present (G.Cycles)); + + if LGC_Lists.Is_Empty (G.Cycles) then + return No_Library_Graph_Cycle; + + -- The highest precedence cycle is always the first in the list of + -- all cycles. + + else + return LGC_Lists.First (G.Cycles); + end if; + end Highest_Precedence_Cycle; + + ----------------------------- + -- Highest_Precedence_Edge -- + ----------------------------- + + function Highest_Precedence_Edge + (G : Library_Graph; + Left : Library_Graph_Edge_Id; + Right : Library_Graph_Edge_Id) return Library_Graph_Edge_Id + is + Edge_Prec : Precedence_Kind; + + begin + pragma Assert (Present (G)); + + -- Both edges are available, pick the one with highest precedence + + if Present (Left) and then Present (Right) then + Edge_Prec := + Precedence + (G => G, + Edge => Left, + Compared_To => Right); + + if Edge_Prec = Higher_Precedence then + return Left; + + -- The precedence rules for edges are such that no two edges can + -- ever have the same precedence. + + else + pragma Assert (Edge_Prec = Lower_Precedence); + return Right; + end if; + + -- Otherwise at least one edge must be present + + elsif Present (Left) then + return Left; + + else + pragma Assert (Present (Right)); + + return Right; + end if; + end Highest_Precedence_Edge; + -------------------------- -- In_Elaboration_Order -- -------------------------- function In_Elaboration_Order (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - return Get_LGV_Attributes (G, LGV_Id).In_Elaboration_Order; + return Get_LGV_Attributes (G, Vertex).In_Elaboration_Order; end In_Elaboration_Order; + ----------------------- + -- In_Same_Component -- + ----------------------- + + function In_Same_Component + (G : Library_Graph; + Left : Library_Graph_Vertex_Id; + Right : Library_Graph_Vertex_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Left)); + pragma Assert (Present (Right)); + + return Component (G, Left) = Component (G, Right); + end In_Same_Component; + ---------------------------------------- -- Increment_Library_Graph_Edge_Count -- ---------------------------------------- @@ -1832,17 +2903,17 @@ package body Bindo.Graphs is procedure Increment_Pending_Predecessors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) is Attrs : Library_Graph_Vertex_Attributes; begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - Attrs := Get_LGV_Attributes (G, LGV_Id); + Attrs := Get_LGV_Attributes (G, Vertex); Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1; - Set_LGV_Attributes (G, LGV_Id, Attrs); + Set_LGV_Attributes (G, Vertex, Attrs); end Increment_Pending_Predecessors; --------------------------- @@ -1858,26 +2929,100 @@ package body Bindo.Graphs is -- be computed. if Number_Of_Components (G) > 0 then - CA.Destroy (G.Component_Attributes); - G.Component_Attributes := CA.Create (Number_Of_Vertices (G)); + Component_Tables.Destroy (G.Component_Attributes); + + G.Component_Attributes := + Component_Tables.Create (Number_Of_Vertices (G)); end if; end Initialize_Components; + --------------------- + -- Insert_And_Sort -- + --------------------- + + procedure Insert_And_Sort + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + Lesser_Cycle : Library_Graph_Cycle_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + pragma Assert (LGC_Lists.Present (G.Cycles)); + + -- The input cycle is the first to be inserted + + if LGC_Lists.Is_Empty (G.Cycles) then + LGC_Lists.Prepend (G.Cycles, Cycle); + + -- Otherwise the list of all cycles contains at least one cycle. + -- Insert the input cycle based on its precedence. + + else + Lesser_Cycle := Find_First_Lower_Precedence_Cycle (G, Cycle); + + -- The list contains at least one cycle, and the input cycle has a + -- higher precedence compared to some cycle in the list. + + if Present (Lesser_Cycle) then + LGC_Lists.Insert_Before + (L => G.Cycles, + Before => Lesser_Cycle, + Elem => Cycle); + + -- Otherwise the input cycle has the lowest precedence among all + -- cycles. + + else + LGC_Lists.Append (G.Cycles, Cycle); + end if; + end if; + end Insert_And_Sort; + + --------------------------- + -- Invocation_Edge_Count -- + --------------------------- + + function Invocation_Edge_Count + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Natural + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + return Get_LGC_Attributes (G, Cycle).Invocation_Edge_Count; + end Invocation_Edge_Count; + + ------------------------------- + -- Invocation_Graph_Encoding -- + ------------------------------- + + function Invocation_Graph_Encoding + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) + return Invocation_Graph_Encoding_Kind + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + return Invocation_Graph_Encoding (Unit (G, Vertex)); + end Invocation_Graph_Encoding; + ------------- -- Is_Body -- ------------- function Is_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); + pragma Assert (Present (Vertex)); + U_Id : constant Unit_Id := Unit (G, Vertex); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); begin @@ -1890,19 +3035,17 @@ package body Bindo.Graphs is function Is_Body_Of_Spec_With_Elaborate_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is - Spec_LGV_Id : Library_Graph_Vertex_Id; - begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - if Is_Body_With_Spec (G, LGV_Id) then - Spec_LGV_Id := Proper_Spec (G, LGV_Id); - pragma Assert (Present (Spec_LGV_Id)); - - return Is_Spec_With_Elaborate_Body (G, Spec_LGV_Id); + if Is_Body_With_Spec (G, Vertex) then + return + Is_Spec_With_Elaborate_Body + (G => G, + Vertex => Proper_Spec (G, Vertex)); end if; return False; @@ -1914,21 +3057,172 @@ package body Bindo.Graphs is function Is_Body_With_Spec (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); + pragma Assert (Present (Vertex)); + U_Id : constant Unit_Id := Unit (G, Vertex); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); begin return U_Rec.Utype = Is_Body; end Is_Body_With_Spec; + ------------------------------ + -- Is_Cycle_Initiating_Edge -- + ------------------------------ + + function Is_Cycle_Initiating_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Cyclic_Elaborate_All_Edge (G, Edge) + or else Is_Cyclic_Elaborate_Body_Edge (G, Edge) + or else Is_Cyclic_Elaborate_Edge (G, Edge) + or else Is_Cyclic_Forced_Edge (G, Edge) + or else Is_Cyclic_Invocation_Edge (G, Edge); + end Is_Cycle_Initiating_Edge; + + -------------------- + -- Is_Cyclic_Edge -- + -------------------- + + function Is_Cyclic_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Cycle_Initiating_Edge (G, Edge) + or else Is_Cyclic_With_Edge (G, Edge); + end Is_Cyclic_Edge; + + ---------------------------------- + -- Is_Cyclic_Elaborate_All_Edge -- + ---------------------------------- + + function Is_Cyclic_Elaborate_All_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Elaborate_All_Edge (G, Edge) + and then Links_Vertices_In_Same_Component (G, Edge); + end Is_Cyclic_Elaborate_All_Edge; + + ----------------------------------- + -- Is_Cyclic_Elaborate_Body_Edge -- + ----------------------------------- + + function Is_Cyclic_Elaborate_Body_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Elaborate_Body_Edge (G, Edge) + and then Links_Vertices_In_Same_Component (G, Edge); + end Is_Cyclic_Elaborate_Body_Edge; + + ------------------------------ + -- Is_Cyclic_Elaborate_Edge -- + ------------------------------ + + function Is_Cyclic_Elaborate_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Elaborate_Edge (G, Edge) + and then Links_Vertices_In_Same_Component (G, Edge); + end Is_Cyclic_Elaborate_Edge; + + --------------------------- + -- Is_Cyclic_Forced_Edge -- + --------------------------- + + function Is_Cyclic_Forced_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Forced_Edge (G, Edge) + and then Links_Vertices_In_Same_Component (G, Edge); + end Is_Cyclic_Forced_Edge; + + ------------------------------- + -- Is_Cyclic_Invocation_Edge -- + ------------------------------- + + function Is_Cyclic_Invocation_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Invocation_Edge (G, Edge) + and then Links_Vertices_In_Same_Component (G, Edge); + end Is_Cyclic_Invocation_Edge; + + ------------------------- + -- Is_Cyclic_With_Edge -- + ------------------------- + + function Is_Cyclic_With_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + -- Ignore Elaborate_Body edges because they also appear as with + -- edges, but have special successors. + + return + Is_With_Edge (G, Edge) + and then Links_Vertices_In_Same_Component (G, Edge) + and then not Is_Elaborate_Body_Edge (G, Edge); + end Is_Cyclic_With_Edge; + + ------------------------------- + -- Is_Dynamically_Elaborated -- + ------------------------------- + + function Is_Dynamically_Elaborated (G : Library_Graph) return Boolean is + begin + pragma Assert (Present (G)); + + return G.Dynamically_Elaborated; + end Is_Dynamically_Elaborated; + ----------------------------- -- Is_Elaborable_Component -- ----------------------------- @@ -1955,29 +3249,28 @@ package body Bindo.Graphs is function Is_Elaborable_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is - Check_LGV_Id : Library_Graph_Vertex_Id; + Check_Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - Check_LGV_Id := LGV_Id; + Check_Vertex := Vertex; -- A spec-body pair where the spec carries pragma Elaborate_Body must -- be treated as one vertex for elaboration purposes. Use the spec as -- the point of reference for the composite vertex. - if Is_Body_Of_Spec_With_Elaborate_Body (G, Check_LGV_Id) then - Check_LGV_Id := Proper_Spec (G, Check_LGV_Id); - pragma Assert (Present (Check_LGV_Id)); + if Is_Body_Of_Spec_With_Elaborate_Body (G, Check_Vertex) then + Check_Vertex := Proper_Spec (G, Check_Vertex); end if; return Is_Elaborable_Vertex (G => G, - LGV_Id => Check_LGV_Id, + Vertex => Check_Vertex, Predecessors => 0); end Is_Elaborable_Vertex; @@ -1987,34 +3280,30 @@ package body Bindo.Graphs is function Is_Elaborable_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Predecessors : Natural) return Boolean is - pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - Comp : constant Component_Id := Component (G, LGV_Id); - - pragma Assert (Present (Comp)); - - Body_LGV_Id : Library_Graph_Vertex_Id; + Body_Vertex : Library_Graph_Vertex_Id; begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + -- The vertex must not be re-elaborated once it has been elaborated - if In_Elaboration_Order (G, LGV_Id) then + if In_Elaboration_Order (G, Vertex) then return False; -- The vertex must not be waiting on more precedessors than requested -- to be elaborated. - elsif Pending_Predecessors (G, LGV_Id) /= Predecessors then + elsif Pending_Predecessors (G, Vertex) /= Predecessors then return False; -- The component where the vertex resides must not be waiting on any -- of its precedessors to be elaborated. - elsif not Is_Elaborable_Component (G, Comp) then + elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then return False; -- The vertex denotes a spec with a completing body, and is subject @@ -2022,14 +3311,14 @@ package body Bindo.Graphs is -- vertex to be elaborated. Account for the sole predecessor of the -- body which is the vertex itself. - elsif Is_Spec_With_Elaborate_Body (G, LGV_Id) then - Body_LGV_Id := Proper_Body (G, LGV_Id); - pragma Assert (Present (Body_LGV_Id)); + elsif Is_Spec_With_Elaborate_Body (G, Vertex) then + Body_Vertex := Proper_Body (G, Vertex); + pragma Assert (Present (Body_Vertex)); return Is_Elaborable_Vertex (G => G, - LGV_Id => Body_LGV_Id, + Vertex => Body_Vertex, Predecessors => 1); end if; @@ -2038,21 +3327,71 @@ package body Bindo.Graphs is return True; end Is_Elaborable_Vertex; - ------------------------------------------------ - -- Is_Existing_Predecessor_Successor_Relation -- - ------------------------------------------------ + --------------------------- + -- Is_Elaborate_All_Edge -- + --------------------------- - function Is_Existing_Predecessor_Successor_Relation - (G : Library_Graph; - Rel : Predecessor_Successor_Relation) return Boolean + function Is_Elaborate_All_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean is begin pragma Assert (Present (G)); - pragma Assert (Present (Rel.Predecessor)); - pragma Assert (Present (Rel.Successor)); + pragma Assert (Present (Edge)); - return PS.Contains (G.Relations, Rel); - end Is_Existing_Predecessor_Successor_Relation; + return Kind (G, Edge) = Elaborate_All_Edge; + end Is_Elaborate_All_Edge; + + ---------------------------- + -- Is_Elaborate_Body_Edge -- + ---------------------------- + + function Is_Elaborate_Body_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); + + begin + return + Kind (G, Edge) = With_Edge + and then + (Is_Spec_With_Elaborate_Body (G, Succ) + or else Is_Body_Of_Spec_With_Elaborate_Body (G, Succ)); + end Is_Elaborate_Body_Edge; + + ----------------------- + -- Is_Elaborate_Edge -- + ----------------------- + + function Is_Elaborate_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return Kind (G, Edge) = Elaborate_Edge; + end Is_Elaborate_Edge; + + -------------------- + -- Is_Forced_Edge -- + -------------------- + + function Is_Forced_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return Kind (G, Edge) = Forced_Edge; + end Is_Forced_Edge; ---------------------- -- Is_Internal_Unit -- @@ -2060,18 +3399,29 @@ package body Bindo.Graphs is function Is_Internal_Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is + begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - U_Id : constant Unit_Id := Unit (G, LGV_Id); + return Is_Internal_Unit (Unit (G, Vertex)); + end Is_Internal_Unit; - pragma Assert (Present (U_Id)); + ------------------------ + -- Is_Invocation_Edge -- + ------------------------ + function Is_Invocation_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is begin - return Is_Internal_Unit (U_Id); - end Is_Internal_Unit; + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return Kind (G, Edge) = Invocation_Edge; + end Is_Invocation_Edge; ------------------------ -- Is_Predefined_Unit -- @@ -2079,17 +3429,13 @@ package body Bindo.Graphs is function Is_Predefined_Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is + begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); - - begin - return Is_Predefined_Unit (U_Id); + return Is_Predefined_Unit (Unit (G, Vertex)); end Is_Predefined_Unit; --------------------------- @@ -2098,36 +3444,60 @@ package body Bindo.Graphs is function Is_Preelaborated_Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); + pragma Assert (Present (Vertex)); + U_Id : constant Unit_Id := Unit (G, Vertex); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); begin return U_Rec.Preelab or else U_Rec.Pure; end Is_Preelaborated_Unit; + ----------------------- + -- Is_Recorded_Cycle -- + ----------------------- + + function Is_Recorded_Cycle + (G : Library_Graph; + Attrs : Library_Graph_Cycle_Attributes) return Boolean + is + begin + pragma Assert (Present (G)); + + return RC_Sets.Contains (G.Recorded_Cycles, Attrs); + end Is_Recorded_Cycle; + + ---------------------- + -- Is_Recorded_Edge -- + ---------------------- + + function Is_Recorded_Edge + (G : Library_Graph; + Rel : Predecessor_Successor_Relation) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Rel.Predecessor)); + pragma Assert (Present (Rel.Successor)); + + return RE_Sets.Contains (G.Recorded_Edges, Rel); + end Is_Recorded_Edge; + ------------- -- Is_Spec -- ------------- function Is_Spec (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); + pragma Assert (Present (Vertex)); + U_Id : constant Unit_Id := Unit (G, Vertex); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); begin @@ -2140,15 +3510,12 @@ package body Bindo.Graphs is function Is_Spec_With_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); + pragma Assert (Present (Vertex)); + U_Id : constant Unit_Id := Unit (G, Vertex); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); begin @@ -2161,17 +3528,45 @@ package body Bindo.Graphs is function Is_Spec_With_Elaborate_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); return - Is_Spec_With_Body (G, LGV_Id) - and then Has_Elaborate_Body (G, LGV_Id); + Is_Spec_With_Body (G, Vertex) + and then Has_Elaborate_Body (G, Vertex); end Is_Spec_With_Elaborate_Body; + ------------------ + -- Is_With_Edge -- + ------------------ + + function Is_With_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return Kind (G, Edge) = With_Edge; + end Is_With_Edge; + + ------------------------ + -- Iterate_All_Cycles -- + ------------------------ + + function Iterate_All_Cycles + (G : Library_Graph) return All_Cycle_Iterator + is + begin + pragma Assert (Present (G)); + + return All_Cycle_Iterator (LGC_Lists.Iterate (G.Cycles)); + end Iterate_All_Cycles; + ----------------------- -- Iterate_All_Edges -- ----------------------- @@ -2228,22 +3623,36 @@ package body Bindo.Graphs is (DG.Iterate_Component_Vertices (G.Graph, Comp)); end Iterate_Component_Vertices; + ---------------------------- + -- Iterate_Edges_Of_Cycle -- + ---------------------------- + + function Iterate_Edges_Of_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Edges_Of_Cycle_Iterator + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + return Edges_Of_Cycle_Iterator (LGE_Lists.Iterate (Path (G, Cycle))); + end Iterate_Edges_Of_Cycle; + --------------------------------- -- Iterate_Edges_To_Successors -- --------------------------------- function Iterate_Edges_To_Successors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) - return Edges_To_Successors_Iterator + Vertex : Library_Graph_Vertex_Id) return Edges_To_Successors_Iterator is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); return Edges_To_Successors_Iterator - (DG.Iterate_Outgoing_Edges (G.Graph, LGV_Id)); + (DG.Iterate_Outgoing_Edges (G.Graph, Vertex)); end Iterate_Edges_To_Successors; ---------- @@ -2252,15 +3661,45 @@ package body Bindo.Graphs is function Kind (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind + Cycle : Library_Graph_Cycle_Id) return Library_Graph_Cycle_Kind is begin pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Cycle)); - return Get_LGE_Attributes (G, LGE_Id).Kind; + return Get_LGC_Attributes (G, Cycle).Kind; end Kind; + ---------- + -- Kind -- + ---------- + + function Kind + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return Get_LGE_Attributes (G, Edge).Kind; + end Kind; + + ------------ + -- Length -- + ------------ + + function Length + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Natural + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + return LGE_Lists.Size (Path (G, Cycle)); + end Length; + ------------------------------ -- Library_Graph_Edge_Count -- ------------------------------ @@ -2280,27 +3719,45 @@ package body Bindo.Graphs is -------------------------------------- function Links_Vertices_In_Same_Component - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Boolean + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean is + begin pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Edge)); - Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id); - Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id); + -- An edge is part of a cycle when both the successor and predecessor + -- reside in the same component. - pragma Assert (Present (Pred)); - pragma Assert (Present (Succ)); + return + In_Same_Component + (G => G, + Left => Predecessor (G, Edge), + Right => Successor (G, Edge)); + end Links_Vertices_In_Same_Component; + + ----------------------------------- + -- Maximum_Invocation_Edge_Count -- + ----------------------------------- + + function Maximum_Invocation_Edge_Count + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Count : Natural) return Natural + is + New_Count : Natural; + + begin + pragma Assert (Present (G)); - Pred_Comp : constant Component_Id := Component (G, Pred); - Succ_Comp : constant Component_Id := Component (G, Succ); + New_Count := Count; - pragma Assert (Present (Pred_Comp)); - pragma Assert (Present (Succ_Comp)); + if Present (Edge) and then Is_Invocation_Edge (G, Edge) then + New_Count := New_Count + 1; + end if; - begin - return Pred_Comp = Succ_Comp; - end Links_Vertices_In_Same_Component; + return New_Count; + end Maximum_Invocation_Edge_Count; ---------- -- Name -- @@ -2308,17 +3765,13 @@ package body Bindo.Graphs is function Name (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Unit_Name_Type + Vertex : Library_Graph_Vertex_Id) return Unit_Name_Type is + begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); - - U_Id : constant Unit_Id := Unit (G, LGV_Id); + pragma Assert (Present (Vertex)); - pragma Assert (Present (U_Id)); - - begin - return Name (U_Id); + return Name (Unit (G, Vertex)); end Name; ----------------------- @@ -2327,29 +3780,37 @@ package body Bindo.Graphs is function Needs_Elaboration (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean + Vertex : Library_Graph_Vertex_Id) return Boolean is + begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - U_Id : constant Unit_Id := Unit (G, LGV_Id); + return Needs_Elaboration (Unit (G, Vertex)); + end Needs_Elaboration; - pragma Assert (Present (U_Id)); + ---------- + -- Next -- + ---------- + procedure Next + (Iter : in out All_Cycle_Iterator; + Cycle : out Library_Graph_Cycle_Id) + is begin - return Needs_Elaboration (U_Id); - end Needs_Elaboration; + LGC_Lists.Next (LGC_Lists.Iterator (Iter), Cycle); + end Next; ---------- -- Next -- ---------- procedure Next - (Iter : in out All_Edge_Iterator; - LGE_Id : out Library_Graph_Edge_Id) + (Iter : in out All_Edge_Iterator; + Edge : out Library_Graph_Edge_Id) is begin - DG.Next (DG.All_Edge_Iterator (Iter), LGE_Id); + DG.Next (DG.All_Edge_Iterator (Iter), Edge); end Next; ---------- @@ -2358,10 +3819,22 @@ package body Bindo.Graphs is procedure Next (Iter : in out All_Vertex_Iterator; - LGV_Id : out Library_Graph_Vertex_Id) + Vertex : out Library_Graph_Vertex_Id) + is + begin + DG.Next (DG.All_Vertex_Iterator (Iter), Vertex); + end Next; + + ---------- + -- Next -- + ---------- + + procedure Next + (Iter : in out Edges_Of_Cycle_Iterator; + Edge : out Library_Graph_Edge_Id) is begin - DG.Next (DG.All_Vertex_Iterator (Iter), LGV_Id); + LGE_Lists.Next (LGE_Lists.Iterator (Iter), Edge); end Next; ---------- @@ -2381,11 +3854,11 @@ package body Bindo.Graphs is ---------- procedure Next - (Iter : in out Edges_To_Successors_Iterator; - LGE_Id : out Library_Graph_Edge_Id) + (Iter : in out Edges_To_Successors_Iterator; + Edge : out Library_Graph_Edge_Id) is begin - DG.Next (DG.Outgoing_Edge_Iterator (Iter), LGE_Id); + DG.Next (DG.Outgoing_Edge_Iterator (Iter), Edge); end Next; ---------- @@ -2394,12 +3867,95 @@ package body Bindo.Graphs is procedure Next (Iter : in out Component_Vertex_Iterator; - LGV_Id : out Library_Graph_Vertex_Id) + Vertex : out Library_Graph_Vertex_Id) is begin - DG.Next (DG.Component_Vertex_Iterator (Iter), LGV_Id); + DG.Next (DG.Component_Vertex_Iterator (Iter), Vertex); end Next; + ----------------------------- + -- Normalize_And_Add_Cycle -- + ----------------------------- + + procedure Normalize_And_Add_Cycle + (G : Library_Graph; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Indent : Indentation_Level) + is + Path : LGE_Lists.Doubly_Linked_List; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Most_Significant_Edge)); + pragma Assert (LGE_Lists.Present (Cycle_Path)); + + -- Replicate the path of the cycle in order to avoid sharing lists + + Path := Copy_Cycle_Path (Cycle_Path); + + -- Normalize the path of the cycle such that its most significant + -- edge is the first in the list of edges. + + Normalize_Cycle_Path + (Cycle_Path => Path, + Most_Significant_Edge => Most_Significant_Edge); + + -- Save the cycle for diagnostic purposes. Its kind is determined by + -- its most significant edge. + + Add_Cycle + (G => G, + Attrs => + (Invocation_Edge_Count => Invocation_Edge_Count, + Kind => + Cycle_Kind_Of + (G => G, + Edge => Most_Significant_Edge), + Path => Path), + Indent => Indent); + end Normalize_And_Add_Cycle; + + -------------------------- + -- Normalize_Cycle_Path -- + -------------------------- + + procedure Normalize_Cycle_Path + (Cycle_Path : LGE_Lists.Doubly_Linked_List; + Most_Significant_Edge : Library_Graph_Edge_Id) + is + Edge : Library_Graph_Edge_Id; + + begin + pragma Assert (LGE_Lists.Present (Cycle_Path)); + pragma Assert (Present (Most_Significant_Edge)); + + -- Perform at most |Cycle_Path| rotations in case the cycle is + -- malformed and the significant edge does not appear within. + + for Rotation in 1 .. LGE_Lists.Size (Cycle_Path) loop + Edge := LGE_Lists.First (Cycle_Path); + + -- The cycle is already rotated such that the most significant + -- edge is first. + + if Edge = Most_Significant_Edge then + return; + + -- Otherwise rotate the cycle by relocating the current edge from + -- the start to the end of the path. This preserves the order of + -- the path. + + else + LGE_Lists.Delete_First (Cycle_Path); + LGE_Lists.Append (Cycle_Path, Edge); + end if; + end loop; + + pragma Assert (False); + end Normalize_Cycle_Path; + ---------------------------------- -- Number_Of_Component_Vertices -- ---------------------------------- @@ -2426,6 +3982,17 @@ package body Bindo.Graphs is return DG.Number_Of_Components (G.Graph); end Number_Of_Components; + ---------------------- + -- Number_Of_Cycles -- + ---------------------- + + function Number_Of_Cycles (G : Library_Graph) return Natural is + begin + pragma Assert (Present (G)); + + return LGC_Lists.Size (G.Cycles); + end Number_Of_Cycles; + --------------------- -- Number_Of_Edges -- --------------------- @@ -2443,12 +4010,12 @@ package body Bindo.Graphs is function Number_Of_Edges_To_Successors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Natural + Vertex : Library_Graph_Vertex_Id) return Natural is begin pragma Assert (Present (G)); - return DG.Number_Of_Outgoing_Edges (G.Graph, LGV_Id); + return DG.Number_Of_Outgoing_Edges (G.Graph, Vertex); end Number_Of_Edges_To_Successors; ------------------------ @@ -2462,6 +4029,21 @@ package body Bindo.Graphs is return DG.Number_Of_Vertices (G.Graph); end Number_Of_Vertices; + ---------- + -- Path -- + ---------- + + function Path + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return LGE_Lists.Doubly_Linked_List + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + return Get_LGC_Attributes (G, Cycle).Path; + end Path; + -------------------------- -- Pending_Predecessors -- -------------------------- @@ -2483,28 +4065,168 @@ package body Bindo.Graphs is function Pending_Predecessors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Natural + Vertex : Library_Graph_Vertex_Id) return Natural is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - return Get_LGV_Attributes (G, LGV_Id).Pending_Predecessors; + return Get_LGV_Attributes (G, Vertex).Pending_Predecessors; end Pending_Predecessors; + ---------------- + -- Precedence -- + ---------------- + + function Precedence + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Compared_To : Library_Graph_Cycle_Id) return Precedence_Kind + is + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + pragma Assert (Present (Compared_To)); + + Comp_Invs : constant Natural := + Invocation_Edge_Count (G, Compared_To); + Comp_Len : constant Natural := Length (G, Compared_To); + Cycle_Invs : constant Natural := Invocation_Edge_Count (G, Cycle); + Cycle_Len : constant Natural := Length (G, Cycle); + Kind_Prec : constant Precedence_Kind := + Precedence + (Kind => Kind (G, Cycle), + Compared_To => Kind (G, Compared_To)); + + begin + if Kind_Prec = Higher_Precedence + or else + Kind_Prec = Lower_Precedence + then + return Kind_Prec; + + -- Otherwise both cycles have the same precedence based on their + -- kind. Prefer a cycle with fewer invocation edges. + + elsif Cycle_Invs < Comp_Invs then + return Higher_Precedence; + + elsif Cycle_Invs > Comp_Invs then + return Lower_Precedence; + + -- Otherwise both cycles have the same number of invocation edges. + -- Prefer a cycle with a smaller length. + + elsif Cycle_Len < Comp_Len then + return Higher_Precedence; + + elsif Cycle_Len > Comp_Len then + return Lower_Precedence; + + else + return Equal_Precedence; + end if; + end Precedence; + + ---------------- + -- Precedence -- + ---------------- + + function Precedence + (Kind : Library_Graph_Cycle_Kind; + Compared_To : Library_Graph_Cycle_Kind) return Precedence_Kind + is + Comp_Pos : constant Integer := + Library_Graph_Cycle_Kind'Pos (Compared_To); + Kind_Pos : constant Integer := Library_Graph_Cycle_Kind'Pos (Kind); + + begin + -- A lower ordinal indicates higher precedence + + if Kind_Pos < Comp_Pos then + return Higher_Precedence; + + elsif Kind_Pos > Comp_Pos then + return Lower_Precedence; + + else + return Equal_Precedence; + end if; + end Precedence; + + ---------------- + -- Precedence -- + ---------------- + + function Precedence + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Compared_To : Library_Graph_Edge_Id) return Precedence_Kind + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + pragma Assert (Present (Compared_To)); + + Kind_Prec : constant Precedence_Kind := + Precedence + (Kind => Cycle_Kind_Of (G, Edge), + Compared_To => Cycle_Kind_Of (G, Compared_To)); + + begin + if Kind_Prec = Higher_Precedence + or else + Kind_Prec = Lower_Precedence + then + return Kind_Prec; + + -- Otherwise both edges have the same precedence based on their cycle + -- kinds. Prefer an edge whose successor has higher precedence. + + else + return + Precedence + (G => G, + Vertex => Successor (G, Edge), + Compared_To => Successor (G, Compared_To)); + end if; + end Precedence; + + ---------------- + -- Precedence -- + ---------------- + + function Precedence + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + pragma Assert (Present (Compared_To)); + + -- Use lexicographical order to determine precedence and ensure + -- deterministic behavior. + + if Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then + return Higher_Precedence; + else + return Lower_Precedence; + end if; + end Precedence; + ----------------- -- Predecessor -- ----------------- function Predecessor - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Edge)); - return DG.Source_Vertex (G.Graph, LGE_Id); + return DG.Source_Vertex (G.Graph, Edge); end Predecessor; ------------- @@ -2522,23 +4244,23 @@ package body Bindo.Graphs is function Proper_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); -- When the vertex denotes a spec with a completing body, return the -- body. - if Is_Spec_With_Body (G, LGV_Id) then - return Corresponding_Item (G, LGV_Id); + if Is_Spec_With_Body (G, Vertex) then + return Corresponding_Item (G, Vertex); -- Otherwise the vertex must be a body else - pragma Assert (Is_Body (G, LGV_Id)); - return LGV_Id; + pragma Assert (Is_Body (G, Vertex)); + return Vertex; end if; end Proper_Body; @@ -2548,26 +4270,76 @@ package body Bindo.Graphs is function Proper_Spec (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); -- When the vertex denotes a body that completes a spec, return the -- spec. - if Is_Body_With_Spec (G, LGV_Id) then - return Corresponding_Item (G, LGV_Id); + if Is_Body_With_Spec (G, Vertex) then + return Corresponding_Item (G, Vertex); -- Otherwise the vertex must denote a spec else - pragma Assert (Is_Spec (G, LGV_Id)); - return LGV_Id; + pragma Assert (Is_Spec (G, Vertex)); + return Vertex; end if; end Proper_Spec; + ---------------------------------- + -- Remove_Vertex_And_Complement -- + ---------------------------------- + + procedure Remove_Vertex_And_Complement + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; + Do_Complement : Boolean) + is + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + pragma Assert (LGV_Sets.Present (Set)); + + Complement : constant Library_Graph_Vertex_Id := + Complementary_Vertex + (G => G, + Vertex => Vertex, + Do_Complement => Do_Complement); + + begin + LGV_Sets.Delete (Set, Vertex); + + if Present (Complement) then + LGV_Sets.Delete (Set, Complement); + end if; + end Remove_Vertex_And_Complement; + + ----------------------------------------- + -- Same_Library_Graph_Cycle_Attributes -- + ----------------------------------------- + + function Same_Library_Graph_Cycle_Attributes + (Left : Library_Graph_Cycle_Attributes; + Right : Library_Graph_Cycle_Attributes) return Boolean + is + begin + -- Two cycles are the same when + -- + -- * They are of the same kind + -- * They have the same number of invocation edges in their paths + -- * Their paths are the same length + -- * The edges comprising their paths are the same + + return + Left.Invocation_Edge_Count = Right.Invocation_Edge_Count + and then Left.Kind = Right.Kind + and then LGE_Lists.Equal (Left.Path, Right.Path); + end Same_Library_Graph_Cycle_Attributes; + ------------------------------ -- Set_Component_Attributes -- ------------------------------ @@ -2581,7 +4353,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Comp)); - CA.Put (G.Component_Attributes, Comp, Val); + Component_Tables.Put (G.Component_Attributes, Comp, Val); end Set_Component_Attributes; ---------------------------- @@ -2590,18 +4362,18 @@ package body Bindo.Graphs is procedure Set_Corresponding_Item (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Val : Library_Graph_Vertex_Id) is Attrs : Library_Graph_Vertex_Attributes; begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - Attrs := Get_LGV_Attributes (G, LGV_Id); + Attrs := Get_LGV_Attributes (G, Vertex); Attrs.Corresponding_Item := Val; - Set_LGV_Attributes (G, LGV_Id, Attrs); + Set_LGV_Attributes (G, Vertex, Attrs); end Set_Corresponding_Item; ------------------------------ @@ -2617,7 +4389,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (U_Id)); - UV.Put (G.Unit_To_Vertex, U_Id, Val); + Unit_Tables.Put (G.Unit_To_Vertex, U_Id, Val); end Set_Corresponding_Vertex; ------------------------------ @@ -2626,25 +4398,44 @@ package body Bindo.Graphs is procedure Set_In_Elaboration_Order (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Val : Boolean := True) is Attrs : Library_Graph_Vertex_Attributes; begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - Attrs := Get_LGV_Attributes (G, LGV_Id); + Attrs := Get_LGV_Attributes (G, Vertex); Attrs.In_Elaboration_Order := Val; - Set_LGV_Attributes (G, LGV_Id, Attrs); + Set_LGV_Attributes (G, Vertex, Attrs); end Set_In_Elaboration_Order; - ---------------------------------------------------- - -- Set_Is_Existing_Predecessor_Successor_Relation -- - ---------------------------------------------------- + --------------------------- + -- Set_Is_Recorded_Cycle -- + --------------------------- + + procedure Set_Is_Recorded_Cycle + (G : Library_Graph; + Attrs : Library_Graph_Cycle_Attributes; + Val : Boolean := True) + is + begin + pragma Assert (Present (G)); + + if Val then + RC_Sets.Insert (G.Recorded_Cycles, Attrs); + else + RC_Sets.Delete (G.Recorded_Cycles, Attrs); + end if; + end Set_Is_Recorded_Cycle; + + -------------------------- + -- Set_Is_Recorded_Edge -- + -------------------------- - procedure Set_Is_Existing_Predecessor_Successor_Relation + procedure Set_Is_Recorded_Edge (G : Library_Graph; Rel : Predecessor_Successor_Relation; Val : Boolean := True) @@ -2655,11 +4446,27 @@ package body Bindo.Graphs is pragma Assert (Present (Rel.Successor)); if Val then - PS.Insert (G.Relations, Rel); + RE_Sets.Insert (G.Recorded_Edges, Rel); else - PS.Delete (G.Relations, Rel); + RE_Sets.Delete (G.Recorded_Edges, Rel); end if; - end Set_Is_Existing_Predecessor_Successor_Relation; + end Set_Is_Recorded_Edge; + + ------------------------ + -- Set_LGC_Attributes -- + ------------------------ + + procedure Set_LGC_Attributes + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Val : Library_Graph_Cycle_Attributes) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + LGC_Tables.Put (G.Cycle_Attributes, Cycle, Val); + end Set_LGC_Attributes; ------------------------ -- Set_LGE_Attributes -- @@ -2667,14 +4474,14 @@ package body Bindo.Graphs is procedure Set_LGE_Attributes (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id; + Edge : Library_Graph_Edge_Id; Val : Library_Graph_Edge_Attributes) is begin pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Edge)); - EA.Put (G.Edge_Attributes, LGE_Id, Val); + LGE_Tables.Put (G.Edge_Attributes, Edge, Val); end Set_LGE_Attributes; ------------------------ @@ -2683,14 +4490,14 @@ package body Bindo.Graphs is procedure Set_LGV_Attributes (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Val : Library_Graph_Vertex_Attributes) is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - VA.Put (G.Vertex_Attributes, LGV_Id, Val); + LGV_Tables.Put (G.Vertex_Attributes, Vertex, Val); end Set_LGV_Attributes; --------------- @@ -2698,29 +4505,201 @@ package body Bindo.Graphs is --------------- function Successor - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Edge)); - return DG.Destination_Vertex (G.Graph, LGE_Id); + return DG.Destination_Vertex (G.Graph, Edge); end Successor; + ----------------- + -- Trace_Cycle -- + ----------------- + + procedure Trace_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Indent : Indentation_Level) + is + Attr_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + Edge_Indent : constant Indentation_Level := + Attr_Indent + Nested_Indentation; + + Edge : Library_Graph_Edge_Id; + Iter : Edges_Of_Cycle_Iterator; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. + + if not Debug_Flag_Underscore_TT then + return; + end if; + + Indent_By (Indent); + Write_Str ("cycle (Cycle_Id_"); + Write_Int (Int (Cycle)); + Write_Str (")"); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("kind = "); + Write_Str (Kind (G, Cycle)'Img); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("invocation edges = "); + Write_Int (Int (Invocation_Edge_Count (G, Cycle))); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("length: "); + Write_Int (Int (Length (G, Cycle))); + Write_Eol; + + Iter := Iterate_Edges_Of_Cycle (G, Cycle); + while Has_Next (Iter) loop + Next (Iter, Edge); + + Indent_By (Edge_Indent); + Write_Str ("library graph edge (Edge_"); + Write_Int (Int (Edge)); + Write_Str (")"); + Write_Eol; + end loop; + end Trace_Cycle; + + ---------------- + -- Trace_Edge -- + ---------------- + + procedure Trace_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Indent : Indentation_Level) + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + Attr_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + + Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge); + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); + + begin + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. + + if not Debug_Flag_Underscore_TT then + return; + end if; + + Indent_By (Indent); + Write_Str ("library graph edge (Edge_"); + Write_Int (Int (Edge)); + Write_Str (")"); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("kind = "); + Write_Str (Kind (G, Edge)'Img); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("Predecessor (Vertex_"); + Write_Int (Int (Pred)); + Write_Str (") name = "); + Write_Name (Name (G, Pred)); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("Successor (Vertex_"); + Write_Int (Int (Succ)); + Write_Str (") name = "); + Write_Name (Name (G, Succ)); + Write_Eol; + end Trace_Edge; + + --------------- + -- Trace_Eol -- + --------------- + + procedure Trace_Eol is + begin + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. + + if not Debug_Flag_Underscore_TT then + return; + end if; + + Write_Eol; + end Trace_Eol; + + ------------------ + -- Trace_Vertex -- + ------------------ + + procedure Trace_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Indent : Indentation_Level) + is + Attr_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. + + if not Debug_Flag_Underscore_TT then + return; + end if; + + Indent_By (Indent); + Write_Str ("library graph vertex (Vertex_"); + Write_Int (Int (Vertex)); + Write_Str (")"); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("Component (Comp_Id_"); + Write_Int (Int (Component (G, Vertex))); + Write_Str (")"); + Write_Eol; + + Indent_By (Attr_Indent); + Write_Str ("Unit (U_Id_"); + Write_Int (Int (Unit (G, Vertex))); + Write_Str (") name = "); + Write_Name (Name (G, Vertex)); + Write_Eol; + end Trace_Vertex; + ---------- -- Unit -- ---------- function Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Unit_Id + Vertex : Library_Graph_Vertex_Id) return Unit_Id is begin pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); - return Get_LGV_Attributes (G, LGV_Id).Unit; + return Get_LGV_Attributes (G, Vertex).Unit; end Unit; ----------------------------------------------- @@ -2730,18 +4709,17 @@ package body Bindo.Graphs is procedure Update_Pending_Predecessors_Of_Components (G : Library_Graph) is - Iter : All_Edge_Iterator; - LGE_Id : Library_Graph_Edge_Id; + Edge : Library_Graph_Edge_Id; + Iter : All_Edge_Iterator; begin pragma Assert (Present (G)); Iter := Iterate_All_Edges (G); while Has_Next (Iter) loop - Next (Iter, LGE_Id); - pragma Assert (Present (LGE_Id)); + Next (Iter, Edge); - Update_Pending_Predecessors_Of_Components (G, LGE_Id); + Update_Pending_Predecessors_Of_Components (G, Edge); end loop; end Update_Pending_Predecessors_Of_Components; @@ -2750,20 +4728,16 @@ package body Bindo.Graphs is ----------------------------------------------- procedure Update_Pending_Predecessors_Of_Components - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) is pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); - - Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id); - Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id); - - pragma Assert (Present (Pred)); - pragma Assert (Present (Succ)); + pragma Assert (Present (Edge)); - Pred_Comp : constant Component_Id := Component (G, Pred); - Succ_Comp : constant Component_Id := Component (G, Succ); + Pred_Comp : constant Component_Id := + Component (G, Predecessor (G, Edge)); + Succ_Comp : constant Component_Id := + Component (G, Successor (G, Edge)); pragma Assert (Present (Pred_Comp)); pragma Assert (Present (Succ_Comp)); @@ -2783,104 +4757,125 @@ package body Bindo.Graphs is -- Present -- ------------- - function Present (IGE_Id : Invocation_Graph_Edge_Id) return Boolean is + function Present (Edge : Invocation_Graph_Edge_Id) return Boolean is + begin + return Edge /= No_Invocation_Graph_Edge; + end Present; + + ------------- + -- Present -- + ------------- + + function Present (Vertex : Invocation_Graph_Vertex_Id) return Boolean is begin - return IGE_Id /= No_Invocation_Graph_Edge; + return Vertex /= No_Invocation_Graph_Vertex; end Present; ------------- -- Present -- ------------- - function Present (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean is + function Present (Cycle : Library_Graph_Cycle_Id) return Boolean is begin - return IGV_Id /= No_Invocation_Graph_Vertex; + return Cycle /= No_Library_Graph_Cycle; end Present; ------------- -- Present -- ------------- - function Present (LGE_Id : Library_Graph_Edge_Id) return Boolean is + function Present (Edge : Library_Graph_Edge_Id) return Boolean is begin - return LGE_Id /= No_Library_Graph_Edge; + return Edge /= No_Library_Graph_Edge; end Present; ------------- -- Present -- ------------- - function Present (LGV_Id : Library_Graph_Vertex_Id) return Boolean is + function Present (Vertex : Library_Graph_Vertex_Id) return Boolean is begin - return LGV_Id /= No_Library_Graph_Vertex; + return Vertex /= No_Library_Graph_Vertex; end Present; -------------------------- - -- Sequence_Next_IGE_Id -- + -- Sequence_Next_Edge -- -------------------------- IGE_Sequencer : Invocation_Graph_Edge_Id := First_Invocation_Graph_Edge; -- The counter for invocation graph edges. Do not directly manipulate its -- value. - function Sequence_Next_IGE_Id return Invocation_Graph_Edge_Id is - IGE_Id : constant Invocation_Graph_Edge_Id := IGE_Sequencer; + function Sequence_Next_Edge return Invocation_Graph_Edge_Id is + Edge : constant Invocation_Graph_Edge_Id := IGE_Sequencer; begin IGE_Sequencer := IGE_Sequencer + 1; - return IGE_Id; - end Sequence_Next_IGE_Id; + return Edge; + end Sequence_Next_Edge; -------------------------- - -- Sequence_Next_IGV_Id -- + -- Sequence_Next_Vertex -- -------------------------- IGV_Sequencer : Invocation_Graph_Vertex_Id := First_Invocation_Graph_Vertex; -- The counter for invocation graph vertices. Do not directly manipulate -- its value. + function Sequence_Next_Vertex return Invocation_Graph_Vertex_Id is + Vertex : constant Invocation_Graph_Vertex_Id := IGV_Sequencer; + + begin + IGV_Sequencer := IGV_Sequencer + 1; + return Vertex; + end Sequence_Next_Vertex; + -------------------------- - -- Sequence_Next_IGV_Id -- + -- Sequence_Next_Cycle -- -------------------------- - function Sequence_Next_IGV_Id return Invocation_Graph_Vertex_Id is - IGV_Id : constant Invocation_Graph_Vertex_Id := IGV_Sequencer; + LGC_Sequencer : Library_Graph_Cycle_Id := First_Library_Graph_Cycle; + -- The couhnter for library graph cycles. Do not directly manipulate its + -- value. + + function Sequence_Next_Cycle return Library_Graph_Cycle_Id is + Cycle : constant Library_Graph_Cycle_Id := LGC_Sequencer; begin - IGV_Sequencer := IGV_Sequencer + 1; - return IGV_Id; - end Sequence_Next_IGV_Id; + LGC_Sequencer := LGC_Sequencer + 1; + return Cycle; + end Sequence_Next_Cycle; -------------------------- - -- Sequence_Next_LGE_Id -- + -- Sequence_Next_Edge -- -------------------------- LGE_Sequencer : Library_Graph_Edge_Id := First_Library_Graph_Edge; -- The counter for library graph edges. Do not directly manipulate its -- value. - function Sequence_Next_LGE_Id return Library_Graph_Edge_Id is - LGE_Id : constant Library_Graph_Edge_Id := LGE_Sequencer; + function Sequence_Next_Edge return Library_Graph_Edge_Id is + Edge : constant Library_Graph_Edge_Id := LGE_Sequencer; begin LGE_Sequencer := LGE_Sequencer + 1; - return LGE_Id; - end Sequence_Next_LGE_Id; + return Edge; + end Sequence_Next_Edge; -------------------------- - -- Sequence_Next_LGV_Id -- + -- Sequence_Next_Vertex -- -------------------------- LGV_Sequencer : Library_Graph_Vertex_Id := First_Library_Graph_Vertex; -- The counter for library graph vertices. Do not directly manipulate its -- value. - function Sequence_Next_LGV_Id return Library_Graph_Vertex_Id is - LGV_Id : constant Library_Graph_Vertex_Id := LGV_Sequencer; + function Sequence_Next_Vertex return Library_Graph_Vertex_Id is + Vertex : constant Library_Graph_Vertex_Id := LGV_Sequencer; begin LGV_Sequencer := LGV_Sequencer + 1; - return LGV_Id; - end Sequence_Next_LGV_Id; + return Vertex; + end Sequence_Next_Vertex; end Bindo.Graphs; diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads index a5dc6ea..02f8e52 100644 --- a/gcc/ada/bindo-graphs.ads +++ b/gcc/ada/bindo-graphs.ads @@ -28,11 +28,14 @@ -- The following unit defines the various graphs used in determining the -- elaboration order of units. +with Types; use Types; + with Bindo.Units; use Bindo.Units; with GNAT; use GNAT; with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables; with GNAT.Graphs; use GNAT.Graphs; +with GNAT.Lists; use GNAT.Lists; with GNAT.Sets; use GNAT.Sets; package Bindo.Graphs is @@ -49,14 +52,24 @@ package Bindo.Graphs is First_Invocation_Graph_Edge : constant Invocation_Graph_Edge_Id := No_Invocation_Graph_Edge + 1; + procedure Destroy_Invocation_Graph_Edge + (Edge : in out Invocation_Graph_Edge_Id); + pragma Inline (Destroy_Invocation_Graph_Edge); + -- Destroy invocation graph edge Edge + function Hash_Invocation_Graph_Edge - (IGE_Id : Invocation_Graph_Edge_Id) return Bucket_Range_Type; + (Edge : Invocation_Graph_Edge_Id) return Bucket_Range_Type; pragma Inline (Hash_Invocation_Graph_Edge); - -- Obtain the hash value of key IGE_Id + -- Obtain the hash value of key Edge - function Present (IGE_Id : Invocation_Graph_Edge_Id) return Boolean; + function Present (Edge : Invocation_Graph_Edge_Id) return Boolean; pragma Inline (Present); - -- Determine whether invocation graph edge IGE_Id exists + -- Determine whether invocation graph edge Edge exists + + package IGE_Lists is new Doubly_Linked_Lists + (Element_Type => Invocation_Graph_Edge_Id, + "=" => "=", + Destroy_Element => Destroy_Invocation_Graph_Edge); ------------------------------ -- Invocation graph vertex -- @@ -71,13 +84,47 @@ package Bindo.Graphs is No_Invocation_Graph_Vertex + 1; function Hash_Invocation_Graph_Vertex - (IGV_Id : Invocation_Graph_Vertex_Id) return Bucket_Range_Type; + (Vertex : Invocation_Graph_Vertex_Id) return Bucket_Range_Type; pragma Inline (Hash_Invocation_Graph_Vertex); - -- Obtain the hash value of key IGV_Id + -- Obtain the hash value of key Vertex - function Present (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean; + function Present (Vertex : Invocation_Graph_Vertex_Id) return Boolean; + pragma Inline (Present); + -- Determine whether invocation graph vertex Vertex exists + + package IGV_Sets is new Membership_Sets + (Element_Type => Invocation_Graph_Vertex_Id, + "=" => "=", + Hash => Hash_Invocation_Graph_Vertex); + + ------------------------- + -- Library graph cycle -- + ------------------------- + + type Library_Graph_Cycle_Id is new Natural; + No_Library_Graph_Cycle : constant Library_Graph_Cycle_Id := + Library_Graph_Cycle_Id'First; + First_Library_Graph_Cycle : constant Library_Graph_Cycle_Id := + No_Library_Graph_Cycle + 1; + + procedure Destroy_Library_Graph_Cycle + (Cycle : in out Library_Graph_Cycle_Id); + pragma Inline (Destroy_Library_Graph_Cycle); + -- Destroy library graph cycle Cycle + + function Hash_Library_Graph_Cycle + (Cycle : Library_Graph_Cycle_Id) return Bucket_Range_Type; + pragma Inline (Hash_Library_Graph_Cycle); + -- Obtain the hash value of key Cycle + + function Present (Cycle : Library_Graph_Cycle_Id) return Boolean; pragma Inline (Present); - -- Determine whether invocation graph vertex IGV_Id exists + -- Determine whether library graph cycle Cycle exists + + package LGC_Lists is new Doubly_Linked_Lists + (Element_Type => Library_Graph_Cycle_Id, + "=" => "=", + Destroy_Element => Destroy_Library_Graph_Cycle); ------------------------ -- Library graph edge -- @@ -91,14 +138,29 @@ package Bindo.Graphs is First_Library_Graph_Edge : constant Library_Graph_Edge_Id := No_Library_Graph_Edge + 1; + procedure Destroy_Library_Graph_Edge + (Edge : in out Library_Graph_Edge_Id); + pragma Inline (Destroy_Library_Graph_Edge); + -- Destroy library graph edge Edge + function Hash_Library_Graph_Edge - (LGE_Id : Library_Graph_Edge_Id) return Bucket_Range_Type; + (Edge : Library_Graph_Edge_Id) return Bucket_Range_Type; pragma Inline (Hash_Library_Graph_Edge); - -- Obtain the hash value of key LGE_Id + -- Obtain the hash value of key Edge - function Present (LGE_Id : Library_Graph_Edge_Id) return Boolean; + function Present (Edge : Library_Graph_Edge_Id) return Boolean; pragma Inline (Present); - -- Determine whether library graph edge LGE_Id exists + -- Determine whether library graph edge Edge exists + + package LGE_Lists is new Doubly_Linked_Lists + (Element_Type => Library_Graph_Edge_Id, + "=" => "=", + Destroy_Element => Destroy_Library_Graph_Edge); + + package LGE_Sets is new Membership_Sets + (Element_Type => Library_Graph_Edge_Id, + "=" => "=", + Hash => Hash_Library_Graph_Edge); -------------------------- -- Library graph vertex -- @@ -113,13 +175,18 @@ package Bindo.Graphs is No_Library_Graph_Vertex + 1; function Hash_Library_Graph_Vertex - (LGV_Id : Library_Graph_Vertex_Id) return Bucket_Range_Type; + (Vertex : Library_Graph_Vertex_Id) return Bucket_Range_Type; pragma Inline (Hash_Library_Graph_Vertex); - -- Obtain the hash value of key LGV_Id + -- Obtain the hash value of key Vertex - function Present (LGV_Id : Library_Graph_Vertex_Id) return Boolean; + function Present (Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Present); - -- Determine whether library graph vertex LGV_Id exists + -- Determine whether library graph vertex Vertex exists + + package LGV_Sets is new Membership_Sets + (Element_Type => Library_Graph_Vertex_Id, + "=" => "=", + Hash => Hash_Library_Graph_Vertex); ----------------------- -- Invocation_Graphs -- @@ -152,13 +219,16 @@ package Bindo.Graphs is -- describes. procedure Add_Vertex - (G : Invocation_Graph; - IC_Id : Invocation_Construct_Id; - LGV_Id : Library_Graph_Vertex_Id); + (G : Invocation_Graph; + IC_Id : Invocation_Construct_Id; + Body_Vertex : Library_Graph_Vertex_Id; + Spec_Vertex : Library_Graph_Vertex_Id); pragma Inline (Add_Vertex); -- Create a new vertex in invocation graph G. IC_Id is the invocation - -- construct the vertex describes. LGV_Id is the library graph vertex - -- where the invocation construct appears. + -- construct the vertex describes. Body_Vertex denotes the library graph + -- vertex where the invocation construct's body is declared. Spec_Vertex + -- is the library graph vertex where the invocation construct's spec is + -- declared. function Create (Initial_Vertices : Positive; @@ -179,11 +249,26 @@ package Bindo.Graphs is -- Vertex attributes -- ----------------------- + function Body_Vertex + (G : Invocation_Graph; + Vertex : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id; + pragma Inline (Body_Vertex); + -- Obtain the library graph vertex where the body of the invocation + -- construct represented by vertex Vertex of invocation graph G is + -- declared. + + function Column + (G : Invocation_Graph; + Vertex : Invocation_Graph_Vertex_Id) return Nat; + pragma Inline (Column); + -- Obtain the column number where the invocation construct vertex Vertex + -- of invocation graph G describes. + function Construct (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Invocation_Construct_Id; + Vertex : Invocation_Graph_Vertex_Id) return Invocation_Construct_Id; pragma Inline (Construct); - -- Obtain the invocation construct vertex IGV_Id of invocation graph G + -- Obtain the invocation construct vertex Vertex of invocation graph G -- describes. function Corresponding_Vertex @@ -193,41 +278,56 @@ package Bindo.Graphs is -- Obtain the vertex of invocation graph G that corresponds to signature -- IS_Id. - function Lib_Vertex + function Line (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id; - pragma Inline (Lib_Vertex); - -- Obtain the library graph vertex where vertex IGV_Id of invocation - -- graph appears. + Vertex : Invocation_Graph_Vertex_Id) return Nat; + pragma Inline (Line); + -- Obtain the line number where the invocation construct vertex Vertex + -- of invocation graph G describes. function Name (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Name_Id; + Vertex : Invocation_Graph_Vertex_Id) return Name_Id; pragma Inline (Name); - -- Obtain the name of the construct vertex IGV_Id of invocation graph G + -- Obtain the name of the construct vertex Vertex of invocation graph G -- describes. + function Spec_Vertex + (G : Invocation_Graph; + Vertex : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id; + pragma Inline (Spec_Vertex); + -- Obtain the library graph vertex where the spec of the invocation + -- construct represented by vertex Vertex of invocation graph G is + -- declared. + --------------------- -- Edge attributes -- --------------------- + function Extra + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Name_Id; + pragma Inline (Extra); + -- Obtain the extra name used in error diagnostics of edge Edge of + -- invocation graph G. + function Kind - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Kind; + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Invocation_Kind; pragma Inline (Kind); - -- Obtain the nature of edge IGE_Id of invocation graph G + -- Obtain the nature of edge Edge of invocation graph G function Relation - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Relation_Id; + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Invocation_Relation_Id; pragma Inline (Relation); - -- Obtain the relation edge IGE_Id of invocation graph G describes + -- Obtain the relation edge Edge of invocation graph G describes function Target - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Graph_Vertex_Id; + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) return Invocation_Graph_Vertex_Id; pragma Inline (Target); - -- Obtain the target vertex edge IGE_Id of invocation graph G designates + -- Obtain the target vertex edge Edge of invocation graph G designates ---------------- -- Statistics -- @@ -245,9 +345,9 @@ package Bindo.Graphs is function Number_Of_Edges_To_Targets (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Natural; + Vertex : Invocation_Graph_Vertex_Id) return Natural; pragma Inline (Number_Of_Edges_To_Targets); - -- Obtain the total number of edges to targets vertex IGV_Id of + -- Obtain the total number of edges to targets vertex Vertex of -- invocation graph G has. function Number_Of_Elaboration_Roots @@ -278,8 +378,8 @@ package Bindo.Graphs is -- Obtain an iterator over all edges of invocation graph G procedure Next - (Iter : in out All_Edge_Iterator; - IGE_Id : out Invocation_Graph_Edge_Id); + (Iter : in out All_Edge_Iterator; + Edge : out Invocation_Graph_Edge_Id); pragma Inline (Next); -- Return the current edge referenced by iterator Iter and advance to -- the next available edge. @@ -300,7 +400,7 @@ package Bindo.Graphs is procedure Next (Iter : in out All_Vertex_Iterator; - IGV_Id : out Invocation_Graph_Vertex_Id); + Vertex : out Invocation_Graph_Vertex_Id); pragma Inline (Next); -- Return the current vertex referenced by iterator Iter and advance -- to the next available vertex. @@ -316,14 +416,14 @@ package Bindo.Graphs is function Iterate_Edges_To_Targets (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) return Edges_To_Targets_Iterator; + Vertex : Invocation_Graph_Vertex_Id) return Edges_To_Targets_Iterator; pragma Inline (Iterate_Edges_To_Targets); -- Obtain an iterator over all edges to targets with source vertex - -- IGV_Id of invocation graph G. + -- Vertex of invocation graph G. procedure Next - (Iter : in out Edges_To_Targets_Iterator; - IGE_Id : out Invocation_Graph_Edge_Id); + (Iter : in out Edges_To_Targets_Iterator; + Edge : out Invocation_Graph_Edge_Id); pragma Inline (Next); -- Return the current edge referenced by iterator Iter and advance to -- the next available edge. @@ -357,32 +457,38 @@ package Bindo.Graphs is -------------- procedure Destroy_Invocation_Graph_Vertex - (IGV_Id : in out Invocation_Graph_Vertex_Id); + (Vertex : in out Invocation_Graph_Vertex_Id); pragma Inline (Destroy_Invocation_Graph_Vertex); - -- Destroy invocation graph vertex IGV_Id + -- Destroy invocation graph vertex Vertex -- The following type represents the attributes of an invocation graph -- vertex. type Invocation_Graph_Vertex_Attributes is record + Body_Vertex : Library_Graph_Vertex_Id := No_Library_Graph_Vertex; + -- Reference to the library graph vertex where the body of this + -- vertex resides. + Construct : Invocation_Construct_Id := No_Invocation_Construct; -- Reference to the invocation construct this vertex represents - Lib_Vertex : Library_Graph_Vertex_Id := No_Library_Graph_Vertex; - -- Reference to the library graph vertex where this vertex resides + Spec_Vertex : Library_Graph_Vertex_Id := No_Library_Graph_Vertex; + -- Reference to the library graph vertex where the spec of this + -- vertex resides. end record; No_Invocation_Graph_Vertex_Attributes : constant Invocation_Graph_Vertex_Attributes := - (Construct => No_Invocation_Construct, - Lib_Vertex => No_Library_Graph_Vertex); + (Body_Vertex => No_Library_Graph_Vertex, + Construct => No_Invocation_Construct, + Spec_Vertex => No_Library_Graph_Vertex); procedure Destroy_Invocation_Graph_Vertex_Attributes (Attrs : in out Invocation_Graph_Vertex_Attributes); pragma Inline (Destroy_Invocation_Graph_Vertex_Attributes); -- Destroy the contents of attributes Attrs - package VA is new Dynamic_Hash_Tables + package IGV_Tables is new Dynamic_Hash_Tables (Key_Type => Invocation_Graph_Vertex_Id, Value_Type => Invocation_Graph_Vertex_Attributes, No_Value => No_Invocation_Graph_Vertex_Attributes, @@ -399,9 +505,9 @@ package Bindo.Graphs is ----------- procedure Destroy_Invocation_Graph_Edge - (IGE_Id : in out Invocation_Graph_Edge_Id); + (Edge : in out Invocation_Graph_Edge_Id); pragma Inline (Destroy_Invocation_Graph_Edge); - -- Destroy invocation graph edge IGE_Id + -- Destroy invocation graph edge Edge -- The following type represents the attributes of an invocation graph -- edge. @@ -420,7 +526,7 @@ package Bindo.Graphs is pragma Inline (Destroy_Invocation_Graph_Edge_Attributes); -- Destroy the contents of attributes Attrs - package EA is new Dynamic_Hash_Tables + package IGE_Tables is new Dynamic_Hash_Tables (Key_Type => Invocation_Graph_Edge_Id, Value_Type => Invocation_Graph_Edge_Attributes, No_Value => No_Invocation_Graph_Edge_Attributes, @@ -457,7 +563,7 @@ package Bindo.Graphs is pragma Inline (Hash_Source_Target_Relation); -- Obtain the hash value of key Rel - package ST is new Membership_Sets + package Relation_Sets is new Membership_Sets (Element_Type => Source_Target_Relation, "=" => "=", Hash => Hash_Source_Target_Relation); @@ -477,7 +583,7 @@ package Bindo.Graphs is pragma Inline (Hash_Invocation_Signature); -- Obtain the hash value of key IS_Id - package SV is new Dynamic_Hash_Tables + package Signature_Tables is new Dynamic_Hash_Tables (Key_Type => Invocation_Signature_Id, Value_Type => Invocation_Graph_Vertex_Id, No_Value => No_Invocation_Graph_Vertex, @@ -493,7 +599,7 @@ package Bindo.Graphs is -- Elaboration roots -- ----------------------- - package ER is new Membership_Sets + package IGV_Sets is new Membership_Sets (Element_Type => Invocation_Graph_Vertex_Id, "=" => "=", Hash => Hash_Invocation_Graph_Vertex); @@ -518,24 +624,25 @@ package Bindo.Graphs is Counts : Invocation_Graph_Edge_Counts := (others => 0); -- Edge statistics - Edge_Attributes : EA.Dynamic_Hash_Table := EA.Nil; + Edge_Attributes : IGE_Tables.Dynamic_Hash_Table := IGE_Tables.Nil; -- The map of edge -> edge attributes for all edges in the graph Graph : DG.Directed_Graph := DG.Nil; -- The underlying graph describing the relations between edges and -- vertices. - Relations : ST.Membership_Set := ST.Nil; + Relations : Relation_Sets.Membership_Set := Relation_Sets.Nil; -- The set of relations between source and targets, used to prevent -- duplicate edges in the graph. - Roots : ER.Membership_Set := ER.Nil; + Roots : IGV_Sets.Membership_Set := IGV_Sets.Nil; -- The set of elaboration root vertices - Signature_To_Vertex : SV.Dynamic_Hash_Table := SV.Nil; + Signature_To_Vertex : Signature_Tables.Dynamic_Hash_Table := + Signature_Tables.Nil; -- The map of signature -> vertex - Vertex_Attributes : VA.Dynamic_Hash_Table := VA.Nil; + Vertex_Attributes : IGV_Tables.Dynamic_Hash_Table := IGV_Tables.Nil; -- The map of vertex -> vertex attributes for all vertices in the -- graph. end record; @@ -550,7 +657,7 @@ package Bindo.Graphs is type All_Edge_Iterator is new DG.All_Edge_Iterator; type All_Vertex_Iterator is new DG.All_Vertex_Iterator; type Edges_To_Targets_Iterator is new DG.Outgoing_Edge_Iterator; - type Elaboration_Root_Iterator is new ER.Iterator; + type Elaboration_Root_Iterator is new IGV_Sets.Iterator; end Invocation_Graphs; -------------------- @@ -559,6 +666,32 @@ package Bindo.Graphs is package Library_Graphs is + -- The following type represents the various kinds of library graph + -- cycles. The ordering of kinds is significant, where a literal with + -- lower ordinal has a higner precedence than one with higher ordinal. + + type Library_Graph_Cycle_Kind is + (Elaborate_Body_Cycle, + -- A cycle that involves at least one spec-body pair, where the + -- spec is subject to pragma Elaborate_Body. This is the highest + -- precedence cycle. + + Elaborate_Cycle, + -- A cycle that involves at least one Elaborate edge + + Elaborate_All_Cycle, + -- A cycle that involves at least one Elaborate_All edge + + Forced_Cycle, + -- A cycle that involves at least one edge which is a byproduct of + -- the forced-elaboration-order file. + + Invocation_Cycle, + -- A cycle that involves at least one invocation edge. This is the + -- lowest precedence cycle. + + No_Cycle_Kind); + -- The following type represents the various kinds of library edges type Library_Graph_Edge_Kind is @@ -620,11 +753,13 @@ package Bindo.Graphs is -- describes. function Create - (Initial_Vertices : Positive; - Initial_Edges : Positive) return Library_Graph; + (Initial_Vertices : Positive; + Initial_Edges : Positive; + Dynamically_Elaborated : Boolean) return Library_Graph; pragma Inline (Create); -- Create a new empty graph with vertex capacity Initial_Vertices and - -- edge capacity Initial_Edges. + -- edge capacity Initial_Edges. Flag Dynamically_Elaborated must be set + -- when the main library unit was compiled using the dynamic model. procedure Destroy (G : in out Library_Graph); pragma Inline (Destroy); @@ -634,6 +769,16 @@ package Bindo.Graphs is pragma Inline (Find_Components); -- Find all components in library graph G + procedure Find_Cycles (G : Library_Graph); + pragma Inline (Find_Cycles); + -- Find all cycles in library graph G + + function Highest_Precedence_Cycle + (G : Library_Graph) return Library_Graph_Cycle_Id; + pragma Inline (Highest_Precedence_Cycle); + -- Obtain the cycle with highest precedence among all other cycles of + -- library graph G. + function Present (G : Library_Graph) return Boolean; pragma Inline (Present); -- Determine whether library graph G exists @@ -644,16 +789,16 @@ package Bindo.Graphs is function Component (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Component_Id; + Vertex : Library_Graph_Vertex_Id) return Component_Id; pragma Inline (Component); - -- Obtain the component where vertex LGV_Id of library graph G resides + -- Obtain the component where vertex Vertex of library graph G resides function Corresponding_Item (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; pragma Inline (Corresponding_Item); -- Obtain the complementary vertex which represents the corresponding - -- spec or body of vertex LGV_Id of library graph G. + -- spec or body of vertex Vertex of library graph G. function Corresponding_Vertex (G : Library_Graph; @@ -664,75 +809,91 @@ package Bindo.Graphs is procedure Decrement_Pending_Predecessors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id); pragma Inline (Decrement_Pending_Predecessors); - -- Decrease the number of pending predecessors vertex LGV_Id of library + -- Decrease the number of pending predecessors vertex Vertex of library -- graph G must wait on until it can be elaborated. + function File_Name + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return File_Name_Type; + pragma Inline (File_Name); + -- Obtain the name of the file where vertex Vertex of library graph G + -- resides. + function In_Elaboration_Order (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (In_Elaboration_Order); - -- Determine whether vertex LGV_Id of library graph G is already in some + -- Determine whether vertex Vertex of library graph G is already in some -- elaboration order. + function Invocation_Graph_Encoding + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) + return Invocation_Graph_Encoding_Kind; + pragma Inline (Invocation_Graph_Encoding); + -- Obtain the encoding format used to capture information related to + -- invocation vertices and edges that reside within vertex Vertex of + -- library graph G. + function Name (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Unit_Name_Type; + Vertex : Library_Graph_Vertex_Id) return Unit_Name_Type; pragma Inline (Name); - -- Obtain the name of the unit which vertex LGV_Id of library graph G + -- Obtain the name of the unit which vertex Vertex of library graph G -- represents. function Pending_Predecessors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Natural; + Vertex : Library_Graph_Vertex_Id) return Natural; pragma Inline (Pending_Predecessors); - -- Obtain the number of pending predecessors vertex LGV_Id of library + -- Obtain the number of pending predecessors vertex Vertex of library -- graph G must wait on until it can be elaborated. procedure Set_Corresponding_Item (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Val : Library_Graph_Vertex_Id); pragma Inline (Set_Corresponding_Item); -- Set the complementary vertex which represents the corresponding - -- spec or body of vertex LGV_Id of library graph G to value Val. + -- spec or body of vertex Vertex of library graph G to value Val. procedure Set_In_Elaboration_Order (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; Val : Boolean := True); pragma Inline (Set_In_Elaboration_Order); - -- Mark vertex LGV_Id of library graph G as included in some elaboration + -- Mark vertex Vertex of library graph G as included in some elaboration -- order depending on value Val. function Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Unit_Id; + Vertex : Library_Graph_Vertex_Id) return Unit_Id; pragma Inline (Unit); - -- Obtain the unit vertex LGV_Id of library graph G represents + -- Obtain the unit vertex Vertex of library graph G represents --------------------- -- Edge attributes -- --------------------- function Kind - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind; + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind; pragma Inline (Kind); - -- Obtain the nature of edge LGE_Id of library graph G + -- Obtain the nature of edge Edge of library graph G function Predecessor - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id; + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id; pragma Inline (Predecessor); - -- Obtain the predecessor vertex of edge LGE_Id of library graph G + -- Obtain the predecessor vertex of edge Edge of library graph G function Successor - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id; + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id; pragma Inline (Successor); - -- Obtain the successor vertex of edge LGE_Id of library graph G + -- Obtain the successor vertex of edge Edge of library graph G -------------------------- -- Component attributes -- @@ -752,30 +913,71 @@ package Bindo.Graphs is -- Obtain the number of pending predecessors component Comp of library -- graph G must wait on until it can be elaborated. + ---------------------- + -- Cycle attributes -- + ---------------------- + + function Invocation_Edge_Count + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Natural; + pragma Inline (Invocation_Edge_Count); + -- Obtain the number of invocation edges in cycle Cycle of library + -- graph G. + + function Kind + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Library_Graph_Cycle_Kind; + pragma Inline (Kind); + -- Obtain the nature of cycle Cycle of library graph G + + function Length + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Natural; + pragma Inline (Length); + -- Obtain the length of cycle Cycle of library graph G + --------------- -- Semantics -- --------------- + function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean; + pragma Inline (Has_Elaborate_All_Cycle); + -- Determine whether library graph G contains a cycle involving pragma + -- Elaborate_All. + + function In_Same_Component + (G : Library_Graph; + Left : Library_Graph_Vertex_Id; + Right : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (In_Same_Component); + -- Determine whether vertices Left and Right of library graph G reside + -- in the same component. + function Is_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Body); - -- Determine whether vertex LGV_Id of library graph G denotes a body + -- Determine whether vertex Vertex of library graph G denotes a body function Is_Body_Of_Spec_With_Elaborate_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Body_Of_Spec_With_Elaborate_Body); - -- Determine whether vertex LGV_Id of library graph G denotes a body + -- Determine whether vertex Vertex of library graph G denotes a body -- with a corresponding spec, and the spec has pragma Elaborate_Body. function Is_Body_With_Spec (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Body_With_Spec); - -- Determine whether vertex LGV_Id of library graph G denotes a body + -- Determine whether vertex Vertex of library graph G denotes a body -- with a corresponding spec. + function Is_Dynamically_Elaborated (G : Library_Graph) return Boolean; + pragma Inline (Is_Dynamically_Elaborated); + -- Determine whether library graph G was created from a set of units + -- where the main library unit was compiled using the dynamic model. + function Is_Elaborable_Component (G : Library_Graph; Comp : Component_Id) return Boolean; @@ -784,76 +986,112 @@ package Bindo.Graphs is function Is_Elaborable_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Elaborable_Vertex); - -- Determine whether vertex LGV_Id of library graph G can be elaborated + -- Determine whether vertex Vertex of library graph G can be elaborated + + function Is_Elaborate_All_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Elaborate_All_Edge); + -- Determine whether edge Edge of library graph G is an edge whose + -- predecessor is subject to pragma Elaborate_All. + + function Is_Elaborate_Body_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Elaborate_Body_Edge); + -- Determine whether edge Edge of library graph G has a successor + -- that is either a spec subject to pragma Elaborate_Body, or a body + -- that completes such a spec. + + function Is_Elaborate_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Elaborate_Edge); + -- Determine whether edge Edge of library graph G is an edge whose + -- predecessor is subject to pragma Elaborate. + + function Is_Forced_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Forced_Edge); + -- Determine whether edge Edge of library graph G is a byproduct of the + -- forced-elaboration-order file. function Is_Internal_Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Internal_Unit); - -- Determine whether vertex LGV_Id of library graph G denotes an + -- Determine whether vertex Vertex of library graph G denotes an -- internal unit. + function Is_Invocation_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Invocation_Edge); + -- Determine whether edge Edge of library graph G came from the + -- traversal of the invocation graph. + function Is_Predefined_Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Predefined_Unit); - -- Determine whether vertex LGV_Id of library graph G denotes a + -- Determine whether vertex Vertex of library graph G denotes a -- predefined unit. function Is_Preelaborated_Unit (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Preelaborated_Unit); - -- Determine whether vertex LGV_Id of library graph G denotes a unit + -- Determine whether vertex Vertex of library graph G denotes a unit -- subjec to pragma Pure or Preelaborable. function Is_Spec (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Spec); - -- Determine whether vertex LGV_Id of library graph G denotes a spec + -- Determine whether vertex Vertex of library graph G denotes a spec function Is_Spec_With_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Spec_With_Body); - -- Determine whether vertex LGV_Id of library graph G denotes a spec + -- Determine whether vertex Vertex of library graph G denotes a spec -- with a corresponding body. function Is_Spec_With_Elaborate_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Spec_With_Elaborate_Body); - -- Determine whether vertex LGV_Id of library graph G denotes a spec + -- Determine whether vertex Vertex of library graph G denotes a spec -- with a corresponding body, and is subject to pragma Elaborate_Body. - function Links_Vertices_In_Same_Component - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) return Boolean; - pragma Inline (Links_Vertices_In_Same_Component); - -- Determine whether edge LGE_Id of library graph G links a predecessor - -- and a successor that reside within the same component. + function Is_With_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_With_Edge); + -- Determine whether edge Edge of library graph G is the result of a + -- with dependency between its successor and predecessor. function Needs_Elaboration (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Boolean; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Needs_Elaboration); - -- Determine whether vertex LGV_Id of library graph G represents a unit + -- Determine whether vertex Vertex of library graph G represents a unit -- that needs to be elaborated. function Proper_Body (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; pragma Inline (Proper_Body); - -- Obtain the body of vertex LGV_Id of library graph G + -- Obtain the body of vertex Vertex of library graph G function Proper_Spec (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id; pragma Inline (Proper_Spec); - -- Obtain the spec of vertex LGV_Id of library graph G + -- Obtain the spec of vertex Vertex of library graph G ---------------- -- Statistics -- @@ -876,15 +1114,19 @@ package Bindo.Graphs is pragma Inline (Number_Of_Components); -- Obtain the total number of components in library graph G + function Number_Of_Cycles (G : Library_Graph) return Natural; + pragma Inline (Number_Of_Cycles); + -- Obtain the total number of cycles in library graph G + function Number_Of_Edges (G : Library_Graph) return Natural; pragma Inline (Number_Of_Edges); -- Obtain the total number of edges in library graph G function Number_Of_Edges_To_Successors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Natural; + Vertex : Library_Graph_Vertex_Id) return Natural; pragma Inline (Number_Of_Edges_To_Successors); - -- Obtain the total number of edges to successors vertex LGV_Id of + -- Obtain the total number of edges to successors vertex Vertex of -- library graph G has. function Number_Of_Vertices (G : Library_Graph) return Natural; @@ -895,6 +1137,27 @@ package Bindo.Graphs is -- Iterators -- --------------- + -- The following type represents an iterator over all cycles of a + -- library graph. + + type All_Cycle_Iterator is private; + + function Has_Next (Iter : All_Cycle_Iterator) return Boolean; + pragma Inline (Has_Next); + -- Determine whether iterator Iter has more cycles to examine + + function Iterate_All_Cycles + (G : Library_Graph) return All_Cycle_Iterator; + pragma Inline (Iterate_All_Cycles); + -- Obtain an iterator over all cycles of library graph G + + procedure Next + (Iter : in out All_Cycle_Iterator; + Cycle : out Library_Graph_Cycle_Id); + pragma Inline (Next); + -- Return the current cycle referenced by iterator Iter and advance to + -- the next available cycle. + -- The following type represents an iterator over all edges of a library -- graph. @@ -909,8 +1172,8 @@ package Bindo.Graphs is -- Obtain an iterator over all edges of library graph G procedure Next - (Iter : in out All_Edge_Iterator; - LGE_Id : out Library_Graph_Edge_Id); + (Iter : in out All_Edge_Iterator; + Edge : out Library_Graph_Edge_Id); pragma Inline (Next); -- Return the current edge referenced by iterator Iter and advance to -- the next available edge. @@ -931,7 +1194,7 @@ package Bindo.Graphs is procedure Next (Iter : in out All_Vertex_Iterator; - LGV_Id : out Library_Graph_Vertex_Id); + Vertex : out Library_Graph_Vertex_Id); pragma Inline (Next); -- Return the current vertex referenced by iterator Iter and advance -- to the next available vertex. @@ -975,11 +1238,34 @@ package Bindo.Graphs is procedure Next (Iter : in out Component_Vertex_Iterator; - LGV_Id : out Library_Graph_Vertex_Id); + Vertex : out Library_Graph_Vertex_Id); pragma Inline (Next); -- Return the current vertex referenced by iterator Iter and advance -- to the next available vertex. + -- The following type represents an iterator over all edges that form a + -- cycle. + + type Edges_Of_Cycle_Iterator is private; + + function Has_Next (Iter : Edges_Of_Cycle_Iterator) return Boolean; + pragma Inline (Has_Next); + -- Determine whether iterator Iter has more edges to examine + + function Iterate_Edges_Of_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Edges_Of_Cycle_Iterator; + pragma Inline (Iterate_Edges_Of_Cycle); + -- Obtain an iterator over all edges that form cycle Cycle of library + -- graph G. + + procedure Next + (Iter : in out Edges_Of_Cycle_Iterator; + Edge : out Library_Graph_Edge_Id); + pragma Inline (Next); + -- Return the current edge referenced by iterator Iter and advance to + -- the next available edge. + -- The following type represents an iterator over all edges that reach -- successors starting from a particular predecessor vertex. @@ -991,14 +1277,14 @@ package Bindo.Graphs is function Iterate_Edges_To_Successors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) return Edges_To_Successors_Iterator; + Vertex : Library_Graph_Vertex_Id) return Edges_To_Successors_Iterator; pragma Inline (Iterate_Components); -- Obtain an iterator over all edges to successors with predecessor - -- vertex LGV_Id of library graph G. + -- vertex Vertex of library graph G. procedure Next - (Iter : in out Edges_To_Successors_Iterator; - LGE_Id : out Library_Graph_Edge_Id); + (Iter : in out Edges_To_Successors_Iterator; + Edge : out Library_Graph_Edge_Id); pragma Inline (Next); -- Return the current edge referenced by iterator Iter and advance to -- the next available edge. @@ -1010,9 +1296,9 @@ package Bindo.Graphs is -------------- procedure Destroy_Library_Graph_Vertex - (LGV_Id : in out Library_Graph_Vertex_Id); + (Vertex : in out Library_Graph_Vertex_Id); pragma Inline (Destroy_Library_Graph_Vertex); - -- Destroy library graph vertex LGV_Id + -- Destroy library graph vertex Vertex -- The following type represents the attributes of a library graph -- vertex. @@ -1054,7 +1340,7 @@ package Bindo.Graphs is pragma Inline (Destroy_Library_Graph_Vertex_Attributes); -- Destroy the contents of attributes Attrs - package VA is new Dynamic_Hash_Tables + package LGV_Tables is new Dynamic_Hash_Tables (Key_Type => Library_Graph_Vertex_Id, Value_Type => Library_Graph_Vertex_Attributes, No_Value => No_Library_Graph_Vertex_Attributes, @@ -1070,11 +1356,6 @@ package Bindo.Graphs is -- Edges -- ----------- - procedure Destroy_Library_Graph_Edge - (LGE_Id : in out Library_Graph_Edge_Id); - pragma Inline (Destroy_Library_Graph_Edge); - -- Destroy library graph edge LGE_Id - -- The following type represents the attributes of a library graph edge type Library_Graph_Edge_Attributes is record @@ -1091,7 +1372,7 @@ package Bindo.Graphs is pragma Inline (Destroy_Library_Graph_Edge_Attributes); -- Destroy the contents of attributes Attrs - package EA is new Dynamic_Hash_Tables + package LGE_Tables is new Dynamic_Hash_Tables (Key_Type => Library_Graph_Edge_Id, Value_Type => Library_Graph_Edge_Attributes, No_Value => No_Library_Graph_Edge_Attributes, @@ -1123,7 +1404,7 @@ package Bindo.Graphs is pragma Inline (Destroy_Component_Attributes); -- Destroy the contents of attributes Attrs - package CA is new Dynamic_Hash_Tables + package Component_Tables is new Dynamic_Hash_Tables (Key_Type => Component_Id, Value_Type => Component_Attributes, No_Value => No_Component_Attributes, @@ -1135,9 +1416,69 @@ package Bindo.Graphs is Destroy_Value => Destroy_Component_Attributes, Hash => Hash_Component); - --------------- - -- Relations -- - --------------- + ------------ + -- Cycles -- + ------------ + + -- The following type represents the attributes of a cycle + + type Library_Graph_Cycle_Attributes is record + Invocation_Edge_Count : Natural := 0; + -- The number of invocation edges within the cycle + + Kind : Library_Graph_Cycle_Kind := No_Cycle_Kind; + -- The nature of the cycle + + Path : LGE_Lists.Doubly_Linked_List := LGE_Lists.Nil; + -- The path of edges that form the cycle + end record; + + No_Library_Graph_Cycle_Attributes : + constant Library_Graph_Cycle_Attributes := + (Invocation_Edge_Count => 0, + Kind => No_Cycle_Kind, + Path => LGE_Lists.Nil); + + procedure Destroy_Library_Graph_Cycle_Attributes + (Attrs : in out Library_Graph_Cycle_Attributes); + pragma Inline (Destroy_Library_Graph_Cycle_Attributes); + -- Destroy the contents of attributes Attrs + + function Hash_Library_Graph_Cycle_Attributes + (Attrs : Library_Graph_Cycle_Attributes) return Bucket_Range_Type; + pragma Inline (Hash_Library_Graph_Cycle_Attributes); + -- Obtain the hash of key Attrs + + function Same_Library_Graph_Cycle_Attributes + (Left : Library_Graph_Cycle_Attributes; + Right : Library_Graph_Cycle_Attributes) return Boolean; + pragma Inline (Same_Library_Graph_Cycle_Attributes); + -- Determine whether cycle attributes Left and Right are the same + + package LGC_Tables is new Dynamic_Hash_Tables + (Key_Type => Library_Graph_Cycle_Id, + Value_Type => Library_Graph_Cycle_Attributes, + No_Value => No_Library_Graph_Cycle_Attributes, + Expansion_Threshold => 1.5, + Expansion_Factor => 2, + Compression_Threshold => 0.3, + Compression_Factor => 2, + "=" => "=", + Destroy_Value => Destroy_Library_Graph_Cycle_Attributes, + Hash => Hash_Library_Graph_Cycle); + + --------------------- + -- Recorded cycles -- + --------------------- + + package RC_Sets is new Membership_Sets + (Element_Type => Library_Graph_Cycle_Attributes, + "=" => Same_Library_Graph_Cycle_Attributes, + Hash => Hash_Library_Graph_Cycle_Attributes); + + -------------------- + -- Recorded edges -- + -------------------- -- The following type represents a relation between a predecessor and -- successor vertices. @@ -1160,7 +1501,7 @@ package Bindo.Graphs is pragma Inline (Hash_Predecessor_Successor_Relation); -- Obtain the hash value of key Rel - package PS is new Membership_Sets + package RE_Sets is new Membership_Sets (Element_Type => Predecessor_Successor_Relation, "=" => "=", Hash => Hash_Predecessor_Successor_Relation); @@ -1176,7 +1517,7 @@ package Bindo.Graphs is -- Units -- ----------- - package UV is new Dynamic_Hash_Tables + package Unit_Tables is new Dynamic_Hash_Tables (Key_Type => Unit_Id, Value_Type => Library_Graph_Vertex_Id, No_Value => No_Library_Graph_Vertex, @@ -1205,28 +1546,43 @@ package Bindo.Graphs is -- The following type represents the attributes of a library graph type Library_Graph_Attributes is record - Component_Attributes : CA.Dynamic_Hash_Table := CA.Nil; + Component_Attributes : Component_Tables.Dynamic_Hash_Table := + Component_Tables.Nil; -- The map of component -> component attributes for all components in -- the graph. Counts : Library_Graph_Edge_Counts := (others => 0); -- Edge statistics - Edge_Attributes : EA.Dynamic_Hash_Table := EA.Nil; + Cycle_Attributes : LGC_Tables.Dynamic_Hash_Table := LGC_Tables.Nil; + -- The map of cycle -> cycle attributes for all cycles in the graph + + Cycles : LGC_Lists.Doubly_Linked_List := LGC_Lists.Nil; + -- The list of all cycles in the graph, sorted based on precedence + + Dynamically_Elaborated : Boolean := False; + -- Set when the main library unit was compiled using the dynamic + -- model. + + Edge_Attributes : LGE_Tables.Dynamic_Hash_Table := LGE_Tables.Nil; -- The map of edge -> edge attributes for all edges in the graph Graph : DG.Directed_Graph := DG.Nil; -- The underlying graph describing the relations between edges and -- vertices. - Relations : PS.Membership_Set := PS.Nil; - -- The set of relations between successors and predecessors, used to - -- prevent duplicate edges in the graph. + Recorded_Cycles : RC_Sets.Membership_Set := RC_Sets.Nil; + -- The set of recorded cycles, used to prevent duplicate cycles in + -- the graph. + + Recorded_Edges : RE_Sets.Membership_Set := RE_Sets.Nil; + -- The set of recorded edges, used to prevent duplicate edges in the + -- graph. - Unit_To_Vertex : UV.Dynamic_Hash_Table := UV.Nil; + Unit_To_Vertex : Unit_Tables.Dynamic_Hash_Table := Unit_Tables.Nil; -- The map of unit -> vertex - Vertex_Attributes : VA.Dynamic_Hash_Table := VA.Nil; + Vertex_Attributes : LGV_Tables.Dynamic_Hash_Table := LGV_Tables.Nil; -- The map of vertex -> vertex attributes for all vertices in the -- graph. end record; @@ -1238,10 +1594,12 @@ package Bindo.Graphs is -- Iterators -- --------------- + type All_Cycle_Iterator is new LGC_Lists.Iterator; type All_Edge_Iterator is new DG.All_Edge_Iterator; type All_Vertex_Iterator is new DG.All_Vertex_Iterator; type Component_Iterator is new DG.Component_Iterator; type Component_Vertex_Iterator is new DG.Component_Vertex_Iterator; + type Edges_Of_Cycle_Iterator is new LGE_Lists.Iterator; type Edges_To_Successors_Iterator is new DG.Outgoing_Edge_Iterator; end Library_Graphs; diff --git a/gcc/ada/bindo-units.adb b/gcc/ada/bindo-units.adb index de0afb9..d2501e0 100644 --- a/gcc/ada/bindo-units.adb +++ b/gcc/ada/bindo-units.adb @@ -29,7 +29,7 @@ package body Bindo.Units is -- Signature set -- ------------------- - package SS is new Membership_Sets + package Signature_Sets is new Membership_Sets (Element_Type => Invocation_Signature_Id, "=" => "=", Hash => Hash_Invocation_Signature); @@ -41,11 +41,13 @@ package body Bindo.Units is -- The following set stores all invocation signatures that appear in -- elaborable units. - Elaborable_Constructs : SS.Membership_Set := SS.Nil; + Elaborable_Constructs : Signature_Sets.Membership_Set := Signature_Sets.Nil; -- The following set stores all units the need to be elaborated - Elaborable_Units : US.Membership_Set := US.Nil; + -- Kirchev + + Elaborable_Units : Unit_Sets.Membership_Set := Unit_Sets.Nil; ----------------------- -- Local subprograms -- @@ -139,14 +141,27 @@ package body Bindo.Units is return Corresponding_Unit (Name_Id (UNam)); end Corresponding_Unit; + --------------- + -- File_Name -- + --------------- + + function File_Name (U_Id : Unit_Id) return File_Name_Type is + pragma Assert (Present (U_Id)); + + U_Rec : Unit_Record renames ALI.Units.Table (U_Id); + + begin + return U_Rec.Sfile; + end File_Name; + -------------------- -- Finalize_Units -- -------------------- procedure Finalize_Units is begin - SS.Destroy (Elaborable_Constructs); - US.Destroy (Elaborable_Units); + Signature_Sets.Destroy (Elaborable_Constructs); + Unit_Sets.Destroy (Elaborable_Units); end Finalize_Units; ------------------------------ @@ -183,7 +198,7 @@ package body Bindo.Units is function Has_Next (Iter : Elaborable_Units_Iterator) return Boolean is begin - return US.Has_Next (US.Iterator (Iter)); + return Unit_Sets.Has_Next (Unit_Sets.Iterator (Iter)); end Has_Next; ------------------------------- @@ -216,11 +231,26 @@ package body Bindo.Units is procedure Initialize_Units is begin - Elaborable_Constructs := SS.Create (Number_Of_Units); - Elaborable_Units := US.Create (Number_Of_Units); + Elaborable_Constructs := Signature_Sets.Create (Number_Of_Units); + Elaborable_Units := Unit_Sets.Create (Number_Of_Units); end Initialize_Units; ------------------------------- + -- Invocation_Graph_Encoding -- + ------------------------------- + + function Invocation_Graph_Encoding + (U_Id : Unit_Id) return Invocation_Graph_Encoding_Kind + is + pragma Assert (Present (U_Id)); + + U_Rec : Unit_Record renames ALI.Units.Table (U_Id); + + begin + return U_Rec.Invocation_Graph_Encoding; + end Invocation_Graph_Encoding; + + ------------------------------- -- Is_Dynamically_Elaborated -- ------------------------------- @@ -278,7 +308,7 @@ package body Bindo.Units is function Iterate_Elaborable_Units return Elaborable_Units_Iterator is begin - return Elaborable_Units_Iterator (US.Iterate (Elaborable_Units)); + return Elaborable_Units_Iterator (Unit_Sets.Iterate (Elaborable_Units)); end Iterate_Elaborable_Units; ---------- @@ -304,7 +334,7 @@ package body Bindo.Units is begin pragma Assert (Present (IS_Id)); - return SS.Contains (Elaborable_Constructs, IS_Id); + return Signature_Sets.Contains (Elaborable_Constructs, IS_Id); end Needs_Elaboration; ----------------------- @@ -315,7 +345,7 @@ package body Bindo.Units is begin pragma Assert (Present (U_Id)); - return US.Contains (Elaborable_Units, U_Id); + return Unit_Sets.Contains (Elaborable_Units, U_Id); end Needs_Elaboration; ---------- @@ -327,7 +357,7 @@ package body Bindo.Units is U_Id : out Unit_Id) is begin - US.Next (US.Iterator (Iter), U_Id); + Unit_Sets.Next (Unit_Sets.Iterator (Iter), U_Id); end Next; -------------------------------- @@ -336,7 +366,7 @@ package body Bindo.Units is function Number_Of_Elaborable_Units return Natural is begin - return US.Size (Elaborable_Units); + return Unit_Sets.Size (Elaborable_Units); end Number_Of_Elaborable_Units; --------------------- @@ -355,14 +385,12 @@ package body Bindo.Units is procedure Process_Invocation_Construct (IC_Id : Invocation_Construct_Id) is pragma Assert (Present (IC_Id)); - IC_Rec : Invocation_Construct_Record renames - Invocation_Constructs.Table (IC_Id); - IC_Sig : constant Invocation_Signature_Id := IC_Rec.Signature; + IS_Id : constant Invocation_Signature_Id := Signature (IC_Id); - pragma Assert (Present (IC_Sig)); + pragma Assert (Present (IS_Id)); begin - SS.Insert (Elaborable_Constructs, IC_Sig); + Signature_Sets.Insert (Elaborable_Constructs, IS_Id); end Process_Invocation_Construct; ----------------------------------- @@ -402,7 +430,7 @@ package body Bindo.Units is -- signatures of constructs it declares. else - US.Insert (Elaborable_Units, U_Id); + Unit_Sets.Insert (Elaborable_Units, U_Id); Process_Invocation_Constructs (U_Id); end if; end Process_Unit; diff --git a/gcc/ada/bindo-units.ads b/gcc/ada/bindo-units.ads index 93caadf..3749393 100644 --- a/gcc/ada/bindo-units.ads +++ b/gcc/ada/bindo-units.ads @@ -33,6 +33,19 @@ with GNAT.Sets; use GNAT.Sets; package Bindo.Units is + --------------- + -- Unit sets -- + --------------- + + function Hash_Unit (U_Id : Unit_Id) return Bucket_Range_Type; + pragma Inline (Hash_Unit); + -- Obtain the hash value of key U_Id + + package Unit_Sets is new Membership_Sets + (Element_Type => Unit_Id, + "=" => "=", + Hash => Hash_Unit); + procedure Collect_Elaborable_Units; pragma Inline (Collect_Elaborable_Units); -- Gather all units in the bind that require elaboration. The units are @@ -54,6 +67,10 @@ package Bindo.Units is pragma Inline (Corresponding_Unit); -- Obtain the unit which corresponds to name FNam + function File_Name (U_Id : Unit_Id) return File_Name_Type; + pragma Inline (File_Name); + -- Obtain the file name of unit U_Id + type Unit_Processor_Ptr is access procedure (U_Id : Unit_Id); procedure For_Each_Elaborable_Unit (Processor : Unit_Processor_Ptr); @@ -69,9 +86,11 @@ package Bindo.Units is pragma Inline (Hash_Invocation_Signature); -- Obtain the hash value of key IS_Id - function Hash_Unit (U_Id : Unit_Id) return Bucket_Range_Type; - pragma Inline (Hash_Unit); - -- Obtain the hash value of key U_Id + function Invocation_Graph_Encoding + (U_Id : Unit_Id) return Invocation_Graph_Encoding_Kind; + pragma Inline (Invocation_Graph_Encoding); + -- Obtain the encoding format used to capture invocation constructs and + -- relations in the ALI file of unit U_Id. function Is_Dynamically_Elaborated (U_Id : Unit_Id) return Boolean; pragma Inline (Is_Dynamically_Elaborated); @@ -144,11 +163,6 @@ package Bindo.Units is -- Initialize the internal structures of this unit private - package US is new Membership_Sets - (Element_Type => Unit_Id, - "=" => "=", - Hash => Hash_Unit); - - type Elaborable_Units_Iterator is new US.Iterator; + type Elaborable_Units_Iterator is new Unit_Sets.Iterator; end Bindo.Units; diff --git a/gcc/ada/bindo-validators.adb b/gcc/ada/bindo-validators.adb index 54d2fc6..aed4960 100644 --- a/gcc/ada/bindo-validators.adb +++ b/gcc/ada/bindo-validators.adb @@ -29,22 +29,183 @@ with Types; use Types; with Bindo.Units; use Bindo.Units; -with GNAT; use GNAT; -with GNAT.Sets; use GNAT.Sets; - package body Bindo.Validators is + ----------------------- + -- Local subprograms -- + ----------------------- + + procedure Write_Error + (Msg : String; + Flag : out Boolean); + pragma Inline (Write_Error); + -- Write error message Msg to standard output and set flag Flag to True + + ---------------------- + -- Cycle_Validators -- + ---------------------- + + package body Cycle_Validators is + Has_Invalid_Cycle : Boolean := False; + -- Flag set when the library graph contains an invalid cycle + + ----------------------- + -- Local subprograms -- + ----------------------- + + procedure Validate_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Validate_Cycle); + -- Ensure that a cycle meets the following requirements: + -- + -- * Is of proper kind + -- * Has enough edges to form a circuit + -- * No edge is repeated + + procedure Validate_Cycle_Path + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Validate_Cycle_Path); + -- Ensure that the path of a cycle meets the following requirements: + -- + -- * No edge is repeated + + -------------------- + -- Validate_Cycle -- + -------------------- + + procedure Validate_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + Msg : constant String := "Validate_Cycle"; + + begin + pragma Assert (Present (G)); + + if not Present (Cycle) then + Write_Error (Msg, Has_Invalid_Cycle); + + Write_Str (" empty cycle"); + Write_Eol; + Write_Eol; + return; + end if; + + if Kind (G, Cycle) = No_Cycle_Kind then + Write_Error (Msg, Has_Invalid_Cycle); + + Write_Str (" cycle (LGC_Id_"); + Write_Int (Int (Cycle)); + Write_Str (") is a No_Cycle"); + Write_Eol; + Write_Eol; + end if; + + -- A cycle requires at least one edge (self cycle) to form a circuit + + if Length (G, Cycle) < 1 then + Write_Error (Msg, Has_Invalid_Cycle); + + Write_Str (" cycle (LGC_Id_"); + Write_Int (Int (Cycle)); + Write_Str (") does not contain enough edges"); + Write_Eol; + Write_Eol; + end if; + + Validate_Cycle_Path (G, Cycle); + end Validate_Cycle; + + ------------------------- + -- Validate_Cycle_Path -- + ------------------------- + + procedure Validate_Cycle_Path + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + Msg : constant String := "Validate_Cycle_Path"; + + Edge : Library_Graph_Edge_Id; + Edges : LGE_Sets.Membership_Set; + Iter : Edges_Of_Cycle_Iterator; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- Use a set to detect duplicate edges while traversing the cycle + + Edges := LGE_Sets.Create (Length (G, Cycle)); + + -- Inspect the edges of the cucle, trying to catch duplicates + + Iter := Iterate_Edges_Of_Cycle (G, Cycle); + while Has_Next (Iter) loop + Next (Iter, Edge); + + -- The current edge has already been encountered while traversing + -- the cycle. This indicates that the cycle is malformed as edges + -- are not repeated in the circuit. + + if LGE_Sets.Contains (Edges, Edge) then + Write_Error (Msg, Has_Invalid_Cycle); + + Write_Str (" library graph edge (LGE_Id_"); + Write_Int (Int (Edge)); + Write_Str (") is repeaded in cycle (LGC_Id_"); + Write_Int (Int (Cycle)); + Write_Str (")"); + Write_Eol; + + -- Otherwise add the current edge to the set of encountered edges + + else + LGE_Sets.Insert (Edges, Edge); + end if; + end loop; + + LGE_Sets.Destroy (Edges); + end Validate_Cycle_Path; + + --------------------- + -- Validate_Cycles -- + --------------------- + + procedure Validate_Cycles (G : Library_Graph) is + Cycle : Library_Graph_Cycle_Id; + Iter : All_Cycle_Iterator; + + begin + pragma Assert (Present (G)); + + -- Nothing to do when switch -d_V (validate bindo cycles, graphs, and + -- order) is not in effect. + + if not Debug_Flag_Underscore_VV then + return; + end if; + + Iter := Iterate_All_Cycles (G); + while Has_Next (Iter) loop + Next (Iter, Cycle); + + Validate_Cycle (G, Cycle); + end loop; + + if Has_Invalid_Cycle then + raise Invalid_Cycle; + end if; + end Validate_Cycles; + end Cycle_Validators; + ---------------------------------- -- Elaboration_Order_Validators -- ---------------------------------- package body Elaboration_Order_Validators is - package US is new Membership_Sets - (Element_Type => Unit_Id, - "=" => "=", - Hash => Hash_Unit); - use US; - Has_Invalid_Data : Boolean := False; -- Flag set when the elaboration order contains invalid data @@ -52,7 +213,7 @@ package body Bindo.Validators is -- Local subprograms -- ----------------------- - function Build_Elaborable_Unit_Set return Membership_Set; + function Build_Elaborable_Unit_Set return Unit_Sets.Membership_Set; pragma Inline (Build_Elaborable_Unit_Set); -- Create a set from all units that need to be elaborated @@ -61,7 +222,7 @@ package body Bindo.Validators is -- Emit an error concerning unit U_Id that must be elaborated, but was -- not. - procedure Report_Missing_Elaborations (Set : Membership_Set); + procedure Report_Missing_Elaborations (Set : Unit_Sets.Membership_Set); pragma Inline (Report_Missing_Elaborations); -- Emit errors on all units in set Set that must be elaborated, but were -- not. @@ -70,7 +231,9 @@ package body Bindo.Validators is pragma Inline (Report_Spurious_Elaboration); -- Emit an error concerning unit U_Id that is incorrectly elaborated - procedure Validate_Unit (U_Id : Unit_Id; Elab_Set : Membership_Set); + procedure Validate_Unit + (U_Id : Unit_Id; + Elab_Set : Unit_Sets.Membership_Set); pragma Inline (Validate_Unit); -- Validate the elaboration status of unit U_Id. Elab_Set is the set of -- all units that need to be elaborated. @@ -79,28 +242,22 @@ package body Bindo.Validators is pragma Inline (Validate_Units); -- Validate all units in elaboration order Order - procedure Write_Error (Msg : String); - pragma Inline (Write_Error); - -- Write error message Msg to standard output and signal that the - -- elaboration order is incorrect. - ------------------------------- -- Build_Elaborable_Unit_Set -- ------------------------------- - function Build_Elaborable_Unit_Set return Membership_Set is + function Build_Elaborable_Unit_Set return Unit_Sets.Membership_Set is Iter : Elaborable_Units_Iterator; - Set : Membership_Set; + Set : Unit_Sets.Membership_Set; U_Id : Unit_Id; begin - Set := Create (Number_Of_Elaborable_Units); + Set := Unit_Sets.Create (Number_Of_Elaborable_Units); Iter := Iterate_Elaborable_Units; while Has_Next (Iter) loop Next (Iter, U_Id); - pragma Assert (Present (U_Id)); - Insert (Set, U_Id); + Unit_Sets.Insert (Set, U_Id); end loop; return Set; @@ -115,7 +272,7 @@ package body Bindo.Validators is begin pragma Assert (Present (U_Id)); - Write_Error (Msg); + Write_Error (Msg, Has_Invalid_Data); Write_Str ("unit (U_Id_"); Write_Int (Int (U_Id)); @@ -129,15 +286,14 @@ package body Bindo.Validators is -- Report_Missing_Elaborations -- --------------------------------- - procedure Report_Missing_Elaborations (Set : Membership_Set) is - Iter : Iterator; + procedure Report_Missing_Elaborations (Set : Unit_Sets.Membership_Set) is + Iter : Unit_Sets.Iterator; U_Id : Unit_Id; begin - Iter := Iterate (Set); - while Has_Next (Iter) loop - Next (Iter, U_Id); - pragma Assert (Present (U_Id)); + Iter := Unit_Sets.Iterate (Set); + while Unit_Sets.Has_Next (Iter) loop + Unit_Sets.Next (Iter, U_Id); Report_Missing_Elaboration (U_Id); end loop; @@ -152,7 +308,7 @@ package body Bindo.Validators is begin pragma Assert (Present (U_Id)); - Write_Error (Msg); + Write_Error (Msg, Has_Invalid_Data); Write_Str ("unit (U_Id_"); Write_Int (Int (U_Id)); @@ -167,8 +323,8 @@ package body Bindo.Validators is procedure Validate_Elaboration_Order (Order : Unit_Id_Table) is begin - -- Nothing to do when switch -d_V (validate bindo graphs and order) - -- is not in effect. + -- Nothing to do when switch -d_V (validate bindo cycles, graphs, and + -- order) is not in effect. if not Debug_Flag_Underscore_VV then return; @@ -185,15 +341,18 @@ package body Bindo.Validators is -- Validate_Unit -- ------------------- - procedure Validate_Unit (U_Id : Unit_Id; Elab_Set : Membership_Set) is + procedure Validate_Unit + (U_Id : Unit_Id; + Elab_Set : Unit_Sets.Membership_Set) + is begin pragma Assert (Present (U_Id)); -- The current unit in the elaboration order appears within the set -- of units that require elaboration. Remove it from the set. - if Contains (Elab_Set, U_Id) then - Delete (Elab_Set, U_Id); + if Unit_Sets.Contains (Elab_Set, U_Id) then + Unit_Sets.Delete (Elab_Set, U_Id); -- Otherwise the current unit in the elaboration order must not be -- elaborated. @@ -208,7 +367,7 @@ package body Bindo.Validators is -------------------- procedure Validate_Units (Order : Unit_Id_Table) is - Elab_Set : Membership_Set; + Elab_Set : Unit_Sets.Membership_Set; begin -- Collect all units in the compilation that need to be elaborated @@ -230,21 +389,8 @@ package body Bindo.Validators is -- their elaboration. Report_Missing_Elaborations (Elab_Set); - Destroy (Elab_Set); + Unit_Sets.Destroy (Elab_Set); end Validate_Units; - - ----------------- - -- Write_Error -- - ----------------- - - procedure Write_Error (Msg : String) is - begin - Has_Invalid_Data := True; - - Write_Str ("ERROR: "); - Write_Str (Msg); - Write_Eol; - end Write_Error; end Elaboration_Order_Validators; --------------------------------- @@ -260,10 +406,10 @@ package body Bindo.Validators is ----------------------- procedure Validate_Invocation_Graph_Edge - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id); + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id); pragma Inline (Validate_Invocation_Graph_Edge); - -- Verify that the attributes of edge IGE_Id of invocation graph G are + -- Verify that the attributes of edge Edge of invocation graph G are -- properly set. procedure Validate_Invocation_Graph_Edges (G : Invocation_Graph); @@ -273,9 +419,9 @@ package body Bindo.Validators is procedure Validate_Invocation_Graph_Vertex (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id); + Vertex : Invocation_Graph_Vertex_Id); pragma Inline (Validate_Invocation_Graph_Vertex); - -- Verify that the attributes of vertex IGV_Id of inbocation graph G are + -- Verify that the attributes of vertex Vertex of inbocation graph G are -- properly set. procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph); @@ -283,11 +429,6 @@ package body Bindo.Validators is -- Verify that the attributes of all vertices of invocation graph G are -- properly set. - procedure Write_Error (Msg : String); - pragma Inline (Write_Error); - -- Write error message Msg to standard output and signal that the - -- invocation graph is incorrect. - ------------------------------- -- Validate_Invocation_Graph -- ------------------------------- @@ -296,8 +437,8 @@ package body Bindo.Validators is begin pragma Assert (Present (G)); - -- Nothing to do when switch -d_V (validate bindo graphs and order) - -- is not in effect. + -- Nothing to do when switch -d_V (validate bindo cycles, graphs, and + -- order) is not in effect. if not Debug_Flag_Underscore_VV then return; @@ -316,16 +457,16 @@ package body Bindo.Validators is ------------------------------------ procedure Validate_Invocation_Graph_Edge - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) is Msg : constant String := "Validate_Invocation_Graph_Edge"; begin pragma Assert (Present (G)); - if not Present (IGE_Id) then - Write_Error (Msg); + if not Present (Edge) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" emply invocation graph edge"); Write_Eol; @@ -333,21 +474,21 @@ package body Bindo.Validators is return; end if; - if not Present (Relation (G, IGE_Id)) then - Write_Error (Msg); + if not Present (Relation (G, Edge)) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" invocation graph edge (IGE_Id_"); - Write_Int (Int (IGE_Id)); + Write_Int (Int (Edge)); Write_Str (") lacks Relation"); Write_Eol; Write_Eol; end if; - if not Present (Target (G, IGE_Id)) then - Write_Error (Msg); + if not Present (Target (G, Edge)) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" invocation graph edge (IGE_Id_"); - Write_Int (Int (IGE_Id)); + Write_Int (Int (Edge)); Write_Str (") lacks Target"); Write_Eol; Write_Eol; @@ -359,17 +500,17 @@ package body Bindo.Validators is ------------------------------------- procedure Validate_Invocation_Graph_Edges (G : Invocation_Graph) is - IGE_Id : Invocation_Graph_Edge_Id; - Iter : Invocation_Graphs.All_Edge_Iterator; + Edge : Invocation_Graph_Edge_Id; + Iter : Invocation_Graphs.All_Edge_Iterator; begin pragma Assert (Present (G)); Iter := Iterate_All_Edges (G); while Has_Next (Iter) loop - Next (Iter, IGE_Id); + Next (Iter, Edge); - Validate_Invocation_Graph_Edge (G, IGE_Id); + Validate_Invocation_Graph_Edge (G, Edge); end loop; end Validate_Invocation_Graph_Edges; @@ -379,15 +520,15 @@ package body Bindo.Validators is procedure Validate_Invocation_Graph_Vertex (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) + Vertex : Invocation_Graph_Vertex_Id) is Msg : constant String := "Validate_Invocation_Graph_Vertex"; begin pragma Assert (Present (G)); - if not Present (IGV_Id) then - Write_Error (Msg); + if not Present (Vertex) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" emply invocation graph vertex"); Write_Eol; @@ -395,22 +536,32 @@ package body Bindo.Validators is return; end if; - if not Present (Construct (G, IGV_Id)) then - Write_Error (Msg); + if not Present (Body_Vertex (G, Vertex)) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" invocation graph vertex (IGV_Id_"); - Write_Int (Int (IGV_Id)); + Write_Int (Int (Vertex)); + Write_Str (") lacks Body_Vertex"); + Write_Eol; + Write_Eol; + end if; + + if not Present (Construct (G, Vertex)) then + Write_Error (Msg, Has_Invalid_Data); + + Write_Str (" invocation graph vertex (IGV_Id_"); + Write_Int (Int (Vertex)); Write_Str (") lacks Construct"); Write_Eol; Write_Eol; end if; - if not Present (Lib_Vertex (G, IGV_Id)) then - Write_Error (Msg); + if not Present (Spec_Vertex (G, Vertex)) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" invocation graph vertex (IGV_Id_"); - Write_Int (Int (IGV_Id)); - Write_Str (") lacks Lib_Vertex"); + Write_Int (Int (Vertex)); + Write_Str (") lacks Spec_Vertex"); Write_Eol; Write_Eol; end if; @@ -421,32 +572,19 @@ package body Bindo.Validators is ---------------------------------------- procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph) is - IGV_Id : Invocation_Graph_Vertex_Id; Iter : Invocation_Graphs.All_Vertex_Iterator; + Vertex : Invocation_Graph_Vertex_Id; begin pragma Assert (Present (G)); Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop - Next (Iter, IGV_Id); + Next (Iter, Vertex); - Validate_Invocation_Graph_Vertex (G, IGV_Id); + Validate_Invocation_Graph_Vertex (G, Vertex); end loop; end Validate_Invocation_Graph_Vertices; - - ----------------- - -- Write_Error -- - ----------------- - - procedure Write_Error (Msg : String) is - begin - Has_Invalid_Data := True; - - Write_Str ("ERROR: "); - Write_Str (Msg); - Write_Eol; - end Write_Error; end Invocation_Graph_Validators; ------------------------------ @@ -462,10 +600,10 @@ package body Bindo.Validators is ----------------------- procedure Validate_Library_Graph_Edge - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id); + (G : Library_Graph; + Edge : Library_Graph_Edge_Id); pragma Inline (Validate_Library_Graph_Edge); - -- Verify that the attributes of edge LGE_Id of library graph G are + -- Verify that the attributes of edge Edge of library graph G are -- properly set. procedure Validate_Library_Graph_Edges (G : Library_Graph); @@ -475,9 +613,9 @@ package body Bindo.Validators is procedure Validate_Library_Graph_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id); pragma Inline (Validate_Library_Graph_Vertex); - -- Verify that the attributes of vertex LGV_Id of library graph G are + -- Verify that the attributes of vertex Vertex of library graph G are -- properly set. procedure Validate_Library_Graph_Vertices (G : Library_Graph); @@ -485,11 +623,6 @@ package body Bindo.Validators is -- Verify that the attributes of all vertices of library graph G are -- properly set. - procedure Write_Error (Msg : String); - pragma Inline (Write_Error); - -- Write error message Msg to standard output and signal that the - -- library graph is incorrect. - ---------------------------- -- Validate_Library_Graph -- ---------------------------- @@ -498,8 +631,8 @@ package body Bindo.Validators is begin pragma Assert (Present (G)); - -- Nothing to do when switch -d_V (validate bindo graphs and order) - -- is not in effect. + -- Nothing to do when switch -d_V (validate bindo cycles, graphs, and + -- order) is not in effect. if not Debug_Flag_Underscore_VV then return; @@ -518,16 +651,16 @@ package body Bindo.Validators is --------------------------------- procedure Validate_Library_Graph_Edge - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) is Msg : constant String := "Validate_Library_Graph_Edge"; begin pragma Assert (Present (G)); - if not Present (LGE_Id) then - Write_Error (Msg); + if not Present (Edge) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" emply library graph edge"); Write_Eol; @@ -535,40 +668,40 @@ package body Bindo.Validators is return; end if; - if Kind (G, LGE_Id) = No_Edge then - Write_Error (Msg); + if Kind (G, Edge) = No_Edge then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" library graph edge (LGE_Id_"); - Write_Int (Int (LGE_Id)); + Write_Int (Int (Edge)); Write_Str (") is not a valid edge"); Write_Eol; Write_Eol; - elsif Kind (G, LGE_Id) = Body_Before_Spec_Edge then - Write_Error (Msg); + elsif Kind (G, Edge) = Body_Before_Spec_Edge then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" library graph edge (LGE_Id_"); - Write_Int (Int (LGE_Id)); + Write_Int (Int (Edge)); Write_Str (") is a Body_Before_Spec edge"); Write_Eol; Write_Eol; end if; - if not Present (Predecessor (G, LGE_Id)) then - Write_Error (Msg); + if not Present (Predecessor (G, Edge)) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" library graph edge (LGE_Id_"); - Write_Int (Int (LGE_Id)); + Write_Int (Int (Edge)); Write_Str (") lacks Predecessor"); Write_Eol; Write_Eol; end if; - if not Present (Successor (G, LGE_Id)) then - Write_Error (Msg); + if not Present (Successor (G, Edge)) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" library graph edge (LGE_Id_"); - Write_Int (Int (LGE_Id)); + Write_Int (Int (Edge)); Write_Str (") lacks Successor"); Write_Eol; Write_Eol; @@ -580,18 +713,17 @@ package body Bindo.Validators is ---------------------------------- procedure Validate_Library_Graph_Edges (G : Library_Graph) is - Iter : Library_Graphs.All_Edge_Iterator; - LGE_Id : Library_Graph_Edge_Id; + Edge : Library_Graph_Edge_Id; + Iter : Library_Graphs.All_Edge_Iterator; begin pragma Assert (Present (G)); Iter := Iterate_All_Edges (G); while Has_Next (Iter) loop - Next (Iter, LGE_Id); - pragma Assert (Present (LGE_Id)); + Next (Iter, Edge); - Validate_Library_Graph_Edge (G, LGE_Id); + Validate_Library_Graph_Edge (G, Edge); end loop; end Validate_Library_Graph_Edges; @@ -601,15 +733,15 @@ package body Bindo.Validators is procedure Validate_Library_Graph_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) is Msg : constant String := "Validate_Library_Graph_Vertex"; begin pragma Assert (Present (G)); - if not Present (LGV_Id) then - Write_Error (Msg); + if not Present (Vertex) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" empty library graph vertex"); Write_Eol; @@ -617,25 +749,25 @@ package body Bindo.Validators is return; end if; - if (Is_Body_With_Spec (G, LGV_Id) + if (Is_Body_With_Spec (G, Vertex) or else - Is_Spec_With_Body (G, LGV_Id)) - and then not Present (Corresponding_Item (G, LGV_Id)) + Is_Spec_With_Body (G, Vertex)) + and then not Present (Corresponding_Item (G, Vertex)) then - Write_Error (Msg); + Write_Error (Msg, Has_Invalid_Data); Write_Str (" library graph vertex (LGV_Id_"); - Write_Int (Int (LGV_Id)); + Write_Int (Int (Vertex)); Write_Str (") lacks Corresponding_Item"); Write_Eol; Write_Eol; end if; - if not Present (Unit (G, LGV_Id)) then - Write_Error (Msg); + if not Present (Unit (G, Vertex)) then + Write_Error (Msg, Has_Invalid_Data); Write_Str (" library graph vertex (LGV_Id_"); - Write_Int (Int (LGV_Id)); + Write_Int (Int (Vertex)); Write_Str (") lacks Unit"); Write_Eol; Write_Eol; @@ -648,32 +780,34 @@ package body Bindo.Validators is procedure Validate_Library_Graph_Vertices (G : Library_Graph) is Iter : Library_Graphs.All_Vertex_Iterator; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop - Next (Iter, LGV_Id); - pragma Assert (Present (LGV_Id)); + Next (Iter, Vertex); - Validate_Library_Graph_Vertex (G, LGV_Id); + Validate_Library_Graph_Vertex (G, Vertex); end loop; end Validate_Library_Graph_Vertices; - - ----------------- - -- Write_Error -- - ----------------- - - procedure Write_Error (Msg : String) is - begin - Has_Invalid_Data := True; - - Write_Str ("ERROR: "); - Write_Str (Msg); - Write_Eol; - end Write_Error; end Library_Graph_Validators; + ----------------- + -- Write_Error -- + ----------------- + + procedure Write_Error + (Msg : String; + Flag : out Boolean) + is + begin + Write_Str ("ERROR: "); + Write_Str (Msg); + Write_Eol; + + Flag := True; + end Write_Error; + end Bindo.Validators; diff --git a/gcc/ada/bindo-validators.ads b/gcc/ada/bindo-validators.ads index 39fccc6..d70447b 100644 --- a/gcc/ada/bindo-validators.ads +++ b/gcc/ada/bindo-validators.ads @@ -35,6 +35,26 @@ use Bindo.Graphs.Library_Graphs; package Bindo.Validators is + ---------------------- + -- Cycle_Validators -- + ---------------------- + + package Cycle_Validators is + Invalid_Cycle : exception; + -- Exception raised when the library graph contains an invalid cycle + + procedure Validate_Cycles (G : Library_Graph); + -- Ensure that all cycles of library graph G meet the following + -- requirements: + -- + -- * Are of proper kind + -- * Have enough edges to form a circuit + -- * No edge is repeated + -- + -- Diagnose issues and raise Invalid_Cycle if this is not the case. + + end Cycle_Validators; + ---------------------------------- -- Elaboration_Order_Validators -- ---------------------------------- diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb index 7450c15..067ba1f 100644 --- a/gcc/ada/bindo-writers.adb +++ b/gcc/ada/bindo-writers.adb @@ -28,7 +28,8 @@ with Fname; use Fname; with Opt; use Opt; with Output; use Output; -with Bindo.Units; use Bindo.Units; +with Bindo.Units; +use Bindo.Units; with GNAT; use GNAT; with GNAT.Graphs; use GNAT.Graphs; @@ -124,26 +125,27 @@ package body Bindo.Writers is -------------------------------- procedure Write_Invocation_Construct (IC_Id : Invocation_Construct_Id) is + begin pragma Assert (Present (IC_Id)); - IC_Rec : Invocation_Construct_Record renames - Invocation_Constructs.Table (IC_Id); - - begin Write_Str (" invocation construct (IC_Id_"); Write_Int (Int (IC_Id)); Write_Str (")"); Write_Eol; + Write_Str (" Body_Placement = "); + Write_Str (Body_Placement (IC_Id)'Img); + Write_Eol; + Write_Str (" Kind = "); - Write_Str (IC_Rec.Kind'Img); + Write_Str (Kind (IC_Id)'Img); Write_Eol; - Write_Str (" Placement = "); - Write_Str (IC_Rec.Placement'Img); + Write_Str (" Spec_Placement = "); + Write_Str (Spec_Placement (IC_Id)'Img); Write_Eol; - Write_Invocation_Signature (IC_Rec.Signature); + Write_Invocation_Signature (Signature (IC_Id)); Write_Eol; end Write_Invocation_Construct; @@ -152,20 +154,17 @@ package body Bindo.Writers is ------------------------------- procedure Write_Invocation_Relation (IR_Id : Invocation_Relation_Id) is + begin pragma Assert (Present (IR_Id)); - IR_Rec : Invocation_Relation_Record renames - Invocation_Relations.Table (IR_Id); - - begin Write_Str (" invocation relation (IR_Id_"); Write_Int (Int (IR_Id)); Write_Str (")"); Write_Eol; - if Present (IR_Rec.Extra) then + if Present (Extra (IR_Id)) then Write_Str (" Extra = "); - Write_Name (IR_Rec.Extra); + Write_Name (Extra (IR_Id)); else Write_Str (" Extra = none"); end if; @@ -174,16 +173,16 @@ package body Bindo.Writers is Write_Str (" Invoker"); Write_Eol; - Write_Invocation_Signature (IR_Rec.Invoker); + Write_Invocation_Signature (Invoker (IR_Id)); Write_Str (" Kind = "); - Write_Str (IR_Rec.Kind'Img); + Write_Str (Kind (IR_Id)'Img); Write_Eol; Write_Str (" Target"); Write_Eol; - Write_Invocation_Signature (IR_Rec.Target); + Write_Invocation_Signature (Target (IR_Id)); Write_Eol; end Write_Invocation_Relation; @@ -192,39 +191,36 @@ package body Bindo.Writers is -------------------------------- procedure Write_Invocation_Signature (IS_Id : Invocation_Signature_Id) is + begin pragma Assert (Present (IS_Id)); - IS_Rec : Invocation_Signature_Record renames - Invocation_Signatures.Table (IS_Id); - - begin Write_Str (" Signature (IS_Id_"); Write_Int (Int (IS_Id)); Write_Str (")"); Write_Eol; Write_Str (" Column = "); - Write_Int (Int (IS_Rec.Column)); + Write_Int (Int (Column (IS_Id))); Write_Eol; Write_Str (" Line = "); - Write_Int (Int (IS_Rec.Line)); + Write_Int (Int (Line (IS_Id))); Write_Eol; - if Present (IS_Rec.Locations) then + if Present (Locations (IS_Id)) then Write_Str (" Locations = "); - Write_Name (IS_Rec.Locations); + Write_Name (Locations (IS_Id)); else Write_Str (" Locations = none"); end if; Write_Eol; Write_Str (" Name = "); - Write_Name (IS_Rec.Name); + Write_Name (Name (IS_Id)); Write_Eol; Write_Str (" Scope = "); - Write_Name (IS_Rec.Scope); + Write_Name (Scope (IS_Id)); Write_Eol; end Write_Invocation_Signature; @@ -277,17 +273,8 @@ package body Bindo.Writers is Write_Eol; Write_Eol; - for IC_Id in U_Rec.First_Invocation_Construct .. - U_Rec.Last_Invocation_Construct - loop - Write_Invocation_Construct (IC_Id); - end loop; - - for IR_Id in U_Rec.First_Invocation_Relation .. - U_Rec.Last_Invocation_Relation - loop - Write_Invocation_Relation (IR_Id); - end loop; + For_Each_Invocation_Construct (Write_Invocation_Construct'Access); + For_Each_Invocation_Relation (Write_Invocation_Relation'Access); end Write_Unit; ----------------------- @@ -313,6 +300,131 @@ package body Bindo.Writers is end Write_Unit_Common; end ALI_Writers; + ------------------- + -- Cycle_Writers -- + ------------------- + + package body Cycle_Writers is + + ----------------------- + -- Local subprograms -- + ----------------------- + + procedure Write_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Write_Cycle); + -- Write the path of cycle Cycle found in library graph G to standard + -- output. + + procedure Write_Cyclic_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id); + pragma Inline (Write_Cyclic_Edge); + -- Write cyclic edge Edge of library graph G to standard + + ----------------- + -- Write_Cycle -- + ----------------- + + procedure Write_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + Edge : Library_Graph_Edge_Id; + Iter : Edges_Of_Cycle_Iterator; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- Nothing to do when switch -d_P (output cycle paths) is not in + -- effect. + + if not Debug_Flag_Underscore_PP then + return; + end if; + + Write_Str ("cycle (LGC_Id_"); + Write_Int (Int (Cycle)); + Write_Str (")"); + Write_Eol; + + Iter := Iterate_Edges_Of_Cycle (G, Cycle); + while Has_Next (Iter) loop + Next (Iter, Edge); + + Write_Cyclic_Edge (G, Edge); + end loop; + + Write_Eol; + end Write_Cycle; + + ------------------ + -- Write_Cycles -- + ------------------ + + procedure Write_Cycles (G : Library_Graph) is + Cycle : Library_Graph_Cycle_Id; + Iter : All_Cycle_Iterator; + + begin + pragma Assert (Present (G)); + + Iter := Iterate_All_Cycles (G); + while Has_Next (Iter) loop + Next (Iter, Cycle); + + Write_Cycle (G, Cycle); + end loop; + end Write_Cycles; + + ----------------------- + -- Write_Cyclic_Edge -- + ----------------------- + + procedure Write_Cyclic_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge); + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); + + begin + Indent_By (Nested_Indentation); + Write_Name (Name (G, Succ)); + Write_Str (" --> "); + Write_Name (Name (G, Pred)); + Write_Str (" "); + + if Is_Elaborate_All_Edge (G, Edge) then + Write_Str ("Elaborate_All edge"); + + elsif Is_Elaborate_Body_Edge (G, Edge) then + Write_Str ("Elaborate_Body edge"); + + elsif Is_Elaborate_Edge (G, Edge) then + Write_Str ("Elaborate edge"); + + elsif Is_Forced_Edge (G, Edge) then + Write_Str ("forced edge"); + + elsif Is_Invocation_Edge (G, Edge) then + Write_Str ("invocation edge"); + + else + pragma Assert (Is_With_Edge (G, Edge)); + + Write_Str ("with edge"); + end if; + + Write_Eol; + end Write_Cyclic_Edge; + end Cycle_Writers; + ------------------------------- -- Elaboration_Order_Writers -- ------------------------------- @@ -416,22 +528,23 @@ package body Bindo.Writers is -- Write all elaboration roots of invocation graph G to standard output procedure Write_Invocation_Graph_Edge - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id); + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id); pragma Inline (Write_Invocation_Graph_Edge); - -- Write edge IGE_Id of invocation graph G to standard output + -- Write edge Edge of invocation graph G to standard output procedure Write_Invocation_Graph_Edges (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id); + Vertex : Invocation_Graph_Vertex_Id); pragma Inline (Write_Invocation_Graph_Edges); - -- Write all edges of invocation graph G to standard output + -- Write all edges to targets of vertex Vertex of invocation graph G to + -- standard output. procedure Write_Invocation_Graph_Vertex (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id); + Vertex : Invocation_Graph_Vertex_Id); pragma Inline (Write_Invocation_Graph_Vertex); - -- Write vertex IGV_Id of invocation graph G to standard output + -- Write vertex Vertex of invocation graph G to standard output procedure Write_Invocation_Graph_Vertices (G : Invocation_Graph); pragma Inline (Write_Invocation_Graph_Vertices); @@ -447,14 +560,13 @@ package body Bindo.Writers is ----------- procedure pige - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) - renames Write_Invocation_Graph_Edge; + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) renames Write_Invocation_Graph_Edge; pragma Unreferenced (pige); procedure pigv (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) + Vertex : Invocation_Graph_Vertex_Id) renames Write_Invocation_Graph_Vertex; pragma Unreferenced (pigv); @@ -498,7 +610,6 @@ package body Bindo.Writers is Iter := Iterate_Elaboration_Roots (G); while Has_Next (Iter) loop Next (Iter, Root); - pragma Assert (Present (Root)); Write_Elaboration_Root (G, Root); end loop; @@ -541,24 +652,22 @@ package body Bindo.Writers is --------------------------------- procedure Write_Invocation_Graph_Edge - (G : Invocation_Graph; - IGE_Id : Invocation_Graph_Edge_Id) + (G : Invocation_Graph; + Edge : Invocation_Graph_Edge_Id) is pragma Assert (Present (G)); - pragma Assert (Present (IGE_Id)); - - Targ : constant Invocation_Graph_Vertex_Id := Target (G, IGE_Id); + pragma Assert (Present (Edge)); - pragma Assert (Present (Targ)); + Targ : constant Invocation_Graph_Vertex_Id := Target (G, Edge); begin Write_Str (" invocation graph edge (IGE_Id_"); - Write_Int (Int (IGE_Id)); + Write_Int (Int (Edge)); Write_Str (")"); Write_Eol; Write_Str (" Relation (IR_Id_"); - Write_Int (Int (Relation (G, IGE_Id))); + Write_Int (Int (Relation (G, Edge))); Write_Str (")"); Write_Eol; @@ -577,16 +686,16 @@ package body Bindo.Writers is procedure Write_Invocation_Graph_Edges (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) + Vertex : Invocation_Graph_Vertex_Id) is pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); Num_Of_Edges : constant Natural := - Number_Of_Edges_To_Targets (G, IGV_Id); + Number_Of_Edges_To_Targets (G, Vertex); - IGE_Id : Invocation_Graph_Edge_Id; - Iter : Invocation_Graphs.Edges_To_Targets_Iterator; + Edge : Invocation_Graph_Edge_Id; + Iter : Invocation_Graphs.Edges_To_Targets_Iterator; begin Write_Str (" Edges to targets: "); @@ -594,12 +703,11 @@ package body Bindo.Writers is Write_Eol; if Num_Of_Edges > 0 then - Iter := Iterate_Edges_To_Targets (G, IGV_Id); + Iter := Iterate_Edges_To_Targets (G, Vertex); while Has_Next (Iter) loop - Next (Iter, IGE_Id); - pragma Assert (Present (IGE_Id)); + Next (Iter, Edge); - Write_Invocation_Graph_Edge (G, IGE_Id); + Write_Invocation_Graph_Edge (G, Edge); end loop; else Write_Eol; @@ -612,29 +720,34 @@ package body Bindo.Writers is procedure Write_Invocation_Graph_Vertex (G : Invocation_Graph; - IGV_Id : Invocation_Graph_Vertex_Id) + Vertex : Invocation_Graph_Vertex_Id) is begin pragma Assert (Present (G)); - pragma Assert (Present (IGV_Id)); + pragma Assert (Present (Vertex)); Write_Str ("invocation graph vertex (IGV_Id_"); - Write_Int (Int (IGV_Id)); + Write_Int (Int (Vertex)); Write_Str (") name = "); - Write_Name (Name (G, IGV_Id)); + Write_Name (Name (G, Vertex)); + Write_Eol; + + Write_Str (" Body_Vertex (LGV_Id_"); + Write_Int (Int (Body_Vertex (G, Vertex))); + Write_Str (")"); Write_Eol; Write_Str (" Construct (IC_Id_"); - Write_Int (Int (Construct (G, IGV_Id))); + Write_Int (Int (Construct (G, Vertex))); Write_Str (")"); Write_Eol; - Write_Str (" Lib_Vertex (LGV_Id_"); - Write_Int (Int (Lib_Vertex (G, IGV_Id))); + Write_Str (" Spec_Vertex (LGV_Id_"); + Write_Int (Int (Spec_Vertex (G, Vertex))); Write_Str (")"); Write_Eol; - Write_Invocation_Graph_Edges (G, IGV_Id); + Write_Invocation_Graph_Edges (G, Vertex); end Write_Invocation_Graph_Vertex; ------------------------------------- @@ -642,18 +755,17 @@ package body Bindo.Writers is ------------------------------------- procedure Write_Invocation_Graph_Vertices (G : Invocation_Graph) is - IGV_Id : Invocation_Graph_Vertex_Id; Iter : Invocation_Graphs.All_Vertex_Iterator; + Vertex : Invocation_Graph_Vertex_Id; begin pragma Assert (Present (G)); Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop - Next (Iter, IGV_Id); - pragma Assert (Present (IGV_Id)); + Next (Iter, Vertex); - Write_Invocation_Graph_Vertex (G, IGV_Id); + Write_Invocation_Graph_Vertex (G, Vertex); end loop; end Write_Invocation_Graph_Vertices; @@ -719,22 +831,22 @@ package body Bindo.Writers is procedure Write_Edges_To_Successors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id); pragma Inline (Write_Edges_To_Successors); - -- Write all edges to successors of predecessor LGV_Id of library graph + -- Write all edges to successors of predecessor Vertex of library graph -- G to standard output. procedure Write_Library_Graph_Edge - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id); + (G : Library_Graph; + Edge : Library_Graph_Edge_Id); pragma Inline (Write_Library_Graph_Edge); - -- Write edge LGE_Id of library graph G to standard output + -- Write edge Edge of library graph G to standard output procedure Write_Library_Graph_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id); pragma Inline (Write_Library_Graph_Vertex); - -- Write vertex LGV_Id of library graph G to standard output + -- Write vertex Vertex of library graph G to standard output procedure Write_Library_Graph_Vertices (G : Library_Graph); pragma Inline (Write_Library_Graph_Vertices); @@ -755,13 +867,13 @@ package body Bindo.Writers is pragma Unreferenced (pc); procedure plge - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) renames Write_Library_Graph_Edge; + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) renames Write_Library_Graph_Edge; pragma Unreferenced (plge); procedure plgv (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) renames Write_Library_Graph_Vertex; + Vertex : Library_Graph_Vertex_Id) renames Write_Library_Graph_Vertex; pragma Unreferenced (plgv); --------------------- @@ -797,7 +909,7 @@ package body Bindo.Writers is Comp : Component_Id) is Iter : Component_Vertex_Iterator; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); @@ -805,13 +917,12 @@ package body Bindo.Writers is Iter := Iterate_Component_Vertices (G, Comp); while Has_Next (Iter) loop - Next (Iter, LGV_Id); - pragma Assert (Present (LGV_Id)); + Next (Iter, Vertex); Write_Str (" library graph vertex (LGV_Id_"); - Write_Int (Int (LGV_Id)); + Write_Int (Int (Vertex)); Write_Str (") name = "); - Write_Name (Name (G, LGV_Id)); + Write_Name (Name (G, Vertex)); Write_Eol; end loop; @@ -835,7 +946,6 @@ package body Bindo.Writers is Iter := Iterate_Components (G); while Has_Next (Iter) loop Next (Iter, Comp); - pragma Assert (Present (Comp)); Write_Component (G, Comp); end loop; @@ -850,16 +960,16 @@ package body Bindo.Writers is procedure Write_Edges_To_Successors (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); Num_Of_Edges : constant Natural := - Number_Of_Edges_To_Successors (G, LGV_Id); + Number_Of_Edges_To_Successors (G, Vertex); - Iter : Edges_To_Successors_Iterator; - LGE_Id : Library_Graph_Edge_Id; + Edge : Library_Graph_Edge_Id; + Iter : Edges_To_Successors_Iterator; begin Write_Str (" Edges to successors: "); @@ -867,12 +977,11 @@ package body Bindo.Writers is Write_Eol; if Num_Of_Edges > 0 then - Iter := Iterate_Edges_To_Successors (G, LGV_Id); + Iter := Iterate_Edges_To_Successors (G, Vertex); while Has_Next (Iter) loop - Next (Iter, LGE_Id); - pragma Assert (Present (LGE_Id)); + Next (Iter, Edge); - Write_Library_Graph_Edge (G, LGE_Id); + Write_Library_Graph_Edge (G, Edge); end loop; else Write_Eol; @@ -913,26 +1022,23 @@ package body Bindo.Writers is ------------------------------ procedure Write_Library_Graph_Edge - (G : Library_Graph; - LGE_Id : Library_Graph_Edge_Id) + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) is pragma Assert (Present (G)); - pragma Assert (Present (LGE_Id)); + pragma Assert (Present (Edge)); - Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id); - Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id); - - pragma Assert (Present (Pred)); - pragma Assert (Present (Succ)); + Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge); + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); begin Write_Str (" library graph edge (LGE_Id_"); - Write_Int (Int (LGE_Id)); + Write_Int (Int (Edge)); Write_Str (")"); Write_Eol; Write_Str (" Kind = "); - Write_Str (Kind (G, LGE_Id)'Img); + Write_Str (Kind (G, Edge)'Img); Write_Eol; Write_Str (" Predecessor (LGV_Id_"); @@ -956,22 +1062,20 @@ package body Bindo.Writers is procedure Write_Library_Graph_Vertex (G : Library_Graph; - LGV_Id : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id) is pragma Assert (Present (G)); - pragma Assert (Present (LGV_Id)); + pragma Assert (Present (Vertex)); Item : constant Library_Graph_Vertex_Id := - Corresponding_Item (G, LGV_Id); - U_Id : constant Unit_Id := Unit (G, LGV_Id); - - pragma Assert (Present (U_Id)); + Corresponding_Item (G, Vertex); + U_Id : constant Unit_Id := Unit (G, Vertex); begin Write_Str ("library graph vertex (LGV_Id_"); - Write_Int (Int (LGV_Id)); + Write_Int (Int (Vertex)); Write_Str (") name = "); - Write_Name (Name (G, LGV_Id)); + Write_Name (Name (G, Vertex)); Write_Eol; if Present (Item) then @@ -986,7 +1090,7 @@ package body Bindo.Writers is Write_Eol; Write_Str (" In_Elaboration_Order = "); - if In_Elaboration_Order (G, LGV_Id) then + if In_Elaboration_Order (G, Vertex) then Write_Str ("True"); else Write_Str ("False"); @@ -994,11 +1098,11 @@ package body Bindo.Writers is Write_Eol; Write_Str (" Pending_Predecessors = "); - Write_Int (Int (Pending_Predecessors (G, LGV_Id))); + Write_Int (Int (Pending_Predecessors (G, Vertex))); Write_Eol; Write_Str (" Component (Comp_Id_"); - Write_Int (Int (Component (G, LGV_Id))); + Write_Int (Int (Component (G, Vertex))); Write_Str (")"); Write_Eol; @@ -1008,7 +1112,7 @@ package body Bindo.Writers is Write_Name (Name (U_Id)); Write_Eol; - Write_Edges_To_Successors (G, LGV_Id); + Write_Edges_To_Successors (G, Vertex); end Write_Library_Graph_Vertex; ---------------------------------- @@ -1017,17 +1121,16 @@ package body Bindo.Writers is procedure Write_Library_Graph_Vertices (G : Library_Graph) is Iter : Library_Graphs.All_Vertex_Iterator; - LGV_Id : Library_Graph_Vertex_Id; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop - Next (Iter, LGV_Id); - pragma Assert (Present (LGV_Id)); + Next (Iter, Vertex); - Write_Library_Graph_Vertex (G, LGV_Id); + Write_Library_Graph_Vertex (G, Vertex); end loop; end Write_Library_Graph_Vertices; @@ -1071,11 +1174,11 @@ package body Bindo.Writers is pragma Inline (Hash_File_Name); -- Obtain the hash value of key Nam - package FS is new Membership_Sets + package File_Name_Tables is new Membership_Sets (Element_Type => File_Name_Type, "=" => "=", Hash => Hash_File_Name); - use FS; + use File_Name_Tables; ----------------------- -- Local subprograms -- diff --git a/gcc/ada/bindo-writers.ads b/gcc/ada/bindo-writers.ads index 9ed598e..b791638 100644 --- a/gcc/ada/bindo-writers.ads +++ b/gcc/ada/bindo-writers.ads @@ -81,6 +81,16 @@ package Bindo.Writers is end ALI_Writers; + ------------------- + -- Cycle_Writers -- + ------------------- + + package Cycle_Writers is + procedure Write_Cycles (G : Library_Graph); + -- Write all cycles of library graph G to standard output + + end Cycle_Writers; + ------------------------------- -- Elaboration_Order_Writers -- ------------------------------- diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index 7d26476..039fd0d 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -23,8 +23,11 @@ -- -- ------------------------------------------------------------------------------ +with Binde; +with Debug; use Debug; + with Bindo.Elaborators; -use Bindo.Elaborators.Invocation_And_Library_Graph_Elaborators; +use Bindo.Elaborators; package body Bindo is @@ -47,30 +50,44 @@ package body Bindo is -- - The flow of execution at elaboration time. -- -- - Additional dependencies between units supplied to the binder by - -- means of a file. + -- means of a forced-elaboration-order file. + -- + -- The high-level idea empoyed by the EO mechanism is to construct two + -- graphs and use the information they represent to find an ordering of + -- all units. -- - -- The high-level idea is to construct two graphs: + -- The invocation graph represents the flow of execution at elaboration + -- time. -- - -- - Invocation graph - Models the flow of execution at elaboration - -- time. + -- The library graph captures the dependencies between units expressed + -- by with clause and elaboration-related pragmas. The library graph is + -- further augmented with additional information from the invocation + -- graph by exploring the execution paths from a unit with elaboration + -- code to other external units. -- - -- - Library graph - Represents with clause and pragma dependencies - -- between units. + -- The strongly connected components of the library graph are computed. -- - -- The library graph is further augmented with additional information - -- from the invocation graph by exploring the execution paths from a - -- unit with elaboration code to other external units. All strongly - -- connected components of the library graph are discovered. Finally, - -- the order is obtained via a topological sort-like algorithm which - -- attempts to order available units while enabling other units to be + -- The order is obtained using a topological sort-like algorithm which + -- traverses the library graph and its strongly connected components in + -- an attempt to order available units while enabling other units to be -- ordered. -- -- * Diagnose elaboration circularities between units -- - -- The library graph may contain at least one cycle, in which case no - -- ordering is possible. + -- An elaboration circularity arrises when either + -- + -- - At least one unit cannot be ordered, or + -- + -- - All units can be ordered, but an edge with an Elaborate_All + -- pragma links two vertices within the same component of the + -- library graph. -- - -- ??? more on this later + -- The library graph is traversed to discover, collect, and sort all + -- cycles that hinder the elaboration order. + -- + -- The most important cycle is diagnosed by describing its effects on + -- the elaboration order and listing all units comprising the circuit. + -- Various suggestions on how to break the cycle are offered. ----------------- -- Terminology -- @@ -78,6 +95,8 @@ package body Bindo is -- * Component - A strongly connected component of a graph. -- + -- * Elaboration circularity - A cycle involving units from the bind. + -- -- * Elaboration root - A special invocation construct which denotes the -- elaboration procedure of a unit. -- @@ -162,7 +181,11 @@ package body Bindo is -- | -- +------ | -------------- Diagnostics phase -------------------------+ -- | | | - -- | +--> ??? more on this later | + -- | +--> Find_Cycles | + -- | +--> Validate_Cycles | + -- | +--> Write_Cycles | + -- | | | + -- | +--> Diagnose_Cycle / Diagnose_All_Cycles | -- | | -- +-------------------------------------------------------------------+ @@ -225,7 +248,37 @@ package body Bindo is -- Diagnostics phase -- ----------------------- - -- ??? more on this later + -- The Diagnostics phase has the following objectives: + -- + -- * Discover, save, and sort all cycles in the library graph. The cycles + -- are sorted based on the following heiristics: + -- + -- - A cycle with higher precedence is preferred. + -- + -- - A cycle with fewer invocation edges is preferred. + -- + -- - A cycle with a shorter length is preferred. + -- + -- * Validate the consistency of cycles, only when switch -d_V is in + -- effect. + -- + -- * Write the contents of all cycles in human-readable form to standard + -- output when switch -d_O is in effect. + -- + -- * Diagnose the most important cycle, or all cycles when switch -d_C is + -- in effect. The diagnostic consists of: + -- + -- - The reason for the existance of the cycle, along with the unit + -- whose elaboration cannot be guaranteed. + -- + -- - A detailed traceback of the cycle, showcasing the transition + -- between units, along with any other elaboration order-related + -- information. + -- + -- - A set of suggestions on how to break the cycle considering the + -- the edges coprising the circuit, the elaboration model used to + -- compile the units, the availability of invocation information, + -- and the state of various relevant switches. -------------- -- Switches -- @@ -236,6 +289,11 @@ package body Bindo is -- GNATbind outputs the contents of ALI table Invocation_Constructs -- and Invocation_Edges in textual format to standard output. -- + -- -d_C Diagnose all cycles + -- + -- GNATbind outputs diagnostics for all unique cycles in the bind, + -- rather than just the most important one. + -- -- -d_I Output invocation graph -- -- GNATbind outputs the invocation graph in text format to standard @@ -255,16 +313,20 @@ package body Bindo is -- GNATbind outputs the elaboration order in text format to standard -- output. -- + -- -d_P Output cycle paths + -- + -- GNATbind output the cycle paths in text format to standard output + -- -- -d_T Output elaboration order trace information -- - -- GNATbind outputs trace information on elaboration order activities - -- to standard output. + -- GNATbind outputs trace information on elaboration order and cycle + -- detection activities to standard output. -- - -- -d_V Validate bindo graphs and order + -- -d_V Validate bindo cycles, graphs, and order -- - -- GNATbind validates the invocation graph, library graph, SCC graph - -- and elaboration order by detecting inconsistencies and producing - -- error reports. + -- GNATbind validates the invocation graph, library graph along with + -- its cycles, and elaboration order by detecting inconsistencies and + -- producing error reports. ---------------------------------------- -- Debugging elaboration order issues -- @@ -281,7 +343,20 @@ package body Bindo is Main_Lib_File : File_Name_Type) is begin - Elaborate_Units (Order, Main_Lib_File); + -- Use the invocation and library graph-based elaboration order when + -- switch -d_N (new bindo order) is in effect. + + if Debug_Flag_Underscore_NN then + Invocation_And_Library_Graph_Elaborators.Elaborate_Units + (Order => Order, + Main_Lib_File => Main_Lib_File); + + -- Otherwise use the library graph and heuristic-based elaboration + -- order. + + else + Binde.Find_Elab_Order (Order, Main_Lib_File); + end if; end Find_Elaboration_Order; end Bindo; diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index d76d93d..fb9ebba 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -378,7 +378,7 @@ package body Debug is -- d_A Output ALI invocation tables -- d_B - -- d_C + -- d_C Diagnose all cycles -- d_D -- d_F -- d_G @@ -390,13 +390,13 @@ package body Debug is -- d_M -- d_N New bindo order -- d_O Output elaboration order - -- d_P + -- d_P Output cycle paths -- d_Q -- d_R -- d_S - -- d_T Output elaboration order trace information + -- d_T Output elaboration order and cycle detection trace information -- d_U - -- d_V Validate bindo graphs and order + -- d_V Validate bindo cycles, graphs, and order -- d_W -- d_X -- d_Y @@ -1150,22 +1150,27 @@ package body Debug is -- d_A GNATBIND output the contents of all ALI invocation-related tables -- in textual format to standard output. - -- + + -- d_C GNATBIND diagnoses all unique cycles within the bind, rather than + -- just the most important one. + -- d_I GNATBIND outputs the contents of the invocation graph in textual -- format to standard output. - -- + -- d_L GNATBIND outputs the contents of the library graph in textual -- format to standard output. - -- + -- d_N GNATBIND utilizes the elaboration order provided by bindo - -- + -- d_O GNATBIND outputs the elaboration order of units to standard output - -- - -- d_T GNATBIND outputs trace information of elaboration order activities - -- to standard output. - -- - -- d_V GNATBIND validates the invocation graph, library graph, SCC graph - -- and elaboration order. + + -- d_P GNATBIND outputs the cycle paths to standard output + + -- d_T GNATBIND outputs trace information of elaboration order and cycle + -- detection activities to standard output. + + -- d_V GNATBIND validates the invocation graph, library graph along with + -- its cycles, and the elaboration order. -------------------------------------------- -- Documentation for gnatmake Debug Flags -- diff --git a/gcc/ada/gnatbind.adb b/gcc/ada/gnatbind.adb index 41541c3..40c85b9 100644 --- a/gcc/ada/gnatbind.adb +++ b/gcc/ada/gnatbind.adb @@ -26,7 +26,6 @@ with ALI; use ALI; with ALI.Util; use ALI.Util; with Bcheck; use Bcheck; -with Binde; use Binde; with Binderr; use Binderr; with Bindgen; use Bindgen; with Bindo; use Bindo; @@ -883,14 +882,7 @@ begin Elab_Order : Unit_Id_Table; begin - -- Use the invocation and library graph-based elaboration order - -- when switch -d_N (new bindo order) is in effect. - - if Debug_Flag_Underscore_NN then - Find_Elaboration_Order (Elab_Order, First_Main_Lib_File); - else - Find_Elab_Order (Elab_Order, First_Main_Lib_File); - end if; + Find_Elaboration_Order (Elab_Order, First_Main_Lib_File); if Errors_Detected = 0 and then not Check_Only then Gen_Output_File diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index ffd6a90..861d58e 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -59,65 +59,32 @@ with System.WCh_Con; use System.WCh_Con; package body Lib.Writ is ----------------------- - -- Local Subprograms -- + -- Local subprograms -- ----------------------- - function Column (IS_Id : Invocation_Signature_Id) return Nat; - pragma Inline (Column); - -- Obtain attribute Column of an invocation signature with id IS_Id - - function Extra (IR_Id : Invocation_Relation_Id) return Name_Id; - pragma Inline (Extra); - -- Obtain attribute Extra of an invocation relation with id IR_Id - - function Invoker - (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id; - pragma Inline (Invoker); - -- Obtain attribute Invoker of an invocation relation with id IR_Id - - function Kind - (IC_Id : Invocation_Construct_Id) return Invocation_Construct_Kind; - pragma Inline (Kind); - -- Obtain attribute Kind of an invocation construct with id IC_Id - - function Kind (IR_Id : Invocation_Relation_Id) return Invocation_Kind; - pragma Inline (Kind); - -- Obtain attribute Kind of an invocation relation with id IR_Id - - function Line (IS_Id : Invocation_Signature_Id) return Nat; - pragma Inline (Line); - -- Obtain attribute Line of an invocation signature with id IS_Id - - function Locations (IS_Id : Invocation_Signature_Id) return Name_Id; - pragma Inline (Locations); - -- Obtain attribute Locations of an invocation signature with id IS_Id - - function Name (IS_Id : Invocation_Signature_Id) return Name_Id; - pragma Inline (Name); - -- Obtain attribute Name of an invocation signature with id IS_Id - - function Placement - (IC_Id : Invocation_Construct_Id) return Body_Placement_Kind; - pragma Inline (Placement); - -- Obtain attribute Placement of an invocation construct with id IC_Id - function Present (N_Id : Name_Id) return Boolean; pragma Inline (Present); -- Determine whether a name with id N_Id exists - function Scope (IS_Id : Invocation_Signature_Id) return Name_Id; - pragma Inline (Scope); - -- Obtain attribute Scope of an invocation signature with id IS_Id + procedure Write_Invocation_Construct (IC_Id : Invocation_Construct_Id); + pragma Inline (Write_Invocation_Construct); + -- Write invocation construct IC_Id to the ALI file + + procedure Write_Invocation_Graph; + pragma Inline (Write_Invocation_Graph); + -- Write out the invocation graph - function Signature - (IC_Id : Invocation_Construct_Id) return Invocation_Signature_Id; - pragma Inline (Signature); - -- Obtain attribute Signature of an invocation construct with id IC_Id + procedure Write_Invocation_Graph_Attributes; + pragma Inline (Write_Invocation_Graph_Attributes); + -- Write out the attributes of the invocation graph - function Target - (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id; - pragma Inline (Target); - -- Obtain attribute Target of an invocation relation with id IR_Id + procedure Write_Invocation_Relation (IR_Id : Invocation_Relation_Id); + pragma Inline (Write_Invocation_Relation); + -- Write invocation relation IR_Id to the ALI file + + procedure Write_Invocation_Signature (IS_Id : Invocation_Signature_Id); + pragma Inline (Write_Invocation_Signature); + -- Write invocation signature IS_Id to the ALI file procedure Write_Unit_Name (N : Node_Id); -- Used to write out the unit name for R (pragma Restriction) lines @@ -161,16 +128,6 @@ package body Lib.Writ is OA_Setting => 'O'); end Add_Preprocessing_Dependency; - ------------ - -- Column -- - ------------ - - function Column (IS_Id : Invocation_Signature_Id) return Nat is - begin - pragma Assert (Present (IS_Id)); - return Invocation_Signatures.Table (IS_Id).Column; - end Column; - ------------------------------ -- Ensure_System_Dependency -- ------------------------------ @@ -252,92 +209,6 @@ package body Lib.Writ is end; end Ensure_System_Dependency; - ----------- - -- Extra -- - ----------- - - function Extra (IR_Id : Invocation_Relation_Id) return Name_Id is - begin - pragma Assert (Present (IR_Id)); - return Invocation_Relations.Table (IR_Id).Extra; - end Extra; - - ------------- - -- Invoker -- - ------------- - - function Invoker - (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id - is - begin - pragma Assert (Present (IR_Id)); - return Invocation_Relations.Table (IR_Id).Invoker; - end Invoker; - - ---------- - -- Kind -- - ---------- - - function Kind - (IC_Id : Invocation_Construct_Id) return Invocation_Construct_Kind - is - begin - pragma Assert (Present (IC_Id)); - return Invocation_Constructs.Table (IC_Id).Kind; - end Kind; - - ---------- - -- Kind -- - ---------- - - function Kind (IR_Id : Invocation_Relation_Id) return Invocation_Kind is - begin - pragma Assert (Present (IR_Id)); - return Invocation_Relations.Table (IR_Id).Kind; - end Kind; - - ---------- - -- Line -- - ---------- - - function Line (IS_Id : Invocation_Signature_Id) return Nat is - begin - pragma Assert (Present (IS_Id)); - return Invocation_Signatures.Table (IS_Id).Line; - end Line; - - --------------- - -- Locations -- - --------------- - - function Locations (IS_Id : Invocation_Signature_Id) return Name_Id is - begin - pragma Assert (Present (IS_Id)); - return Invocation_Signatures.Table (IS_Id).Locations; - end Locations; - - ---------- - -- Name -- - ---------- - - function Name (IS_Id : Invocation_Signature_Id) return Name_Id is - begin - pragma Assert (Present (IS_Id)); - return Invocation_Signatures.Table (IS_Id).Name; - end Name; - - --------------- - -- Placement -- - --------------- - - function Placement - (IC_Id : Invocation_Construct_Id) return Body_Placement_Kind - is - begin - pragma Assert (Present (IC_Id)); - return Invocation_Constructs.Table (IC_Id).Placement; - end Placement; - ------------- -- Present -- ------------- @@ -347,40 +218,6 @@ package body Lib.Writ is return N_Id /= No_Name; end Present; - ----------- - -- Scope -- - ----------- - - function Scope (IS_Id : Invocation_Signature_Id) return Name_Id is - begin - pragma Assert (Present (IS_Id)); - return Invocation_Signatures.Table (IS_Id).Scope; - end Scope; - - --------------- - -- Signature -- - --------------- - - function Signature - (IC_Id : Invocation_Construct_Id) return Invocation_Signature_Id - is - begin - pragma Assert (Present (IC_Id)); - return Invocation_Constructs.Table (IC_Id).Signature; - end Signature; - - ------------ - -- Target -- - ------------ - - function Target - (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id - is - begin - pragma Assert (Present (IR_Id)); - return Invocation_Relations.Table (IR_Id).Target; - end Target; - --------------- -- Write_ALI -- --------------- @@ -441,9 +278,6 @@ package body Lib.Writ is -- this file (using Scan_ALI) and returns True. If no file exists, -- or the file is not up to date, then False is returned. - procedure Write_Invocation_Graph; - -- Write out the invocation graph - procedure Write_Unit_Information (Unit_Num : Unit_Number_Type); -- Write out the library information for one unit for which code is -- generated (includes unit line and with lines). @@ -633,175 +467,6 @@ package body Lib.Writ is end Update_Tables_From_ALI_File; ---------------------------- - -- Write_Invocation_Graph -- - ---------------------------- - - procedure Write_Invocation_Graph is - procedure Write_Invocation_Construct - (IC_Id : Invocation_Construct_Id); - pragma Inline (Write_Invocation_Construct); - -- Write invocation construct IC_Id to the ALI file - - procedure Write_Invocation_Relation (IR_Id : Invocation_Relation_Id); - pragma Inline (Write_Invocation_Relation); - -- Write invocation relation IR_Id to the ALI file - - procedure Write_Invocation_Signature - (IS_Id : Invocation_Signature_Id); - pragma Inline (Write_Invocation_Signature); - -- Write invocation signature IS_Id to the ALI file - - -------------------------------- - -- Write_Invocation_Construct -- - -------------------------------- - - procedure Write_Invocation_Construct - (IC_Id : Invocation_Construct_Id) - is - begin - -- G header - - Write_Info_Initiate ('G'); - Write_Info_Char (' '); - - -- line-kind - - Write_Info_Char - (Invocation_Graph_Line_Kind_To_Code (Invocation_Construct_Line)); - Write_Info_Char (' '); - - -- construct-kind - - Write_Info_Char (Invocation_Construct_Kind_To_Code (Kind (IC_Id))); - Write_Info_Char (' '); - - -- construct-body-placement - - Write_Info_Char (Body_Placement_Kind_To_Code (Placement (IC_Id))); - Write_Info_Char (' '); - - -- construct-signature - - Write_Invocation_Signature (Signature (IC_Id)); - Write_Info_EOL; - end Write_Invocation_Construct; - - ------------------------------- - -- Write_Invocation_Relation -- - ------------------------------- - - procedure Write_Invocation_Relation - (IR_Id : Invocation_Relation_Id) - is - begin - -- G header - - Write_Info_Initiate ('G'); - Write_Info_Char (' '); - - -- line-kind - - Write_Info_Char - (Invocation_Graph_Line_Kind_To_Code (Invocation_Relation_Line)); - Write_Info_Char (' '); - - -- relation-kind - - Write_Info_Char (Invocation_Kind_To_Code (Kind (IR_Id))); - Write_Info_Char (' '); - - -- (extra-name | "none") - - if Present (Extra (IR_Id)) then - Write_Info_Name (Extra (IR_Id)); - else - Write_Info_Str ("none"); - end if; - - Write_Info_Char (' '); - - -- invoker-signature - - Write_Invocation_Signature (Invoker (IR_Id)); - Write_Info_Char (' '); - - -- target-signature - - Write_Invocation_Signature (Target (IR_Id)); - - Write_Info_EOL; - end Write_Invocation_Relation; - - -------------------------------- - -- Write_Invocation_Signature -- - -------------------------------- - - procedure Write_Invocation_Signature - (IS_Id : Invocation_Signature_Id) - is - begin - -- [ - - Write_Info_Char ('['); - - -- name - - Write_Info_Name (Name (IS_Id)); - Write_Info_Char (' '); - - -- scope - - Write_Info_Name (Scope (IS_Id)); - Write_Info_Char (' '); - - -- line - - Write_Info_Nat (Line (IS_Id)); - Write_Info_Char (' '); - - -- column - - Write_Info_Nat (Column (IS_Id)); - Write_Info_Char (' '); - - -- (locations | "none") - - if Present (Locations (IS_Id)) then - Write_Info_Name (Locations (IS_Id)); - else - Write_Info_Str ("none"); - end if; - - -- ] - - Write_Info_Char (']'); - end Write_Invocation_Signature; - - -- Start of processing for Write_Invocation_Graph - - begin - -- First write out all invocation constructs declared within the - -- current unit. This ensures that when this invocation is read, - -- the invocation constructs are materialized before they are - -- referenced by invocation relations. - - for IC_Id in Invocation_Constructs.First .. - Invocation_Constructs.Last - loop - Write_Invocation_Construct (IC_Id); - end loop; - - -- Write out all invocation relations that originate from invocation - -- constructs delared in the current unit. - - for IR_Id in Invocation_Relations.First .. - Invocation_Relations.Last - loop - Write_Invocation_Relation (IR_Id); - end loop; - end Write_Invocation_Graph; - - ---------------------------- -- Write_Unit_Information -- ---------------------------- @@ -2010,6 +1675,179 @@ package body Lib.Writ is Close_Output_Library_Info; end Write_ALI; + -------------------------------- + -- Write_Invocation_Construct -- + -------------------------------- + + procedure Write_Invocation_Construct (IC_Id : Invocation_Construct_Id) is + begin + -- G header + + Write_Info_Initiate ('G'); + Write_Info_Char (' '); + + -- line-kind + + Write_Info_Char + (Invocation_Graph_Line_Kind_To_Code (Invocation_Construct_Line)); + Write_Info_Char (' '); + + -- construct-kind + + Write_Info_Char (Invocation_Construct_Kind_To_Code (Kind (IC_Id))); + Write_Info_Char (' '); + + -- construct-spec-placement + + Write_Info_Char + (Declaration_Placement_Kind_To_Code (Spec_Placement (IC_Id))); + Write_Info_Char (' '); + + -- construct-body-placement + + Write_Info_Char + (Declaration_Placement_Kind_To_Code (Body_Placement (IC_Id))); + Write_Info_Char (' '); + + -- construct-signature + + Write_Invocation_Signature (Signature (IC_Id)); + Write_Info_EOL; + end Write_Invocation_Construct; + + --------------------------------------- + -- Write_Invocation_Graph_Attributes -- + --------------------------------------- + + procedure Write_Invocation_Graph_Attributes is + begin + -- G header + + Write_Info_Initiate ('G'); + Write_Info_Char (' '); + + -- line-kind + + Write_Info_Char + (Invocation_Graph_Line_Kind_To_Code + (Invocation_Graph_Attributes_Line)); + Write_Info_Char (' '); + + -- encoding-kind + + Write_Info_Char + (Invocation_Graph_Encoding_Kind_To_Code (Invocation_Graph_Encoding)); + Write_Info_EOL; + end Write_Invocation_Graph_Attributes; + + ---------------------------- + -- Write_Invocation_Graph -- + ---------------------------- + + procedure Write_Invocation_Graph is + begin + Write_Invocation_Graph_Attributes; + + -- First write out all invocation constructs declared within the current + -- unit. This ensures that when this invocation is read, the invocation + -- constructs are materialized before they are referenced by invocation + -- relations. + + For_Each_Invocation_Construct (Write_Invocation_Construct'Access); + + -- Write out all invocation relations that originate from invocation + -- constructs delared in the current unit. + + For_Each_Invocation_Relation (Write_Invocation_Relation'Access); + end Write_Invocation_Graph; + + ------------------------------- + -- Write_Invocation_Relation -- + ------------------------------- + + procedure Write_Invocation_Relation (IR_Id : Invocation_Relation_Id) is + begin + -- G header + + Write_Info_Initiate ('G'); + Write_Info_Char (' '); + + -- line-kind + + Write_Info_Char + (Invocation_Graph_Line_Kind_To_Code (Invocation_Relation_Line)); + Write_Info_Char (' '); + + -- relation-kind + + Write_Info_Char (Invocation_Kind_To_Code (Kind (IR_Id))); + Write_Info_Char (' '); + + -- (extra-name | "none") + + if Present (Extra (IR_Id)) then + Write_Info_Name (Extra (IR_Id)); + else + Write_Info_Str ("none"); + end if; + + Write_Info_Char (' '); + + -- invoker-signature + + Write_Invocation_Signature (Invoker (IR_Id)); + Write_Info_Char (' '); + + -- target-signature + + Write_Invocation_Signature (Target (IR_Id)); + + Write_Info_EOL; + end Write_Invocation_Relation; + + -------------------------------- + -- Write_Invocation_Signature -- + -------------------------------- + + procedure Write_Invocation_Signature (IS_Id : Invocation_Signature_Id) is + begin + -- [ + + Write_Info_Char ('['); + + -- name + + Write_Info_Name (Name (IS_Id)); + Write_Info_Char (' '); + + -- scope + + Write_Info_Name (Scope (IS_Id)); + Write_Info_Char (' '); + + -- line + + Write_Info_Nat (Line (IS_Id)); + Write_Info_Char (' '); + + -- column + + Write_Info_Nat (Column (IS_Id)); + Write_Info_Char (' '); + + -- (locations | "none") + + if Present (Locations (IS_Id)) then + Write_Info_Name (Locations (IS_Id)); + else + Write_Info_Str ("none"); + end if; + + -- ] + + Write_Info_Char (']'); + end Write_Invocation_Signature; + --------------------- -- Write_Unit_Name -- --------------------- diff --git a/gcc/ada/lib-writ.ads b/gcc/ada/lib-writ.ads index c17233a..7248a61 100644 --- a/gcc/ada/lib-writ.ads +++ b/gcc/ada/lib-writ.ads @@ -880,18 +880,32 @@ package Lib.Writ is -- locations of all instances where the initial declaration of the -- construct appears. -- + -- When the line-kind denotes invocation graph attributes, line-attributes + -- are set as follows: + -- + -- encoding-kind + -- + -- Attribute encoding-kind is a Character which specifies the encoding + -- kind used when collecting invocation constructs and relations. Table + -- ALI.Invocation_Graph_Encoding_Codes lists all legal values. + -- -- When the line-kind denotes an invocation construct, line-attributes are -- set as follows: -- - -- construct-kind construct-body-placement construct-signature + -- construct-kind construct-spec-placement construct-body-placement + -- construct-signature -- -- Attribute construct-kind is a Character which denotes the nature of -- the construct. Table ALI.Invocation_Construct_Codes lists all legal -- values. -- + -- Attribute construct-spec-placement is a Character which denotes the + -- placement of the construct's spec within the unit. All legal values + -- are listed in table ALI.Spec_And_Body_Placement_Codes. + -- -- Attribute construct-body-placement is a Character which denotes the -- placement of the construct's body within the unit. All legal values - -- are listed in table ALI.Body_Placement_Codes. + -- are listed in table ALI.Spec_And_Body_Placement_Codes. -- -- Attribute construct-signature is the invocation signature of the -- construct. @@ -925,7 +939,7 @@ package Lib.Writ is -- Postcondition_Verification - related routine -- Protected_Entry_Call - not present -- Protected_Subprogram_Call - not present - -- Task_Activation - related task object + -- Task_Activation - not present -- Task_Entry_Call - not present -- Type_Initialization - related type -- diff --git a/gcc/ada/libgnat/g-lists.adb b/gcc/ada/libgnat/g-lists.adb index f7447a5..817274a 100644 --- a/gcc/ada/libgnat/g-lists.adb +++ b/gcc/ada/libgnat/g-lists.adb @@ -337,6 +337,57 @@ package body GNAT.Lists is end if; end Ensure_Unlocked; + ----------- + -- Equal -- + ----------- + + function Equal + (Left : Doubly_Linked_List; + Right : Doubly_Linked_List) return Boolean + is + Left_Head : Node_Ptr; + Left_Nod : Node_Ptr; + Right_Head : Node_Ptr; + Right_Nod : Node_Ptr; + + begin + -- Two non-existent lists are considered equal + + if Left = Nil and then Right = Nil then + return True; + + -- A non-existent list is never equal to an already created list + + elsif Left = Nil or else Right = Nil then + return False; + + -- The two lists must contain the same number of elements to be equal + + elsif Size (Left) /= Size (Right) then + return False; + end if; + + -- Compare the two lists element by element + + Left_Head := Left.Nodes'Access; + Left_Nod := Left_Head.Next; + Right_Head := Right.Nodes'Access; + Right_Nod := Right_Head.Next; + while Is_Valid (Left_Nod, Left_Head) + and then + Is_Valid (Right_Nod, Right_Head) + loop + if Left_Nod.Elem /= Right_Nod.Elem then + return False; + end if; + + Left_Nod := Left_Nod.Next; + Right_Nod := Right_Nod.Next; + end loop; + + return True; + end Equal; + --------------- -- Find_Node -- --------------- diff --git a/gcc/ada/libgnat/g-lists.ads b/gcc/ada/libgnat/g-lists.ads index b64ef08..fdcaed6 100644 --- a/gcc/ada/libgnat/g-lists.ads +++ b/gcc/ada/libgnat/g-lists.ads @@ -117,6 +117,12 @@ package GNAT.Lists is -- end of a list's lifetime. This action will raise Iterated if the -- list has outstanding iterators. + function Equal + (Left : Doubly_Linked_List; + Right : Doubly_Linked_List) return Boolean; + -- Determine whether lists Left and Right have the same characteristics + -- and contain the same elements. + function First (L : Doubly_Linked_List) return Element_Type; -- Obtain an element from the start of list L. This action will raise -- List_Empty if the list is empty. diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb index ce0950d..2bd38c8 100644 --- a/gcc/ada/sem_elab.adb +++ b/gcc/ada/sem_elab.adb @@ -11689,6 +11689,11 @@ package body Sem_Elab is -- active scenarios. In_State is the current state of the Processing -- phase. + procedure Record_Invocation_Graph_Encoding; + pragma Inline (Record_Invocation_Graph_Encoding); + -- Record the encoding format used to capture information related to + -- invocation constructs and relations. + procedure Record_Invocation_Path (In_State : Processing_In_State); pragma Inline (Record_Invocation_Path); -- Record the invocation relations found within the path represented in @@ -11938,40 +11943,32 @@ package body Sem_Elab is (Constr_Id : Entity_Id; In_State : Processing_In_State) is + function Body_Placement_Of + (Id : Entity_Id) return Declaration_Placement_Kind; + pragma Inline (Body_Placement_Of); + -- Obtain the placement of arbitrary entity Id's body + + function Declaration_Placement_Of_Node + (N : Node_Id) return Declaration_Placement_Kind; + pragma Inline (Declaration_Placement_Of_Node); + -- Obtain the placement of arbitrary node N + function Kind_Of (Id : Entity_Id) return Invocation_Construct_Kind; pragma Inline (Kind_Of); -- Obtain the invocation construct kind of arbitrary entity Id - function Placement_Of (Id : Entity_Id) return Body_Placement_Kind; - pragma Inline (Placement_Of); - -- Obtain the body placement of arbitrary entity Id - - function Placement_Of_Node (N : Node_Id) return Body_Placement_Kind; - pragma Inline (Placement_Of_Node); - -- Obtain the body placement of arbitrary node N - - ------------- - -- Kind_Of -- - ------------- - - function Kind_Of (Id : Entity_Id) return Invocation_Construct_Kind is - begin - if Id = Elab_Body_Id then - return Elaborate_Body_Procedure; - - elsif Id = Elab_Spec_Id then - return Elaborate_Spec_Procedure; - - else - return Regular_Construct; - end if; - end Kind_Of; + function Spec_Placement_Of + (Id : Entity_Id) return Declaration_Placement_Kind; + pragma Inline (Spec_Placement_Of); + -- Obtain the placement of arbitrary entity Id's spec - ------------------ - -- Placement_Of -- - ------------------ + ----------------------- + -- Body_Placement_Of -- + ----------------------- - function Placement_Of (Id : Entity_Id) return Body_Placement_Kind is + function Body_Placement_Of + (Id : Entity_Id) return Declaration_Placement_Kind + is Id_Rep : constant Target_Rep_Id := Target_Representation_Of (Id, In_State); Body_Decl : constant Node_Id := Body_Declaration (Id_Rep); @@ -11981,21 +11978,23 @@ package body Sem_Elab is -- The entity has a body if Present (Body_Decl) then - return Placement_Of_Node (Body_Decl); + return Declaration_Placement_Of_Node (Body_Decl); -- Otherwise the entity must have a spec else pragma Assert (Present (Spec_Decl)); - return Placement_Of_Node (Spec_Decl); + return Declaration_Placement_Of_Node (Spec_Decl); end if; - end Placement_Of; + end Body_Placement_Of; - ----------------------- - -- Placement_Of_Node -- - ----------------------- + ----------------------------------- + -- Declaration_Placement_Of_Node -- + ----------------------------------- - function Placement_Of_Node (N : Node_Id) return Body_Placement_Kind is + function Declaration_Placement_Of_Node + (N : Node_Id) return Declaration_Placement_Kind + is Main_Unit_Id : constant Entity_Id := Cunit_Entity (Main_Unit); N_Unit_Id : constant Entity_Id := Find_Top_Unit (N); @@ -12039,11 +12038,50 @@ package body Sem_Elab is else return In_Body; end if; - end Placement_Of_Node; + end Declaration_Placement_Of_Node; - -- Local variables + ------------- + -- Kind_Of -- + ------------- + + function Kind_Of (Id : Entity_Id) return Invocation_Construct_Kind is + begin + if Id = Elab_Body_Id then + return Elaborate_Body_Procedure; + + elsif Id = Elab_Spec_Id then + return Elaborate_Spec_Procedure; + + else + return Regular_Construct; + end if; + end Kind_Of; - IC_Rec : Invocation_Construct_Record; + ----------------------- + -- Spec_Placement_Of -- + ----------------------- + + function Spec_Placement_Of + (Id : Entity_Id) return Declaration_Placement_Kind + is + Id_Rep : constant Target_Rep_Id := + Target_Representation_Of (Id, In_State); + Body_Decl : constant Node_Id := Body_Declaration (Id_Rep); + Spec_Decl : constant Node_Id := Spec_Declaration (Id_Rep); + + begin + -- The entity has a spec + + if Present (Spec_Decl) then + return Declaration_Placement_Of_Node (Spec_Decl); + + -- Otherwise the entity must have a body + + else + pragma Assert (Present (Body_Decl)); + return Declaration_Placement_Of_Node (Body_Decl); + end if; + end Spec_Placement_Of; -- Start of processing for Declare_Invocation_Construct @@ -12059,15 +12097,14 @@ package body Sem_Elab is Set_Is_Saved_Construct (Constr_Id); - IC_Rec.Kind := Kind_Of (Constr_Id); - IC_Rec.Placement := Placement_Of (Constr_Id); - IC_Rec.Signature := Signature_Of (Constr_Id); - -- Add the construct in the ALI file Add_Invocation_Construct - (IC_Rec => IC_Rec, - Update_Units => False); + (Body_Placement => Body_Placement_Of (Constr_Id), + Kind => Kind_Of (Constr_Id), + Signature => Signature_Of (Constr_Id), + Spec_Placement => Spec_Placement_Of (Constr_Id), + Update_Units => False); end Declare_Invocation_Construct; ------------------------------- @@ -12809,6 +12846,12 @@ package body Sem_Elab is return; end if; + -- Save the encoding format used to capture information about the + -- invocation constructs and relations in the ALI file of the main + -- unit. + + Record_Invocation_Graph_Encoding; + -- Examine all library level invocation scenarios and perform DFS -- traversals from each one. Encode a path in the ALI file of the -- main unit if it reaches into an external unit. @@ -12824,6 +12867,30 @@ package body Sem_Elab is Process_Main_Unit; end Record_Invocation_Graph; + -------------------------------------- + -- Record_Invocation_Graph_Encoding -- + -------------------------------------- + + procedure Record_Invocation_Graph_Encoding is + Kind : Invocation_Graph_Encoding_Kind := No_Encoding; + + begin + -- Switch -gnatd_F (encode full invocation paths in ALI files) is in + -- effect. + + if Debug_Flag_Underscore_FF then + Kind := Full_Path_Encoding; + else + Kind := Endpoints_Encoding; + end if; + + -- Save the encoding format in the ALI file of the main unit + + Set_Invocation_Graph_Encoding + (Kind => Kind, + Update_Units => False); + end Record_Invocation_Graph_Encoding; + ---------------------------- -- Record_Invocation_Path -- ---------------------------- @@ -12882,6 +12949,10 @@ package body Sem_Elab is (Extra : out Entity_Id; Kind : out Invocation_Kind) is + Targ_Rep : constant Target_Rep_Id := + Target_Representation_Of (Targ_Id, In_State); + Spec_Decl : constant Node_Id := Spec_Declaration (Targ_Rep); + begin -- Accept within a task body @@ -12970,7 +13041,7 @@ package body Sem_Elab is -- Postcondition verification elsif Is_Postconditions_Proc (Targ_Id) then - Extra := Find_Enclosing_Scope (Targ_Id); + Extra := Find_Enclosing_Scope (Spec_Decl); Kind := Postcondition_Verification; -- Protected entry call @@ -13013,7 +13084,6 @@ package body Sem_Elab is Extra : Entity_Id; Extra_Nam : Name_Id; - IR_Rec : Invocation_Relation_Record; Kind : Invocation_Kind; Rel : Invoker_Target_Relation; @@ -13052,15 +13122,13 @@ package body Sem_Elab is Extra_Nam := No_Name; end if; - IR_Rec.Extra := Extra_Nam; - IR_Rec.Invoker := Signature_Of (Invk_Id); - IR_Rec.Kind := Kind; - IR_Rec.Target := Signature_Of (Targ_Id); - -- Add the relation in the ALI file Add_Invocation_Relation - (IR_Rec => IR_Rec, + (Extra => Extra_Nam, + Invoker => Signature_Of (Invk_Id), + Kind => Kind, + Target => Signature_Of (Targ_Id), Update_Units => False); end Record_Invocation_Relation; -- cgit v1.1 From 9cbb5574cd580de25e8aaf402e0f3d3c704a7157 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Fri, 5 Jul 2019 07:02:13 +0000 Subject: [Ada] Accept compilation switches -Og/-Ofast in non-GCC backends Tools like GNATprove built as GNAT backends rely on adabkend.adb to handle generic switches like the optimisation switches -Oxxx. This patch adds support for -Og and -Ofast that was missing. There is no impact on compilation. 2019-07-05 Yannick Moy gcc/ada/ * adabkend.adb (Scan_Back_End_Switches): Accept -Og and -Ofast switches. From-SVN: r273108 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/adabkend.adb | 23 ++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 279eac5..7fe9577 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Yannick Moy + + * adabkend.adb (Scan_Back_End_Switches): Accept -Og and -Ofast + switches. + 2019-07-05 Hristian Kirtchev * ali.adb: Relocate types Invocation_Construct_Record, diff --git a/gcc/ada/adabkend.adb b/gcc/ada/adabkend.adb index c42f3bd..3e1b14d 100644 --- a/gcc/ada/adabkend.adb +++ b/gcc/ada/adabkend.adb @@ -117,9 +117,11 @@ package body Adabkend is -- Set optimization indicators appropriately. In gcc-based GNAT this -- is picked up from imported variables set by the gcc driver, but - -- for compilers with non-gcc back ends we do it here to allow use - -- of these switches by the front end. Allowed optimization switches - -- are -Os (optimize for size), -O[0123], and -O (same as -O1). + -- for compilers with non-gcc back ends we do it here to allow use of + -- these switches by the front end. Allowed optimization switches are + -- -Os (optimize for size), -O[0123], -O (same as -O1), -Ofast + -- (disregard strict standards compliance), and -Og (optimize + -- debugging experience). elsif Switch_Chars (First) = 'O' then if First = Last then @@ -134,10 +136,21 @@ package body Adabkend is Optimization_Level := Character'Pos (Switch_Chars (Last)) - Character'Pos ('0'); + -- Switch -Og is between -O0 and -O1 in GCC. Consider it like + -- -O0 for other back ends. + + elsif Switch_Chars (Last) = 'g' then + Optimization_Level := 0; + else Fail ("invalid switch: " & Switch_Chars); end if; + -- Switch -Ofast enables -O3 + + elsif Switch_Chars (First + 1 .. Last) = "fast" then + Optimization_Level := 3; + else Fail ("invalid switch: " & Switch_Chars); end if; @@ -169,7 +182,7 @@ package body Adabkend is return; - -- Special check, the back end switch -fno-inline also sets the + -- Special check, the back-end switch -fno-inline also sets the -- front end flags to entirely inhibit all inlining. So we store it -- and set the appropriate flags. @@ -206,7 +219,7 @@ package body Adabkend is end case; end if; - -- Ignore all other back end switches + -- Ignore all other back-end switches elsif Is_Back_End_Switch (Switch_Chars) then null; -- cgit v1.1 From 13e8f0ed8e2cb25baa3fb424b4e721c46165ff93 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 5 Jul 2019 07:02:17 +0000 Subject: [Ada] Import documentation from the RM for Ada.Strings.Fixed 2019-07-05 Pierre-Marie de Rodat gcc/ada/ * libgnat/a-strfix.ads: Import documentation from the RM From-SVN: r273109 --- gcc/ada/ChangeLog | 4 + gcc/ada/libgnat/a-strfix.ads | 223 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 202 insertions(+), 25 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7fe9577..4c75bc9 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-05 Pierre-Marie de Rodat + + * libgnat/a-strfix.ads: Import documentation from the RM + 2019-07-05 Yannick Moy * adabkend.adb (Scan_Back_End_Switches): Accept -Og and -Ofast diff --git a/gcc/ada/libgnat/a-strfix.ads b/gcc/ada/libgnat/a-strfix.ads index 56db8bc..1571861 100644 --- a/gcc/ada/libgnat/a-strfix.ads +++ b/gcc/ada/libgnat/a-strfix.ads @@ -15,6 +15,25 @@ with Ada.Strings.Maps; +-- The language-defined package Strings.Fixed provides string-handling +-- subprograms for fixed-length strings; that is, for values of type +-- Standard.String. Several of these subprograms are procedures that modify +-- the contents of a String that is passed as an out or an in out parameter; +-- each has additional parameters to control the effect when the logical +-- length of the result differs from the parameter's length. +-- +-- For each function that returns a String, the lower bound of the returned +-- value is 1. +-- +-- The basic model embodied in the package is that a fixed-length string +-- comprises significant characters and possibly padding (with space +-- characters) on either or both ends. When a shorter string is copied to a +-- longer string, padding is inserted, and when a longer string is copied to a +-- shorter one, padding is stripped. The Move procedure in Strings.Fixed, +-- which takes a String as an out parameter, allows the programmer to control +-- these effects. Similar control is provided by the string transformation +-- procedures. + package Ada.Strings.Fixed is pragma Preelaborate; @@ -28,6 +47,44 @@ package Ada.Strings.Fixed is Drop : Truncation := Error; Justify : Alignment := Left; Pad : Character := Space); + -- The Move procedure copies characters from Source to Target. If Source + -- has the same length as Target, then the effect is to assign Source to + -- Target. If Source is shorter than Target then: + -- + -- * If Justify=Left, then Source is copied into the first Source'Length + -- characters of Target. + -- + -- * If Justify=Right, then Source is copied into the last Source'Length + -- characters of Target. + -- + -- * If Justify=Center, then Source is copied into the middle Source'Length + -- characters of Target. In this case, if the difference in length + -- between Target and Source is odd, then the extra Pad character is on + -- the right. + -- + -- * Pad is copied to each Target character not otherwise assigned. + -- + -- If Source is longer than Target, then the effect is based on Drop. + -- + -- * If Drop=Left, then the rightmost Target'Length characters of Source + -- are copied into Target. + -- + -- * If Drop=Right, then the leftmost Target'Length characters of Source + -- are copied into Target. + -- + -- * If Drop=Error, then the effect depends on the value of the Justify + -- parameter and also on whether any characters in Source other than Pad + -- would fail to be copied: + -- + -- * If Justify=Left, and if each of the rightmost + -- Source'Length-Target'Length characters in Source is Pad, then the + -- leftmost Target'Length characters of Source are copied to Target. + -- + -- * If Justify=Right, and if each of the leftmost + -- Source'Length-Target'Length characters in Source is Pad, then the + -- rightmost Target'Length characters of Source are copied to Target. + -- + -- * Otherwise, Length_Error is propagated. ------------------------ -- Search Subprograms -- @@ -36,36 +93,57 @@ package Ada.Strings.Fixed is function Index (Source : String; Pattern : String; + From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural; + pragma Ada_05 (Index); function Index (Source : String; Pattern : String; + From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + pragma Ada_05 (Index); - function Index - (Source : String; - Set : Maps.Character_Set; - Test : Membership := Inside; - Going : Direction := Forward) return Natural; + -- Each Index function searches, starting from From, for a slice of + -- Source, with length Pattern'Length, that matches Pattern with respect to + -- Mapping; the parameter Going indicates the direction of the lookup. If + -- Source is the null string, Index returns 0; otherwise, if From is not in + -- Source'Range, then Index_Error is propagated. If Going = Forward, then + -- Index returns the smallest index I which is greater than or equal to + -- From such that the slice of Source starting at I matches Pattern. If + -- Going = Backward, then Index returns the largest index I such that the + -- slice of Source starting at I matches Pattern and has an upper bound + -- less than or equal to From. If there is no such slice, then 0 is + -- returned. If Pattern is the null string, then Pattern_Error is + -- propagated. function Index (Source : String; Pattern : String; - From : Positive; Going : Direction := Forward; Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; - pragma Ada_05 (Index); function Index (Source : String; Pattern : String; - From : Positive; Going : Direction := Forward; Mapping : Maps.Character_Mapping_Function) return Natural; - pragma Ada_05 (Index); + + -- If Going = Forward, returns: + -- + -- Index (Source, Pattern, Source'First, Forward, Mapping) + -- + -- otherwise, returns: + -- + -- Index (Source, Pattern, Source'Last, Backward, Mapping). + + function Index + (Source : String; + Set : Maps.Character_Set; + Test : Membership := Inside; + Going : Direction := Forward) return Natural; function Index (Source : String; @@ -74,16 +152,26 @@ package Ada.Strings.Fixed is Test : Membership := Inside; Going : Direction := Forward) return Natural; pragma Ada_05 (Index); + -- Index searches for the first or last occurrence of any of a set of + -- characters (when Test=Inside), or any of the complement of a set of + -- characters (when Test=Outside). If Source is the null string, Index + -- returns 0; otherwise, if From is not in Source'Range, then Index_Error + -- is propagated. Otherwise, it returns the smallest index I >= From (if + -- Going=Forward) or the largest index I <= From (if Going=Backward) such + -- that Source(I) satisfies the Test condition with respect to Set; it + -- returns 0 if there is no such Character in Source. function Index_Non_Blank (Source : String; + From : Positive; Going : Direction := Forward) return Natural; + pragma Ada_05 (Index_Non_Blank); + -- Returns Index (Source, Maps.To_Set(Space), From, Outside, Going) function Index_Non_Blank (Source : String; - From : Positive; Going : Direction := Forward) return Natural; - pragma Ada_05 (Index_Non_Blank); + -- Returns Index (Source, Maps.To_Set(Space), Outside, Going) function Count (Source : String; @@ -95,9 +183,15 @@ package Ada.Strings.Fixed is Pattern : String; Mapping : Maps.Character_Mapping_Function) return Natural; + -- Returns the maximum number of nonoverlapping slices of Source that match + -- Pattern with respect to Mapping. If Pattern is the null string then + -- Pattern_Error is propagated. + function Count (Source : String; Set : Maps.Character_Set) return Natural; + -- Returns the number of occurrences in Source of characters that are in + -- Set. procedure Find_Token (Source : String; @@ -107,6 +201,13 @@ package Ada.Strings.Fixed is First : out Positive; Last : out Natural); pragma Ada_2012 (Find_Token); + -- If Source is not the null string and From is not in Source'Range, then + -- Index_Error is raised. Otherwise, First is set to the index of the first + -- character in Source(From .. Source'Last) that satisfies the Test + -- condition. Last is set to the largest index such that all characters in + -- Source(First .. Last) satisfy the Test condition. If no characters in + -- Source(From .. Source'Last) satisfy the Test condition, First is set to + -- From, and Last is set to 0. procedure Find_Token (Source : String; @@ -114,6 +215,7 @@ package Ada.Strings.Fixed is Test : Membership; First : out Positive; Last : out Natural); + -- Equivalent to Find_Token (Source, Set, Source'First, Test, First, Last) ------------------------------------ -- String Translation Subprograms -- @@ -121,30 +223,30 @@ package Ada.Strings.Fixed is function Translate (Source : String; - Mapping : Maps.Character_Mapping) return String; - - procedure Translate - (Source : in out String; - Mapping : Maps.Character_Mapping); + Mapping : Maps.Character_Mapping_Function) return String; function Translate (Source : String; - Mapping : Maps.Character_Mapping_Function) return String; + Mapping : Maps.Character_Mapping) return String; + + -- Returns the string S whose length is Source'Length and such that S (I) + -- is the character to which Mapping maps the corresponding element of + -- Source, for I in 1 .. Source'Length. procedure Translate (Source : in out String; Mapping : Maps.Character_Mapping_Function); + procedure Translate + (Source : in out String; + Mapping : Maps.Character_Mapping); + + -- Equivalent to Source := Translate(Source, Mapping) + --------------------------------------- -- String Transformation Subprograms -- --------------------------------------- - function Replace_Slice - (Source : String; - Low : Positive; - High : Natural; - By : String) return String; - procedure Replace_Slice (Source : in out String; Low : Positive; @@ -153,33 +255,67 @@ package Ada.Strings.Fixed is Drop : Truncation := Error; Justify : Alignment := Left; Pad : Character := Space); + -- If Low > Source'Last+1, or High < Source'First - 1, then Index_Error is + -- propagated. Otherwise: + -- + -- * If High >= Low, then the returned string comprises + -- Source (Source'First .. Low - 1) + -- & By & Source(High + 1 .. Source'Last), but with lower bound 1. + -- + -- * If High < Low, then the returned string is + -- Insert (Source, Before => Low, New_Item => By). + + function Replace_Slice + (Source : String; + Low : Positive; + High : Natural; + By : String) return String; + -- Equivalent to: + -- + -- Move (Replace_Slice (Source, Low, High, By), + -- Source, Drop, Justify, Pad). function Insert (Source : String; Before : Positive; New_Item : String) return String; + -- Propagates Index_Error if Before is not in + -- Source'First .. Source'Last+1; otherwise, returns + -- Source (Source'First .. Before - 1) + -- & New_Item & Source(Before..Source'Last), but with lower bound 1. procedure Insert (Source : in out String; Before : Positive; New_Item : String; Drop : Truncation := Error); + -- Equivalent to Move (Insert (Source, Before, New_Item), Source, Drop) function Overwrite (Source : String; Position : Positive; New_Item : String) return String; + -- Propagates Index_Error if Position is not in + -- Source'First .. Source'Last + 1; otherwise, returns the string obtained + -- from Source by consecutively replacing characters starting at Position + -- with corresponding characters from New_Item. If the end of Source is + -- reached before the characters in New_Item are exhausted, the remaining + -- characters from New_Item are appended to the string. procedure Overwrite (Source : in out String; Position : Positive; New_Item : String; Drop : Truncation := Right); + -- Equivalent to Move(Overwrite(Source, Position, New_Item), Source, Drop) function Delete (Source : String; From : Positive; Through : Natural) return String; + -- If From <= Through, the returned string is + -- Replace_Slice(Source, From, Through, ""); otherwise, it is Source with + -- lower bound 1. procedure Delete (Source : in out String; @@ -187,6 +323,10 @@ package Ada.Strings.Fixed is Through : Natural; Justify : Alignment := Left; Pad : Character := Space); + -- Equivalent to: + -- + -- Move (Delete (Source, From, Through), + -- Source, Justify => Justify, Pad => Pad). --------------------------------- -- String Selector Subprograms -- @@ -195,17 +335,26 @@ package Ada.Strings.Fixed is function Trim (Source : String; Side : Trim_End) return String; + -- Returns the string obtained by removing from Source all leading Space + -- characters (if Side = Left), all trailing Space characters (if + -- Side = Right), or all leading and trailing Space characters (if + -- Side = Both). procedure Trim (Source : in out String; Side : Trim_End; Justify : Alignment := Left; Pad : Character := Space); + -- Equivalent to: + -- + -- Move (Trim (Source, Side), Source, Justify=>Justify, Pad=>Pad). function Trim (Source : String; Left : Maps.Character_Set; Right : Maps.Character_Set) return String; + -- Returns the string obtained by removing from Source all leading + -- characters in Left and all trailing characters in Right. procedure Trim (Source : in out String; @@ -213,28 +362,46 @@ package Ada.Strings.Fixed is Right : Maps.Character_Set; Justify : Alignment := Strings.Left; Pad : Character := Space); + -- Equivalent to: + -- + -- Move (Trim (Source, Left, Right), + -- Source, Justify => Justify, Pad=>Pad). function Head (Source : String; Count : Natural; Pad : Character := Space) return String; + -- Returns a string of length Count. If Count <= Source'Length, the string + -- comprises the first Count characters of Source. Otherwise, its contents + -- are Source concatenated with Count - Source'Length Pad characters. procedure Head (Source : in out String; Count : Natural; Justify : Alignment := Left; Pad : Character := Space); + -- Equivalent to: + -- + -- Move (Head (Source, Count, Pad), + -- Source, Drop => Error, Justify => Justify, Pad => Pad). function Tail (Source : String; Count : Natural; Pad : Character := Space) return String; + -- Returns a string of length Count. If Count <= Source'Length, the string + -- comprises the last Count characters of Source. Otherwise, its contents + -- are Count-Source'Length Pad characters concatenated with Source. procedure Tail (Source : in out String; Count : Natural; Justify : Alignment := Left; Pad : Character := Space); + -- Equivalent to: + -- + -- Move (Tail (Source, Count, Pad), + -- Source, Drop => Error, Justify => Justify, Pad => Pad). ---------------------------------- -- String Constructor Functions -- @@ -248,4 +415,10 @@ package Ada.Strings.Fixed is (Left : Natural; Right : String) return String; + -- These functions replicate a character or string a specified number of + -- times. The first function returns a string whose length is Left and each + -- of whose elements is Right. The second function returns a string whose + -- length is Left * Right'Length and whose value is the null string if + -- Left = 0 and otherwise is (Left - 1)*Right & Right with lower bound 1. + end Ada.Strings.Fixed; -- cgit v1.1 From 034a6629f4b3d64bf53dda42bf79b328c6d83190 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 5 Jul 2019 07:02:23 +0000 Subject: [Ada] Import documentation from the RM for Ada.Strings.Unbounded 2019-07-05 Pierre-Marie de Rodat gcc/ada/ * libgnat/a-strunb.ads: Import documentation from the RM From-SVN: r273110 --- gcc/ada/ChangeLog | 4 +++ gcc/ada/libgnat/a-strunb.ads | 80 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4c75bc9..a3bdd0c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,9 @@ 2019-07-05 Pierre-Marie de Rodat + * libgnat/a-strunb.ads: Import documentation from the RM + +2019-07-05 Pierre-Marie de Rodat + * libgnat/a-strfix.ads: Import documentation from the RM 2019-07-05 Yannick Moy diff --git a/gcc/ada/libgnat/a-strunb.ads b/gcc/ada/libgnat/a-strunb.ads index 601e69e..c0caf10 100644 --- a/gcc/ada/libgnat/a-strunb.ads +++ b/gcc/ada/libgnat/a-strunb.ads @@ -36,6 +36,15 @@ with Ada.Strings.Maps; with Ada.Finalization; +-- The language-defined package Strings.Unbounded provides a private type +-- Unbounded_String and a set of operations. An object of type +-- Unbounded_String represents a String whose low bound is 1 and whose length +-- can vary conceptually between 0 and Natural'Last. The subprograms for +-- fixed-length string handling are either overloaded directly for +-- Unbounded_String, or are modified as needed to reflect the flexibility in +-- length. Since the Unbounded_String type is private, relevant constructor +-- and selector operations are provided. + package Ada.Strings.Unbounded is pragma Preelaborate; @@ -43,12 +52,19 @@ package Ada.Strings.Unbounded is pragma Preelaborable_Initialization (Unbounded_String); Null_Unbounded_String : constant Unbounded_String; + -- Represents the null String. If an object of type Unbounded_String is not + -- otherwise initialized, it will be initialized to the same value as + -- Null_Unbounded_String. function Length (Source : Unbounded_String) return Natural; + -- Returns the length of the String represented by Source type String_Access is access all String; + -- Provides a (nonprivate) access type for explicit processing of + -- unbounded-length strings. procedure Free (X : in out String_Access); + -- Performs an unchecked deallocation of an object of type String_Access -------------------------------------------------------- -- Conversion, Concatenation, and Selection Functions -- @@ -56,16 +72,28 @@ package Ada.Strings.Unbounded is function To_Unbounded_String (Source : String) return Unbounded_String; + -- Returns an Unbounded_String that represents Source function To_Unbounded_String (Length : Natural) return Unbounded_String; + -- Returns an Unbounded_String that represents an uninitialized String + -- whose length is Length. function To_String (Source : Unbounded_String) return String; + -- Returns the String with lower bound 1 represented by Source + + -- To_String and To_Unbounded_String are related as follows: + -- + -- * If S is a String, then To_String (To_Unbounded_String (S)) = S. + -- + -- * If U is an Unbounded_String, then + -- To_Unbounded_String (To_String (U)) = U. procedure Set_Unbounded_String (Target : out Unbounded_String; Source : String); pragma Ada_05 (Set_Unbounded_String); + -- Sets Target to an Unbounded_String that represents Source procedure Append (Source : in out Unbounded_String; @@ -79,6 +107,10 @@ package Ada.Strings.Unbounded is (Source : in out Unbounded_String; New_Item : Character); + -- For each of the Append procedures, the resulting string represented by + -- the Source parameter is given by the concatenation of the original value + -- of Source and the value of New_Item. + function "&" (Left : Unbounded_String; Right : Unbounded_String) return Unbounded_String; @@ -99,25 +131,43 @@ package Ada.Strings.Unbounded is (Left : Character; Right : Unbounded_String) return Unbounded_String; + -- Each of the "&" functions returns an Unbounded_String obtained by + -- concatenating the string or character given or represented by one of the + -- parameters, with the string or character given or represented by the + -- other parameter, and applying To_Unbounded_String to the concatenation + -- result string. + function Element (Source : Unbounded_String; Index : Positive) return Character; + -- Returns the character at position Index in the string represented by + -- Source; propagates Index_Error if Index > Length (Source). procedure Replace_Element (Source : in out Unbounded_String; Index : Positive; By : Character); + -- Updates Source such that the character at position Index in the string + -- represented by Source is By; propagates Index_Error if + -- Index > Length (Source). function Slice (Source : Unbounded_String; Low : Positive; High : Natural) return String; + -- Returns the slice at positions Low through High in the string + -- represented by Source; propagates Index_Error if + -- Low > Length (Source) + 1 or High > Length (Source). The bounds of the + -- returned string are Low and High. function Unbounded_Slice (Source : Unbounded_String; Low : Positive; High : Natural) return Unbounded_String; pragma Ada_05 (Unbounded_Slice); + -- Returns the slice at positions Low through High in the string + -- represented by Source as an Unbounded_String. This propagates + -- Index_Error if Low > Length(Source) + 1 or High > Length (Source). procedure Unbounded_Slice (Source : Unbounded_String; @@ -125,6 +175,9 @@ package Ada.Strings.Unbounded is Low : Positive; High : Natural); pragma Ada_05 (Unbounded_Slice); + -- Sets Target to the Unbounded_String representing the slice at positions + -- Low through High in the string represented by Source. This propagates + -- Index_Error if Low > Length(Source) + 1 or High > Length (Source). function "=" (Left : Unbounded_String; @@ -186,6 +239,10 @@ package Ada.Strings.Unbounded is (Left : String; Right : Unbounded_String) return Boolean; + -- Each of the functions "=", "<", ">", "<=", and ">=" returns the same + -- result as the corresponding String operation applied to the String + -- values given or represented by Left and Right. + ------------------------ -- Search Subprograms -- ------------------------ @@ -272,6 +329,11 @@ package Ada.Strings.Unbounded is First : out Positive; Last : out Natural); + -- Each of the search subprograms (Index, Index_Non_Blank, Count, + -- Find_Token) has the same effect as the corresponding subprogram in + -- Strings.Fixed applied to the string represented by the Unbounded_String + -- parameter. + ------------------------------------ -- String Translation Subprograms -- ------------------------------------ @@ -292,6 +354,11 @@ package Ada.Strings.Unbounded is (Source : in out Unbounded_String; Mapping : Maps.Character_Mapping_Function); + -- The Translate function has an analogous effect to the corresponding + -- subprogram in Strings.Fixed. The translation is applied to the string + -- represented by the Unbounded_String parameter, and the result is + -- converted (via To_Unbounded_String) to an Unbounded_String. + --------------------------------------- -- String Transformation Subprograms -- --------------------------------------- @@ -388,6 +455,19 @@ package Ada.Strings.Unbounded is (Left : Natural; Right : Unbounded_String) return Unbounded_String; + -- Each of the transformation functions (Replace_Slice, Insert, Overwrite, + -- Delete), selector functions (Trim, Head, Tail), and constructor + -- functions ("*") is likewise analogous to its corresponding subprogram in + -- Strings.Fixed. For each of the subprograms, the corresponding + -- fixed-length string subprogram is applied to the string represented by + -- the Unbounded_String parameter, and To_Unbounded_String is applied the + -- result string. + -- + -- For each of the procedures Translate, Replace_Slice, Insert, Overwrite, + -- Delete, Trim, Head, and Tail, the resulting string represented by the + -- Source parameter is given by the corresponding function for fixed-length + -- strings applied to the string represented by Source's original value. + private pragma Inline (Length); -- cgit v1.1 From de70d01f1a3f52654d39ecb97bd769032e5e2a60 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Fri, 5 Jul 2019 07:02:28 +0000 Subject: [Ada] Removing support for SCIL "contract-only" subprogram bodies Remove support added for CodePeer (which was never enabled by default; it was controlled by the -gnatd.K option) for generation of SCIL "contract-only" subprogram bodies. These were intended for use when a subprogram's "real" body is unavailable but the subprogram spec has pre/post-conditions specified. 2019-07-05 Javier Miranda gcc/ada/ * debug.adb (-gnatd.K): Leave available this switch. * contracts.adb (Build_And_Analyze_Contract_Only_Subprograms): Remove. * scil_ll.ads, scil_ll.adb (Contract_Only_Body_Flag, Contract_Only_Body_Nodes, Get_Contract_Only_Body, Is_Contract_Only_Body, Set_Contract_Only_Body): Remove. From-SVN: r273111 --- gcc/ada/ChangeLog | 9 + gcc/ada/contracts.adb | 495 -------------------------------------------------- gcc/ada/debug.adb | 9 +- gcc/ada/scil_ll.adb | 67 ------- gcc/ada/scil_ll.ads | 14 +- 5 files changed, 11 insertions(+), 583 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a3bdd0c..ac29b92 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-05 Javier Miranda + + * debug.adb (-gnatd.K): Leave available this switch. + * contracts.adb (Build_And_Analyze_Contract_Only_Subprograms): + Remove. + * scil_ll.ads, scil_ll.adb (Contract_Only_Body_Flag, + Contract_Only_Body_Nodes, Get_Contract_Only_Body, + Is_Contract_Only_Body, Set_Contract_Only_Body): Remove. + 2019-07-05 Pierre-Marie de Rodat * libgnat/a-strunb.ads: Import documentation from the RM diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb index af7c1b9..4610b53 100644 --- a/gcc/ada/contracts.adb +++ b/gcc/ada/contracts.adb @@ -25,7 +25,6 @@ with Aspects; use Aspects; with Atree; use Atree; -with Debug; use Debug; with Einfo; use Einfo; with Elists; use Elists; with Errout; use Errout; @@ -51,7 +50,6 @@ with Sinfo; use Sinfo; with Snames; use Snames; with Stand; use Stand; with Stringt; use Stringt; -with SCIL_LL; use SCIL_LL; with Tbuild; use Tbuild; package body Contracts is @@ -63,11 +61,6 @@ package body Contracts is -- -- Part_Of - procedure Build_And_Analyze_Contract_Only_Subprograms (L : List_Id); - -- (CodePeer): Subsidiary procedure to Analyze_Contracts which builds the - -- contract-only subprogram body of eligible subprograms found in L, adds - -- them to their corresponding list of declarations, and analyzes them. - procedure Expand_Subprogram_Contract (Body_Id : Entity_Id); -- Expand the contracts of a subprogram body and its correspoding spec (if -- any). This routine processes all [refined] pre- and postconditions as @@ -354,10 +347,6 @@ package body Contracts is Decl : Node_Id; begin - if CodePeer_Mode and then Debug_Flag_Dot_KK then - Build_And_Analyze_Contract_Only_Subprograms (L); - end if; - Decl := First (L); while Present (Decl) loop @@ -1305,490 +1294,6 @@ package body Contracts is Restore_SPARK_Mode (Saved_SM, Saved_SMP); end Analyze_Task_Contract; - ------------------------------------------------- - -- Build_And_Analyze_Contract_Only_Subprograms -- - ------------------------------------------------- - - procedure Build_And_Analyze_Contract_Only_Subprograms (L : List_Id) is - procedure Analyze_Contract_Only_Subprograms; - -- Analyze the contract-only subprograms of L - - procedure Append_Contract_Only_Subprograms (Subp_List : List_Id); - -- Append the contract-only bodies of Subp_List to its declarations list - - function Build_Contract_Only_Subprogram (E : Entity_Id) return Node_Id; - -- If E is an entity for a non-imported subprogram specification with - -- pre/postconditions and we are compiling with CodePeer mode, then - -- this procedure will create a wrapper to help Gnat2scil process its - -- contracts. Return Empty if the wrapper cannot be built. - - function Build_Contract_Only_Subprograms (L : List_Id) return List_Id; - -- Build the contract-only subprograms of all eligible subprograms found - -- in list L. - - function Has_Private_Declarations (N : Node_Id) return Boolean; - -- Return True for package specs, task definitions, and protected type - -- definitions whose list of private declarations is not empty. - - --------------------------------------- - -- Analyze_Contract_Only_Subprograms -- - --------------------------------------- - - procedure Analyze_Contract_Only_Subprograms is - procedure Analyze_Contract_Only_Bodies; - -- Analyze all the contract-only bodies of L - - ---------------------------------- - -- Analyze_Contract_Only_Bodies -- - ---------------------------------- - - procedure Analyze_Contract_Only_Bodies is - Decl : Node_Id; - - begin - Decl := First (L); - while Present (Decl) loop - if Nkind (Decl) = N_Subprogram_Body - and then Is_Contract_Only_Body - (Defining_Unit_Name (Specification (Decl))) - then - Analyze (Decl); - end if; - - Next (Decl); - end loop; - end Analyze_Contract_Only_Bodies; - - -- Start of processing for Analyze_Contract_Only_Subprograms - - begin - if Ekind (Current_Scope) /= E_Package then - Analyze_Contract_Only_Bodies; - - else - declare - Pkg_Spec : constant Node_Id := - Package_Specification (Current_Scope); - - begin - if not Has_Private_Declarations (Pkg_Spec) then - Analyze_Contract_Only_Bodies; - - -- For packages with private declarations, the contract-only - -- bodies of subprograms defined in the visible part of the - -- package are added to its private declarations (to ensure - -- that they do not cause premature freezing of types and also - -- that they are analyzed with proper visibility). Hence they - -- will be analyzed later. - - elsif Visible_Declarations (Pkg_Spec) = L then - null; - - elsif Private_Declarations (Pkg_Spec) = L then - Analyze_Contract_Only_Bodies; - end if; - end; - end if; - end Analyze_Contract_Only_Subprograms; - - -------------------------------------- - -- Append_Contract_Only_Subprograms -- - -------------------------------------- - - procedure Append_Contract_Only_Subprograms (Subp_List : List_Id) is - begin - if No (Subp_List) then - return; - end if; - - if Ekind (Current_Scope) /= E_Package then - Append_List (Subp_List, To => L); - - else - declare - Pkg_Spec : constant Node_Id := - Package_Specification (Current_Scope); - - begin - if not Has_Private_Declarations (Pkg_Spec) then - Append_List (Subp_List, To => L); - - -- If the package has private declarations then append them to - -- its private declarations; they will be analyzed when the - -- contracts of its private declarations are analyzed. - - else - Append_List - (List => Subp_List, - To => Private_Declarations (Pkg_Spec)); - end if; - end; - end if; - end Append_Contract_Only_Subprograms; - - ------------------------------------ - -- Build_Contract_Only_Subprogram -- - ------------------------------------ - - -- This procedure takes care of building a wrapper to generate better - -- analysis results in the case of a call to a subprogram whose body - -- is unavailable to CodePeer but whose specification includes Pre/Post - -- conditions. The body might be unavailable for any of a number or - -- reasons (it is imported, the .adb file is simply missing, or the - -- subprogram might be subject to an Annotate (CodePeer, Skip_Analysis) - -- pragma). The built subprogram has the following contents: - -- * check preconditions - -- * call the subprogram - -- * check postconditions - - function Build_Contract_Only_Subprogram (E : Entity_Id) return Node_Id is - Loc : constant Source_Ptr := Sloc (E); - - Missing_Body_Name : constant Name_Id := - New_External_Name (Chars (E), "__missing_body"); - - function Build_Missing_Body_Decls return List_Id; - -- Build the declaration of the missing body subprogram and its - -- corresponding pragma Import. - - function Build_Missing_Body_Subprogram_Call return Node_Id; - -- Build the call to the missing body subprogram - - function Skip_Contract_Only_Subprogram (E : Entity_Id) return Boolean; - -- Return True for cases where the wrapper is not needed or we cannot - -- build it. - - ------------------------------ - -- Build_Missing_Body_Decls -- - ------------------------------ - - function Build_Missing_Body_Decls return List_Id is - Spec : constant Node_Id := Declaration_Node (E); - Decl : Node_Id; - Prag : Node_Id; - - begin - Decl := - Make_Subprogram_Declaration (Loc, Copy_Subprogram_Spec (Spec)); - Set_Chars (Defining_Entity (Decl), Missing_Body_Name); - - Prag := - Make_Pragma (Loc, - Chars => Name_Import, - Pragma_Argument_Associations => New_List ( - Make_Pragma_Argument_Association (Loc, - Expression => Make_Identifier (Loc, Name_Ada)), - - Make_Pragma_Argument_Association (Loc, - Expression => Make_Identifier (Loc, Missing_Body_Name)))); - - return New_List (Decl, Prag); - end Build_Missing_Body_Decls; - - ---------------------------------------- - -- Build_Missing_Body_Subprogram_Call -- - ---------------------------------------- - - function Build_Missing_Body_Subprogram_Call return Node_Id is - Forml : Entity_Id; - Parms : List_Id; - - begin - Parms := New_List; - - -- Build parameter list that we need - - Forml := First_Formal (E); - while Present (Forml) loop - Append_To (Parms, Make_Identifier (Loc, Chars (Forml))); - Next_Formal (Forml); - end loop; - - -- Build the call to the missing body subprogram - - if Ekind_In (E, E_Function, E_Generic_Function) then - return - Make_Simple_Return_Statement (Loc, - Expression => - Make_Function_Call (Loc, - Name => - Make_Identifier (Loc, Missing_Body_Name), - Parameter_Associations => Parms)); - - else - return - Make_Procedure_Call_Statement (Loc, - Name => - Make_Identifier (Loc, Missing_Body_Name), - Parameter_Associations => Parms); - end if; - end Build_Missing_Body_Subprogram_Call; - - ----------------------------------- - -- Skip_Contract_Only_Subprogram -- - ----------------------------------- - - function Skip_Contract_Only_Subprogram - (E : Entity_Id) return Boolean - is - function Depends_On_Enclosing_Private_Type return Boolean; - -- Return True if some formal of E (or its return type) are - -- private types defined in an enclosing package. - - function Some_Enclosing_Package_Has_Private_Decls return Boolean; - -- Return True if some enclosing package of the current scope has - -- private declarations. - - --------------------------------------- - -- Depends_On_Enclosing_Private_Type -- - --------------------------------------- - - function Depends_On_Enclosing_Private_Type return Boolean is - function Defined_In_Enclosing_Package - (Typ : Entity_Id) return Boolean; - -- Return True if Typ is an entity defined in an enclosing - -- package of the current scope. - - ---------------------------------- - -- Defined_In_Enclosing_Package -- - ---------------------------------- - - function Defined_In_Enclosing_Package - (Typ : Entity_Id) return Boolean - is - Scop : Entity_Id := Scope (Current_Scope); - - begin - while Scop /= Scope (Typ) - and then not Is_Compilation_Unit (Scop) - loop - Scop := Scope (Scop); - end loop; - - return Scop = Scope (Typ); - end Defined_In_Enclosing_Package; - - -- Local variables - - Param_E : Entity_Id; - Typ : Entity_Id; - - -- Start of processing for Depends_On_Enclosing_Private_Type - - begin - Param_E := First_Entity (E); - while Present (Param_E) loop - Typ := Etype (Param_E); - - if Is_Private_Type (Typ) - and then Defined_In_Enclosing_Package (Typ) - then - return True; - end if; - - Next_Entity (Param_E); - end loop; - - return - Ekind (E) = E_Function - and then Is_Private_Type (Etype (E)) - and then Defined_In_Enclosing_Package (Etype (E)); - end Depends_On_Enclosing_Private_Type; - - ---------------------------------------------- - -- Some_Enclosing_Package_Has_Private_Decls -- - ---------------------------------------------- - - function Some_Enclosing_Package_Has_Private_Decls return Boolean is - Scop : Entity_Id := Current_Scope; - Pkg_Spec : Node_Id := Package_Specification (Scop); - - begin - loop - if Ekind (Scop) = E_Package - and then Has_Private_Declarations - (Package_Specification (Scop)) - then - Pkg_Spec := Package_Specification (Scop); - end if; - - exit when Is_Compilation_Unit (Scop); - Scop := Scope (Scop); - end loop; - - return Pkg_Spec /= Package_Specification (Current_Scope); - end Some_Enclosing_Package_Has_Private_Decls; - - -- Start of processing for Skip_Contract_Only_Subprogram - - begin - if not CodePeer_Mode - or else Inside_A_Generic - or else not Is_Subprogram (E) - or else Is_Abstract_Subprogram (E) - or else Is_Imported (E) - or else No (Contract (E)) - or else No (Pre_Post_Conditions (Contract (E))) - or else Is_Contract_Only_Body (E) - or else Convention (E) = Convention_Protected - then - return True; - - -- We do not support building the contract-only subprogram if E - -- is a subprogram declared in a nested package that has some - -- formal or return type depending on a private type defined in - -- an enclosing package. - - elsif Ekind (Current_Scope) = E_Package - and then Some_Enclosing_Package_Has_Private_Decls - and then Depends_On_Enclosing_Private_Type - then - if Debug_Flag_Dot_KK then - declare - Saved_Mode : constant Warning_Mode_Type := Warning_Mode; - - begin - -- Warnings are disabled by default under CodePeer_Mode - -- (see switch-c). Enable them temporarily. - - Warning_Mode := Normal; - Error_Msg_N - ("cannot generate contract-only subprogram?", E); - Warning_Mode := Saved_Mode; - end; - end if; - - return True; - end if; - - return False; - end Skip_Contract_Only_Subprogram; - - -- Start of processing for Build_Contract_Only_Subprogram - - begin - -- Test cases where the wrapper is not needed and cases where we - -- cannot build it. - - if Skip_Contract_Only_Subprogram (E) then - return Empty; - end if; - - -- Note on calls to Copy_Separate_Tree. The trees we are copying - -- here are fully analyzed, but we definitely want fully syntactic - -- unanalyzed trees in the body we construct, so that the analysis - -- generates the right visibility, and that is exactly what the - -- calls to Copy_Separate_Tree give us. - - declare - Name : constant Name_Id := - New_External_Name (Chars (E), "__contract_only"); - Id : Entity_Id; - Bod : Node_Id; - - begin - Bod := - Make_Subprogram_Body (Loc, - Specification => - Copy_Subprogram_Spec (Declaration_Node (E)), - Declarations => - Build_Missing_Body_Decls, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Build_Missing_Body_Subprogram_Call), - End_Label => Make_Identifier (Loc, Name))); - - Id := Defining_Unit_Name (Specification (Bod)); - - -- Copy only the pre/postconditions of the original contract - -- since it is what we need, but also because pragmas stored in - -- the other fields have N_Pragmas with N_Aspect_Specifications - -- that reference their associated pragma (thus causing an endless - -- loop when trying to copy the subtree). - - declare - New_Contract : constant Node_Id := Make_Contract (Sloc (E)); - - begin - Set_Pre_Post_Conditions (New_Contract, - Copy_Separate_Tree (Pre_Post_Conditions (Contract (E)))); - Set_Contract (Id, New_Contract); - end; - - -- Fix the name of this new subprogram and link the original - -- subprogram with its Contract_Only_Body subprogram. - - Set_Chars (Id, Name); - Set_Is_Contract_Only_Body (Id); - Set_Contract_Only_Body (E, Id); - - return Bod; - end; - end Build_Contract_Only_Subprogram; - - ------------------------------------- - -- Build_Contract_Only_Subprograms -- - ------------------------------------- - - function Build_Contract_Only_Subprograms (L : List_Id) return List_Id is - Decl : Node_Id; - New_Subp : Node_Id; - Result : List_Id := No_List; - Subp_Id : Entity_Id; - - begin - Decl := First (L); - while Present (Decl) loop - if Nkind (Decl) = N_Subprogram_Declaration then - Subp_Id := Defining_Unit_Name (Specification (Decl)); - New_Subp := Build_Contract_Only_Subprogram (Subp_Id); - - if Present (New_Subp) then - if No (Result) then - Result := New_List; - end if; - - Append_To (Result, New_Subp); - end if; - end if; - - Next (Decl); - end loop; - - return Result; - end Build_Contract_Only_Subprograms; - - ------------------------------ - -- Has_Private_Declarations -- - ------------------------------ - - function Has_Private_Declarations (N : Node_Id) return Boolean is - begin - if not Nkind_In (N, N_Package_Specification, - N_Protected_Definition, - N_Task_Definition) - then - return False; - else - return - Present (Private_Declarations (N)) - and then Is_Non_Empty_List (Private_Declarations (N)); - end if; - end Has_Private_Declarations; - - -- Local variables - - Subp_List : List_Id; - - -- Start of processing for Build_And_Analyze_Contract_Only_Subprograms - - begin - Subp_List := Build_Contract_Only_Subprograms (L); - Append_Contract_Only_Subprograms (Subp_List); - Analyze_Contract_Only_Subprograms; - end Build_And_Analyze_Contract_Only_Subprograms; - ----------------------------- -- Create_Generic_Contract -- ----------------------------- diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index fb9ebba..2635654 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -128,7 +128,7 @@ package body Debug is -- d.H GNSA mode for ASIS -- d.I Do not ignore enum representation clauses in CodePeer mode -- d.J Relaxed rules for pragma No_Return - -- d.K Enable generation of contract-only procedures in CodePeer mode + -- d.K -- d.L Depend on back end for limited types in if and case expressions -- d.M Relaxed RM semantics -- d.N Add node to all entities @@ -904,13 +904,6 @@ package body Debug is -- for that. If the procedure does in fact return normally, execution -- is erroneous, and therefore unpredictable. - -- d.K Enable generation of contract-only procedures in CodePeer mode and - -- report a warning on subprograms for which the contract-only body - -- cannot be built. Currently reported on subprograms defined in - -- nested package specs that have some formal (or return type) whose - -- type is a private type defined in some enclosing package and that - -- have pre/postconditions. - -- d.L Normally the front end generates special expansion for conditional -- expressions of a limited type. This debug flag removes this special -- case expansion, leaving it up to the back end to handle conditional diff --git a/gcc/ada/scil_ll.adb b/gcc/ada/scil_ll.adb index 58efe51..841206d 100644 --- a/gcc/ada/scil_ll.adb +++ b/gcc/ada/scil_ll.adb @@ -49,25 +49,6 @@ package body SCIL_LL is -- Internal Hash Tables -- -------------------------- - package Contract_Only_Body_Flag is new Simple_HTable - (Header_Num => Header_Num, - Element => Boolean, - No_Element => False, - Key => Node_Id, - Hash => Hash, - Equal => "="); - -- This table records the value of flag Is_Contract_Only_Flag of tree nodes - - package Contract_Only_Body_Nodes is new Simple_HTable - (Header_Num => Header_Num, - Element => Node_Id, - No_Element => Empty, - Key => Node_Id, - Hash => Hash, - Equal => "="); - -- This table records the value of attribute Contract_Only_Body of tree - -- nodes. - package SCIL_Nodes is new Simple_HTable (Header_Num => Header_Num, Element => Node_Id, @@ -86,21 +67,6 @@ package body SCIL_LL is Set_SCIL_Node (Target, Get_SCIL_Node (Source)); end Copy_SCIL_Node; - ---------------------------- - -- Get_Contract_Only_Body -- - ---------------------------- - - function Get_Contract_Only_Body (N : Node_Id) return Node_Id is - begin - if CodePeer_Mode - and then Present (N) - then - return Contract_Only_Body_Nodes.Get (N); - else - return Empty; - end if; - end Get_Contract_Only_Body; - ------------------- -- Get_SCIL_Node -- ------------------- @@ -132,42 +98,9 @@ package body SCIL_LL is procedure Initialize is begin SCIL_Nodes.Reset; - Contract_Only_Body_Nodes.Reset; - Contract_Only_Body_Flag.Reset; Set_Reporting_Proc (Copy_SCIL_Node'Access); end Initialize; - --------------------------- - -- Is_Contract_Only_Body -- - --------------------------- - - function Is_Contract_Only_Body (E : Entity_Id) return Boolean is - begin - return Contract_Only_Body_Flag.Get (E); - end Is_Contract_Only_Body; - - ---------------------------- - -- Set_Contract_Only_Body -- - ---------------------------- - - procedure Set_Contract_Only_Body (N : Node_Id; Value : Node_Id) is - begin - pragma Assert (CodePeer_Mode - and then Present (N) - and then Is_Contract_Only_Body (Value)); - - Contract_Only_Body_Nodes.Set (N, Value); - end Set_Contract_Only_Body; - - ------------------------------- - -- Set_Is_Contract_Only_Body -- - ------------------------------- - - procedure Set_Is_Contract_Only_Body (E : Entity_Id) is - begin - Contract_Only_Body_Flag.Set (E, True); - end Set_Is_Contract_Only_Body; - ------------------- -- Set_SCIL_Node -- ------------------- diff --git a/gcc/ada/scil_ll.ads b/gcc/ada/scil_ll.ads index 81d8260..6246af7 100644 --- a/gcc/ada/scil_ll.ads +++ b/gcc/ada/scil_ll.ads @@ -30,31 +30,19 @@ ------------------------------------------------------------------------------ -- This package extends the tree nodes with fields that are used to reference --- the SCIL node and the Contract_Only_Body of a subprogram with aspects. +-- the SCIL node. with Types; use Types; package SCIL_LL is - function Get_Contract_Only_Body (N : Node_Id) return Node_Id; - -- Read the value of attribute Contract_Only_Body - function Get_SCIL_Node (N : Node_Id) return Node_Id; -- Read the value of attribute SCIL node - procedure Set_Contract_Only_Body (N : Node_Id; Value : Node_Id); - -- Set the value of attribute Contract_Only_Body - procedure Set_SCIL_Node (N : Node_Id; Value : Node_Id); -- Set the value of attribute SCIL node procedure Initialize; -- Initialize the table of SCIL nodes - function Is_Contract_Only_Body (E : Entity_Id) return Boolean; - -- Return True if E is a Contract_Only_Body subprogram - - procedure Set_Is_Contract_Only_Body (E : Entity_Id); - -- Set E as Contract_Only_Body subprogram - end SCIL_LL; -- cgit v1.1 From 7145d799a347800ea6ef5c5e3114db11469137a8 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Fri, 5 Jul 2019 07:02:32 +0000 Subject: [Ada] Spurious error on aggregate with choice that is predicted subtype This patch fixes a spurious error on a record aggregate for a variant record when a choice in the aggregate is given by a subtype with a static predicate. The same expansion mechanism for such a variant, used in case statements, must be used here as well. 2019-07-05 Ed Schonberg gcc/ada/ * sem_util.adb (Encloing_Subprogram): If Enclosing_Dynamic_Scope is a loop, continue climbing the scope stack to find the enclosing subprogram. (Gather_Components): Handle properly a choice in a record aggregate that is given by a subtype with a static predicate. gcc/testsuite/ * gnat.dg/aggr25.adb, gnat.dg/aggr25.ads: New testcase. From-SVN: r273112 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/sem_util.adb | 8 +++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/aggr25.adb | 7 +++++++ gcc/testsuite/gnat.dg/aggr25.ads | 23 +++++++++++++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/aggr25.adb create mode 100644 gcc/testsuite/gnat.dg/aggr25.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ac29b92..cac6be7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-05 Ed Schonberg + + * sem_util.adb (Encloing_Subprogram): If Enclosing_Dynamic_Scope + is a loop, continue climbing the scope stack to find the + enclosing subprogram. + (Gather_Components): Handle properly a choice in a record + aggregate that is given by a subtype with a static predicate. + 2019-07-05 Javier Miranda * debug.adb (-gnatd.K): Leave available this switch. diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 55e6443..5c33694 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -6895,7 +6895,7 @@ package body Sem_Util is elsif Ekind (Dyn_Scop) = E_Subprogram_Body then return Corresponding_Spec (Parent (Parent (Dyn_Scop))); - elsif Ekind_In (Dyn_Scop, E_Block, E_Return_Statement) then + elsif Ekind_In (Dyn_Scop, E_Block, E_Return_Statement, E_Loop) then return Enclosing_Subprogram (Dyn_Scop); elsif Ekind (Dyn_Scop) = E_Entry then @@ -8939,6 +8939,12 @@ package body Sem_Util is begin Find_Discrete_Value : while Present (Variant) loop + + -- If a choice is a subtype with a static predicate, it must + -- be rewritten as an explicit list of non-predicated choices. + + Expand_Static_Predicates_In_Choices (Variant); + Discrete_Choice := First (Discrete_Choices (Variant)); while Present (Discrete_Choice) loop exit Find_Discrete_Value when diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d5905f0..82b8c22 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-05 Ed Schonberg + * gnat.dg/aggr25.adb, gnat.dg/aggr25.ads: New testcase. + +2019-07-05 Ed Schonberg + * gnat.dg/predicate7.adb, gnat.dg/predicate7.ads, gnat.dg/predicate7_pkg.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/aggr25.adb b/gcc/testsuite/gnat.dg/aggr25.adb new file mode 100644 index 0000000..d1bb32a --- /dev/null +++ b/gcc/testsuite/gnat.dg/aggr25.adb @@ -0,0 +1,7 @@ +-- { dg-do compile } + +package body Aggr25 is + + procedure Foo is null; + +end Aggr25; diff --git a/gcc/testsuite/gnat.dg/aggr25.ads b/gcc/testsuite/gnat.dg/aggr25.ads new file mode 100644 index 0000000..5637cfe --- /dev/null +++ b/gcc/testsuite/gnat.dg/aggr25.ads @@ -0,0 +1,23 @@ +package Aggr25 is + + type T_A is (A, B , C ,D); + + subtype Has_B_D is T_A with Static_Predicate => Has_B_D in B | D; + + type Obj_T (Kind : T_A) is + record + case Kind is + --OK-- when A | C => null; --OK-- + when Has_B_D => Value : Boolean; + --BAD-- when A | C => null; + when others => null; + end case; + end record; + + type T is access Obj_T; + + Unavailable : constant T := new Obj_T'(Kind => A); + + procedure Foo; + +end Aggr25; -- cgit v1.1 From adc81ec81db382128869cd62ca4e48bd87d1d880 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Fri, 5 Jul 2019 07:02:37 +0000 Subject: [Ada] Crash on exported build-in-place function This patch fixes a bug where if a function is build-in-place, and is exported, and contains an extended_return_statement whose object is initialized with another build-in-place function call, then the compiler will crash. 2019-07-05 Bob Duff gcc/ada/ * exp_ch6.adb (Is_Build_In_Place_Function): Narrow the check for Has_Foreign_Convention to the imported case only. If a build-in-place function is exported, and called from Ada code, build-in-place protocols should be used. gcc/testsuite/ * gnat.dg/bip_export.adb, gnat.dg/bip_export.ads: New testcase. From-SVN: r273113 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/exp_ch6.adb | 16 +++++++--------- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/bip_export.adb | 15 +++++++++++++++ gcc/testsuite/gnat.dg/bip_export.ads | 6 ++++++ 5 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/bip_export.adb create mode 100644 gcc/testsuite/gnat.dg/bip_export.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cac6be7..880f261 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Bob Duff + + * exp_ch6.adb (Is_Build_In_Place_Function): Narrow the check for + Has_Foreign_Convention to the imported case only. If a + build-in-place function is exported, and called from Ada code, + build-in-place protocols should be used. + 2019-07-05 Ed Schonberg * sem_util.adb (Encloing_Subprogram): If Enclosing_Dynamic_Scope diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index bd7ae2c..db9484f 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -7765,22 +7765,20 @@ package body Exp_Ch6 is -- For now we test whether E denotes a function or access-to-function -- type whose result subtype is inherently limited. Later this test - -- may be revised to allow composite nonlimited types. Functions with - -- a foreign convention or whose result type has a foreign convention - -- never qualify. + -- may be revised to allow composite nonlimited types. if Ekind_In (E, E_Function, E_Generic_Function) or else (Ekind (E) = E_Subprogram_Type and then Etype (E) /= Standard_Void_Type) then - -- Note: If the function has a foreign convention, it cannot build - -- its result in place, so you're on your own. On the other hand, - -- if only the return type has a foreign convention, its layout is - -- intended to be compatible with the other language, but the build- - -- in place machinery can ensure that the object is not copied. + -- If the function is imported from a foreign language, we don't do + -- build-in-place. Note that Import (Ada) functions can do + -- build-in-place. Note that it is OK for a build-in-place function + -- to return a type with a foreign convention; the build-in-place + -- machinery will ensure there is no copying. return Is_Build_In_Place_Result_Type (Etype (E)) - and then not Has_Foreign_Convention (E) + and then not (Has_Foreign_Convention (E) and then Is_Imported (E)) and then not Debug_Flag_Dot_L; else return False; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 82b8c22..3bd1aab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-05 Bob Duff + + * gnat.dg/bip_export.adb, gnat.dg/bip_export.ads: New testcase. + 2019-07-05 Ed Schonberg * gnat.dg/aggr25.adb, gnat.dg/aggr25.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/bip_export.adb b/gcc/testsuite/gnat.dg/bip_export.adb new file mode 100644 index 0000000..2935a84 --- /dev/null +++ b/gcc/testsuite/gnat.dg/bip_export.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } + +package body Bip_Export is + function F return T is + begin + return Result : constant T := G do + null; + end return; + end F; + + function G return T is + begin + return (null record); + end G; +end Bip_Export; diff --git a/gcc/testsuite/gnat.dg/bip_export.ads b/gcc/testsuite/gnat.dg/bip_export.ads new file mode 100644 index 0000000..dbbecf5 --- /dev/null +++ b/gcc/testsuite/gnat.dg/bip_export.ads @@ -0,0 +1,6 @@ +package Bip_Export is + type T is limited null record; + function F return T; + pragma Export (C, F); + function G return T; +end Bip_Export; -- cgit v1.1 From 6cc855048364cdfe4960e9f960e619efce6a9e4a Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Fri, 5 Jul 2019 07:02:41 +0000 Subject: [Ada] Typo fixes 2019-07-05 Piotr Trojanek gcc/ada/ * einfo.ads, sem_res.adb: Typo fixes in comments. From-SVN: r273114 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/einfo.ads | 2 +- gcc/ada/sem_res.adb | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 880f261..0d90861 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-05 Piotr Trojanek + + * einfo.ads, sem_res.adb: Typo fixes in comments. + 2019-07-05 Bob Duff * exp_ch6.adb (Is_Build_In_Place_Function): Narrow the check for diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 9dc6cc2..a248568 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -4490,7 +4490,7 @@ package Einfo is -- Suppress_Initialization (Flag105) -- Defined in all variable, type and subtype entities. If set for a base -- type, then the generation of initialization procedures is suppressed --- for the type. Any other implicit initialiation (e.g. from the use of +-- for the type. Any other implicit initialization (e.g. from the use of -- pragma Initialize_Scalars) is also suppressed if this flag is set for -- either the subtype in question, or for the base type. For variables, -- this flag suppresses all implicit initialization for the object, even diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 9c22635..7363abf 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -6070,7 +6070,7 @@ package body Sem_Res is -- is frozen in the usual fashion, by the appearance of a real body, -- or at the end of a declarative part. However an implicit call to -- an expression function may appear when it is part of a default - -- expression in a call to an initialiation procedure, and must be + -- expression in a call to an initialization procedure, and must be -- frozen now, even if the body is inserted at a later point. if Is_Entity_Name (Subp) -- cgit v1.1 From 43fa58c26a05f206ac36ab7d0340744c2769424f Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Fri, 5 Jul 2019 07:02:46 +0000 Subject: [Ada] Wrong accessibility level under -gnat12 For an anonymous allocator whose type is that of a stand-alone object of an anonymous access-to-object type, the accessibility level is that of the declaration of the stand-alone object; however it was incorrectly computed as being library level compiling under -gnat12 mode. 2019-07-05 Javier Miranda gcc/ada/ * exp_ch4.adb (Expand_N_Type_Conversion): Do not apply an accessibility check when the conversion is an access to class-wide interface type and it is an actual parameter. * exp_ch6.adb (Expand_Call_Helper): Add documentation on the accessibility level of an anonymous allocator defining the value of an access parameter. * sem_util.ads, sem_util.adb (Dynamic_Accessibility_Level): Add support for an anonymous allocator whose type is that of a stand-alone object of an anonymous access to object type. gcc/testsuite/ * gnat.dg/access6.adb: New testcase. From-SVN: r273115 --- gcc/ada/ChangeLog | 12 +++++++ gcc/ada/exp_ch4.adb | 3 +- gcc/ada/exp_ch6.adb | 5 ++- gcc/ada/sem_util.adb | 75 ++++++++++++++++++++++++++++++++++----- gcc/ada/sem_util.ads | 10 +++--- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gnat.dg/access6.adb | 28 +++++++++++++++ 7 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/access6.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0d90861..d07b468 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,15 @@ +2019-07-05 Javier Miranda + + * exp_ch4.adb (Expand_N_Type_Conversion): Do not apply an + accessibility check when the conversion is an access to + class-wide interface type and it is an actual parameter. + * exp_ch6.adb (Expand_Call_Helper): Add documentation on the + accessibility level of an anonymous allocator defining the value + of an access parameter. + * sem_util.ads, sem_util.adb (Dynamic_Accessibility_Level): Add + support for an anonymous allocator whose type is that of a + stand-alone object of an anonymous access to object type. + 2019-07-05 Piotr Trojanek * einfo.ads, sem_res.adb: Typo fixes in comments. diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 0d4c294..7a048c6 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -11471,7 +11471,8 @@ package body Exp_Ch4 is then if not Comes_From_Source (N) and then Nkind_In (Parent (N), N_Function_Call, - N_Procedure_Call_Statement) + N_Procedure_Call_Statement, + N_Parameter_Association) and then Is_Interface (Designated_Type (Target_Type)) and then Is_Class_Wide_Type (Designated_Type (Target_Type)) then diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index db9484f..6e7299a 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -3271,7 +3271,10 @@ package body Exp_Ch6 is -- For allocators we pass the level of the execution of the -- called subprogram, which is one greater than the current - -- scope level. + -- scope level. However, according to RM 3.10.2(14/3) this + -- is wrong since for an anonymous allocator defining the + -- value of an access parameter, the accessibility level is + -- that of the innermost master of the call??? when N_Allocator => Add_Extra_Actual diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 5c33694..48822e2 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -6452,8 +6452,8 @@ package body Sem_Util is -- Dynamic_Accessibility_Level -- --------------------------------- - function Dynamic_Accessibility_Level (Expr : Node_Id) return Node_Id is - Loc : constant Source_Ptr := Sloc (Expr); + function Dynamic_Accessibility_Level (N : Node_Id) return Node_Id is + Loc : constant Source_Ptr := Sloc (N); function Make_Level_Literal (Level : Uint) return Node_Id; -- Construct an integer literal representing an accessibility level @@ -6473,7 +6473,12 @@ package body Sem_Util is -- Local variables - E : Entity_Id; + Expr : constant Node_Id := Original_Node (N); + -- Expr references the original node because at this stage N may be the + -- reference to a variable internally created by the frontend to remove + -- side effects of an expression. + + E : Entity_Id; -- Start of processing for Dynamic_Accessibility_Level @@ -6530,12 +6535,66 @@ package body Sem_Util is when N_Allocator => - -- Unimplemented: depends on context. As an actual parameter where - -- formal type is anonymous, use - -- Scope_Depth (Current_Scope) + 1. - -- For other cases, see 3.10.2(14/3) and following. ??? + -- This is not fully implemented since it depends on context (see + -- 3.10.2(14/3-14.2/3). More work is needed in the following cases + -- + -- 1) For an anonymous allocator defining the value of an access + -- parameter, the accessibility level is that of the innermost + -- master of the call; however currently we pass the level of + -- execution of the called subprogram, which is one greater + -- than the current scope level (see Expand_Call_Helper). + -- + -- For example, a statement is a master and a declaration is + -- not a master; so we should not pass in the same level for + -- the following cases: + -- + -- function F (X : access Integer) return T is ... ; + -- Decl : T := F (new Integer); -- level is off by one + -- begin + -- Decl := F (new Integer); -- we get this case right + -- + -- 2) For an anonymous allocator that defines the result of a + -- function with an access result, the accessibility level is + -- determined as though the allocator were in place of the call + -- of the function. In the special case of a call that is the + -- operand of a type conversion the level is that of the target + -- access type of the conversion. + -- + -- 3) For an anonymous allocator defining an access discriminant + -- the accessibility level is determined as follows: + -- * for an allocator used to define the discriminant of an + -- object, the level of the object + -- * for an allocator used to define the constraint in a + -- subtype_indication in any other context, the level of + -- the master that elaborates the subtype_indication. + + case Nkind (Parent (N)) is + when N_Object_Declaration => + + -- For an anonymous allocator whose type is that of a + -- stand-alone object of an anonymous access-to-object type, + -- the accessibility level is that of the declaration of the + -- stand-alone object. - null; + return Make_Level_Literal + (Object_Access_Level + (Defining_Identifier (Parent (N)))); + + when N_Assignment_Statement => + return Make_Level_Literal + (Object_Access_Level (Name (Parent (N)))); + + when others => + declare + S : constant String := + Node_Kind'Image (Nkind (Parent (N))); + begin + Error_Msg_Strlen := S'Length; + Error_Msg_String (1 .. Error_Msg_Strlen) := S; + Error_Msg_N ("unsupported context for anonymous " & + "allocator (~)", Parent (N)); + end; + end case; when N_Type_Conversion => if not Is_Local_Anonymous_Access (Etype (Expr)) then diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 43c0bc5..3eb9d57 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -622,11 +622,11 @@ package Sem_Util is -- private components of protected objects, but is generally useful when -- restriction No_Implicit_Heap_Allocation is active. - function Dynamic_Accessibility_Level (Expr : Node_Id) return Node_Id; - -- Expr should be an expression of an access type. Builds an integer - -- literal except in cases involving anonymous access types, where - -- accessibility levels are tracked at run time (access parameters and - -- Ada 2012 stand-alone objects). + function Dynamic_Accessibility_Level (N : Node_Id) return Node_Id; + -- N should be an expression of an access type. Builds an integer literal + -- except in cases involving anonymous access types, where accessibility + -- levels are tracked at run time (access parameters and Ada 2012 stand- + -- alone objects). function Effective_Extra_Accessibility (Id : Entity_Id) return Entity_Id; -- Same as Einfo.Extra_Accessibility except thtat object renames diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3bd1aab..08d8695 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-05 Javier Miranda + + * gnat.dg/access6.adb: New testcase. + 2019-07-05 Bob Duff * gnat.dg/bip_export.adb, gnat.dg/bip_export.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/access6.adb b/gcc/testsuite/gnat.dg/access6.adb new file mode 100644 index 0000000..3956061 --- /dev/null +++ b/gcc/testsuite/gnat.dg/access6.adb @@ -0,0 +1,28 @@ +-- { dg-do run } +-- { dg-options "-gnat12" } + +procedure Access6 is + type Int_Ref is access all Integer; + Ptr : Int_Ref; + + procedure update_ptr (X : access integer) is + begin + -- Failed accessibility test: supposed to raise a Program_Error + Ptr := Int_Ref (X); + end; + + procedure bar is + ref : access integer := new integer; + begin + update_ptr (ref); + end; +begin + bar; + + -- As the call to bar must raise a Program_Error, the following is not supposed to be executed: + raise Constraint_Error; + +exception + when Program_Error => + null; +end; -- cgit v1.1 From 60a38ae15cbee078c0886720e3ee3d4118593216 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Fri, 5 Jul 2019 07:02:51 +0000 Subject: [Ada] Failure to detect trivial infinite recursion This patch reimplements the detection of trivial infinite recursion to remove the implicit assumptions concenring the structure and contents of the enclosing subprogram statements. ------------ -- Source -- ------------ -- infinite.adb procedure Infinite with SPARK_Mode is function Func_1 (Val : Integer) return Integer; function Func_2 (Val : Integer) return Integer; function Func_3 (Val : Integer) return Integer; function Func_4 (Val : Integer) return Integer; function Func_5 (Val : Integer) return Integer; function Func_6 (Val : Integer) return Integer; function Func_7 (Val : Integer) return Integer; function Func_8 (Val_1 : Integer; Val_2 : Integer) return Integer; procedure Proc_1 (Val : Integer); function Func_1 (Val : Integer) return Integer is begin return Func_1 (Val); -- WARN end Func_1; function Func_2 (Val : Integer) return Integer is begin return Func_2 (123); -- none end Func_2; function Func_3 (Val : Integer) return Integer is Temp : Integer; begin Temp := Func_3 (Val); -- WARN return Temp; end Func_3; function Func_4 (Val : Integer) return Integer is Temp : Integer; begin Temp := Func_4 (123); -- none return Temp; end Func_4; function Func_5 (Val : Integer) return Integer is begin Proc_1 (Val); return Func_5 (Val); -- none end Func_5; function Func_6 (Val : Integer) return Integer is begin Proc_1 (Val); return Func_6 (123); -- none end Func_6; function Func_7 (Val : Integer) return Integer is begin raise Program_Error; return Func_7 (Val); -- none end Func_7; function Func_8 (Val_1 : Integer; Val_2 : Integer) return Integer is begin return Func_8 (Val_1, 123); -- none end Func_8; procedure Proc_1 (Val : Integer) is begin Proc_1 (Val); -- WARN end Proc_1; begin null; end Infinite; ---------------------------- -- Compilation and output -- ---------------------------- $ gcc -c infinite.adb infinite.adb:14:14: infinite recursion infinite.adb:14:14: Storage_Error would have been raised at run time infinite.adb:25:15: infinite recursion infinite.adb:25:15: Storage_Error would have been raised at run time infinite.adb:61:07: infinite recursion infinite.adb:61:07: Storage_Error would have been raised at run time 2019-07-05 Hristian Kirtchev gcc/ada/ * sem_res.adb (Check_Infinite_Recursion): Reimplemented. (Enclosing_Declaration_Or_Statement, Invoked_With_Different_Arguments, Is_Conditional_Statement, Is_Control_Flow_Statement, Is_Immediately_Within_Body, Is_Raise_Idiom, Is_Raise_Statement, Is_Sole_Statement, Preceded_By_Control_Flow_Statement, Within_Conditional_Statement): New routines. From-SVN: r273116 --- gcc/ada/ChangeLog | 10 ++ gcc/ada/sem_res.adb | 480 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 371 insertions(+), 119 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d07b468..1ae3a77 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-07-05 Hristian Kirtchev + + * sem_res.adb (Check_Infinite_Recursion): Reimplemented. + (Enclosing_Declaration_Or_Statement, + Invoked_With_Different_Arguments, Is_Conditional_Statement, + Is_Control_Flow_Statement, Is_Immediately_Within_Body, + Is_Raise_Idiom, Is_Raise_Statement, Is_Sole_Statement, + Preceded_By_Control_Flow_Statement, + Within_Conditional_Statement): New routines. + 2019-07-05 Javier Miranda * exp_ch4.adb (Expand_N_Type_Conversion): Do not apply an diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 7363abf..8dc8eeb 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -111,8 +111,8 @@ package body Sem_Res is Pref : Node_Id); -- Check that the type of the prefix of a dereference is not incomplete - function Check_Infinite_Recursion (N : Node_Id) return Boolean; - -- Given a call node, N, which is known to occur immediately within the + function Check_Infinite_Recursion (Call : Node_Id) return Boolean; + -- Given a call node, Call, which is known to occur immediately within the -- subprogram being called, determines whether it is a detectable case of -- an infinite recursion, and if so, outputs appropriate messages. Returns -- True if an infinite recursion is detected, and False otherwise. @@ -695,164 +695,406 @@ package body Sem_Res is -- Check_Infinite_Recursion -- ------------------------------ - function Check_Infinite_Recursion (N : Node_Id) return Boolean is - P : Node_Id; - C : Node_Id; + function Check_Infinite_Recursion (Call : Node_Id) return Boolean is + function Enclosing_Declaration_Or_Statement (N : Node_Id) return Node_Id; + -- Return the nearest enclosing declaration or statement that houses + -- arbitrary node N. - function Same_Argument_List return Boolean; - -- Check whether list of actuals is identical to list of formals of - -- called function (which is also the enclosing scope). + function Invoked_With_Different_Arguments (N : Node_Id) return Boolean; + -- Determine whether call N invokes the related enclosing subprogram + -- with actuals that differ from the subprogram's formals. - ------------------------ - -- Same_Argument_List -- - ------------------------ + function Is_Conditional_Statement (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N denotes a conditional construct + + function Is_Control_Flow_Statement (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N denotes a control flow statement + -- or a construct that may contains such a statement. + + function Is_Immediately_Within_Body (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N appears immediately within the + -- statements of an entry or subprogram body. + + function Is_Raise_Idiom (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N appears immediately within the + -- body of an entry or subprogram, and is preceded by a single raise + -- statement. - function Same_Argument_List return Boolean is - A : Node_Id; - F : Entity_Id; - Subp : Entity_Id; + function Is_Raise_Statement (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N denotes a raise statement + + function Is_Sole_Statement (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N is the sole source statement in + -- the body of the enclosing subprogram. + + function Preceded_By_Control_Flow_Statement (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N is preceded by a control flow + -- statement. + + function Within_Conditional_Statement (N : Node_Id) return Boolean; + -- Determine whether arbitrary node N appears within a conditional + -- construct. + + ---------------------------------------- + -- Enclosing_Declaration_Or_Statement -- + ---------------------------------------- + + function Enclosing_Declaration_Or_Statement + (N : Node_Id) return Node_Id + is + Par : Node_Id; begin - if not Is_Entity_Name (Name (N)) then - return False; - else - Subp := Entity (Name (N)); - end if; + Par := N; + while Present (Par) loop + if Is_Declaration (Par) or else Is_Statement (Par) then + return Par; - F := First_Formal (Subp); - A := First_Actual (N); - while Present (F) and then Present (A) loop - if not Is_Entity_Name (A) or else Entity (A) /= F then - return False; + -- Prevent the search from going too far + + elsif Is_Body_Or_Package_Declaration (Par) then + exit; end if; - Next_Actual (A); - Next_Formal (F); + Par := Parent (Par); end loop; - return True; - end Same_Argument_List; + return N; + end Enclosing_Declaration_Or_Statement; - -- Start of processing for Check_Infinite_Recursion + -------------------------------------- + -- Invoked_With_Different_Arguments -- + -------------------------------------- - begin - -- Special case, if this is a procedure call and is a call to the - -- current procedure with the same argument list, then this is for - -- sure an infinite recursion and we insert a call to raise SE. + function Invoked_With_Different_Arguments (N : Node_Id) return Boolean is + Subp : constant Entity_Id := Entity (Name (N)); - if Is_List_Member (N) - and then List_Length (List_Containing (N)) = 1 - and then Same_Argument_List - then - declare - P : constant Node_Id := Parent (N); - begin - if Nkind (P) = N_Handled_Sequence_Of_Statements - and then Nkind (Parent (P)) = N_Subprogram_Body - and then Is_Empty_List (Declarations (Parent (P))) + Actual : Node_Id; + Formal : Entity_Id; + + begin + -- Determine whether the formals of the invoked subprogram are not + -- used as actuals in the call. + + Actual := First_Actual (Call); + Formal := First_Formal (Subp); + while Present (Actual) and then Present (Formal) loop + + -- The current actual does not match the current formal + + if not (Is_Entity_Name (Actual) + and then Entity (Actual) = Formal) then - Error_Msg_Warn := SPARK_Mode /= On; - Error_Msg_N ("!infinite recursion<<", N); - Error_Msg_N ("\!Storage_Error [<<", N); - Insert_Action (N, - Make_Raise_Storage_Error (Sloc (N), - Reason => SE_Infinite_Recursion)); return True; end if; - end; - end if; - -- If not that special case, search up tree, quitting if we reach a - -- construct (e.g. a conditional) that tells us that this is not a - -- case for an infinite recursion warning. + Next_Actual (Actual); + Next_Formal (Formal); + end loop; - C := N; - loop - P := Parent (C); + return False; + end Invoked_With_Different_Arguments; - -- If no parent, then we were not inside a subprogram, this can for - -- example happen when processing certain pragmas in a spec. Just - -- return False in this case. + ------------------------------ + -- Is_Conditional_Statement -- + ------------------------------ - if No (P) then + function Is_Conditional_Statement (N : Node_Id) return Boolean is + begin + return + Nkind_In (N, N_And_Then, + N_Case_Expression, + N_Case_Statement, + N_If_Expression, + N_If_Statement, + N_Or_Else); + end Is_Conditional_Statement; + + ------------------------------- + -- Is_Control_Flow_Statement -- + ------------------------------- + + function Is_Control_Flow_Statement (N : Node_Id) return Boolean is + begin + -- Delay statements do not affect the control flow because they + -- simply postpone the execution of all subsequent statements. + + if Nkind (N) in N_Delay_Statement then return False; + + -- Otherwise it is assumed that all other statements may affect the + -- control flow in some way. A raise statement may be expanded into + -- a non-statement node. + + else + return Is_Statement (N) or else Is_Raise_Statement (N); end if; + end Is_Control_Flow_Statement; - -- Done if we get to subprogram body, this is definitely an infinite - -- recursion case if we did not find anything to stop us. + -------------------------------- + -- Is_Immediately_Within_Body -- + -------------------------------- - exit when Nkind (P) = N_Subprogram_Body; + function Is_Immediately_Within_Body (N : Node_Id) return Boolean is + HSS : constant Node_Id := Parent (N); - -- If appearing in conditional, result is false + begin + return + Nkind (HSS) = N_Handled_Sequence_Of_Statements + and then Nkind_In (Parent (HSS), N_Entry_Body, N_Subprogram_Body) + and then Is_List_Member (N) + and then List_Containing (N) = Statements (HSS); + end Is_Immediately_Within_Body; - if Nkind_In (P, N_Or_Else, - N_And_Then, - N_Case_Expression, - N_Case_Statement, - N_If_Expression, - N_If_Statement) - then - return False; + -------------------- + -- Is_Raise_Idiom -- + -------------------- - elsif Nkind (P) = N_Handled_Sequence_Of_Statements - and then C /= First (Statements (P)) - then - -- If the call is the expression of a return statement and the - -- actuals are identical to the formals, it's worth a warning. - -- However, we skip this if there is an immediately preceding - -- raise statement, since the call is never executed. + function Is_Raise_Idiom (N : Node_Id) return Boolean is + Raise_Stmt : Node_Id; + Stmt : Node_Id; - -- Furthermore, this corresponds to a common idiom: + begin + if Is_Immediately_Within_Body (N) then - -- function F (L : Thing) return Boolean is - -- begin - -- raise Program_Error; - -- return F (L); - -- end F; + -- Assume that no raise statement has been seen yet - -- for generating a stub function + Raise_Stmt := Empty; - if Nkind (Parent (N)) = N_Simple_Return_Statement - and then Same_Argument_List - then - exit when not Is_List_Member (Parent (N)); + -- Examine the statements preceding the input node, skipping + -- internally-generated constructs. - -- OK, return statement is in a statement list, look for raise + Stmt := Prev (N); + while Present (Stmt) loop - declare - Nod : Node_Id; + -- Multiple raise statements violate the idiom - begin - -- Skip past N_Freeze_Entity nodes generated by expansion + if Is_Raise_Statement (Stmt) then + if Present (Raise_Stmt) then + return False; + end if; - Nod := Prev (Parent (N)); - while Present (Nod) - and then Nkind (Nod) = N_Freeze_Entity - loop - Prev (Nod); - end loop; + Raise_Stmt := Stmt; - -- If no raise statement, give warning. We look at the - -- original node, because in the case of "raise ... with - -- ...", the node has been transformed into a call. + elsif Comes_From_Source (Stmt) then + exit; + end if; - exit when Nkind (Original_Node (Nod)) /= N_Raise_Statement - and then - (Nkind (Nod) not in N_Raise_xxx_Error - or else Present (Condition (Nod))); - end; - end if; + Stmt := Prev (Stmt); + end loop; - return False; + -- At this point the node must be preceded by a raise statement, + -- and the raise statement has to be the sole statement within + -- the enclosing entry or subprogram body. - else - C := P; + return + Present (Raise_Stmt) and then Is_Sole_Statement (Raise_Stmt); end if; - end loop; - Error_Msg_Warn := SPARK_Mode /= On; - Error_Msg_N ("!possible infinite recursion<<", N); - Error_Msg_N ("\!??Storage_Error ]<<", N); + return False; + end Is_Raise_Idiom; + + ------------------------ + -- Is_Raise_Statement -- + ------------------------ + + function Is_Raise_Statement (N : Node_Id) return Boolean is + begin + -- A raise statement may be transfomed into a Raise_xxx_Error node + + return + Nkind (N) = N_Raise_Statement + or else Nkind (N) in N_Raise_xxx_Error; + end Is_Raise_Statement; + + ----------------------- + -- Is_Sole_Statement -- + ----------------------- + + function Is_Sole_Statement (N : Node_Id) return Boolean is + Stmt : Node_Id; + + begin + -- The input node appears within the statements of an entry or + -- subprogram body. Examine the statements preceding the node. + + if Is_Immediately_Within_Body (N) then + Stmt := Prev (N); + + while Present (Stmt) loop + + -- The statement is preceded by another statement or a source + -- construct. This indicates that the node does not appear by + -- itself. + + if Is_Control_Flow_Statement (Stmt) + or else Comes_From_Source (Stmt) + then + return False; + end if; + + Stmt := Prev (Stmt); + end loop; + + return True; + end if; + + -- The input node is within a construct nested inside the entry or + -- subprogram body. + + return False; + end Is_Sole_Statement; + + ---------------------------------------- + -- Preceded_By_Control_Flow_Statement -- + ---------------------------------------- + + function Preceded_By_Control_Flow_Statement + (N : Node_Id) return Boolean + is + Stmt : Node_Id; + + begin + if Is_List_Member (N) then + Stmt := Prev (N); + + -- Examine the statements preceding the input node + + while Present (Stmt) loop + if Is_Control_Flow_Statement (Stmt) then + return True; + end if; + + Stmt := Prev (Stmt); + end loop; + + return False; + end if; + + -- Assume that the node is part of some control flow statement + + return True; + end Preceded_By_Control_Flow_Statement; + + ---------------------------------- + -- Within_Conditional_Statement -- + ---------------------------------- + + function Within_Conditional_Statement (N : Node_Id) return Boolean is + Stmt : Node_Id; + + begin + Stmt := Parent (N); + while Present (Stmt) loop + if Is_Conditional_Statement (Stmt) then + return True; + + -- Prevent the search from going too far + + elsif Is_Body_Or_Package_Declaration (Stmt) then + exit; + end if; + + Stmt := Parent (Stmt); + end loop; + + return False; + end Within_Conditional_Statement; + + -- Local variables + + Call_Context : constant Node_Id := + Enclosing_Declaration_Or_Statement (Call); + + -- Start of processing for Check_Infinite_Recursion + + begin + -- The call is assumed to be safe when the enclosing subprogram is + -- invoked with actuals other than its formals. + -- + -- procedure Proc (F1 : ...; F2 : ...; ...; FN : ...) is + -- begin + -- ... + -- Proc (A1, A2, ..., AN); + -- ... + -- end Proc; + + if Invoked_With_Different_Arguments (Call) then + return False; + + -- The call is assumed to be safe when the invocation of the enclosing + -- subprogram depends on a conditional statement. + -- + -- procedure Proc (F1 : ...; F2 : ...; ...; FN : ...) is + -- begin + -- ... + -- if Some_Condition then + -- Proc (F1, F2, ..., FN); + -- end if; + -- ... + -- end Proc; + + elsif Within_Conditional_Statement (Call) then + return False; + + -- The context of the call is assumed to be safe when the invocation of + -- the enclosing subprogram is preceded by some control flow statement. + -- + -- procedure Proc (F1 : ...; F2 : ...; ...; FN : ...) is + -- begin + -- ... + -- if Some_Condition then + -- ... + -- end if; + -- ... + -- Proc (F1, F2, ..., FN); + -- ... + -- end Proc; + + elsif Preceded_By_Control_Flow_Statement (Call_Context) then + return False; + + -- Detect an idiom where the context of the call is preceded by a single + -- raise statement. + -- + -- procedure Proc (F1 : ...; F2 : ...; ...; FN : ...) is + -- begin + -- raise ...; + -- Proc (F1, F2, ..., FN); + -- end Proc; + + elsif Is_Raise_Idiom (Call_Context) then + return False; + end if; + + -- At this point it is certain that infinite recursion will take place + -- as long as the call is executed. Detect a case where the context of + -- the call is the sole source statement within the subprogram body. + -- + -- procedure Proc (F1 : ...; F2 : ...; ...; FN : ...) is + -- begin + -- Proc (F1, F2, ..., FN); + -- end Proc; + -- + -- Install an explicit raise to prevent the infinite recursion. + + if Is_Sole_Statement (Call_Context) then + Error_Msg_Warn := SPARK_Mode /= On; + Error_Msg_N ("!infinite recursion<<", Call); + Error_Msg_N ("\!Storage_Error [<<", Call); + + Insert_Action (Call, + Make_Raise_Storage_Error (Sloc (Call), + Reason => SE_Infinite_Recursion)); + + -- Otherwise infinite recursion could take place, considering other flow + -- control constructs such as gotos, exit statements, etc. + + else + Error_Msg_Warn := SPARK_Mode /= On; + Error_Msg_N ("!possible infinite recursion<<", Call); + Error_Msg_N ("\!??Storage_Error ]<<", Call); + end if; return True; end Check_Infinite_Recursion; -- cgit v1.1 From fe04f57a81366e5aaf0fec054d87919f6c243947 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Fri, 5 Jul 2019 07:02:56 +0000 Subject: [Ada] System.Linux: fix typos in comments 2019-07-05 Arnaud Charlet gcc/ada/ * libgnarl/s-linux.ads, libgnarl/s-linux__alpha.ads, libgnarl/s-linux__android.ads, libgnarl/s-linux__hppa.ads, libgnarl/s-linux__mips.ads, libgnarl/s-linux__riscv.ads, libgnarl/s-linux__sparc.ads: Fix typos in comments. From-SVN: r273117 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/libgnarl/s-linux.ads | 2 +- gcc/ada/libgnarl/s-linux__alpha.ads | 2 +- gcc/ada/libgnarl/s-linux__android.ads | 2 +- gcc/ada/libgnarl/s-linux__hppa.ads | 2 +- gcc/ada/libgnarl/s-linux__mips.ads | 2 +- gcc/ada/libgnarl/s-linux__riscv.ads | 2 +- gcc/ada/libgnarl/s-linux__sparc.ads | 2 +- 8 files changed, 14 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1ae3a77..65197d5 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Arnaud Charlet + + * libgnarl/s-linux.ads, libgnarl/s-linux__alpha.ads, + libgnarl/s-linux__android.ads, libgnarl/s-linux__hppa.ads, + libgnarl/s-linux__mips.ads, libgnarl/s-linux__riscv.ads, + libgnarl/s-linux__sparc.ads: Fix typos in comments. + 2019-07-05 Hristian Kirtchev * sem_res.adb (Check_Infinite_Recursion): Reimplemented. diff --git a/gcc/ada/libgnarl/s-linux.ads b/gcc/ada/libgnarl/s-linux.ads index 94c2ea1..4220fa0 100644 --- a/gcc/ada/libgnarl/s-linux.ads +++ b/gcc/ada/libgnarl/s-linux.ads @@ -82,7 +82,7 @@ package System.Linux is SIGILL : constant := 4; -- illegal instruction (not reset) SIGTRAP : constant := 5; -- trace trap (not reset) SIGIOT : constant := 6; -- IOT instruction - SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future + SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future SIGFPE : constant := 8; -- floating point exception SIGKILL : constant := 9; -- kill (cannot be caught or ignored) SIGBUS : constant := 7; -- bus error diff --git a/gcc/ada/libgnarl/s-linux__alpha.ads b/gcc/ada/libgnarl/s-linux__alpha.ads index 18a1253..fea3746 100644 --- a/gcc/ada/libgnarl/s-linux__alpha.ads +++ b/gcc/ada/libgnarl/s-linux__alpha.ads @@ -82,7 +82,7 @@ package System.Linux is SIGILL : constant := 4; -- illegal instruction (not reset) SIGTRAP : constant := 5; -- trace trap (not reset) SIGIOT : constant := 6; -- IOT instruction - SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future + SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future SIGFPE : constant := 8; -- floating point exception SIGKILL : constant := 9; -- kill (cannot be caught or ignored) SIGBUS : constant := 10; -- bus error diff --git a/gcc/ada/libgnarl/s-linux__android.ads b/gcc/ada/libgnarl/s-linux__android.ads index 914f08d..8d8a1f4 100644 --- a/gcc/ada/libgnarl/s-linux__android.ads +++ b/gcc/ada/libgnarl/s-linux__android.ads @@ -82,7 +82,7 @@ package System.Linux is SIGILL : constant := 4; -- illegal instruction (not reset) SIGTRAP : constant := 5; -- trace trap (not reset) SIGIOT : constant := 6; -- IOT instruction - SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future + SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future SIGFPE : constant := 8; -- floating point exception SIGKILL : constant := 9; -- kill (cannot be caught or ignored) SIGBUS : constant := 7; -- bus error diff --git a/gcc/ada/libgnarl/s-linux__hppa.ads b/gcc/ada/libgnarl/s-linux__hppa.ads index bc7034a..feb21f6 100644 --- a/gcc/ada/libgnarl/s-linux__hppa.ads +++ b/gcc/ada/libgnarl/s-linux__hppa.ads @@ -82,7 +82,7 @@ package System.Linux is SIGILL : constant := 4; -- illegal instruction (not reset) SIGTRAP : constant := 5; -- trace trap (not reset) SIGIOT : constant := 6; -- IOT instruction - SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future + SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future SIGEMT : constant := 7; -- EMT SIGFPE : constant := 8; -- floating point exception SIGKILL : constant := 9; -- kill (cannot be caught or ignored) diff --git a/gcc/ada/libgnarl/s-linux__mips.ads b/gcc/ada/libgnarl/s-linux__mips.ads index 0fa808f..6aea5a8 100644 --- a/gcc/ada/libgnarl/s-linux__mips.ads +++ b/gcc/ada/libgnarl/s-linux__mips.ads @@ -82,7 +82,7 @@ package System.Linux is SIGILL : constant := 4; -- illegal instruction (not reset) SIGTRAP : constant := 5; -- trace trap (not reset) SIGIOT : constant := 6; -- IOT instruction - SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future + SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future SIGEMT : constant := 7; -- EMT SIGFPE : constant := 8; -- floating point exception SIGKILL : constant := 9; -- kill (cannot be caught or ignored) diff --git a/gcc/ada/libgnarl/s-linux__riscv.ads b/gcc/ada/libgnarl/s-linux__riscv.ads index 6151b29..61ccc3b 100644 --- a/gcc/ada/libgnarl/s-linux__riscv.ads +++ b/gcc/ada/libgnarl/s-linux__riscv.ads @@ -82,7 +82,7 @@ package System.Linux is SIGILL : constant := 4; -- illegal instruction (not reset) SIGTRAP : constant := 5; -- trace trap (not reset) SIGIOT : constant := 6; -- IOT instruction - SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future + SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future SIGBUS : constant := 7; -- bus error SIGFPE : constant := 8; -- floating point exception SIGKILL : constant := 9; -- kill (cannot be caught or ignored) diff --git a/gcc/ada/libgnarl/s-linux__sparc.ads b/gcc/ada/libgnarl/s-linux__sparc.ads index de31105..e619890 100644 --- a/gcc/ada/libgnarl/s-linux__sparc.ads +++ b/gcc/ada/libgnarl/s-linux__sparc.ads @@ -81,7 +81,7 @@ package System.Linux is SIGQUIT : constant := 3; -- quit (ASCD FS) SIGILL : constant := 4; -- illegal instruction (not reset) SIGTRAP : constant := 5; -- trace trap (not reset) - SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future + SIGABRT : constant := 6; -- used by abort, replace SIGIOT in the future SIGIOT : constant := 6; -- IOT instruction SIGEMT : constant := 7; -- EMT SIGFPE : constant := 8; -- floating point exception -- cgit v1.1 From be0443c30242995d615345d546987dace6ca1b07 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Fri, 5 Jul 2019 07:03:00 +0000 Subject: [Ada] Failure to detect trivial infinite recursion This patch includes delay statements in the set of control flow statements since their expressions may have side effects, which in turn may affect an infinite recursion. 2019-07-05 Hristian Kirtchev gcc/ada/ * sem_res.adb (Is_Control_Flow_Statement): Delay statements contain an expression, which in turn may have side effects and affect the infinite recursion. As a result, delay statements should not be treated specially. From-SVN: r273118 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_res.adb | 16 ++++------------ 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 65197d5..9658895 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Hristian Kirtchev + + * sem_res.adb (Is_Control_Flow_Statement): Delay statements + contain an expression, which in turn may have side effects and + affect the infinite recursion. As a result, delay statements + should not be treated specially. + 2019-07-05 Arnaud Charlet * libgnarl/s-linux.ads, libgnarl/s-linux__alpha.ads, diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 8dc8eeb..b86e7cc 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -816,19 +816,11 @@ package body Sem_Res is function Is_Control_Flow_Statement (N : Node_Id) return Boolean is begin - -- Delay statements do not affect the control flow because they - -- simply postpone the execution of all subsequent statements. + -- It is assumed that all statements may affect the control flow in + -- some way. A raise statement may be expanded into a non-statement + -- node. - if Nkind (N) in N_Delay_Statement then - return False; - - -- Otherwise it is assumed that all other statements may affect the - -- control flow in some way. A raise statement may be expanded into - -- a non-statement node. - - else - return Is_Statement (N) or else Is_Raise_Statement (N); - end if; + return Is_Statement (N) or else Is_Raise_Statement (N); end Is_Control_Flow_Statement; -------------------------------- -- cgit v1.1 From 4f469dec551ee19b81d9486e587ebb4945a92948 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Fri, 5 Jul 2019 07:03:05 +0000 Subject: [Ada] Missing range check on assignment to bit-packed array This patch adds an explicit range check on an assignment to a component of a bit-packed array, when the index type of the array is an enumeration type with a non-standard representation, Executing the following: gnatmake -f -gnata -q main ./main must yield: 1 is invalid 4097 is invalid 4116 is invalid 4117 is invalid 4118 is invalid 4119 is invalid 4120 is invalid 4121 is invalid ---- with Example; use Example; with My_Types; use My_Types; with Text_IO; use Text_IO; procedure main is begin --We try to access an invalid array location. begin dummy(idx => 1, action => DISABLE); exception when others => Text_IO.Put_Line ("1 is invalid"); end; for I in typ_uint32'(16#1000#) .. 16#101E# loop declare begin -- Text_IO.Put_Line (typ_uint32'image(I) & " OK"); Dummy (Idx => I, action => Enable); exception when others => put_line (typ_uint32'Image (I) & " is invalid"); end; end loop; end; ---- with Interfaces; use Interfaces; package My_Types is subtype typ_bool is boolean; type typ_uint32 is new Interfaces.Unsigned_32; subtype typ_uint16 is typ_uint32 range 0..2**16 - 1; type typ_dis_en is ( DISABLE, ENABLE ); for typ_dis_en'size use 32; for typ_dis_en use ( DISABLE => 0, ENABLE => 1 ); type typ_rid is ( RID_0, RID_2, RID_3, RID_4, RID_5, RID_6, RID_7, RID_8, RID_9, RID_10, RID_11, RID_12, RID_13, RID_14, RID_15, RID_16, RID_17, RID_18, RID_19, RID_26, RID_27, RID_28, RID_29, RID_30 ); for typ_rid use ( RID_0 => 16#1000#, RID_2 => 16#1002#, RID_3 => 16#1003#, RID_4 => 16#1004#, RID_5 => 16#1005#, RID_6 => 16#1006#, RID_7 => 16#1007#, RID_8 => 16#1008#, RID_9 => 16#1009#, RID_10 => 16#100A#, RID_11 => 16#100B#, RID_12 => 16#100C#, RID_13 => 16#100D#, RID_14 => 16#100E#, RID_15 => 16#100F#, RID_16 => 16#1010#, RID_17 => 16#1011#, RID_18 => 16#1012#, RID_19 => 16#1013#, RID_26 => 16#101A#, RID_27 => 16#101B#, RID_28 => 16#101C#, RID_29 => 16#101D#, RID_30 => 16#101E# ); for typ_rid'size use 16; end My_Types; ---- with My_Types; package Example is procedure Check; procedure dummy ( idx : in My_Types.typ_uint32; action : in My_Types.typ_dis_en ); end Example; ---- with Text_IO; use Text_IO; with Unchecked_Conversion; with my_types; use my_types; package body Example is type typ_rid_sts is array (My_Types.typ_rid) of My_Types.typ_bool; for typ_rid_sts'component_size use 1; is_rid_en : typ_rid_sts := (TRUE, false, True, False, true, False, True, false, True, False, TRUE, false, True, False, true, False, True, false, True, False, TRUE, false, True, False); procedure Check is begin pragma Assert (for all I in is_rid_en'range => is_rid_en (I)); end Check; function toRidEvt is new Unchecked_Conversion ( -- Defining source and target types source => My_Types.typ_uint16, target => My_Types.typ_rid ); procedure dummy ( idx : in My_Types.typ_uint32; action : in My_Types.typ_dis_en) is rid_evt : My_Types.typ_rid; begin rid_evt := toRidEvt(idx); if action = My_Types.ENABLE then is_rid_en(rid_evt) := TRUE; else is_rid_en(rid_evt) := FALSE; end if; end dummy; end Example; 2019-07-05 Ed Schonberg gcc/ada/ * exp_pakd.adb (Expand_Bit_Packed_Element_Set): Add explicit range checks when the index type of the bit-packed array is an enumeration type with a non-standard representation, From-SVN: r273119 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/exp_pakd.adb | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9658895..8daf38b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-05 Ed Schonberg + + * exp_pakd.adb (Expand_Bit_Packed_Element_Set): Add explicit + range checks when the index type of the bit-packed array is an + enumeration type with a non-standard representation, + 2019-07-05 Hristian Kirtchev * sem_res.adb (Is_Control_Flow_Statement): Delay statements diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb index a7d2a0d..9a659fa 100644 --- a/gcc/ada/exp_pakd.adb +++ b/gcc/ada/exp_pakd.adb @@ -1022,7 +1022,9 @@ package body Exp_Pakd is Ass_OK : constant Boolean := Assignment_OK (Lhs); -- Used to preserve assignment OK status when assignment is rewritten - Rhs : Node_Id := Expression (N); + Expr : Node_Id; + + Rhs : Node_Id := Expression (N); -- Initially Rhs is the right hand side value, it will be replaced -- later by an appropriate unchecked conversion for the assignment. @@ -1140,6 +1142,35 @@ package body Exp_Pakd is Analyze_And_Resolve (Rhs, Ctyp); end if; + -- If any of the indices has a nonstandard representation, introduce + -- the proper Rep_To_Pos conversion, which in turn will generate index + -- checks when needed. We do this on a copy of the index expression, + -- rather that rewriting the LHS altogether. + + Expr := First (Expressions (Lhs)); + while Present (Expr) loop + declare + Loc : constant Source_Ptr := Sloc (Expr); + Expr_Typ : constant Entity_Id := Etype (Expr); + Expr_Copy : Node_Id; + + begin + if Is_Enumeration_Type (Expr_Typ) + and then Has_Non_Standard_Rep (Expr_Typ) + then + Expr_Copy := + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (Expr_Typ, Loc), + Attribute_Name => Name_Pos, + Expressions => New_List (Relocate_Node (Expr))); + Set_Parent (Expr_Copy, N); + Analyze_And_Resolve (Expr_Copy, Standard_Natural); + end if; + end; + + Next (Expr); + end loop; + -- Case of component size 1,2,4 or any component size for the modular -- case. These are the cases for which we can inline the code. -- cgit v1.1 From d90eeca129a12d2236f8625d8ea5c93826bb526f Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Fri, 5 Jul 2019 07:03:10 +0000 Subject: [Ada] System.OS_Interface: fix link order on Linux 2019-07-05 Arnaud Charlet gcc/ada/ * libgnarl/s-osinte__linux.ads: Link with -lrt before -lpthread. From-SVN: r273120 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/libgnarl/s-osinte__linux.ads | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8daf38b..fed5a15 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-05 Arnaud Charlet + + * libgnarl/s-osinte__linux.ads: Link with -lrt before -lpthread. + 2019-07-05 Ed Schonberg * exp_pakd.adb (Expand_Bit_Packed_Element_Set): Add explicit diff --git a/gcc/ada/libgnarl/s-osinte__linux.ads b/gcc/ada/libgnarl/s-osinte__linux.ads index ba3b824..80cb2b2 100644 --- a/gcc/ada/libgnarl/s-osinte__linux.ads +++ b/gcc/ada/libgnarl/s-osinte__linux.ads @@ -46,10 +46,11 @@ with System.OS_Constants; package System.OS_Interface is pragma Preelaborate; - pragma Linker_Options ("-lpthread"); pragma Linker_Options ("-lrt"); -- Needed for clock_getres with glibc versions prior to 2.17 + pragma Linker_Options ("-lpthread"); + subtype int is Interfaces.C.int; subtype char is Interfaces.C.char; subtype short is Interfaces.C.short; -- cgit v1.1 From 9880061b346330e7c986016bdec75f38659f8793 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Fri, 5 Jul 2019 07:03:15 +0000 Subject: [Ada] Crash on deallocating component with discriminated task This patch modifies the generation of task deallocation code to examine the underlying type for task components. 2019-07-05 Hristian Kirtchev gcc/ada/ * exp_ch7.adb (Cleanup_Record): Use the underlying type when checking for components with tasks. gcc/testsuite/ * gnat.dg/task3.adb, gnat.dg/task3.ads, gnat.dg/task3_pkg1.ads, gnat.dg/task3_pkg2.ads: New testcase. From-SVN: r273121 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_ch7.adb | 11 ++++++----- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/task3.adb | 11 +++++++++++ gcc/testsuite/gnat.dg/task3.ads | 12 ++++++++++++ gcc/testsuite/gnat.dg/task3_pkg1.ads | 11 +++++++++++ gcc/testsuite/gnat.dg/task3_pkg2.ads | 7 +++++++ 7 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/task3.adb create mode 100644 gcc/testsuite/gnat.dg/task3.ads create mode 100644 gcc/testsuite/gnat.dg/task3_pkg1.ads create mode 100644 gcc/testsuite/gnat.dg/task3_pkg2.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index fed5a15..6da90f2 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Hristian Kirtchev + + * exp_ch7.adb (Cleanup_Record): Use the underlying type when + checking for components with tasks. + 2019-07-05 Arnaud Charlet * libgnarl/s-osinte__linux.ads: Link with -lrt before -lpthread. diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 1e17b19..4526af6 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -3893,11 +3893,12 @@ package body Exp_Ch7 is Typ : Entity_Id) return List_Id is Loc : constant Source_Ptr := Sloc (N); - Tsk : Node_Id; - Comp : Entity_Id; Stmts : constant List_Id := New_List; U_Typ : constant Entity_Id := Underlying_Type (Typ); + Comp : Entity_Id; + Tsk : Node_Id; + begin if Has_Discriminants (U_Typ) and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration @@ -3918,7 +3919,7 @@ package body Exp_Ch7 is return New_List (Make_Null_Statement (Loc)); end if; - Comp := First_Component (Typ); + Comp := First_Component (U_Typ); while Present (Comp) loop if Has_Task (Etype (Comp)) or else Has_Simple_Protected_Object (Etype (Comp)) @@ -3937,8 +3938,8 @@ package body Exp_Ch7 is elsif Is_Record_Type (Etype (Comp)) then - -- Recurse, by generating the prefix of the argument to - -- the eventual cleanup call. + -- Recurse, by generating the prefix of the argument to the + -- eventual cleanup call. Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp))); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 08d8695..cdf0b40 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Hristian Kirtchev + + * gnat.dg/task3.adb, gnat.dg/task3.ads, gnat.dg/task3_pkg1.ads, + gnat.dg/task3_pkg2.ads: New testcase. + 2019-07-05 Javier Miranda * gnat.dg/access6.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/task3.adb b/gcc/testsuite/gnat.dg/task3.adb new file mode 100644 index 0000000..a73c2dc --- /dev/null +++ b/gcc/testsuite/gnat.dg/task3.adb @@ -0,0 +1,11 @@ +-- { dg-do compile } + +with Ada.Unchecked_Deallocation; + +package body Task3 is + procedure Destroy (Obj : in out Child_Wrapper) is + procedure Free is new Ada.Unchecked_Deallocation (Child, Child_Ptr); + begin + Free (Obj.Ptr); + end Destroy; +end Task3; diff --git a/gcc/testsuite/gnat.dg/task3.ads b/gcc/testsuite/gnat.dg/task3.ads new file mode 100644 index 0000000..324d894 --- /dev/null +++ b/gcc/testsuite/gnat.dg/task3.ads @@ -0,0 +1,12 @@ +with Task3_Pkg2; use Task3_Pkg2; + +package Task3 is + type Child is new Root with null record; + type Child_Ptr is access Child; + + type Child_Wrapper is record + Ptr : Child_Ptr := null; + end record; + + procedure Destroy (Obj : in out Child_Wrapper); +end Task3; diff --git a/gcc/testsuite/gnat.dg/task3_pkg1.ads b/gcc/testsuite/gnat.dg/task3_pkg1.ads new file mode 100644 index 0000000..cc41be0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/task3_pkg1.ads @@ -0,0 +1,11 @@ +package Task3_Pkg1 is + type Task_Wrapper (Discr : Integer) is tagged limited private; + +private + task type Task_Typ (Discr : Integer) is + end Task_Typ; + + type Task_Wrapper (Discr : Integer) is tagged limited record + Tsk : Task_Typ (Discr); + end record; +end Task3_Pkg1; diff --git a/gcc/testsuite/gnat.dg/task3_pkg2.ads b/gcc/testsuite/gnat.dg/task3_pkg2.ads new file mode 100644 index 0000000..aee5c73 --- /dev/null +++ b/gcc/testsuite/gnat.dg/task3_pkg2.ads @@ -0,0 +1,7 @@ +with Task3_Pkg1; use Task3_Pkg1; + +package Task3_Pkg2 is + type Root (Discr : Integer) is tagged limited record + Wrap : Task_Wrapper (Discr); + end record; +end Task3_Pkg2; -- cgit v1.1 From c365eb26e87eab31f55b760fe4220b68fb952b72 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Fri, 5 Jul 2019 07:03:20 +0000 Subject: [Ada] Fix position of subprogram body generated for static predicate 2019-07-05 Ed Schonberg gcc/ada/ * sem_ch13.adb (Build_Predicate_Functions): If a subtype that carries a static predicate aspect is frozen immediately after its declaration, ensure that the generated function body created for predicate checking is inserted after the corresponding subprogram declaration, which is created at the point the declaration is elaborated. From-SVN: r273122 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/sem_ch13.adb | 10 ++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6da90f2..c5dcd03 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-05 Ed Schonberg + + * sem_ch13.adb (Build_Predicate_Functions): If a subtype that + carries a static predicate aspect is frozen immediately after + its declaration, ensure that the generated function body created + for predicate checking is inserted after the corresponding + subprogram declaration, which is created at the point the + declaration is elaborated. + 2019-07-05 Hristian Kirtchev * exp_ch7.adb (Cleanup_Record): Use the underlying type when diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index b18f74b..4c74366 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -8902,9 +8902,15 @@ package body Sem_Ch13 is Expression => Expr)))); -- The declaration has been analyzed when created, and placed - -- after type declaration. Insert body itself after freeze node. + -- after type declaration. Insert body itself after freeze node, + -- unless subprogram declaration is already there, in which case + -- body better be placed afterwards. - Insert_After_And_Analyze (N, FBody); + if FDecl = Next (N) then + Insert_After_And_Analyze (FDecl, FBody); + else + Insert_After_And_Analyze (N, FBody); + end if; -- The defining identifier of a quantified expression carries the -- scope in which the type appears, but when unnesting we need -- cgit v1.1 From 6d0289b1ec9e1f2b963d6dc6bb5cf262913c429c Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Fri, 5 Jul 2019 07:03:25 +0000 Subject: [Ada] Minor reformatting 2019-07-05 Hristian Kirtchev gcc/ada/ * bindo-units.adb, checks.adb, exp_attr.adb, exp_ch3.adb, exp_ch4.adb, exp_pakd.adb, lib-writ.adb, libgnat/g-traceb.adb, libgnat/g-traceb.ads, libgnat/s-stratt.ads, sem_aux.ads, sem_util.adb: Minor reformatting. From-SVN: r273123 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/bindo-units.adb | 2 -- gcc/ada/checks.adb | 2 +- gcc/ada/exp_attr.adb | 3 ++- gcc/ada/exp_ch3.adb | 6 +++--- gcc/ada/exp_ch4.adb | 4 ++-- gcc/ada/exp_pakd.adb | 5 +++-- gcc/ada/lib-writ.adb | 2 +- gcc/ada/libgnat/g-traceb.adb | 6 ++++-- gcc/ada/libgnat/g-traceb.ads | 3 ++- gcc/ada/libgnat/s-stratt.ads | 2 +- gcc/ada/sem_aux.ads | 2 +- gcc/ada/sem_util.adb | 24 ++++++++++++++---------- 13 files changed, 41 insertions(+), 27 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c5dcd03..1899bff 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Hristian Kirtchev + + * bindo-units.adb, checks.adb, exp_attr.adb, exp_ch3.adb, + exp_ch4.adb, exp_pakd.adb, lib-writ.adb, libgnat/g-traceb.adb, + libgnat/g-traceb.ads, libgnat/s-stratt.ads, sem_aux.ads, + sem_util.adb: Minor reformatting. + 2019-07-05 Ed Schonberg * sem_ch13.adb (Build_Predicate_Functions): If a subtype that diff --git a/gcc/ada/bindo-units.adb b/gcc/ada/bindo-units.adb index d2501e0..f234f40 100644 --- a/gcc/ada/bindo-units.adb +++ b/gcc/ada/bindo-units.adb @@ -45,8 +45,6 @@ package body Bindo.Units is -- The following set stores all units the need to be elaborated - -- Kirchev - Elaborable_Units : Unit_Sets.Membership_Set := Unit_Sets.Nil; ----------------------- diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 8176f85..ec4e96f 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -2722,7 +2722,7 @@ package body Checks is then declare In_Body : Boolean := False; - P : Node_Id := Parent (N); + P : Node_Id := Parent (N); begin while Present (P) loop diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index a4350ca..ac99ec1 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -3997,8 +3997,9 @@ package body Exp_Attr is declare Rtyp : constant Entity_Id := Root_Type (P_Type); + + Expr : Node_Id; -- call to Descendant_Tag Get_Tag : Node_Id; -- expression to read the 'Tag - Expr : Node_Id; -- call to Descendant_Tag begin -- Read the internal tag (RM 13.13.2(34)) and use it to diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index e48c188..834aaa3 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -9550,9 +9550,9 @@ package body Exp_Ch3 is if No (Eq_Call) then Next_Test := Make_Op_Ne (Loc, Lhs, Rhs); - -- If a component has a defined abstract equality, - -- its application raises Program_Error on that - -- component and therefore on the current variant. + -- If a component has a defined abstract equality, its + -- application raises Program_Error on that component + -- and therefore on the current variant. elsif Nkind (Eq_Call) = N_Raise_Program_Error then Set_Etype (Eq_Call, Standard_Boolean); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7a048c6..a611e03 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -11471,8 +11471,8 @@ package body Exp_Ch4 is then if not Comes_From_Source (N) and then Nkind_In (Parent (N), N_Function_Call, - N_Procedure_Call_Statement, - N_Parameter_Association) + N_Parameter_Association, + N_Procedure_Call_Statement) and then Is_Interface (Designated_Type (Target_Type)) and then Is_Class_Wide_Type (Designated_Type (Target_Type)) then diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb index 9a659fa..f6a7eed 100644 --- a/gcc/ada/exp_pakd.adb +++ b/gcc/ada/exp_pakd.adb @@ -1150,8 +1150,9 @@ package body Exp_Pakd is Expr := First (Expressions (Lhs)); while Present (Expr) loop declare - Loc : constant Source_Ptr := Sloc (Expr); - Expr_Typ : constant Entity_Id := Etype (Expr); + Expr_Typ : constant Entity_Id := Etype (Expr); + Loc : constant Source_Ptr := Sloc (Expr); + Expr_Copy : Node_Id; begin diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 861d58e..31ef8e2 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -1081,7 +1081,7 @@ package body Lib.Writ is begin -- We never write an ALI file if the original operating mode was - -- syntax-only (-gnats switch used in compiler invocation line) + -- syntax-only (-gnats switch used in compiler invocation line). if Original_Operating_Mode = Check_Syntax then return; diff --git a/gcc/ada/libgnat/g-traceb.adb b/gcc/ada/libgnat/g-traceb.adb index f40d84e..9cf04de 100644 --- a/gcc/ada/libgnat/g-traceb.adb +++ b/gcc/ada/libgnat/g-traceb.adb @@ -41,13 +41,15 @@ package body GNAT.Traceback is procedure Call_Chain (Traceback : out Tracebacks_Array; - Len : out Natural) is + Len : out Natural) + is begin System.Traceback.Call_Chain (Traceback, Traceback'Length, Len); end Call_Chain; function Call_Chain - (Max_Len : Positive; Skip_Frames : Natural := 1) return Tracebacks_Array + (Max_Len : Positive; + Skip_Frames : Natural := 1) return Tracebacks_Array is Traceback : Tracebacks_Array (1 .. Max_Len); Len : Natural; diff --git a/gcc/ada/libgnat/g-traceb.ads b/gcc/ada/libgnat/g-traceb.ads index bdd46b2..6a565c9 100644 --- a/gcc/ada/libgnat/g-traceb.ads +++ b/gcc/ada/libgnat/g-traceb.ads @@ -99,7 +99,8 @@ package GNAT.Traceback is -- are undefined on return. function Call_Chain - (Max_Len : Positive; Skip_Frames : Natural := 1) return Tracebacks_Array; + (Max_Len : Positive; + Skip_Frames : Natural := 1) return Tracebacks_Array; -- Returns up to Max_Len tracebacks corresponding to the current call -- chain. Result array order is the same as in above procedure Call_Chain -- except that Skip_Frames says how many of the most recent calls should be diff --git a/gcc/ada/libgnat/s-stratt.ads b/gcc/ada/libgnat/s-stratt.ads index 20dc4e6..e050bc1 100644 --- a/gcc/ada/libgnat/s-stratt.ads +++ b/gcc/ada/libgnat/s-stratt.ads @@ -154,7 +154,7 @@ package System.Stream_Attributes is function Block_IO_OK return Boolean; -- Package System.Stream_Attributes has several bodies - the default one - -- distributed with GNAT, and s-stratt-xdr.adb, which is based on the XDR + -- distributed with GNAT, and s-stratt__xdr.adb, which is based on the XDR -- standard. Both bodies share the same spec. The role of this function is -- to indicate whether the current version of System.Stream_Attributes -- supports block IO. See System.Strings.Stream_Ops (s-ststop) for details. diff --git a/gcc/ada/sem_aux.ads b/gcc/ada/sem_aux.ads index ec0f5e7..f3b7f24 100644 --- a/gcc/ada/sem_aux.ads +++ b/gcc/ada/sem_aux.ads @@ -87,7 +87,7 @@ package Sem_Aux is ----------------- function Ancestor_Subtype (Typ : Entity_Id) return Entity_Id; - -- The argument Id is a type or subtype entity. If the argument is a + -- The argument Typ is a type or subtype entity. If the argument is a -- subtype then it returns the subtype or type from which the subtype was -- obtained, otherwise it returns Empty. diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 48822e2..67bc4de 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -6576,13 +6576,15 @@ package body Sem_Util is -- the accessibility level is that of the declaration of the -- stand-alone object. - return Make_Level_Literal - (Object_Access_Level - (Defining_Identifier (Parent (N)))); + return + Make_Level_Literal + (Object_Access_Level + (Defining_Identifier (Parent (N)))); when N_Assignment_Statement => - return Make_Level_Literal - (Object_Access_Level (Name (Parent (N)))); + return + Make_Level_Literal + (Object_Access_Level (Name (Parent (N)))); when others => declare @@ -6591,8 +6593,9 @@ package body Sem_Util is begin Error_Msg_Strlen := S'Length; Error_Msg_String (1 .. Error_Msg_Strlen) := S; - Error_Msg_N ("unsupported context for anonymous " & - "allocator (~)", Parent (N)); + Error_Msg_N + ("unsupported context for anonymous allocator (~)", + Parent (N)); end; end case; @@ -6899,8 +6902,9 @@ package body Sem_Util is elsif Dynamic_Scope = Empty then return Empty; - elsif Ekind_In (Dynamic_Scope, E_Package, E_Package_Body, - E_Generic_Package) + elsif Ekind_In (Dynamic_Scope, E_Generic_Package, + E_Package, + E_Package_Body) then return Dynamic_Scope; @@ -6954,7 +6958,7 @@ package body Sem_Util is elsif Ekind (Dyn_Scop) = E_Subprogram_Body then return Corresponding_Spec (Parent (Parent (Dyn_Scop))); - elsif Ekind_In (Dyn_Scop, E_Block, E_Return_Statement, E_Loop) then + elsif Ekind_In (Dyn_Scop, E_Block, E_Loop, E_Return_Statement) then return Enclosing_Subprogram (Dyn_Scop); elsif Ekind (Dyn_Scop) = E_Entry then -- cgit v1.1 From d21328a0d42f1b6a92f777acf4972e3c1c5d330c Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 5 Jul 2019 07:03:30 +0000 Subject: [Ada] Fix internal error on packed array In/Out actual parameter This fixes an issue introduced in Ada 2012 for calls to functions taking an In/Out parameter and for which the actual is the component of a packed array. In this case, the front-end needs to create a temporary for the actual, initialize it before the call and assign it back after it, because operations on bit-packed arrays are converted into mask-and-shift sequences. 2019-07-05 Eric Botcazou gcc/ada/ * exp_ch4.adb (Expand_N_Indexed_Component): Do not expand actual parameters of function calls here either. gcc/testsuite/ * gnat.dg/pack23.adb, gnat.dg/pack23_pkg.ads: New testcase. From-SVN: r273124 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_ch4.adb | 11 ++++++----- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/pack23.adb | 14 ++++++++++++++ gcc/testsuite/gnat.dg/pack23_pkg.ads | 5 +++++ 5 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/pack23.adb create mode 100644 gcc/testsuite/gnat.dg/pack23_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1899bff..8373be7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Eric Botcazou + + * exp_ch4.adb (Expand_N_Indexed_Component): Do not expand actual + parameters of function calls here either. + 2019-07-05 Hristian Kirtchev * bindo-units.adb, checks.adb, exp_attr.adb, exp_ch3.adb, diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index a611e03..78b5028 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -6762,7 +6762,7 @@ package body Exp_Ch4 is -- Renaming objects in renaming associations -- This case is handled when a use of the renamed variable occurs - -- Actual parameters for a procedure call + -- Actual parameters for a subprogram call -- This case is handled in Exp_Ch6.Expand_Actuals -- The second expression in a 'Read attribute reference @@ -6783,11 +6783,12 @@ package body Exp_Ch4 is if Nkind (Parnt) = N_Unchecked_Expression then null; - elsif Nkind_In (Parnt, N_Object_Renaming_Declaration, - N_Procedure_Call_Statement) + elsif Nkind (Parnt) = N_Object_Renaming_Declaration then + return; + + elsif Nkind (Parnt) in N_Subprogram_Call or else (Nkind (Parnt) = N_Parameter_Association - and then - Nkind (Parent (Parnt)) = N_Procedure_Call_Statement) + and then Nkind (Parent (Parnt)) in N_Subprogram_Call) then return; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cdf0b40..53d7994 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-05 Eric Botcazou + + * gnat.dg/pack23.adb, gnat.dg/pack23_pkg.ads: New testcase. + 2019-07-05 Hristian Kirtchev * gnat.dg/task3.adb, gnat.dg/task3.ads, gnat.dg/task3_pkg1.ads, diff --git a/gcc/testsuite/gnat.dg/pack23.adb b/gcc/testsuite/gnat.dg/pack23.adb new file mode 100644 index 0000000..aa8099f --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack23.adb @@ -0,0 +1,14 @@ +-- { dg-do compile } +-- { dg-options "-gnatws" } + +with Pack23_Pkg; + +function Pack23 return Integer is + + type Arr is array (1 .. 32) of Boolean with Size => 32, Pack; + + A : Arr; + +begin + return Pack23_Pkg.Func (A (1)); +end; diff --git a/gcc/testsuite/gnat.dg/pack23_pkg.ads b/gcc/testsuite/gnat.dg/pack23_pkg.ads new file mode 100644 index 0000000..beacbad --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack23_pkg.ads @@ -0,0 +1,5 @@ +package Pack23_Pkg is + + function Func (B : in out Boolean) return Integer; + +end Pack23_Pkg; -- cgit v1.1 From 1e70cf2ebacb8eed39b0e7a4191c07052ce64181 Mon Sep 17 00:00:00 2001 From: Vasiliy Fofanov Date: Fri, 5 Jul 2019 07:03:35 +0000 Subject: [Ada] Ada.Wide_Wide_Characters.Handling: fix comments 2019-07-05 Vasiliy Fofanov gcc/ada/ * libgnat/a-wichha.ads (Is_Alphanumeric): Replace comment with the correct one. Also capitalize references to False throughout. From-SVN: r273125 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/libgnat/a-wichha.ads | 30 +++++++++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8373be7..eb04023 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-05 Vasiliy Fofanov + + * libgnat/a-wichha.ads (Is_Alphanumeric): Replace comment with + the correct one. Also capitalize references to False + throughout. + 2019-07-05 Eric Botcazou * exp_ch4.adb (Expand_N_Indexed_Component): Do not expand actual diff --git a/gcc/ada/libgnat/a-wichha.ads b/gcc/ada/libgnat/a-wichha.ads index 583308e..a906e02 100644 --- a/gcc/ada/libgnat/a-wichha.ads +++ b/gcc/ada/libgnat/a-wichha.ads @@ -25,28 +25,28 @@ package Ada.Wide_Characters.Handling is function Is_Control (Item : Wide_Character) return Boolean; pragma Inline (Is_Control); -- Returns True if the Wide_Character designated by Item is categorized as - -- other_control, otherwise returns false. + -- other_control, otherwise returns False. function Is_Letter (Item : Wide_Character) return Boolean; pragma Inline (Is_Letter); -- Returns True if the Wide_Character designated by Item is categorized as -- letter_uppercase, letter_lowercase, letter_titlecase, letter_modifier, - -- letter_other, or number_letter. Otherwise returns false. + -- letter_other, or number_letter. Otherwise returns False. function Is_Lower (Item : Wide_Character) return Boolean; pragma Inline (Is_Lower); -- Returns True if the Wide_Character designated by Item is categorized as - -- letter_lowercase, otherwise returns false. + -- letter_lowercase, otherwise returns False. function Is_Upper (Item : Wide_Character) return Boolean; pragma Inline (Is_Upper); -- Returns True if the Wide_Character designated by Item is categorized as - -- letter_uppercase, otherwise returns false. + -- letter_uppercase, otherwise returns False. function Is_Digit (Item : Wide_Character) return Boolean; pragma Inline (Is_Digit); -- Returns True if the Wide_Character designated by Item is categorized as - -- number_decimal, otherwise returns false. + -- number_decimal, otherwise returns False. function Is_Decimal_Digit (Item : Wide_Character) return Boolean renames Is_Digit; @@ -54,51 +54,51 @@ package Ada.Wide_Characters.Handling is function Is_Hexadecimal_Digit (Item : Wide_Character) return Boolean; -- Returns True if the Wide_Character designated by Item is categorized as -- number_decimal, or is in the range 'A' .. 'F' or 'a' .. 'f', otherwise - -- returns false. + -- returns False. function Is_Alphanumeric (Item : Wide_Character) return Boolean; pragma Inline (Is_Alphanumeric); -- Returns True if the Wide_Character designated by Item is categorized as - -- number_decimal, or is in the range 'A' .. 'F' or 'a' .. 'f', otherwise - -- returns false. + -- letter_uppercase, letter_lowercase, letter_titlecase, letter_modifier, + -- letter_other, number_letter, or number_decimal; otherwise returns False. function Is_Special (Item : Wide_Character) return Boolean; pragma Inline (Is_Special); -- Returns True if the Wide_Character designated by Item is categorized -- as graphic_character, but not categorized as letter_uppercase, -- letter_lowercase, letter_titlecase, letter_modifier, letter_other, - -- number_letter, or number_decimal. Otherwise returns false. + -- number_letter, or number_decimal. Otherwise returns False. function Is_Line_Terminator (Item : Wide_Character) return Boolean; pragma Inline (Is_Line_Terminator); -- Returns True if the Wide_Character designated by Item is categorized as -- separator_line or separator_paragraph, or if Item is a conventional line - -- terminator character (CR, LF, VT, or FF). Otherwise returns false. + -- terminator character (CR, LF, VT, or FF). Otherwise returns False. function Is_Mark (Item : Wide_Character) return Boolean; pragma Inline (Is_Mark); -- Returns True if the Wide_Character designated by Item is categorized as - -- mark_non_spacing or mark_spacing_combining, otherwise returns false. + -- mark_non_spacing or mark_spacing_combining, otherwise returns False. function Is_Other_Format (Item : Wide_Character) return Boolean; pragma Inline (Is_Other_Format); -- Returns True if the Wide_Character designated by Item is categorized as - -- other_format, otherwise returns false. + -- other_format, otherwise returns False. function Is_Punctuation_Connector (Item : Wide_Character) return Boolean; pragma Inline (Is_Punctuation_Connector); -- Returns True if the Wide_Character designated by Item is categorized as - -- punctuation_connector, otherwise returns false. + -- punctuation_connector, otherwise returns False. function Is_Space (Item : Wide_Character) return Boolean; pragma Inline (Is_Space); -- Returns True if the Wide_Character designated by Item is categorized as - -- separator_space, otherwise returns false. + -- separator_space, otherwise returns False. function Is_Graphic (Item : Wide_Character) return Boolean; pragma Inline (Is_Graphic); -- Returns True if the Wide_Character designated by Item is categorized as - -- graphic_character, otherwise returns false. + -- graphic_character, otherwise returns False. function To_Lower (Item : Wide_Character) return Wide_Character; pragma Inline (To_Lower); -- cgit v1.1 From b7469acf1c7f70bebd703bb25120f18e509f90f3 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Fri, 5 Jul 2019 07:03:39 +0000 Subject: [Ada] GNAT UGN: refresh doc on installing from the cmd line on Windows 2019-07-05 Arnaud Charlet gcc/ada/ * doc/gnat_ugn/platform_specific_information.rst: Refresh doc on installing from the command line on Windows. Remove obsolete part. * gnat_ugn.texi: Regenerate. From-SVN: r273126 --- gcc/ada/ChangeLog | 7 +++++ .../doc/gnat_ugn/platform_specific_information.rst | 30 +++++----------------- gcc/ada/gnat_ugn.texi | 3 --- 3 files changed, 13 insertions(+), 27 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index eb04023..002d535 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Arnaud Charlet + + * doc/gnat_ugn/platform_specific_information.rst: Refresh doc on + installing from the command line on Windows. Remove obsolete + part. + * gnat_ugn.texi: Regenerate. + 2019-07-05 Vasiliy Fofanov * libgnat/a-wichha.ads (Is_Alphanumeric): Replace comment with diff --git a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst index 53f4d98..13993b8 100644 --- a/gcc/ada/doc/gnat_ugn/platform_specific_information.rst +++ b/gcc/ada/doc/gnat_ugn/platform_specific_information.rst @@ -260,7 +260,7 @@ This section describes topics that are specific to the Microsoft Windows platforms. -.. only:: PRO or GPL +.. only:: PRO .. rubric:: Installing from the Command Line @@ -273,32 +273,15 @@ platforms. line you should pass parameter :switch:`/S` (and, optionally, :switch:`/D=`) as command-line arguments. -.. only:: PRO - - For example, for an unattended installation of - GNAT 7.0.2 into the default directory - ``C:\\GNATPRO\\7.0.2`` you would run: - - :: - - gnatpro-7.0.2-i686-pc-mingw32-bin.exe /S - - To install into a custom directory, say, ``C:\\TOOLS\\GNATPRO\\7.0.2``: - - :: - - gnatpro-7.0.2-i686-pc-mingw32-bin /S /D=C:\TOOLS\GNATPRO\7.0.2 - -.. only:: GPL - For example, for an unattended installation of - GNAT 2012 into ``C:\\GNAT\\2012``: + GNAT 19.2 into the default directory :file:`C:\\GNATPRO\\19.2` you + would run:: - :: + gnatpro-19.2-x86-windows-bin /S - gnat-gpl-2012-i686-pc-mingw32-bin /S /D=C:\GNAT\2012 + To install into a custom directory, say, :file:`C:\\TOOLS\\GNATPRO\\19.2`:: -.. only:: PRO or GPL + gnatpro-19.2-x86-windows-bin /S /D=C:\TOOLS\GNATPRO\19.2 You can use the same syntax for all installers. @@ -306,7 +289,6 @@ platforms. associations, so such activities need to be done by hand. - .. _Using_GNAT_on_Windows: Using GNAT on Windows diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 8551a17b..5ace5cf 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -23901,9 +23901,6 @@ This section describes topics that are specific to the Microsoft Windows platforms. - - - @menu * Using GNAT on Windows:: * Using a network installation of GNAT:: -- cgit v1.1 From 2ff7c604377c1220702aeb4c4b63ed76e56aa577 Mon Sep 17 00:00:00 2001 From: Joffrey Huguet Date: Fri, 5 Jul 2019 07:03:44 +0000 Subject: [Ada] Add contracts to Ada.Text_IO for SPARK This change removes the warnings returned when using Ada.Text_IO library in SPARK. An abstract state and global contracts were added to modelize the action of Text_IO procedures and function on the memory and the files. 2019-07-05 Joffrey Huguet gcc/ada/ * libgnat/a-textio.adb: Add abstract state refinment. * libgnat/a-textio.ads: Add File_System abstract state. Add global contracts, contract cases, preconditions and postconditions to procedures and functions. (Set_Input, Set_Output, Set_Error, Standard_Input, Standard_Output, Standard_Error, Current_Input, Current_Output, Current_Error): Turn SPARK_Mode off. (Get_Line): Turn SPARK_Mode off on Get_Line functions. * libgnat/a-tideio.ads, libgnat/a-tienio.ads, libgnat/a-tifiio.ads, libgnat/a-tiflio.ads, libgnat/a-tiinio.ads, libgnat/a-timoio.ads: Add global contracts, contract cases, preconditions and postconditions to procedures and functions. From-SVN: r273127 --- gcc/ada/ChangeLog | 16 ++ gcc/ada/libgnat/a-textio.adb | 13 +- gcc/ada/libgnat/a-textio.ads | 466 +++++++++++++++++++++++++++++++++---------- gcc/ada/libgnat/a-tideio.ads | 35 +++- gcc/ada/libgnat/a-tienio.ads | 33 ++- gcc/ada/libgnat/a-tifiio.ads | 35 +++- gcc/ada/libgnat/a-tiflio.ads | 35 +++- gcc/ada/libgnat/a-tiinio.ads | 35 +++- gcc/ada/libgnat/a-timoio.ads | 35 +++- 9 files changed, 561 insertions(+), 142 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 002d535..8820113 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,19 @@ +2019-07-05 Joffrey Huguet + + * libgnat/a-textio.adb: Add abstract state refinment. + * libgnat/a-textio.ads: Add File_System abstract state. Add + global contracts, contract cases, preconditions and + postconditions to procedures and functions. + (Set_Input, Set_Output, Set_Error, Standard_Input, + Standard_Output, Standard_Error, Current_Input, Current_Output, + Current_Error): Turn SPARK_Mode off. + (Get_Line): Turn SPARK_Mode off on Get_Line functions. + * libgnat/a-tideio.ads, libgnat/a-tienio.ads, + libgnat/a-tifiio.ads, libgnat/a-tiflio.ads, + libgnat/a-tiinio.ads, libgnat/a-timoio.ads: Add global + contracts, contract cases, preconditions and postconditions to + procedures and functions. + 2019-07-05 Arnaud Charlet * doc/gnat_ugn/platform_specific_information.rst: Refresh doc on diff --git a/gcc/ada/libgnat/a-textio.adb b/gcc/ada/libgnat/a-textio.adb index 5b6e28a..276be12 100644 --- a/gcc/ada/libgnat/a-textio.adb +++ b/gcc/ada/libgnat/a-textio.adb @@ -43,7 +43,18 @@ with Ada.Unchecked_Deallocation; pragma Elaborate_All (System.File_IO); -- Needed because of calls to Chain_File in package body elaboration -package body Ada.Text_IO is +package body Ada.Text_IO with + Refined_State => (File_System => (Standard_In, + Standard_Out, + Standard_Err, + Current_In, + Current_Out, + Current_Err, + In_Name, + Out_Name, + Err_Name, + WC_Encoding)) +is package FIO renames System.File_IO; diff --git a/gcc/ada/libgnat/a-textio.ads b/gcc/ada/libgnat/a-textio.ads index 32bbc6c..a2e1daf 100644 --- a/gcc/ada/libgnat/a-textio.ads +++ b/gcc/ada/libgnat/a-textio.ads @@ -33,6 +33,14 @@ -- -- ------------------------------------------------------------------------------ +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. This is enforced by +-- setting the corresponding assertion policy to Ignore. These preconditions +-- are partial and protect against Status_Error, Mode_Error, and Layout_Error, +-- but not against other types of errors. + +pragma Assertion_Policy (Pre => Ignore); + -- Note: the generic subpackages of Text_IO (Integer_IO, Float_IO, Fixed_IO, -- Modular_IO, Decimal_IO and Enumeration_IO) appear as private children in -- GNAT. These children are with'ed automatically if they are referenced, so @@ -46,10 +54,15 @@ with System; with System.File_Control_Block; with System.WCh_Con; -package Ada.Text_IO is +package Ada.Text_IO with + Abstract_State => (File_System), + Initializes => (File_System), + Initial_Condition => Line_Length = 0 and Page_Length = 0 +is pragma Elaborate_Body; - type File_Type is limited private with Default_Initial_Condition; + type File_Type is limited private with + Default_Initial_Condition => (not Is_Open (File_Type)); type File_Mode is (In_File, Out_File, Append_File); -- The following representation clause allows the use of unchecked @@ -87,50 +100,97 @@ package Ada.Text_IO is (File : in out File_Type; Mode : File_Mode := Out_File; Name : String := ""; - Form : String := ""); + Form : String := "") + with + Pre => not Is_Open (File), + Post => + Is_Open (File) + and then Ada.Text_IO.Mode (File) = Mode + and then (if Mode /= In_File + then (Line_Length (File) = 0 + and then Page_Length (File) = 0)), + Global => (In_Out => File_System); procedure Open (File : in out File_Type; Mode : File_Mode; Name : String; - Form : String := ""); - - procedure Close (File : in out File_Type); - procedure Delete (File : in out File_Type); - procedure Reset (File : in out File_Type; Mode : File_Mode); - procedure Reset (File : in out File_Type); - - function Mode (File : File_Type) return File_Mode; - function Name (File : File_Type) return String; - function Form (File : File_Type) return String; - - function Is_Open (File : File_Type) return Boolean; + Form : String := "") + with + Pre => not Is_Open (File), + Post => + Is_Open (File) + and then Ada.Text_IO.Mode (File) = Mode + and then (if Mode /= In_File + then (Line_Length (File) = 0 + and then Page_Length (File) = 0)), + Global => (In_Out => File_System); + + procedure Close (File : in out File_Type) with + Pre => Is_Open (File), + Post => not Is_Open (File), + Global => (In_Out => File_System); + procedure Delete (File : in out File_Type) with + Pre => Is_Open (File), + Post => not Is_Open (File), + Global => (In_Out => File_System); + procedure Reset (File : in out File_Type; Mode : File_Mode) with + Pre => Is_Open (File), + Post => + Is_Open (File) + and then Ada.Text_IO.Mode (File) = Mode + and then (if Mode /= In_File + then (Line_Length (File) = 0 + and then Page_Length (File) = 0)), + Global => (In_Out => File_System); + procedure Reset (File : in out File_Type) with + Pre => Is_Open (File), + Post => + Is_Open (File) + and Mode (File)'Old = Mode (File) + and (if Mode (File) /= In_File + then (Line_Length (File) = 0 + and then Page_Length (File) = 0)), + Global => (In_Out => File_System); + + function Mode (File : File_Type) return File_Mode with + Pre => Is_Open (File), + Global => null; + function Name (File : File_Type) return String with + Pre => Is_Open (File), + Global => null; + function Form (File : File_Type) return String with + Pre => Is_Open (File), + Global => null; + + function Is_Open (File : File_Type) return Boolean with + Global => null; ------------------------------------------------------ -- Control of default input, output and error files -- ------------------------------------------------------ - procedure Set_Input (File : File_Type); - procedure Set_Output (File : File_Type); - procedure Set_Error (File : File_Type); + procedure Set_Input (File : File_Type) with SPARK_Mode => Off; + procedure Set_Output (File : File_Type) with SPARK_Mode => Off; + procedure Set_Error (File : File_Type) with SPARK_Mode => Off; - function Standard_Input return File_Type; - function Standard_Output return File_Type; - function Standard_Error return File_Type; + function Standard_Input return File_Type with SPARK_Mode => Off; + function Standard_Output return File_Type with SPARK_Mode => Off; + function Standard_Error return File_Type with SPARK_Mode => Off; - function Current_Input return File_Type; - function Current_Output return File_Type; - function Current_Error return File_Type; + function Current_Input return File_Type with SPARK_Mode => Off; + function Current_Output return File_Type with SPARK_Mode => Off; + function Current_Error return File_Type with SPARK_Mode => Off; type File_Access is access constant File_Type; - function Standard_Input return File_Access; - function Standard_Output return File_Access; - function Standard_Error return File_Access; + function Standard_Input return File_Access with SPARK_Mode => Off; + function Standard_Output return File_Access with SPARK_Mode => Off; + function Standard_Error return File_Access with SPARK_Mode => Off; - function Current_Input return File_Access; - function Current_Output return File_Access; - function Current_Error return File_Access; + function Current_Input return File_Access with SPARK_Mode => Off; + function Current_Output return File_Access with SPARK_Mode => Off; + function Current_Error return File_Access with SPARK_Mode => Off; -------------------- -- Buffer control -- @@ -139,129 +199,319 @@ package Ada.Text_IO is -- Note: The parameter file is IN OUT in the RM, but this is clearly -- an oversight, and was intended to be IN, see AI95-00057. - procedure Flush (File : File_Type); - procedure Flush; + procedure Flush (File : File_Type) with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); + procedure Flush with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); -------------------------------------------- -- Specification of line and page lengths -- -------------------------------------------- - procedure Set_Line_Length (File : File_Type; To : Count); - procedure Set_Line_Length (To : Count); - - procedure Set_Page_Length (File : File_Type; To : Count); - procedure Set_Page_Length (To : Count); - - function Line_Length (File : File_Type) return Count; - function Line_Length return Count; - - function Page_Length (File : File_Type) return Count; - function Page_Length return Count; + procedure Set_Line_Length (File : File_Type; To : Count) with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File) = To + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); + procedure Set_Line_Length (To : Count) with + Post => + Line_Length = To + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + + procedure Set_Page_Length (File : File_Type; To : Count) with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Page_Length (File) = To + and Line_Length (File)'Old = Line_Length (File), + Global => (In_Out => File_System); + procedure Set_Page_Length (To : Count) with + Post => + Page_Length = To + and Line_Length'Old = Line_Length, + Global => (In_Out => File_System); + + function Line_Length (File : File_Type) return Count with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Global => (Input => File_System); + function Line_Length return Count with + Global => (Input => File_System); + + function Page_Length (File : File_Type) return Count with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Global => (Input => File_System); + function Page_Length return Count with + Global => (Input => File_System); ------------------------------------ -- Column, Line, and Page Control -- ------------------------------------ - procedure New_Line (File : File_Type; Spacing : Positive_Count := 1); - procedure New_Line (Spacing : Positive_Count := 1); - - procedure Skip_Line (File : File_Type; Spacing : Positive_Count := 1); - procedure Skip_Line (Spacing : Positive_Count := 1); - - function End_Of_Line (File : File_Type) return Boolean; - function End_Of_Line return Boolean; - - procedure New_Page (File : File_Type); - procedure New_Page; - - procedure Skip_Page (File : File_Type); - procedure Skip_Page; - - function End_Of_Page (File : File_Type) return Boolean; - function End_Of_Page return Boolean; - - function End_Of_File (File : File_Type) return Boolean; - function End_Of_File return Boolean; - - procedure Set_Col (File : File_Type; To : Positive_Count); - procedure Set_Col (To : Positive_Count); - - procedure Set_Line (File : File_Type; To : Positive_Count); - procedure Set_Line (To : Positive_Count); - - function Col (File : File_Type) return Positive_Count; - function Col return Positive_Count; - - function Line (File : File_Type) return Positive_Count; - function Line return Positive_Count; - - function Page (File : File_Type) return Positive_Count; - function Page return Positive_Count; + procedure New_Line (File : File_Type; Spacing : Positive_Count := 1) with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); + procedure New_Line (Spacing : Positive_Count := 1) with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + + procedure Skip_Line (File : File_Type; Spacing : Positive_Count := 1) with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); + procedure Skip_Line (Spacing : Positive_Count := 1) with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + + function End_Of_Line (File : File_Type) return Boolean with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (Input => File_System); + function End_Of_Line return Boolean with + Global => (Input => File_System); + + procedure New_Page (File : File_Type) with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); + procedure New_Page with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + + procedure Skip_Page (File : File_Type) with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); + procedure Skip_Page with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + + function End_Of_Page (File : File_Type) return Boolean with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (Input => File_System); + function End_Of_Page return Boolean with + Global => (Input => File_System); + + function End_Of_File (File : File_Type) return Boolean with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (Input => File_System); + function End_Of_File return Boolean with + Global => (Input => File_System); + + procedure Set_Col (File : File_Type; To : Positive_Count) with + Pre => + Is_Open (File) + and then (if Mode (File) /= In_File + then (Line_Length (File) = 0 + or else To <= Line_Length (File))), + Contract_Cases => + (Mode (File) /= In_File => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + others => True), + Global => (In_Out => File_System); + procedure Set_Col (To : Positive_Count) with + Pre => Line_Length = 0 or To <= Line_Length, + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + + procedure Set_Line (File : File_Type; To : Positive_Count) with + Pre => + Is_Open (File) + and then (if Mode (File) /= In_File + then (Page_Length (File) = 0 + or else To <= Page_Length (File))), + Contract_Cases => + (Mode (File) /= In_File => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + others => True), + Global => (In_Out => File_System); + procedure Set_Line (To : Positive_Count) with + Pre => Page_Length = 0 or To <= Page_Length, + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + + function Col (File : File_Type) return Positive_Count with + Pre => Is_Open (File), + Global => (Input => File_System); + function Col return Positive_Count with + Global => (Input => File_System); + + function Line (File : File_Type) return Positive_Count with + Pre => Is_Open (File), + Global => (Input => File_System); + function Line return Positive_Count with + Global => (Input => File_System); + + function Page (File : File_Type) return Positive_Count with + Pre => Is_Open (File), + Global => (Input => File_System); + function Page return Positive_Count with + Global => (Input => File_System); ---------------------------- -- Character Input-Output -- ---------------------------- - procedure Get (File : File_Type; Item : out Character); - procedure Get (Item : out Character); - procedure Put (File : File_Type; Item : Character); - procedure Put (Item : Character); + procedure Get (File : File_Type; Item : out Character) with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); + procedure Get (Item : out Character) with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + procedure Put (File : File_Type; Item : Character) with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); + procedure Put (Item : Character) with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Look_Ahead (File : File_Type; Item : out Character; - End_Of_Line : out Boolean); + End_Of_Line : out Boolean) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (Input => File_System); procedure Look_Ahead (Item : out Character; - End_Of_Line : out Boolean); + End_Of_Line : out Boolean) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (Input => File_System); procedure Get_Immediate (File : File_Type; - Item : out Character); + Item : out Character) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); procedure Get_Immediate - (Item : out Character); + (Item : out Character) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get_Immediate (File : File_Type; Item : out Character; - Available : out Boolean); + Available : out Boolean) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); procedure Get_Immediate (Item : out Character; - Available : out Boolean); + Available : out Boolean) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); ------------------------- -- String Input-Output -- ------------------------- - procedure Get (File : File_Type; Item : out String); - procedure Get (Item : out String); - procedure Put (File : File_Type; Item : String); - procedure Put (Item : String); + procedure Get (File : File_Type; Item : out String) with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); + procedure Get (Item : out String) with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); + procedure Put (File : File_Type; Item : String) with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); + procedure Put (Item : String) with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get_Line (File : File_Type; Item : out String; - Last : out Natural); + Last : out Natural) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Post => (if Item'Length > 0 then Last in Item'First - 1 .. Item'Last + else Last = Item'First - 1), + Global => (In_Out => File_System); procedure Get_Line (Item : out String; - Last : out Natural); - - function Get_Line (File : File_Type) return String; + Last : out Natural) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length + and (if Item'Length > 0 then Last in Item'First - 1 .. Item'Last + else Last = Item'First - 1), + Global => (In_Out => File_System); + + function Get_Line (File : File_Type) return String with SPARK_Mode => Off; pragma Ada_05 (Get_Line); - function Get_Line return String; + function Get_Line return String with SPARK_Mode => Off; pragma Ada_05 (Get_Line); procedure Put_Line (File : File_Type; - Item : String); + Item : String) + with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); procedure Put_Line - (Item : String); + (Item : String) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); --------------------------------------- -- Generic packages for Input-Output -- @@ -447,14 +697,20 @@ private Standard_Out_AFCB : aliased Text_AFCB; Standard_Err_AFCB : aliased Text_AFCB; - Standard_In : aliased File_Type := Standard_In_AFCB'Access; - Standard_Out : aliased File_Type := Standard_Out_AFCB'Access; - Standard_Err : aliased File_Type := Standard_Err_AFCB'Access; + Standard_In : aliased File_Type := Standard_In_AFCB'Access with + Part_Of => File_System; + Standard_Out : aliased File_Type := Standard_Out_AFCB'Access with + Part_Of => File_System; + Standard_Err : aliased File_Type := Standard_Err_AFCB'Access with + Part_Of => File_System; -- Standard files - Current_In : aliased File_Type := Standard_In; - Current_Out : aliased File_Type := Standard_Out; - Current_Err : aliased File_Type := Standard_Err; + Current_In : aliased File_Type := Standard_In with + Part_Of => File_System; + Current_Out : aliased File_Type := Standard_Out with + Part_Of => File_System; + Current_Err : aliased File_Type := Standard_Err with + Part_Of => File_System; -- Current files function EOF_Char return Integer; diff --git a/gcc/ada/libgnat/a-tideio.ads b/gcc/ada/libgnat/a-tideio.ads index c504707..efe52c5 100644 --- a/gcc/ada/libgnat/a-tideio.ads +++ b/gcc/ada/libgnat/a-tideio.ads @@ -52,35 +52,58 @@ package Ada.Text_IO.Decimal_IO is procedure Get (File : File_Type; Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); procedure Get (Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Put (File : File_Type; Item : Num; Fore : Field := Default_Fore; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); procedure Put (Item : Num; Fore : Field := Default_Fore; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get (From : String; Item : out Num; - Last : out Positive); + Last : out Positive) + with + Global => null; procedure Put (To : out String; Item : Num; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Global => null; private pragma Inline (Get); diff --git a/gcc/ada/libgnat/a-tienio.ads b/gcc/ada/libgnat/a-tienio.ads index 68f4694..fb80abd 100644 --- a/gcc/ada/libgnat/a-tienio.ads +++ b/gcc/ada/libgnat/a-tienio.ads @@ -28,28 +28,49 @@ package Ada.Text_IO.Enumeration_IO is Default_Width : Field := 0; Default_Setting : Type_Set := Upper_Case; - procedure Get (File : File_Type; Item : out Enum); - procedure Get (Item : out Enum); + procedure Get (File : File_Type; Item : out Enum) with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); + procedure Get (Item : out Enum) with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Put (File : File_Type; Item : Enum; Width : Field := Default_Width; - Set : Type_Set := Default_Setting); + Set : Type_Set := Default_Setting) + with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); procedure Put (Item : Enum; Width : Field := Default_Width; - Set : Type_Set := Default_Setting); + Set : Type_Set := Default_Setting) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get (From : String; Item : out Enum; - Last : out Positive); + Last : out Positive) + with + Global => null; procedure Put (To : out String; Item : Enum; - Set : Type_Set := Default_Setting); + Set : Type_Set := Default_Setting) + with + Global => null; end Ada.Text_IO.Enumeration_IO; diff --git a/gcc/ada/libgnat/a-tifiio.ads b/gcc/ada/libgnat/a-tifiio.ads index 265600db..1acf67a 100644 --- a/gcc/ada/libgnat/a-tifiio.ads +++ b/gcc/ada/libgnat/a-tifiio.ads @@ -32,35 +32,58 @@ package Ada.Text_IO.Fixed_IO is procedure Get (File : File_Type; Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); procedure Get (Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Put (File : File_Type; Item : Num; Fore : Field := Default_Fore; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); procedure Put (Item : Num; Fore : Field := Default_Fore; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get (From : String; Item : out Num; - Last : out Positive); + Last : out Positive) + with + Global => null; procedure Put (To : out String; Item : Num; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Global => null; private pragma Inline (Get); diff --git a/gcc/ada/libgnat/a-tiflio.ads b/gcc/ada/libgnat/a-tiflio.ads index dcc4856..16e65a5 100644 --- a/gcc/ada/libgnat/a-tiflio.ads +++ b/gcc/ada/libgnat/a-tiflio.ads @@ -52,35 +52,58 @@ package Ada.Text_IO.Float_IO is procedure Get (File : File_Type; Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); procedure Get (Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Put (File : File_Type; Item : Num; Fore : Field := Default_Fore; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); procedure Put (Item : Num; Fore : Field := Default_Fore; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get (From : String; Item : out Num; - Last : out Positive); + Last : out Positive) + with + Global => null; procedure Put (To : out String; Item : Num; Aft : Field := Default_Aft; - Exp : Field := Default_Exp); + Exp : Field := Default_Exp) + with + Global => null; private pragma Inline (Get); diff --git a/gcc/ada/libgnat/a-tiinio.ads b/gcc/ada/libgnat/a-tiinio.ads index 429f3b1..28f8d54 100644 --- a/gcc/ada/libgnat/a-tiinio.ads +++ b/gcc/ada/libgnat/a-tiinio.ads @@ -51,32 +51,55 @@ package Ada.Text_IO.Integer_IO is procedure Get (File : File_Type; Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); procedure Get (Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Put (File : File_Type; Item : Num; Width : Field := Default_Width; - Base : Number_Base := Default_Base); + Base : Number_Base := Default_Base) + with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); procedure Put (Item : Num; Width : Field := Default_Width; - Base : Number_Base := Default_Base); + Base : Number_Base := Default_Base) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get (From : String; Item : out Num; - Last : out Positive); + Last : out Positive) + with + Global => null; procedure Put (To : out String; Item : Num; - Base : Number_Base := Default_Base); + Base : Number_Base := Default_Base) + with + Global => null; private pragma Inline (Get); diff --git a/gcc/ada/libgnat/a-timoio.ads b/gcc/ada/libgnat/a-timoio.ads index 5b8a72e..2d1ab91 100644 --- a/gcc/ada/libgnat/a-timoio.ads +++ b/gcc/ada/libgnat/a-timoio.ads @@ -51,32 +51,55 @@ package Ada.Text_IO.Modular_IO is procedure Get (File : File_Type; Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Pre => Is_Open (File) and then Mode (File) = In_File, + Global => (In_Out => File_System); procedure Get (Item : out Num; - Width : Field := 0); + Width : Field := 0) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Put (File : File_Type; Item : Num; Width : Field := Default_Width; - Base : Number_Base := Default_Base); + Base : Number_Base := Default_Base) + with + Pre => Is_Open (File) and then Mode (File) /= In_File, + Post => + Line_Length (File)'Old = Line_Length (File) + and Page_Length (File)'Old = Page_Length (File), + Global => (In_Out => File_System); procedure Put (Item : Num; Width : Field := Default_Width; - Base : Number_Base := Default_Base); + Base : Number_Base := Default_Base) + with + Post => + Line_Length'Old = Line_Length + and Page_Length'Old = Page_Length, + Global => (In_Out => File_System); procedure Get (From : String; Item : out Num; - Last : out Positive); + Last : out Positive) + with + Global => null; procedure Put (To : out String; Item : Num; - Base : Number_Base := Default_Base); + Base : Number_Base := Default_Base) + with + Global => null; private pragma Inline (Get); -- cgit v1.1 From 3eb5e54a4a50f3e7c39a1f5435f9d4eedb26bb37 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Fri, 5 Jul 2019 07:03:49 +0000 Subject: [Ada] Stabilization of Elaboration order v4.0 This patch introduces several changes to the new elaboration order mechanism: * Instantiations processed in the context of invocation graph encoding now yield a relation which is later transformed into an invocation edge. This ensures that the unit where the instantiation resides properly depends on the unit where the body of the generic is. * The diagnostics of cycles that involve invocation edges now use a set to avoid infinite recursion when visiting paths that represent recursive code. * Various diagnostics that suggest the use of switches have been updated to indicate which tool the switches apply to. * Bindo can now output the dependencies of various units that specify why a predecessor unit must be elaborated prior to a successor unit. This functionality implements binder switch -e (output complete list of elaboration order dependencies). * The output of the elaboration order is now identical to that emitted by Binde. * The nature of the invocation graph encoding is now recorded in the ALI record rather than the Unit record of a unit. This ensures that both the spec and body share the same encoding kind. * A section on debugging elaboration order issues is now available in Bindo. 2019-07-05 Hristian Kirtchev gcc/ada/ * ali.adb (For_Each_Invocation_Construct, For_Each_Invocation_Relation): New version. (Scan_ALI): Initialize field Invocation_Graph_Encoding. (Set_Invocation_Graph_Encoding): Update the setting of the invocation graph encoding. * ali.ads: Move field Invocation_Graph_Encoding from Unit_Record to ALI_Record because the encoding applies to the whole ALI, rather than one of the units (spec or body) for which the ALI file was created. (For_Each_Invocation_Construct, For_Each_Invocation_Relation): New version. * bindo.adb: Update the section on switches. Complete the section of debugging elaboration order issues. (Find_Elaboration_Order): Prepare the routine for the switch from the old to the new elaboration order mechanism. * bindo-diagnostics.adb (Find_And_Output_Invocation_Paths): Manage a visited set used by Visit_Vertex. (Output_All_Cycles_Suggestions, Output_Dynamic_Model_Suggestions): Clarify the nature of the suggested switch. (Output_Elaborate_Body_Transition): Update the diagnostic to emit a better message. (Output_Forced_Suggestions, Output_Full_Encoding_Suggestions): Clarify the nature of the suggested switch. (Visit_Vertex): Update the parameter profile to add a set of invokers visited during the transition. This set prevents infinite exploration of the graph in case the invocations are recursive. * bindo-elaborators.adb: Add a use clause for Bindo.Writers.Dependency_Writers. (Elaborate_Units_Common): Output the library graph after it has been augmented with invocation edges. Output just the components instead of outputting the whole library graph again. (Elaborate_Units_Dynamic, Elaborate_Units_Static): Output the dependencies as expressed in the library graph. * bindo-units.adb (Invocation_Graph_Encoding): Update the extraction of the invocation graph encoding. * bindo-writers.adb: Add with and use clauses for Binderr and Butil. (palgc, plgc): New debug routine. (Write_Components): Moved to the spec. Add a header for the output. (Write_Dependencies, Write_Dependencies_Of_Vertex, Write_Dependency_Edge): New routine. (Write_Elaboration_Order): Update the logic to follow the format of Binde's order output. (Write_Library_Graph): Do not output the components every time the graph is written. (Write_Unit): Output the invocation graph encoding of the unit. Output the invocation constructs and relations for the unit only. * bindo-writers.ads (Write_Components): Moved from the body. (Write_Dependencies): New routine. * bindusg.adb: Prepare the routine for the switch from the old to the new elaboration order mechanism. * debug.adb: Binder switch -d_O is now not associated with any functionality. * einfo.adb (Is_Elaboration_Target): The attribute applies to packages, as specified by the comment on the attribute usage. * opt.ads: Add a global flag which controls the choice between the new and the legacy elaboration order mechanism. * sem_elab.adb: Add Package_Target to type Target_Kind. (Build_Elaborate_Body_Procedure, Build_Elaborate_Procedure, Build_Elaborate_Spec_Procedure, Check_Elaboration_Scenarios, Check_SPARK_Model_In_Effect): Use Main_Unit_Entity to obtain the entity of the main unit. (Create_Package_Rep): New routine. (Create_Target_Rep): Add processing for packages. (Declaration_Placement_Of_Node, Has_Prior_Elaboration): Use Main_Unit_Entity to obtain the entity of the main unit. (Invocation_Graph_Recording_OK): Prepare the routine for the switch from the old to the new elaboration order mechanism. (Main_Unit_Entity): New routine. (Meet_Elaboration_Requirement, Process_Conditional_ABE_Variable_Reference): Use Main_Unit_Entity to obtain the entity of the main unit. (Process_Invocation_Instantiation): New routine. (Process_Invocation_Scenario): Add processing for instantiations. * switch-b.adb (Scan_Binder_Switches): Prepare the routine for the switch from the old to the new elaboration order mechanism. From-SVN: r273128 --- gcc/ada/ChangeLog | 85 +++++++++++++ gcc/ada/ali.adb | 46 ++++++- gcc/ada/ali.ads | 24 +++- gcc/ada/bindo-diagnostics.adb | 63 +++++++--- gcc/ada/bindo-elaborators.adb | 27 +++- gcc/ada/bindo-units.adb | 3 +- gcc/ada/bindo-writers.adb | 277 +++++++++++++++++++++++++++++++++++++----- gcc/ada/bindo-writers.ads | 14 +++ gcc/ada/bindo.adb | 158 +++++++++++++++++++++--- gcc/ada/bindusg.adb | 8 ++ gcc/ada/debug.adb | 4 +- gcc/ada/einfo.adb | 2 +- gcc/ada/opt.ads | 5 + gcc/ada/sem_elab.adb | 129 +++++++++++++++++--- gcc/ada/switch-b.adb | 9 ++ 15 files changed, 765 insertions(+), 89 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8820113..6f04f77 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,88 @@ +2019-07-05 Hristian Kirtchev + + * ali.adb (For_Each_Invocation_Construct, + For_Each_Invocation_Relation): New version. + (Scan_ALI): Initialize field Invocation_Graph_Encoding. + (Set_Invocation_Graph_Encoding): Update the setting of the + invocation graph encoding. + * ali.ads: Move field Invocation_Graph_Encoding from Unit_Record + to ALI_Record because the encoding applies to the whole ALI, + rather than one of the units (spec or body) for which the ALI + file was created. + (For_Each_Invocation_Construct, For_Each_Invocation_Relation): + New version. + * bindo.adb: Update the section on switches. Complete the + section of debugging elaboration order issues. + (Find_Elaboration_Order): Prepare the routine for the switch + from the old to the new elaboration order mechanism. + * bindo-diagnostics.adb (Find_And_Output_Invocation_Paths): + Manage a visited set used by Visit_Vertex. + (Output_All_Cycles_Suggestions, + Output_Dynamic_Model_Suggestions): Clarify the nature of the + suggested switch. + (Output_Elaborate_Body_Transition): Update the diagnostic to + emit a better message. + (Output_Forced_Suggestions, Output_Full_Encoding_Suggestions): + Clarify the nature of the suggested switch. + (Visit_Vertex): Update the parameter profile to add a set of + invokers visited during the transition. This set prevents + infinite exploration of the graph in case the invocations are + recursive. + * bindo-elaborators.adb: Add a use clause for + Bindo.Writers.Dependency_Writers. + (Elaborate_Units_Common): Output the library graph after it has + been augmented with invocation edges. Output just the components + instead of outputting the whole library graph again. + (Elaborate_Units_Dynamic, Elaborate_Units_Static): Output the + dependencies as expressed in the library graph. + * bindo-units.adb (Invocation_Graph_Encoding): Update the + extraction of the invocation graph encoding. + * bindo-writers.adb: Add with and use clauses for Binderr and + Butil. + (palgc, plgc): New debug routine. + (Write_Components): Moved to the spec. Add a header for the + output. + (Write_Dependencies, Write_Dependencies_Of_Vertex, + Write_Dependency_Edge): New routine. + (Write_Elaboration_Order): Update the logic to follow the format + of Binde's order output. + (Write_Library_Graph): Do not output the components every time + the graph is written. + (Write_Unit): Output the invocation graph encoding of the unit. + Output the invocation constructs and relations for the unit + only. + * bindo-writers.ads (Write_Components): Moved from the body. + (Write_Dependencies): New routine. + * bindusg.adb: Prepare the routine for the switch from the old + to the new elaboration order mechanism. + * debug.adb: Binder switch -d_O is now not associated with any + functionality. + * einfo.adb (Is_Elaboration_Target): The attribute applies to + packages, as specified by the comment on the attribute usage. + * opt.ads: Add a global flag which controls the choice between + the new and the legacy elaboration order mechanism. + * sem_elab.adb: Add Package_Target to type Target_Kind. + (Build_Elaborate_Body_Procedure, Build_Elaborate_Procedure, + Build_Elaborate_Spec_Procedure, Check_Elaboration_Scenarios, + Check_SPARK_Model_In_Effect): Use Main_Unit_Entity to obtain the + entity of the main unit. + (Create_Package_Rep): New routine. + (Create_Target_Rep): Add processing for packages. + (Declaration_Placement_Of_Node, Has_Prior_Elaboration): Use + Main_Unit_Entity to obtain the entity of the main + unit. + (Invocation_Graph_Recording_OK): Prepare the routine for the + switch from the old to the new elaboration order mechanism. + (Main_Unit_Entity): New routine. + (Meet_Elaboration_Requirement, + Process_Conditional_ABE_Variable_Reference): Use + Main_Unit_Entity to obtain the entity of the main unit. + (Process_Invocation_Instantiation): New routine. + (Process_Invocation_Scenario): Add processing for + instantiations. + * switch-b.adb (Scan_Binder_Switches): Prepare the routine for + the switch from the old to the new elaboration order mechanism. + 2019-07-05 Joffrey Huguet * libgnat/a-textio.adb: Add abstract state refinment. diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb index aa8b242..feea73f 100644 --- a/gcc/ada/ali.adb +++ b/gcc/ada/ali.adb @@ -510,6 +510,27 @@ package body ALI is end loop; end For_Each_Invocation_Construct; + ----------------------------------- + -- For_Each_Invocation_Construct -- + ----------------------------------- + + procedure For_Each_Invocation_Construct + (U_Id : Unit_Id; + Processor : Invocation_Construct_Processor_Ptr) + is + pragma Assert (Present (U_Id)); + pragma Assert (Processor /= null); + + U_Rec : Unit_Record renames Units.Table (U_Id); + + begin + for IC_Id in U_Rec.First_Invocation_Construct .. + U_Rec.Last_Invocation_Construct + loop + Processor.all (IC_Id); + end loop; + end For_Each_Invocation_Construct; + ---------------------------------- -- For_Each_Invocation_Relation -- ---------------------------------- @@ -527,6 +548,27 @@ package body ALI is end loop; end For_Each_Invocation_Relation; + ---------------------------------- + -- For_Each_Invocation_Relation -- + ---------------------------------- + + procedure For_Each_Invocation_Relation + (U_Id : Unit_Id; + Processor : Invocation_Relation_Processor_Ptr) + is + pragma Assert (Present (U_Id)); + pragma Assert (Processor /= null); + + U_Rec : Unit_Record renames Units.Table (U_Id); + + begin + for IR_Id in U_Rec.First_Invocation_Relation .. + U_Rec.Last_Invocation_Relation + loop + Processor.all (IR_Id); + end loop; + end For_Each_Invocation_Relation; + ---------- -- Hash -- ---------- @@ -1831,6 +1873,7 @@ package body ALI is First_Specific_Dispatching => Specific_Dispatching.Last + 1, First_Unit => No_Unit_Id, GNATprove_Mode => False, + Invocation_Graph_Encoding => No_Encoding, Last_Interrupt_State => Interrupt_States.Last, Last_Sdep => No_Sdep_Id, Last_Specific_Dispatching => Specific_Dispatching.Last, @@ -3807,9 +3850,10 @@ package body ALI is if Update_Units then declare Curr_Unit : Unit_Record renames Units.Table (Units.Last); + Curr_ALI : ALIs_Record renames ALIs.Table (Curr_Unit.My_ALI); begin - Curr_Unit.Invocation_Graph_Encoding := Kind; + Curr_ALI.Invocation_Graph_Encoding := Kind; end; end if; end Set_Invocation_Graph_Encoding; diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads index 6db9e49..3fa527e 100644 --- a/gcc/ada/ali.ads +++ b/gcc/ada/ali.ads @@ -273,6 +273,11 @@ package ALI is -- Last_Specific_Dispatching = First_Specific_Dispatching - 1. That -- is why the 'Base reference is there, it can be one less than the -- lower bound of the subtype. Not set if 'S' appears in Ignore_Lines. + + Invocation_Graph_Encoding : Invocation_Graph_Encoding_Kind; + -- The encoding format used to capture information about the invocation + -- constructs and relations within the corresponding ALI file of this + -- unit. end record; No_Main_Priority : constant Int := -1; @@ -382,11 +387,6 @@ package ALI is Last_Arg : Arg_Id; -- Id of last args table entry for this file - Invocation_Graph_Encoding : Invocation_Graph_Encoding_Kind; - -- The encoding format used to capture information about the invocation - -- constructs and relations within the corresponding ALI file of this - -- unit. - First_Invocation_Construct : Invocation_Construct_Id; -- Id of the first invocation construct for this unit @@ -1271,13 +1271,25 @@ package ALI is pragma Inline (For_Each_Invocation_Construct); -- Invoke Processor on each invocation construct + procedure For_Each_Invocation_Construct + (U_Id : Unit_Id; + Processor : Invocation_Construct_Processor_Ptr); + pragma Inline (For_Each_Invocation_Construct); + -- Invoke Processor on each invocation construct of unit U_Id + type Invocation_Relation_Processor_Ptr is access procedure (IR_Id : Invocation_Relation_Id); procedure For_Each_Invocation_Relation (Processor : Invocation_Relation_Processor_Ptr); pragma Inline (For_Each_Invocation_Relation); - -- Invoker Processor on each invocation relation + -- Invoke Processor on each invocation relation + + procedure For_Each_Invocation_Relation + (U_Id : Unit_Id; + Processor : Invocation_Relation_Processor_Ptr); + pragma Inline (For_Each_Invocation_Relation); + -- Invoke Processor on each invocation relation of unit U_Id function Invocation_Construct_Kind_To_Code (Kind : Invocation_Construct_Kind) return Character; diff --git a/gcc/ada/bindo-diagnostics.adb b/gcc/ada/bindo-diagnostics.adb index a4b031d..0c9da46 100644 --- a/gcc/ada/bindo-diagnostics.adb +++ b/gcc/ada/bindo-diagnostics.adb @@ -247,6 +247,7 @@ package body Bindo.Diagnostics is Last_Vertex : Library_Graph_Vertex_Id; Elaborated_Vertex : Library_Graph_Vertex_Id; End_Vertex : Library_Graph_Vertex_Id; + Visited_Invokers : IGV_Sets.Membership_Set; Path : IGE_Lists.Doubly_Linked_List; Path_Id : in out Nat); pragma Inline (Visit_Vertex); @@ -254,8 +255,9 @@ package body Bindo.Diagnostics is -- vertex Invoker_Vertex as part of a DFS traversal. Last_Vertex denotes -- the previous vertex in the traversal. Elaborated_Vertex is the vertex -- whose elaboration started the traversal. End_Vertex is the vertex that - -- terminates the traversal. All edges along the path are recorded in Path. - -- Path_Id is the id of the path. + -- terminates the traversal. Visited_Invoker is the set of all invokers + -- visited so far. All edges along the path are recorded in Path. Path_Id + -- is the id of the path. ------------------------- -- Diagnose_All_Cycles -- @@ -411,6 +413,7 @@ package body Bindo.Diagnostics is is Path : IGE_Lists.Doubly_Linked_List; Path_Id : Nat; + Visited : IGV_Sets.Membership_Set; begin pragma Assert (Present (Inv_Graph)); @@ -429,6 +432,7 @@ package body Bindo.Diagnostics is Path := IGE_Lists.Create; Path_Id := 1; + Visited := IGV_Sets.Create (Number_Of_Vertices (Inv_Graph)); -- Start a DFS traversal over the invocation graph, in an attempt to -- reach Destination from Source. The actual start of the path is the @@ -447,10 +451,12 @@ package body Bindo.Diagnostics is Last_Vertex => Source, Elaborated_Vertex => Source, End_Vertex => Destination, + Visited_Invokers => Visited, Path => Path, Path_Id => Path_Id); IGE_Lists.Destroy (Path); + IGV_Sets.Destroy (Visited); end Find_And_Output_Invocation_Paths; --------------------------- @@ -511,7 +517,7 @@ package body Bindo.Diagnostics is if Number_Of_Cycles (G) > 1 and then not Debug_Flag_Underscore_CC then Error_Msg_Info - (" diagnose all circularities (-d_C)"); + (" diagnose all circularities (binder switch -d_C)"); end if; end Output_All_Cycles_Suggestions; @@ -535,7 +541,7 @@ package body Bindo.Diagnostics is and then not Is_Dynamically_Elaborated (G) then Error_Msg_Info - (" use the dynamic elaboration model (-gnatE)"); + (" use the dynamic elaboration model (compiler switch -gnatE)"); end if; end Output_Dynamic_Model_Suggestions; @@ -665,17 +671,21 @@ package body Bindo.Diagnostics is pragma Assert (Present (Expected_Destination)); -- The actual and expected destination vertices match, and denote the - -- spec of a unit subject to pragma Elaborate_Body. There is no need to - -- mention the pragma because it does not affect the path of the cycle. - -- Treat the edge as a regular with edge. + -- spec or body of a unit subject to pragma Elaborate_Body. There is no + -- need to mention the pragma because it does not affect the path of the + -- cycle. Treat the edge as a regular with edge. -- -- Actual_Destination -- Source --> spec Elaborate_Body --> -- Expected_Destination + -- + -- spec Elaborate_Body + -- + -- Actual_Destination + -- Source --> body --> + -- Expected_Destination if Actual_Destination = Expected_Destination then - pragma Assert (Is_Spec (G, Actual_Destination)); - Error_Msg_Unit_1 := Name (G, Source); Error_Msg_Unit_2 := Name (G, Actual_Destination); Error_Msg_Info @@ -698,14 +708,18 @@ package body Bindo.Diagnostics is pragma Assert (Proper_Body (G, Actual_Destination) = Expected_Destination); + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause for unit $"); + Error_Msg_Unit_1 := Name (G, Actual_Destination); Error_Msg_Info (" unit $ is subject to pragma Elaborate_Body"); - Error_Msg_Unit_1 := Name (G, Source); - Error_Msg_Unit_2 := Name (G, Expected_Destination); + Error_Msg_Unit_1 := Name (G, Expected_Destination); Error_Msg_Info - (" unit $ has with clause for unit $"); + (" unit $ is in the closure of pragma Elaborate_Body"); end if; end Output_Elaborate_Body_Transition; @@ -832,8 +846,10 @@ package body Bindo.Diagnostics is Error_Msg_Unit_1 := Name (G, Succ); Error_Msg_Unit_2 := Name (G, Pred); Error_Msg_Info - (" remove the dependency of unit $ on unit $ from argument of -f " - & "switch"); + (" remove the dependency of unit $ on unit $ from the argument of " + & "switch -f"); + Error_Msg_Info + (" remove switch -f"); end Output_Forced_Suggestions; ------------------------------ @@ -950,7 +966,8 @@ package body Bindo.Diagnostics is if Invocation_Graph_Encoding (G, Succ) /= Full_Path_Encoding then Error_Msg_Info - (" use detailed invocation information (-gnatd_F)"); + (" use detailed invocation information (compiler switch " + & "-gnatd_F)"); end if; end if; end Output_Full_Encoding_Suggestions; @@ -1410,6 +1427,7 @@ package body Bindo.Diagnostics is Last_Vertex : Library_Graph_Vertex_Id; Elaborated_Vertex : Library_Graph_Vertex_Id; End_Vertex : Library_Graph_Vertex_Id; + Visited_Invokers : IGV_Sets.Membership_Set; Path : IGE_Lists.Doubly_Linked_List; Path_Id : in out Nat) is @@ -1425,6 +1443,7 @@ package body Bindo.Diagnostics is pragma Assert (Present (Last_Vertex)); pragma Assert (Present (Elaborated_Vertex)); pragma Assert (Present (End_Vertex)); + pragma Assert (IGV_Sets.Present (Visited_Invokers)); pragma Assert (IGE_Lists.Present (Path)); -- The current invocation vertex resides within the end library vertex. @@ -1444,7 +1463,14 @@ package body Bindo.Diagnostics is -- Otherwise extend the search for the end library vertex via all edges -- to targets. - else + elsif not IGV_Sets.Contains (Visited_Invokers, Invoker) then + + -- Prepare for invoker backtracking + + IGV_Sets.Insert (Visited_Invokers, Invoker); + + -- Extend the search via all edges to targets + Iter := Iterate_Edges_To_Targets (Inv_Graph, Invoker); while Has_Next (Iter) loop Next (Iter, Edge); @@ -1466,6 +1492,7 @@ package body Bindo.Diagnostics is Last_Vertex => Invoker_Vertex, Elaborated_Vertex => Elaborated_Vertex, End_Vertex => End_Vertex, + Visited_Invokers => Visited_Invokers, Path => Path, Path_Id => Path_Id); @@ -1473,6 +1500,10 @@ package body Bindo.Diagnostics is IGE_Lists.Delete_Last (Path); end loop; + + -- Backtrack the invoker + + IGV_Sets.Delete (Visited_Invokers, Invoker); end if; end Visit_Vertex; diff --git a/gcc/ada/bindo-elaborators.adb b/gcc/ada/bindo-elaborators.adb index d26101a..762198b 100644 --- a/gcc/ada/bindo-elaborators.adb +++ b/gcc/ada/bindo-elaborators.adb @@ -52,6 +52,7 @@ use Bindo.Validators.Library_Graph_Validators; with Bindo.Writers; use Bindo.Writers; use Bindo.Writers.ALI_Writers; +use Bindo.Writers.Dependency_Writers; use Bindo.Writers.Elaboration_Order_Writers; use Bindo.Writers.Invocation_Graph_Writers; use Bindo.Writers.Library_Graph_Writers; @@ -695,12 +696,13 @@ package body Bindo.Elaborators is -- to a unit that result in extra edges within the library graph. Augment_Library_Graph (Inv_Graph, Lib_Graph); + Write_Library_Graph (Lib_Graph); -- Create and output the component graph by collapsing all library -- items into library units and traversing the library graph. - Find_Components (Lib_Graph); - Write_Library_Graph (Lib_Graph); + Find_Components (Lib_Graph); + Write_Components (Lib_Graph); -- Traverse the library graph to determine the elaboration order of -- units. @@ -742,6 +744,11 @@ package body Bindo.Elaborators is if Status = Order_OK then Order := Mix_Order; + -- Output the dependencies of vertices when switch -e (output + -- complete list of elaboration order dependencies) is active. + + Write_Dependencies (Mix_Lib_Graph); + -- The library graph contains an Elaborate_All circularity. There is -- no point in re-elaborating the units without the information from -- the invocation graph because the circularity will persist. @@ -774,6 +781,11 @@ package body Bindo.Elaborators is if Status = Order_OK then Order := Dyn_Order; + -- Output the dependencies of vertices when switch -e (output + -- complete list of elaboration order dependencies) is active. + + Write_Dependencies (Dyn_Lib_Graph); + -- Otherwise the library graph contains a circularity without the -- extra information provided by the invocation graph. Diagnose -- the circularity. @@ -820,9 +832,16 @@ package body Bindo.Elaborators is Order => Order, Status => Status); - -- The augmented library graph contains a circularity + -- The elaboration order is satisfactory. Output the dependencies of + -- vertices when switch -e (output complete list of elaboration order + -- dependencies) is active. - if Status /= Order_OK then + if Status = Order_OK then + Write_Dependencies (Lib_Graph); + + -- Otherwise the augmented library graph contains a circularity + + else Diagnose_Circularities (Inv_Graph => Inv_Graph, Lib_Graph => Lib_Graph); diff --git a/gcc/ada/bindo-units.adb b/gcc/ada/bindo-units.adb index f234f40..05b5250 100644 --- a/gcc/ada/bindo-units.adb +++ b/gcc/ada/bindo-units.adb @@ -243,9 +243,10 @@ package body Bindo.Units is pragma Assert (Present (U_Id)); U_Rec : Unit_Record renames ALI.Units.Table (U_Id); + U_ALI : ALIs_Record renames ALI.ALIs.Table (U_Rec.My_ALI); begin - return U_Rec.Invocation_Graph_Encoding; + return U_ALI.Invocation_Graph_Encoding; end Invocation_Graph_Encoding; ------------------------------- diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb index 067ba1f..a3b45fc 100644 --- a/gcc/ada/bindo-writers.adb +++ b/gcc/ada/bindo-writers.adb @@ -23,10 +23,12 @@ -- -- ------------------------------------------------------------------------------ -with Debug; use Debug; -with Fname; use Fname; -with Opt; use Opt; -with Output; use Output; +with Binderr; use Binderr; +with Butil; use Butil; +with Debug; use Debug; +with Fname; use Fname; +with Opt; use Opt; +with Output; use Output; with Bindo.Units; use Bindo.Units; @@ -271,10 +273,19 @@ package body Bindo.Writers is Write_Int (Int (U_Rec.Last_Invocation_Relation)); Write_Str (")"); Write_Eol; + + Write_Str (" Invocation_Graph_Encoding = "); + Write_Str (Invocation_Graph_Encoding (U_Id)'Img); + Write_Eol; Write_Eol; - For_Each_Invocation_Construct (Write_Invocation_Construct'Access); - For_Each_Invocation_Relation (Write_Invocation_Relation'Access); + For_Each_Invocation_Construct + (U_Id => U_Id, + Processor => Write_Invocation_Construct'Access); + + For_Each_Invocation_Relation + (U_Id => U_Id, + Processor => Write_Invocation_Relation'Access); end Write_Unit; ----------------------- @@ -323,6 +334,18 @@ package body Bindo.Writers is pragma Inline (Write_Cyclic_Edge); -- Write cyclic edge Edge of library graph G to standard + ----------- + -- Debug -- + ----------- + + procedure palgc (G : Library_Graph) renames Write_Cycles; + pragma Unreferenced (palgc); + + procedure plgc + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) renames Write_Cycle; + pragma Unreferenced (plgc); + ----------------- -- Write_Cycle -- ----------------- @@ -425,6 +448,178 @@ package body Bindo.Writers is end Write_Cyclic_Edge; end Cycle_Writers; + ------------------------ + -- Dependency_Writers -- + ------------------------ + + package body Dependency_Writers is + + ----------------------- + -- Local subprograms -- + ----------------------- + + procedure Write_Dependencies_Of_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id); + pragma Inline (Write_Dependencies_Of_Vertex); + -- Write the dependencies of vertex Vertex of library graph G to + -- standard output. + + procedure Write_Dependency_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id); + pragma Inline (Write_Dependency_Edge); + -- Write the dependency described by edge Edge of library graph G to + -- standard output. + + ------------------------ + -- Write_Dependencies -- + ------------------------ + + procedure Write_Dependencies (G : Library_Graph) is + Use_Formatting : constant Boolean := not Zero_Formatting; + + Iter : Library_Graphs.All_Vertex_Iterator; + Vertex : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (G)); + + -- Nothing to do when switch -e (output complete list of elaboration + -- order dependencies) is not in effect. + + if not Elab_Dependency_Output then + return; + end if; + + if Use_Formatting then + Write_Eol; + Write_Line ("ELABORATION ORDER DEPENDENCIES"); + Write_Eol; + end if; + + Info_Prefix_Suppress := True; + + Iter := Iterate_All_Vertices (G); + while Has_Next (Iter) loop + Next (Iter, Vertex); + + Write_Dependencies_Of_Vertex (G, Vertex); + end loop; + + Info_Prefix_Suppress := False; + + if Use_Formatting then + Write_Eol; + end if; + end Write_Dependencies; + + ---------------------------------- + -- Write_Dependencies_Of_Vertex -- + ---------------------------------- + + procedure Write_Dependencies_Of_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) + is + Edge : Library_Graph_Edge_Id; + Iter : Edges_To_Successors_Iterator; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + -- Nothing to do for internal and predefined units + + if Is_Internal_Unit (G, Vertex) + or else Is_Predefined_Unit (G, Vertex) + then + return; + end if; + + Iter := Iterate_Edges_To_Successors (G, Vertex); + while Has_Next (Iter) loop + Next (Iter, Edge); + + Write_Dependency_Edge (G, Edge); + end loop; + end Write_Dependencies_Of_Vertex; + + --------------------------- + -- Write_Dependency_Edge -- + --------------------------- + + procedure Write_Dependency_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge); + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); + + begin + -- Nothing to do for internal and predefined units + + if Is_Internal_Unit (G, Succ) + or else Is_Predefined_Unit (G, Succ) + then + return; + end if; + + Error_Msg_Unit_1 := Name (G, Pred); + Error_Msg_Unit_2 := Name (G, Succ); + Error_Msg_Output + (Msg => " unit $ must be elaborated before unit $", + Info => True); + + Error_Msg_Unit_1 := Name (G, Succ); + Error_Msg_Unit_2 := Name (G, Pred); + + if Is_Elaborate_All_Edge (G, Edge) then + Error_Msg_Output + (Msg => + " reason: unit $ has with clause and pragma " + & "Elaborate_All for unit $", + Info => True); + + elsif Is_Elaborate_Body_Edge (G, Edge) then + Error_Msg_Output + (Msg => " reason: unit $ has with clause for unit $", + Info => True); + + elsif Is_Elaborate_Edge (G, Edge) then + Error_Msg_Output + (Msg => + " reason: unit $ has with clause and pragma Elaborate " + & "for unit $", + Info => True); + + elsif Is_Forced_Edge (G, Edge) then + Error_Msg_Output + (Msg => + " reason: unit $ has a dependency on unit $ forced by -f " + & "switch", + Info => True); + + elsif Is_Invocation_Edge (G, Edge) then + Error_Msg_Output + (Msg => + " reason: unit $ invokes a construct of unit $ at " + & "elaboration time", + Info => True); + + else + pragma Assert (Is_With_Edge (G, Edge)); + + Error_Msg_Output + (Msg => " reason: unit $ has with clause for unit $", + Info => True); + end if; + end Write_Dependency_Edge; + end Dependency_Writers; + ------------------------------- -- Elaboration_Order_Writers -- ------------------------------- @@ -448,25 +643,27 @@ package body Bindo.Writers is ----------------------------- procedure Write_Elaboration_Order (Order : Unit_Id_Table) is + Use_Formatting : constant Boolean := not Zero_Formatting; + begin - -- Nothing to do when switch -d_O (output elaboration order) is not - -- in effect. + -- Nothing to do when switch -l (output chosen elaboration order) is + -- not in effect. - if not Debug_Flag_Underscore_OO then + if not Elab_Order_Output then return; end if; - Write_Str ("Elaboration Order"); - Write_Eol; - Write_Eol; + if Use_Formatting then + Write_Eol; + Write_Str ("ELABORATION ORDER"); + Write_Eol; + end if; Write_Units (Order); - Write_Eol; - Write_Str ("Elaboration Order end"); - Write_Eol; - - Write_Eol; + if Use_Formatting then + Write_Eol; + end if; end Write_Elaboration_Order; ---------------- @@ -474,13 +671,16 @@ package body Bindo.Writers is ---------------- procedure Write_Unit (U_Id : Unit_Id) is + Use_Formatting : constant Boolean := not Zero_Formatting; + begin pragma Assert (Present (U_Id)); - Write_Str ("unit (U_Id_"); - Write_Int (Int (U_Id)); - Write_Str (") name = "); - Write_Name (Name (U_Id)); + if Use_Formatting then + Write_Str (" "); + end if; + + Write_Unit_Name (Name (U_Id)); Write_Eol; end Write_Unit; @@ -825,10 +1025,6 @@ package body Bindo.Writers is -- Write all vertices of component Comp of library graph G to standard -- output. - procedure Write_Components (G : Library_Graph); - pragma Inline (Write_Components); - -- Write all components of library graph G to standard output - procedure Write_Edges_To_Successors (G : Library_Graph; Vertex : Library_Graph_Vertex_Id); @@ -942,7 +1138,22 @@ package body Bindo.Writers is Iter : Component_Iterator; begin + -- Nothing to do when switch -d_L (output library item graph) is not + -- in effect. + + if not Debug_Flag_Underscore_LL then + return; + end if; + + Write_Str ("Library Graph components"); + Write_Eol; + Write_Eol; + if Num_Of_Comps > 0 then + Write_Str ("Components: "); + Write_Num (Int (Num_Of_Comps)); + Write_Eol; + Iter := Iterate_Components (G); while Has_Next (Iter) loop Next (Iter, Comp); @@ -952,6 +1163,11 @@ package body Bindo.Writers is else Write_Eol; end if; + + Write_Str ("Library Graph components end"); + Write_Eol; + + Write_Eol; end Write_Components; ------------------------------- @@ -1009,7 +1225,6 @@ package body Bindo.Writers is Write_Statistics (G); Write_Library_Graph_Vertices (G); - Write_Components (G); Write_Str ("Library Graph end"); Write_Eol; @@ -1231,10 +1446,12 @@ package body Bindo.Writers is --------------------- procedure Write_File_Name (Nam : File_Name_Type) is + Use_Formatting : constant Boolean := not Zero_Formatting; + begin pragma Assert (Present (Nam)); - if not Zero_Formatting then + if Use_Formatting then Write_Str (" "); end if; @@ -1296,6 +1513,8 @@ package body Bindo.Writers is ------------------------ procedure Write_Unit_Closure (Order : Unit_Id_Table) is + Use_Formatting : constant Boolean := not Zero_Formatting; + Set : Membership_Set; begin @@ -1306,7 +1525,7 @@ package body Bindo.Writers is return; end if; - if not Zero_Formatting then + if Use_Formatting then Write_Eol; Write_Line ("REFERENCED SOURCES"); end if; @@ -1320,7 +1539,7 @@ package body Bindo.Writers is Destroy (Set); - if not Zero_Formatting then + if Use_Formatting then Write_Eol; end if; end Write_Unit_Closure; diff --git a/gcc/ada/bindo-writers.ads b/gcc/ada/bindo-writers.ads index b791638..ff6b9b3 100644 --- a/gcc/ada/bindo-writers.ads +++ b/gcc/ada/bindo-writers.ads @@ -91,6 +91,17 @@ package Bindo.Writers is end Cycle_Writers; + ------------------------ + -- Dependency_Writers -- + ------------------------ + + package Dependency_Writers is + procedure Write_Dependencies (G : Library_Graph); + -- Write all elaboration dependencies of the units represented by + -- vertices of library graph G. + + end Dependency_Writers; + ------------------------------- -- Elaboration_Order_Writers -- ------------------------------- @@ -116,6 +127,9 @@ package Bindo.Writers is --------------------------- package Library_Graph_Writers is + procedure Write_Components (G : Library_Graph); + -- Write all components of library graph G to standard output + procedure Write_Library_Graph (G : Library_Graph); -- Write library graph G to standard output diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index 039fd0d..b3106ad 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -32,10 +32,10 @@ use Bindo.Elaborators; package body Bindo is --------------------------------- - -- Elaboration order mechanism -- + -- Elaboration-order mechanism -- --------------------------------- - -- The elaboration order (EO) mechanism implemented in this unit and its + -- The elaboration-order (EO) mechanism implemented in this unit and its -- children has the following objectives: -- -- * Find an ordering of all library items (historically referred to as @@ -272,7 +272,7 @@ package body Bindo is -- whose elaboration cannot be guaranteed. -- -- - A detailed traceback of the cycle, showcasing the transition - -- between units, along with any other elaboration order-related + -- between units, along with any other elaboration-order-related -- information. -- -- - A set of suggestions on how to break the cycle considering the @@ -308,18 +308,13 @@ package body Bindo is -- -- GNATbind utilizes the new bindo elaboration order -- - -- -d_O Output elaboration order - -- - -- GNATbind outputs the elaboration order in text format to standard - -- output. - -- -- -d_P Output cycle paths -- -- GNATbind output the cycle paths in text format to standard output -- - -- -d_T Output elaboration order trace information + -- -d_T Output elaboration-order trace information -- - -- GNATbind outputs trace information on elaboration order and cycle + -- GNATbind outputs trace information on elaboration-order and cycle- -- detection activities to standard output. -- -- -d_V Validate bindo cycles, graphs, and order @@ -327,12 +322,126 @@ package body Bindo is -- GNATbind validates the invocation graph, library graph along with -- its cycles, and elaboration order by detecting inconsistencies and -- producing error reports. + -- + -- -e Output complete list of elaboration-order dependencies + -- + -- GNATbind outputs the dependencies between units to standard + -- output. + -- + -- -f Force elaboration order from given file + -- + -- GNATbind applies an additional set of edges to the library graph. + -- The edges are read from a file specified by the argument of the + -- flag. + -- + -- -H Legacy elaboration-order model enabled + -- + -- GNATbind uses the library-graph and heuristics-based elaboration- + -- order model. + -- + -- -l Output chosen elaboration order + -- + -- GNATbind outputs the elaboration order in text format to standard + -- output. + -- + -- -p Pessimistic (worst-case) elaboration order + -- + -- This switch is not used in Bindo and its children. ---------------------------------------- - -- Debugging elaboration order issues -- + -- Debugging elaboration-order issues -- ---------------------------------------- - -- ??? more on this later + -- Prior to debugging elaboration-order-related issues, enable all relevant + -- debug flags to collect as much information as possible. Depending on the + -- number of files in the bind, Bindo may emit anywhere between several MBs + -- to several hundred MBs of data to standard output. The switches are: + -- + -- -d_A -d_C -d_I -d_L -d_P -d_T -d_V + -- + -- Bindo offers several debugging routines that can be invoked from gdb. + -- Those are defined in the body of Bindo.Writers, in sections denoted by + -- header Debug. For quick reference, the routines are: + -- + -- palgc -- print all library-graph cycles + -- pau -- print all units + -- pc -- print component + -- pige -- print invocation-graph edge + -- pigv -- print invocation-graph vertex + -- plgc -- print library-graph cycle + -- plge -- print library-graph edge + -- plgv -- print library-graph vertex + -- pu -- print units + -- + -- * Invalid elaboration order + -- + -- The elaboration order is invalid when: + -- + -- - A unit that requires elaboration is missing from the order + -- - A unit that does not require elaboration is present in the order + -- + -- Examine the output of the elaboration algorithm available via switch + -- -d_T to determine how the related units were included in or excluded + -- from the order. Determine whether the library graph contains all the + -- relevant edges for those units. + -- + -- Units and routines of interest: + -- Bindo.Elaborators + -- Elaborate_Library_Graph + -- Elaborate_Units_Common + -- Elaborate_Units_Dynamic + -- Elaborate_Units_Static + -- + -- * Invalid invocation graph + -- + -- The invocation graph is invalid when: + -- + -- - An edge lacks an attribute + -- - A vertex lacks an attribute + -- + -- Find the malformed edge or vertex and determine which attribute is + -- missing. Examine the contents of the invocation-related ALI tables + -- available via switch -d_A. If the invocation construct or relation + -- is missing, verify the ALI file. If the ALI lacks all the relevant + -- information, then Sem_Elab most likely failed to discover a valid + -- elaboration path. + -- + -- Units and routines of interest: + -- Bindo.Builders + -- Bindo.Graphs + -- Add_Edge + -- Add_Vertex + -- Build_Invocation_Graph + -- + -- * Invalid library graph + -- + -- The library graph is invalid when: + -- + -- - An edge lacks an attribute + -- - A vertex lacks an attribute + -- + -- Find the malformed edge or vertex and determine which attribute is + -- missing. + -- + -- Units and routines of interest: + -- Bindo.Builders + -- Bindo.Graphs + -- Add_Edge + -- Add_Vertex + -- Build_Library_Graph + -- + -- * Invalid library-graph cycle + -- + -- A library-graph cycle is invalid when: + -- + -- - It lacks enough edges to form a circuit + -- - At least one edge in the circuit is repeated + -- + -- Find the malformed cycle and determine which attribute is missing. + -- + -- Units and routines of interest: + -- Bindo.Graphs + -- Find_Cycles ---------------------------- -- Find_Elaboration_Order -- @@ -343,7 +452,28 @@ package body Bindo is Main_Lib_File : File_Name_Type) is begin - -- Use the invocation and library graph-based elaboration order when + -- ??? Enable the following code when switching from the old to the new + -- elaboration-order mechanism. + + -- Use the library graph and heuristic-based elaboration order when + -- switch -H (legacy elaboration-order mode enabled). + + -- if Legacy_Elaboration_Order then + -- Binde.Find_Elab_Order (Order, Main_Lib_File); + + -- Otherwise use the invocation and library-graph-based elaboration + -- order. + + -- else + -- Invocation_And_Library_Graph_Elaborators.Elaborate_Units + -- (Order => Order, + -- Main_Lib_File => Main_Lib_File); + -- end if; + + -- ??? Remove the following code when switching from the old to the new + -- elaboration-order mechanism. + + -- Use the invocation and library-graph-based elaboration order when -- switch -d_N (new bindo order) is in effect. if Debug_Flag_Underscore_NN then @@ -351,7 +481,7 @@ package body Bindo is (Order => Order, Main_Lib_File => Main_Lib_File); - -- Otherwise use the library graph and heuristic-based elaboration + -- Otherwise use the library-graph and heuristic-based elaboration -- order. else diff --git a/gcc/ada/bindusg.adb b/gcc/ada/bindusg.adb index 8c51d11..a4a9739 100644 --- a/gcc/ada/bindusg.adb +++ b/gcc/ada/bindusg.adb @@ -143,6 +143,14 @@ package body Bindusg is Write_Line (" -h Output this usage (help) information"); + -- ??? Enable the following code when switching from the old to the new + -- elaboration-order mechanism. + + -- Line for -H switch + + -- Write_Line + -- (" -H Legacy elaboration-order model enabled"); + -- Lines for -I switch Write_Line diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 2635654..da4bea1 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -389,7 +389,7 @@ package body Debug is -- d_L Output library graph -- d_M -- d_N New bindo order - -- d_O Output elaboration order + -- d_O -- d_P Output cycle paths -- d_Q -- d_R @@ -1155,8 +1155,6 @@ package body Debug is -- d_N GNATBIND utilizes the elaboration order provided by bindo - -- d_O GNATBIND outputs the elaboration order of units to standard output - -- d_P GNATBIND outputs the cycle paths to standard output -- d_T GNATBIND outputs trace information of elaboration order and cycle diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb index b9a9a8d..5fba0fa 100644 --- a/gcc/ada/einfo.adb +++ b/gcc/ada/einfo.adb @@ -8127,7 +8127,7 @@ package body Einfo is function Is_Elaboration_Target (Id : Entity_Id) return Boolean is begin return - Ekind_In (Id, E_Constant, E_Variable) + Ekind_In (Id, E_Constant, E_Package, E_Variable) or else Is_Entry (Id) or else Is_Generic_Unit (Id) or else Is_Subprogram (Id) diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads index 16b5cba..0b62af8 100644 --- a/gcc/ada/opt.ads +++ b/gcc/ada/opt.ads @@ -947,6 +947,11 @@ package Opt is -- Set to True when the pre-18.x access-before-elaboration model is to be -- used. Modified by use of -gnatH. + Legacy_Elaboration_Order : Boolean := False; + -- GNATBIND + -- Set to True when the pre-20.x elaboration-order model is to be used. + -- Modified by use of -H. + Link_Only : Boolean := False; -- GNATMAKE, GPRBUILD -- Set to True to skip compile and bind steps (except when Bind_Only is diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb index 2bd38c8..8612428 100644 --- a/gcc/ada/sem_elab.adb +++ b/gcc/ada/sem_elab.adb @@ -788,6 +788,9 @@ package body Sem_Elab is (Generic_Target, -- A generic unit being instantiated + Package_Target, + -- The package form of an instantiation + Subprogram_Target, -- An entry, operator, or subprogram being invoked, or aliased through -- 'Access or 'Unrestricted_Access. @@ -2046,6 +2049,10 @@ package body Sem_Elab is pragma Inline (Is_Same_Unit); -- Determine whether entities Unit_1 and Unit_2 denote the same unit + function Main_Unit_Entity return Entity_Id; + pragma Inline (Main_Unit_Entity); + -- Return the entity of the main unit + function Non_Private_View (Typ : Entity_Id) return Entity_Id; pragma Inline (Non_Private_View); -- Return the full view of private type Typ if available, otherwise return @@ -3955,7 +3962,7 @@ package body Sem_Elab is -- Elaboration_Checks which appears on the initial declaration of the -- main unit. - Install_Elaboration_Model (Unit_Entity (Cunit_Entity (Main_Unit))); + Install_Elaboration_Model (Unit_Entity (Main_Unit_Entity)); -- Examine the context of the main unit and record all units with prior -- elaboration with respect to it. @@ -6344,7 +6351,7 @@ package body Sem_Elab is -- because diagnostics on reads are relevant only for external -- variables. - if Is_Same_Unit (Unit_Id, Cunit_Entity (Main_Unit)) then + if Is_Same_Unit (Unit_Id, Main_Unit_Entity) then null; -- Nothing to do when the variable is already initialized. Note that @@ -8163,7 +8170,7 @@ package body Sem_Elab is -- body of A elaborated <-- problem -- -- The generation of an implicit pragma Elaborate_All (B) ensures - -- that the elaboration order mechanism will not pick the above + -- that the elaboration-order mechanism will not pick the above -- order. -- -- An implicit Elaborate is NOT generated when the unit is subject @@ -8502,10 +8509,9 @@ package body Sem_Elab is Elab_Body_OK : Boolean := False; Same_Unit_OK : Boolean := False) return Boolean is - EA_Id : constant Elaboration_Attributes_Id := - Elaboration_Attributes_Of (Unit_Id); - - Main_Id : constant Entity_Id := Cunit_Entity (Main_Unit); + EA_Id : constant Elaboration_Attributes_Id := + Elaboration_Attributes_Of (Unit_Id); + Main_Id : constant Entity_Id := Main_Unit_Entity; Unit_Prag : constant Node_Id := Elab_Pragma (EA_Id); Unit_With : constant Node_Id := With_Clause (EA_Id); @@ -8575,7 +8581,7 @@ package body Sem_Elab is is pragma Assert (Nam_In (Req_Nam, Name_Elaborate, Name_Elaborate_All)); - Main_Id : constant Entity_Id := Cunit_Entity (Main_Unit); + Main_Id : constant Entity_Id := Main_Unit_Entity; Unit_Id : constant Entity_Id := Find_Top_Unit (Targ_Id); procedure Elaboration_Requirement_Error; @@ -10356,6 +10362,11 @@ package body Sem_Elab is pragma Inline (Create_Instantiation_Rep); -- Create the representation of instantiation Inst + function Create_Package_Rep + (Pack_Id : Entity_Id) return Target_Rep_Record; + pragma Inline (Create_Package_Rep); + -- Create the representation of package Pack_Id + function Create_Protected_Entry_Rep (PE_Id : Entity_Id) return Target_Rep_Record; pragma Inline (Create_Protected_Entry_Rep); @@ -10624,6 +10635,26 @@ package body Sem_Elab is return Rec; end Create_Instantiation_Rep; + ------------------------ + -- Create_Package_Rep -- + ------------------------ + + function Create_Package_Rep + (Pack_Id : Entity_Id) return Target_Rep_Record + is + Rec : Target_Rep_Record; + + begin + Rec.Kind := Package_Target; + + Spec_And_Body_From_Entity + (Id => Pack_Id, + Body_Decl => Rec.Body_Decl, + Spec_Decl => Rec.Spec_Decl); + + return Rec; + end Create_Package_Rep; + -------------------------------- -- Create_Protected_Entry_Rep -- -------------------------------- @@ -10846,6 +10877,9 @@ package body Sem_Elab is then Rec := Create_Subprogram_Rep (Id); + elsif Ekind (Id) = E_Package then + Rec := Create_Package_Rep (Id); + else pragma Assert (False); return Rec; @@ -11622,6 +11656,14 @@ package body Sem_Elab is -- Process invocation call scenario Call with representation Call_Rep. -- In_State is the current state of the Processing phase. + procedure Process_Invocation_Instantiation + (Inst : Node_Id; + Inst_Rep : Scenario_Rep_Id; + In_State : Processing_In_State); + pragma Inline (Process_Invocation_Instantiation); + -- Process invocation instantiation scenario Inst with representation + -- Inst_Rep. In_State is the current state of the Processing phase. + procedure Process_Invocation_Scenario (N : Node_Id; In_State : Processing_In_State); @@ -11767,7 +11809,7 @@ package body Sem_Elab is end if; Spec_And_Body_From_Entity - (Id => Cunit_Entity (Main_Unit), + (Id => Main_Unit_Entity, Body_Decl => Body_Decl, Spec_Decl => Spec_Decl); @@ -11799,7 +11841,7 @@ package body Sem_Elab is Set_Ekind (Proc_Id, E_Procedure); Set_Etype (Proc_Id, Standard_Void_Type); - Set_Scope (Proc_Id, Unique_Entity (Cunit_Entity (Main_Unit))); + Set_Scope (Proc_Id, Unique_Entity (Main_Unit_Entity)); -- Create a dummy declaration for the elaboration procedure. The -- declaration does not need to be syntactically legal, but must @@ -11830,7 +11872,7 @@ package body Sem_Elab is end if; Spec_And_Body_From_Entity - (Id => Cunit_Entity (Main_Unit), + (Id => Main_Unit_Entity, Body_Decl => Body_Decl, Spec_Decl => Spec_Decl); @@ -11995,7 +12037,7 @@ package body Sem_Elab is function Declaration_Placement_Of_Node (N : Node_Id) return Declaration_Placement_Kind is - Main_Unit_Id : constant Entity_Id := Cunit_Entity (Main_Unit); + Main_Unit_Id : constant Entity_Id := Main_Unit_Entity; N_Unit_Id : constant Entity_Id := Find_Top_Unit (N); begin @@ -12150,6 +12192,9 @@ package body Sem_Elab is Main_Cunit : constant Node_Id := Cunit (Main_Unit); begin + -- ??? Remove the following use of the debug flag when switching from + -- the old to the new elaboration-order mechanism. + -- Nothing to do when switch -gnatd_G (encode invocation graph in ALI -- files) is not in effect. @@ -12458,6 +12503,43 @@ package body Sem_Elab is end if; end Process_Invocation_Call; + -------------------------------------- + -- Process_Invocation_Instantiation -- + -------------------------------------- + + procedure Process_Invocation_Instantiation + (Inst : Node_Id; + Inst_Rep : Scenario_Rep_Id; + In_State : Processing_In_State) + is + pragma Unreferenced (Inst); + + Gen_Id : constant Entity_Id := Target (Inst_Rep); + + begin + -- Nothing to do when the generic appears within an internal unit + + if In_Internal_Unit (Gen_Id) then + return; + end if; + + -- The generic being instantiated resides within an external unit + -- + -- Main unit External unit + -- +-----------+ +-------------+ + -- | | | | + -- | Start ------------> Generic | + -- | | | | + -- +-----------+ +-------------+ + -- + -- Record the invocation path which originates from Start and reaches + -- the generic. + + if not In_Extended_Main_Code_Unit (Gen_Id) then + Record_Invocation_Path (In_State); + end if; + end Process_Invocation_Instantiation; + --------------------------------- -- Process_Invocation_Scenario -- --------------------------------- @@ -12503,6 +12585,14 @@ package body Sem_Elab is In_State => In_State); end if; end if; + + -- Instantiation + + elsif Is_Suitable_Instantiation (Scen) then + Process_Invocation_Instantiation + (Inst => Scen, + Inst_Rep => Scenario_Representation_Of (Scen, In_State), + In_State => In_State); end if; -- Remove the current scenario from the stack of active scenarios @@ -13590,6 +13680,18 @@ package body Sem_Elab is end Kill_Elaboration_Scenario; ---------------------- + -- Main_Unit_Entity -- + ---------------------- + + function Main_Unit_Entity return Entity_Id is + begin + -- Note that Cunit_Entity (Main_Unit) is not reliable in the presence of + -- generic bodies and may return an outdated entity. + + return Defining_Entity (Unit (Cunit (Main_Unit))); + end Main_Unit_Entity; + + ---------------------- -- Non_Private_View -- ---------------------- @@ -15026,8 +15128,7 @@ package body Sem_Elab is -- emitted multiple times. procedure Check_SPARK_Model_In_Effect is - Spec_Id : constant Entity_Id := - Unique_Entity (Cunit_Entity (Main_Unit)); + Spec_Id : constant Entity_Id := Unique_Entity (Main_Unit_Entity); begin -- Do not emit the warning multiple times as this creates useless diff --git a/gcc/ada/switch-b.adb b/gcc/ada/switch-b.adb index dc62ec2..eefd225 100644 --- a/gcc/ada/switch-b.adb +++ b/gcc/ada/switch-b.adb @@ -353,6 +353,15 @@ package body Switch.B is Ptr := Ptr + 1; Usage_Requested := True; + -- ??? Enable the following code when switching from the old to the + -- new elaboration-order mechanism. + + -- Processing for H switch + + -- when 'H' => + -- Ptr := Ptr + 1; + -- Legacy_Elaboration_Order := True; + -- Processing for i switch when 'i' => -- cgit v1.1 From 76e716d76171e50353e7eb80632ea75165eabdc0 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Fri, 5 Jul 2019 07:03:54 +0000 Subject: [Ada] Compiler loop on illegal nested accept statement This patch fixes a "Compilation abandoned" message in a compiler built with assertions, or a compiler loop otherwise, when an accept statement contains an illegal accept statement for the same entry. Compiling accept_in_accept.adb must yield: accept_in_accept.adb:12:13: duplicate accept statement for same entry (RM 9.5.2 (15)) ---- procedure accept_in_accept is task a_in_a is entry a (i : Integer); end a_in_a; task body a_in_a is begin select accept a (i : Integer) do null; accept a (i : integer) do null; end a; end a; or terminate; end select; end a_in_a; begin a_in_a.a (1); end accept_in_accept; 2019-07-05 Ed Schonberg gcc/ada/ * sem_ch9.adb (Analyze_Accept_Statement): If this is an illegal accept statement for an enclosing entry abandon analysis to prevent scope mismatches and potential infinite loops in compiler. From-SVN: r273129 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch9.adb | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6f04f77..c875ac3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Ed Schonberg + + * sem_ch9.adb (Analyze_Accept_Statement): If this is an illegal + accept statement for an enclosing entry abandon analysis to + prevent scope mismatches and potential infinite loops in + compiler. + 2019-07-05 Hristian Kirtchev * ali.adb (For_Each_Invocation_Construct, diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb index a71c35c..19fff57 100644 --- a/gcc/ada/sem_ch9.adb +++ b/gcc/ada/sem_ch9.adb @@ -883,7 +883,13 @@ package body Sem_Ch9 is exit when Task_Nam = Scope_Stack.Table (J).Entity; if Entry_Nam = Scope_Stack.Table (J).Entity then - Error_Msg_N ("duplicate accept statement for same entry", N); + Error_Msg_N + ("duplicate accept statement for same entry (RM 9.5.2 (15))", N); + + -- Do not continue analysis of accept statement, to prevent + -- cascaded errors. + + return; end if; end loop; -- cgit v1.1 From 8d21ff6025652fa67085d94d5101cd699c57cf0b Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Fri, 5 Jul 2019 07:03:58 +0000 Subject: [Ada] Incorrect accessibility check This patch fixes an issue whereby anonymous access result types were treated as having the same accessibility level as typed results instead of having the level determined by the "master of the call" as per RM 3.10.2 (10). ------------ -- Source -- ------------ -- main.adb with Pack_12; use Pack_12; with Pack_05; use Pack_05; procedure Main is Obj : aliased Integer; begin Test_Alloc (new Rec_T'(Disc => Id_A (Obj'Access))); -- OK Id_A (Obj'Access).all := 0; -- OK Id_B (Obj'Access).all := 0; -- OK Id_C (Obj'Access).all := 0; -- ERROR end Main; -- pack_12.ads pragma Ada_2012; with Ada.Unchecked_Conversion; package Pack_12 is function Id_A (I : access Integer) return access Integer is (I); type Obj_Ptr is access all Integer; function Id_C (I : access Integer) return Obj_Ptr is (I.all'Access); type Rec_T (Disc : access Integer) is null record; procedure Test_Alloc (Access_Param : access Rec_T); end Pack_12; -- pack_12.adb package body Pack_12 is Dummy : Integer; procedure Test_Alloc (Access_Param : access Rec_T) is begin Dummy := Access_Param.Disc.all; end Test_Alloc; end Pack_12; -- pack_05.ads pragma Ada_2005; with Pack_12; use Pack_12; package Pack_05 is function Id_B (I : access Integer) return access Integer renames Id_A; end Pack_05; ----------------- -- Compilation -- ----------------- $ gnatmake -q main.adb $ main raised PROGRAM_ERROR : pack_12.ads:14 accessibility check failed 2019-07-05 Justin Squirek gcc/ada/ * checks.adb (Apply_Accessibility_Check): Add logic to fetch the function result accessibility level if one is required within the generated check. * exp_ch6.adb (Needs_Result_Accessibility_Level): Modify controlling elsif block to handle more cases such as anonymous access results and disable checking for coextensions. From-SVN: r273130 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/checks.adb | 19 +++++++++++++++++-- gcc/ada/exp_ch6.adb | 54 ++++++++++++++++++++++++++++++++--------------------- 3 files changed, 59 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c875ac3..8a729d1 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-05 Justin Squirek + + * checks.adb (Apply_Accessibility_Check): Add logic to fetch the + function result accessibility level if one is required within + the generated check. + * exp_ch6.adb (Needs_Result_Accessibility_Level): Modify + controlling elsif block to handle more cases such as anonymous + access results and disable checking for coextensions. + 2019-07-05 Ed Schonberg * sem_ch9.adb (Analyze_Accept_Statement): If this is an illegal diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index ec4e96f..601b932 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -617,8 +617,23 @@ package body Checks is Param_Level := New_Occurrence_Of (Extra_Accessibility (Param_Ent), Loc); - Type_Level := - Make_Integer_Literal (Loc, Deepest_Type_Access_Level (Typ)); + -- Use the dynamic accessibility parameter for the function's result + -- when one has been created instead of statically referring to the + -- deepest type level so as to appropriatly handle the rules for + -- RM 3.10.2 (10.1/3). + + if Ekind_In (Scope (Param_Ent), E_Function, + E_Operator, + E_Subprogram_Type) + and then Present (Extra_Accessibility_Of_Result (Scope (Param_Ent))) + then + Type_Level := + New_Occurrence_Of + (Extra_Accessibility_Of_Result (Scope (Param_Ent)), Loc); + else + Type_Level := + Make_Integer_Literal (Loc, Deepest_Type_Access_Level (Typ)); + end if; -- Raise Program_Error if the accessibility level of the access -- parameter is deeper than the level of the target access type. diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 6e7299a..ae17a5b 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -9236,8 +9236,9 @@ package body Exp_Ch6 is return False; end Has_Unconstrained_Access_Discriminant_Component; - Feature_Disabled : constant Boolean := True; - -- Temporary + Disable_Coextension_Cases : constant Boolean := True; + -- Flag used to temporarily disable a "True" result for types with + -- access discriminants and related coextension cases. -- Start of processing for Needs_Result_Accessibility_Level @@ -9247,9 +9248,6 @@ package body Exp_Ch6 is if not Present (Func_Typ) then return False; - elsif Feature_Disabled then - return False; - -- False if not a function, also handle enum-lit renames case elsif Func_Typ = Standard_Void_Type @@ -9274,23 +9272,37 @@ package body Exp_Ch6 is elsif Ada_Version < Ada_2012 then return False; - elsif Ekind (Func_Typ) = E_Anonymous_Access_Type - or else Is_Tagged_Type (Func_Typ) - then - -- In the case of, say, a null tagged record result type, the need - -- for this extra parameter might not be obvious. This function - -- returns True for all tagged types for compatibility reasons. - -- A function with, say, a tagged null controlling result type might - -- be overridden by a primitive of an extension having an access - -- discriminant and the overrider and overridden must have compatible - -- calling conventions (including implicitly declared parameters). - -- Similarly, values of one access-to-subprogram type might designate - -- both a primitive subprogram of a given type and a function - -- which is, for example, not a primitive subprogram of any type. - -- Again, this requires calling convention compatibility. - -- It might be possible to solve these issues by introducing - -- wrappers, but that is not the approach that was chosen. + -- Handle the situation where a result is an anonymous access type + -- RM 3.10.2 (10.3/3). + + elsif Ekind (Func_Typ) = E_Anonymous_Access_Type then + return True; + + -- The following cases are related to coextensions and do not fully + -- cover everything mentioned in RM 3.10.2 (12) ??? + + -- Temporarily disabled ??? + + elsif Disable_Coextension_Cases then + return False; + + -- In the case of, say, a null tagged record result type, the need for + -- this extra parameter might not be obvious so this function returns + -- True for all tagged types for compatibility reasons. + + -- A function with, say, a tagged null controlling result type might + -- be overridden by a primitive of an extension having an access + -- discriminant and the overrider and overridden must have compatible + -- calling conventions (including implicitly declared parameters). + + -- Similarly, values of one access-to-subprogram type might designate + -- both a primitive subprogram of a given type and a function which is, + -- for example, not a primitive subprogram of any type. Again, this + -- requires calling convention compatibility. It might be possible to + -- solve these issues by introducing wrappers, but that is not the + -- approach that was chosen. + elsif Is_Tagged_Type (Func_Typ) then return True; elsif Has_Unconstrained_Access_Discriminants (Func_Typ) then -- cgit v1.1 From ffdc40a90faec54d29af76b994c52790685a8e58 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 5 Jul 2019 08:28:36 +0000 Subject: tree-cfg.c (gimple_make_forwarder_block): Propagate location info on phi nodes if possible. * tree-cfg.c (gimple_make_forwarder_block): Propagate location info on phi nodes if possible. * tree-scalar-evolution.c (final_value_replacement_loop): Propagate location info on the newly created statement. * tree-ssa-loop-manip.c (create_iv): Propagate location info on the newly created increment if needed. From-SVN: r273131 --- gcc/ChangeLog | 9 +++++++++ gcc/tree-cfg.c | 7 ++++++- gcc/tree-scalar-evolution.c | 2 ++ gcc/tree-ssa-loop-manip.c | 16 ++++++++++++++-- 4 files changed, 31 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5145487..e6740b6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-03 Eric Botcazou + + * tree-cfg.c (gimple_make_forwarder_block): Propagate location info on + phi nodes if possible. + * tree-scalar-evolution.c (final_value_replacement_loop): Propagate + location info on the newly created statement. + * tree-ssa-loop-manip.c (create_iv): Propagate location info on the + newly created increment if needed. + 2019-07-04 Jakub Jelinek PR middle-end/78884 diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index a585efe..0396aa9 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -5756,6 +5756,7 @@ gimple_make_forwarder_block (edge fallthru) basic_block dummy, bb; tree var; gphi_iterator gsi; + bool forward_location_p; dummy = fallthru->src; bb = fallthru->dest; @@ -5763,6 +5764,9 @@ gimple_make_forwarder_block (edge fallthru) if (single_pred_p (bb)) return; + /* We can forward location info if we have only one predecessor. */ + forward_location_p = single_pred_p (dummy); + /* If we redirected a branch we must create new PHI nodes at the start of BB. */ for (gsi = gsi_start_phis (dummy); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -5774,7 +5778,8 @@ gimple_make_forwarder_block (edge fallthru) new_phi = create_phi_node (var, bb); gimple_phi_set_result (phi, copy_ssa_name (var, phi)); add_phi_arg (new_phi, gimple_phi_result (phi), fallthru, - UNKNOWN_LOCATION); + forward_location_p + ? gimple_phi_arg_location (phi, 0) : UNKNOWN_LOCATION); } /* Add the arguments we have stored on edges. */ diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 81f70f1..b1c15dc 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -3680,6 +3680,8 @@ final_value_replacement_loop (struct loop *loop) true, GSI_SAME_STMT); gassign *ass = gimple_build_assign (rslt, def); + gimple_set_location (ass, + gimple_phi_arg_location (phi, exit->dest_idx)); gsi_insert_before (&gsi, ass, GSI_SAME_STMT); if (dump_file) { diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index 7db4f09..f072418 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -126,10 +126,22 @@ create_iv (tree base, tree step, tree var, struct loop *loop, gsi_insert_seq_on_edge_immediate (pe, stmts); stmt = gimple_build_assign (va, incr_op, vb, step); + /* Prevent the increment from inheriting a bogus location if it is not put + immediately after a statement whose location is known. */ if (after) - gsi_insert_after (incr_pos, stmt, GSI_NEW_STMT); + { + if (gsi_end_p (*incr_pos)) + { + edge e = single_succ_edge (gsi_bb (*incr_pos)); + gimple_set_location (stmt, e->goto_locus); + } + gsi_insert_after (incr_pos, stmt, GSI_NEW_STMT); + } else - gsi_insert_before (incr_pos, stmt, GSI_NEW_STMT); + { + gimple_set_location (stmt, gimple_location (gsi_stmt (*incr_pos))); + gsi_insert_before (incr_pos, stmt, GSI_NEW_STMT); + } initial = force_gimple_operand (base, &stmts, true, var); if (stmts) -- cgit v1.1 From 4500f7510368cdb24b8afcc66e86e09cafe49199 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 5 Jul 2019 08:39:13 +0000 Subject: except.c (emit_to_new_bb_before): Make sure to put a location on SEQ. * except.c (emit_to_new_bb_before): Make sure to put a location on SEQ. * tree-eh.c (replace_goto_queue_1) : Propagate location. (emit_eh_dispatch): Delete. (lower_catch): Emit the eh_dispatch manually and set the location of the first catch statement onto it. (lower_eh_filter): Emit the eh_dispatch manually and set location. (lower_eh_dispatch): Propagate location. * tree-outof-ssa.c (set_location_for_edge): Handle EH edges specially. (eliminate_build): Likewise. From-SVN: r273132 --- gcc/ChangeLog | 14 +++++++++++++- gcc/except.c | 13 +++++++++++-- gcc/tree-eh.c | 35 ++++++++++++++++++++++------------- gcc/tree-outof-ssa.c | 39 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 82 insertions(+), 19 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e6740b6..155c6b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,16 @@ -2019-07-03 Eric Botcazou +2019-07-05 Eric Botcazou + + * except.c (emit_to_new_bb_before): Make sure to put a location on SEQ. + * tree-eh.c (replace_goto_queue_1) : Propagate location. + (emit_eh_dispatch): Delete. + (lower_catch): Emit the eh_dispatch manually and set the location of + the first catch statement onto it. + (lower_eh_filter): Emit the eh_dispatch manually and set location. + (lower_eh_dispatch): Propagate location. + * tree-outof-ssa.c (set_location_for_edge): Handle EH edges specially. + (eliminate_build): Likewise. + +2019-07-05 Eric Botcazou * tree-cfg.c (gimple_make_forwarder_block): Propagate location info on phi nodes if possible. diff --git a/gcc/except.c b/gcc/except.c index 29f3339..b1f04ee 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -921,7 +921,7 @@ assign_filter_values (void) static basic_block emit_to_new_bb_before (rtx_insn *seq, rtx_insn *insn) { - rtx_insn *last; + rtx_insn *next, *last; basic_block bb; edge e; edge_iterator ei; @@ -934,7 +934,16 @@ emit_to_new_bb_before (rtx_insn *seq, rtx_insn *insn) force_nonfallthru (e); else ei_next (&ei); - last = emit_insn_before (seq, insn); + + /* Make sure to put the location of INSN or a subsequent instruction on SEQ + to avoid inheriting the location of the previous instruction. */ + next = insn; + while (next && !NONDEBUG_INSN_P (next)) + next = NEXT_INSN (next); + if (next) + last = emit_insn_before_setloc (seq, insn, INSN_LOCATION (next)); + else + last = emit_insn_before (seq, insn); if (BARRIER_P (last)) last = PREV_INSN (last); bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb); diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 23c56b5..fb7d202 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -503,7 +503,11 @@ replace_goto_queue_1 (gimple *stmt, struct leh_tf_state *tf, seq = find_goto_replacement (tf, temp); if (seq) { - gsi_insert_seq_before (gsi, gimple_seq_copy (seq), GSI_SAME_STMT); + gimple_stmt_iterator i; + seq = gimple_seq_copy (seq); + for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i)) + gimple_set_location (gsi_stmt (i), gimple_location (stmt)); + gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT); gsi_remove (gsi, false); return; } @@ -811,15 +815,6 @@ emit_resx (gimple_seq *seq, eh_region region) record_stmt_eh_region (region->outer, x); } -/* Emit an EH_DISPATCH statement into SEQ for REGION. */ - -static void -emit_eh_dispatch (gimple_seq *seq, eh_region region) -{ - geh_dispatch *x = gimple_build_eh_dispatch (region->index); - gimple_seq_add_stmt (seq, x); -} - /* Note that the current EH region may contain a throw, or a call to a function which itself may contain a throw. */ @@ -1762,7 +1757,9 @@ lower_catch (struct leh_state *state, gtry *tp) tree out_label; gimple_seq new_seq, cleanup; gimple *x; + geh_dispatch *eh_dispatch; location_t try_catch_loc = gimple_location (tp); + location_t catch_loc = UNKNOWN_LOCATION; if (flag_exceptions) { @@ -1776,7 +1773,8 @@ lower_catch (struct leh_state *state, gtry *tp) return gimple_try_eval (tp); new_seq = NULL; - emit_eh_dispatch (&new_seq, try_region); + eh_dispatch = gimple_build_eh_dispatch (try_region->index); + gimple_seq_add_stmt (&new_seq, eh_dispatch); emit_resx (&new_seq, try_region); this_state.cur_region = state->cur_region; @@ -1799,6 +1797,8 @@ lower_catch (struct leh_state *state, gtry *tp) gimple_seq handler; catch_stmt = as_a (gsi_stmt (gsi)); + if (catch_loc == UNKNOWN_LOCATION) + catch_loc = gimple_location (catch_stmt); c = gen_eh_region_catch (try_region, gimple_catch_types (catch_stmt)); handler = gimple_catch_handler (catch_stmt); @@ -1822,6 +1822,10 @@ lower_catch (struct leh_state *state, gtry *tp) break; } + /* Try to set a location on the dispatching construct to avoid inheriting + the location of the previous statement. */ + gimple_set_location (eh_dispatch, catch_loc); + gimple_try_set_cleanup (tp, new_seq); gimple_seq new_eh_seq = eh_seq; @@ -1857,11 +1861,13 @@ lower_eh_filter (struct leh_state *state, gtry *tp) if (!eh_region_may_contain_throw (this_region)) return gimple_try_eval (tp); - new_seq = NULL; this_state.cur_region = state->cur_region; this_state.ehp_region = this_region; - emit_eh_dispatch (&new_seq, this_region); + new_seq = NULL; + x = gimple_build_eh_dispatch (this_region->index); + gimple_set_location (x, gimple_location (tp)); + gimple_seq_add_stmt (&new_seq, x); emit_resx (&new_seq, this_region); this_region->u.allowed.label = create_artificial_label (UNKNOWN_LOCATION); @@ -3752,6 +3758,7 @@ lower_eh_dispatch (basic_block src, geh_dispatch *stmt) filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn))); filter = make_ssa_name (filter, x); gimple_call_set_lhs (x, filter); + gimple_set_location (x, gimple_location (stmt)); gsi_insert_before (&gsi, x, GSI_SAME_STMT); /* Turn the default label into a default case. */ @@ -3759,6 +3766,7 @@ lower_eh_dispatch (basic_block src, geh_dispatch *stmt) sort_case_labels (labels); x = gimple_build_switch (filter, default_label, labels); + gimple_set_location (x, gimple_location (stmt)); gsi_insert_before (&gsi, x, GSI_SAME_STMT); } } @@ -3775,6 +3783,7 @@ lower_eh_dispatch (basic_block src, geh_dispatch *stmt) filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn))); filter = make_ssa_name (filter, x); gimple_call_set_lhs (x, filter); + gimple_set_location (x, gimple_location (stmt)); gsi_insert_before (&gsi, x, GSI_SAME_STMT); r->u.allowed.label = NULL; diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index 713b0b0..d8c8249 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -171,14 +171,43 @@ struct elim_graph use its location. Otherwise search instructions in predecessors of E for a location, and use that one. That makes sense because we insert on edges for PHI nodes, and effects of PHIs happen on - the end of the predecessor conceptually. */ + the end of the predecessor conceptually. An exception is made + for EH edges because we don't want to drag the source location + of unrelated statements at the beginning of handlers; they would + be further reused for various EH constructs, which would damage + the coverage information. */ static void set_location_for_edge (edge e) { if (e->goto_locus) + set_curr_insn_location (e->goto_locus); + else if (e->flags & EDGE_EH) { - set_curr_insn_location (e->goto_locus); + basic_block bb = e->dest; + gimple_stmt_iterator gsi; + + do + { + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) + continue; + if (gimple_has_location (stmt) || gimple_block (stmt)) + { + set_curr_insn_location (gimple_location (stmt)); + return; + } + } + /* Nothing found in this basic block. Make a half-assed attempt + to continue with another block. */ + if (single_succ_p (bb)) + bb = single_succ (bb); + else + bb = e->dest; + } + while (bb != e->dest); } else { @@ -564,7 +593,11 @@ eliminate_build (elim_graph *g) continue; Ti = PHI_ARG_DEF (phi, g->e->dest_idx); - locus = gimple_phi_arg_location_from_edge (phi, g->e); + /* See set_location_for_edge for the rationale. */ + if (g->e->flags & EDGE_EH) + locus = UNKNOWN_LOCATION; + else + locus = gimple_phi_arg_location_from_edge (phi, g->e); /* If this argument is a constant, or a SSA_NAME which is being left in SSA form, just queue a copy to be emitted on this -- cgit v1.1 From 1d776353135272b1fcb7453ae9c8bd4fafd9bd07 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 5 Jul 2019 11:25:45 +0200 Subject: tree-ssa-alias.c (alias_stats): Add nonoverlapping_component_refs_since_match_p_must_overlap. * tree-ssa-alias.c (alias_stats): Add nonoverlapping_component_refs_since_match_p_must_overlap. (dump_alias_stats): Print it. (nonoverlapping_component_refs_since_match_p): Add early exit. (nonoverlapping_component_refs_p): Do not account early exit. From-SVN: r273133 --- gcc/ChangeLog | 8 ++++++++ gcc/tree-ssa-alias.c | 37 +++++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 10 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 155c6b2..d568b08 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-05 Jan Hubicka + + * tree-ssa-alias.c (alias_stats): Add + nonoverlapping_component_refs_since_match_p_must_overlap. + (dump_alias_stats): Print it. + (nonoverlapping_component_refs_since_match_p): Add early exit. + (nonoverlapping_component_refs_p): Do not account early exit. + 2019-07-05 Eric Botcazou * except.c (emit_to_new_bb_before): Make sure to put a location on SEQ. diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 5c5cbe4..d52d47c 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -105,6 +105,7 @@ static struct { unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_may_alias; unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_no_alias; unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_may_alias; + unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_must_overlap; unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_no_alias; } alias_stats; @@ -138,10 +139,13 @@ dump_alias_stats (FILE *s) + alias_stats.nonoverlapping_component_refs_p_may_alias); fprintf (s, " nonoverlapping_component_refs_since_match_p: " HOST_WIDE_INT_PRINT_DEC" disambiguations, " + HOST_WIDE_INT_PRINT_DEC" must overlaps, " HOST_WIDE_INT_PRINT_DEC" queries\n", alias_stats.nonoverlapping_component_refs_since_match_p_no_alias, + alias_stats.nonoverlapping_component_refs_since_match_p_must_overlap, alias_stats.nonoverlapping_component_refs_since_match_p_no_alias - + alias_stats.nonoverlapping_component_refs_since_match_p_may_alias); + + alias_stats.nonoverlapping_component_refs_since_match_p_may_alias + + alias_stats.nonoverlapping_component_refs_since_match_p_must_overlap); fprintf (s, " aliasing_component_refs_p: " HOST_WIDE_INT_PRINT_DEC" disambiguations, " HOST_WIDE_INT_PRINT_DEC" queries\n", @@ -1149,6 +1153,17 @@ static int nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, tree match2, tree ref2) { + /* Early return if there are no references to match, we do not need + to walk the access paths. + + Do not consider this as may-alias for stats - it is more useful + to have information how many disambiguations happened provided that + the query was meaningful. */ + + if (match1 == ref1 || !handled_component_p (ref1) + || match2 == ref2 || !handled_component_p (ref2)) + return -1; + auto_vec component_refs1; auto_vec component_refs2; @@ -1214,7 +1229,7 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, if (component_refs1.is_empty ()) { ++alias_stats - .nonoverlapping_component_refs_since_match_p_may_alias; + .nonoverlapping_component_refs_since_match_p_must_overlap; return 0; } ref1 = component_refs1.pop (); @@ -1226,7 +1241,7 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, if (component_refs2.is_empty ()) { ++alias_stats - .nonoverlapping_component_refs_since_match_p_may_alias; + .nonoverlapping_component_refs_since_match_p_must_overlap; return 0; } ref2 = component_refs2.pop (); @@ -1266,7 +1281,7 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, || DECL_BIT_FIELD_REPRESENTATIVE (field2) == field1) { ++alias_stats - .nonoverlapping_component_refs_since_match_p_may_alias; + .nonoverlapping_component_refs_since_match_p_must_overlap; return 0; } /* Different fields of the same record type cannot overlap. @@ -1274,7 +1289,7 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, if (DECL_BIT_FIELD (field1) && DECL_BIT_FIELD (field2)) { ++alias_stats - .nonoverlapping_component_refs_since_match_p_may_alias; + .nonoverlapping_component_refs_since_match_p_must_overlap; return 0; } ++alias_stats.nonoverlapping_component_refs_since_match_p_no_alias; @@ -1282,7 +1297,7 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, } } - ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias; + ++alias_stats.nonoverlapping_component_refs_since_match_p_must_overlap; return 0; } @@ -1309,14 +1324,16 @@ ncr_compar (const void *field1_, const void *field2_) static bool nonoverlapping_component_refs_p (const_tree x, const_tree y) { + /* Early return if we have nothing to do. + + Do not consider this as may-alias for stats - it is more useful + to have information how many disambiguations happened provided that + the query was meaningful. */ if (!flag_strict_aliasing || !x || !y || !handled_component_p (x) || !handled_component_p (y)) - { - ++alias_stats.nonoverlapping_component_refs_p_may_alias; - return false; - } + return false; auto_vec fieldsx; while (handled_component_p (x)) -- cgit v1.1 From 75fad0a98919da8212be4efc479d098499f4f1c3 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 5 Jul 2019 12:48:42 +0000 Subject: re PR tree-optimization/91091 ([missed optimization] Missing optimization in unaliased pointers) 2019-07-05 Richard Biener PR tree-optimization/91091 * tree-ssa-sccvn.c (vn_reference_lookup_3): Overlap of accesses can happen with -fno-strict-aliasing. * gcc.dg/tree-ssa/pr91091-1.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust. From-SVN: r273134 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c | 23 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c | 2 +- gcc/tree-ssa-sccvn.c | 3 ++- 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d568b08..25e539f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-05 Richard Biener + + PR tree-optimization/91091 + * tree-ssa-sccvn.c (vn_reference_lookup_3): Overlap of + accesses can happen with -fno-strict-aliasing. + 2019-07-05 Jan Hubicka * tree-ssa-alias.c (alias_stats): Add diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 53d7994..6c049d0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-05 Richard Biener + + PR tree-optimization/91091 + * gcc.dg/tree-ssa/pr91091-1.c: New testcase. + * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust. + 2019-07-05 Eric Botcazou * gnat.dg/pack23.adb, gnat.dg/pack23_pkg.ads: New testcase. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c new file mode 100644 index 0000000..2ee75d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-strict-aliasing" } */ + +struct s { int x; } __attribute__((packed)); +struct t { int x; }; + +void __attribute__((noinline,noipa)) +swap(struct s* p, struct t* q) +{ + p->x = q->x; + q->x = p->x; +} + +int main() +{ + struct t a[2]; + a[0].x = 0x12345678; + a[1].x = 0x98765432; + swap ((struct s *)((char *)a + 1), a); + if (a[0].x != 0x12345678) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c index a4d9a71..eae4b15 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c @@ -1,5 +1,5 @@ /* { dg-do link } */ -/* { dg-options "-O -fdump-tree-fre1-details" } */ +/* { dg-options "-O -fstrict-aliasing -fdump-tree-fre1-details" } */ void link_error (void); diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 22dd801..2cc76d8 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1996,7 +1996,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, activation of a union member via a store makes the values of untouched bytes unspecified. */ && (known_eq (ref->size, BITS_PER_UNIT) - || (get_alias_set (lhs) != 0 + || (flag_strict_aliasing + && get_alias_set (lhs) != 0 && ao_ref_alias_set (ref) != 0))) { tree *saved_last_vuse_ptr = data->last_vuse_ptr; -- cgit v1.1 From fb4697e30bd0cd4bda66932e21c183273a5d1e63 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 5 Jul 2019 12:50:45 +0000 Subject: re PR tree-optimization/91091 ([missed optimization] Missing optimization in unaliased pointers) 2019-07-05 Richard Biener PR tree-optimization/91091 * tree-ssa-alias.h (get_continuation_for_phi): Add tbaa_p parameter. (walk_non_aliased_vuses): Likewise. * tree-ssa-alias.c (maybe_skip_until): Pass down tbaa_p. (get_continuation_for_phi): New tbaa_p parameter and pass it down. (walk_non_aliased_vuses): Likewise. * ipa-prop.c (determine_known_aggregate_parts): Adjust. * tree-ssa-pre.c (translate_vuse_through_block): Likewise. * tree-ssa-scopedtables.c (avail_exprs_stack::lookup_avail_expr): Likewise. * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add tbaa_p flag. (adjust_offsets_for_equal_base_address): New function. (vn_reference_lookup_3): Use it to catch more base equivalences. Handle and pass down tbaa_p flag. (vn_reference_lookup_pieces): Adjust. (vn_reference_lookup): Remove alias-set altering, instead pass down false as tbaa_p. * gcc.dg/tree-ssa/pr91091-2.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-70.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-71.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-72.c: Likewise. From-SVN: r273135 --- gcc/ChangeLog | 21 ++++++++ gcc/ipa-prop.c | 3 +- gcc/testsuite/ChangeLog | 8 +++ gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c | 15 ++++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c | 14 ++++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c | 14 ++++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c | 14 ++++++ gcc/tree-ssa-alias.c | 19 +++---- gcc/tree-ssa-alias.h | 4 +- gcc/tree-ssa-pre.c | 4 +- gcc/tree-ssa-sccvn.c | 79 +++++++++++++++++++++++------- gcc/tree-ssa-scopedtables.c | 2 +- 12 files changed, 163 insertions(+), 34 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 25e539f..6dd97ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,27 @@ 2019-07-05 Richard Biener PR tree-optimization/91091 + * tree-ssa-alias.h (get_continuation_for_phi): Add tbaa_p parameter. + (walk_non_aliased_vuses): Likewise. + * tree-ssa-alias.c (maybe_skip_until): Pass down tbaa_p. + (get_continuation_for_phi): New tbaa_p parameter and pass + it down. + (walk_non_aliased_vuses): Likewise. + * ipa-prop.c (determine_known_aggregate_parts): Adjust. + * tree-ssa-pre.c (translate_vuse_through_block): Likewise. + * tree-ssa-scopedtables.c (avail_exprs_stack::lookup_avail_expr): + Likewise. + * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add tbaa_p flag. + (adjust_offsets_for_equal_base_address): New function. + (vn_reference_lookup_3): Use it to catch more base equivalences. + Handle and pass down tbaa_p flag. + (vn_reference_lookup_pieces): Adjust. + (vn_reference_lookup): Remove alias-set altering, instead pass + down false as tbaa_p. + +2019-07-05 Richard Biener + + PR tree-optimization/91091 * tree-ssa-sccvn.c (vn_reference_lookup_3): Overlap of accesses can happen with -fno-strict-aliasing. diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index a53a6ec..f5f8c75 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -1678,7 +1678,8 @@ determine_known_aggregate_parts (gcall *call, tree arg, if (gimple_code (stmt) == GIMPLE_PHI) { - dom_vuse = get_continuation_for_phi (stmt, &r, *aa_walk_budget_p, + dom_vuse = get_continuation_for_phi (stmt, &r, true, + *aa_walk_budget_p, &visited, false, NULL, NULL); continue; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6c049d0..5656a5b2e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,14 @@ 2019-07-05 Richard Biener PR tree-optimization/91091 + * gcc.dg/tree-ssa/pr91091-2.c: New testcase. + * gcc.dg/tree-ssa/ssa-fre-70.c: Likewise. + * gcc.dg/tree-ssa/ssa-fre-71.c: Likewise. + * gcc.dg/tree-ssa/ssa-fre-72.c: Likewise. + +2019-07-05 Richard Biener + + PR tree-optimization/91091 * gcc.dg/tree-ssa/pr91091-1.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c new file mode 100644 index 0000000..b578de7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ + +struct s { int x; }; +struct t { int x; }; + +void swap(struct s* p, struct t* q) +{ + p->x = q->x; + q->x = p->x; +} + +/* The second statement is redundant. */ +/* { dg-final { scan-tree-dump-times "x = " 1 "fre1" } } */ +/* { dg-final { scan-tree-dump-times " = \[^;\]*x;" 1 "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c new file mode 100644 index 0000000..612d753 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple -O -fdump-tree-fre1" } */ + +__GIMPLE (ssa, startwith("fre")) char foo(char *p) +{ + char _1; + +__BB(2): + __MEM (p) = _Literal (char[4]) {}; + _1 = __MEM (p + 1); + return _1; +} + +/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c new file mode 100644 index 0000000..edc8899 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple -O -fdump-tree-fre1-details" } */ + +__GIMPLE (ssa, startwith("fre")) char foo(char *p) +{ + char _1; + +__BB(2): + __MEM (p) = 0; + _1 = __MEM (p + 1); + return _1; +} + +/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c new file mode 100644 index 0000000..b95709f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple -O -fdump-tree-fre1" } */ + +__GIMPLE (ssa,startwith("fre")) char foo(char *p, int i) +{ + char _1; + +__BB(2): + __MEM (p) = i_2(D); + _1 = __MEM (p + 1); + return _1; +} + +/* { dg-final { scan-tree-dump "BIT_FIELD_REF" "fre1" } } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index d52d47c..b5e980d 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -3054,8 +3054,8 @@ stmt_kills_ref_p (gimple *stmt, tree ref) static bool maybe_skip_until (gimple *phi, tree &target, basic_block target_bb, - ao_ref *ref, tree vuse, unsigned int &limit, bitmap *visited, - bool abort_on_visited, + ao_ref *ref, tree vuse, bool tbaa_p, unsigned int &limit, + bitmap *visited, bool abort_on_visited, void *(*translate)(ao_ref *, tree, void *, bool *), void *data) { @@ -3089,7 +3089,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb, /* An already visited PHI node ends the walk successfully. */ if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt)))) return !abort_on_visited; - vuse = get_continuation_for_phi (def_stmt, ref, limit, + vuse = get_continuation_for_phi (def_stmt, ref, tbaa_p, limit, visited, abort_on_visited, translate, data); if (!vuse) @@ -3104,7 +3104,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb, if ((int)limit <= 0) return false; --limit; - if (stmt_may_clobber_ref_p_1 (def_stmt, ref)) + if (stmt_may_clobber_ref_p_1 (def_stmt, ref, tbaa_p)) { bool disambiguate_only = true; if (translate @@ -3136,7 +3136,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb, Returns NULL_TREE if no suitable virtual operand can be found. */ tree -get_continuation_for_phi (gimple *phi, ao_ref *ref, +get_continuation_for_phi (gimple *phi, ao_ref *ref, bool tbaa_p, unsigned int &limit, bitmap *visited, bool abort_on_visited, void *(*translate)(ao_ref *, tree, void *, bool *), @@ -3179,7 +3179,8 @@ get_continuation_for_phi (gimple *phi, ao_ref *ref, arg1 = PHI_ARG_DEF (phi, i); if (arg1 == arg0) ; - else if (! maybe_skip_until (phi, arg0, dom, ref, arg1, limit, visited, + else if (! maybe_skip_until (phi, arg0, dom, ref, arg1, tbaa_p, + limit, visited, abort_on_visited, /* Do not translate when walking over backedges. */ @@ -3223,7 +3224,7 @@ get_continuation_for_phi (gimple *phi, ao_ref *ref, TODO: Cache the vector of equivalent vuses per ref, vuse pair. */ void * -walk_non_aliased_vuses (ao_ref *ref, tree vuse, +walk_non_aliased_vuses (ao_ref *ref, tree vuse, bool tbaa_p, void *(*walker)(ao_ref *, tree, void *), void *(*translate)(ao_ref *, tree, void *, bool *), tree (*valueize)(tree), @@ -3264,7 +3265,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse, if (gimple_nop_p (def_stmt)) break; else if (gimple_code (def_stmt) == GIMPLE_PHI) - vuse = get_continuation_for_phi (def_stmt, ref, limit, + vuse = get_continuation_for_phi (def_stmt, ref, tbaa_p, limit, &visited, translated, translate, data); else { @@ -3274,7 +3275,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse, break; } --limit; - if (stmt_may_clobber_ref_p_1 (def_stmt, ref)) + if (stmt_may_clobber_ref_p_1 (def_stmt, ref, tbaa_p)) { if (!translate) break; diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h index cee8449..ddd28ec 100644 --- a/gcc/tree-ssa-alias.h +++ b/gcc/tree-ssa-alias.h @@ -131,11 +131,11 @@ extern bool call_may_clobber_ref_p (gcall *, tree); extern bool call_may_clobber_ref_p_1 (gcall *, ao_ref *); extern bool stmt_kills_ref_p (gimple *, tree); extern bool stmt_kills_ref_p (gimple *, ao_ref *); -extern tree get_continuation_for_phi (gimple *, ao_ref *, +extern tree get_continuation_for_phi (gimple *, ao_ref *, bool, unsigned int &, bitmap *, bool, void *(*)(ao_ref *, tree, void *, bool *), void *); -extern void *walk_non_aliased_vuses (ao_ref *, tree, +extern void *walk_non_aliased_vuses (ao_ref *, tree, bool, void *(*)(ao_ref *, tree, void *), void *(*)(ao_ref *, tree, void *, bool *), tree (*)(tree), unsigned &, void *); diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 086f8c3..231ac00 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -1185,8 +1185,8 @@ translate_vuse_through_block (vec operands, bitmap visited = NULL; /* Try to find a vuse that dominates this phi node by skipping non-clobbering statements. */ - vuse = get_continuation_for_phi (phi, &ref, cnt, &visited, false, - NULL, NULL); + vuse = get_continuation_for_phi (phi, &ref, true, + cnt, &visited, false, NULL, NULL); if (visited) BITMAP_FREE (visited); } diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 2cc76d8..6d4ad75 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1648,9 +1648,16 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult) struct vn_walk_cb_data { + vn_walk_cb_data (vn_reference_t vr_, tree *last_vuse_ptr_, + vn_lookup_kind vn_walk_kind_, bool tbaa_p_) + : vr (vr_), last_vuse_ptr (last_vuse_ptr_), vn_walk_kind (vn_walk_kind_), + tbaa_p (tbaa_p_) + {} + vn_reference_t vr; tree *last_vuse_ptr; vn_lookup_kind vn_walk_kind; + bool tbaa_p; }; /* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_ @@ -1927,6 +1934,33 @@ public: static rpo_elim *rpo_avail; basic_block vn_context_bb; +/* Return true if BASE1 and BASE2 can be adjusted so they have the + same address and adjust *OFFSET1 and *OFFSET2 accordingly. + Otherwise return false. */ + +static bool +adjust_offsets_for_equal_base_address (tree base1, poly_int64 *offset1, + tree base2, poly_int64 *offset2) +{ + poly_int64 soff; + if (TREE_CODE (base1) == MEM_REF + && TREE_CODE (base2) == MEM_REF) + { + if (mem_ref_offset (base1).to_shwi (&soff)) + { + base1 = TREE_OPERAND (base1, 0); + *offset1 += soff * BITS_PER_UNIT; + } + if (mem_ref_offset (base2).to_shwi (&soff)) + { + base2 = TREE_OPERAND (base2, 0); + *offset2 += soff * BITS_PER_UNIT; + } + return operand_equal_p (base1, base2, 0); + } + return operand_equal_p (base1, base2, OEP_ADDRESS_OF); +} + /* Callback for walk_non_aliased_vuses. Tries to perform a lookup from the statement defining VUSE and if not successful tries to translate *REFP and VR_ through an aggregate copy at the definition @@ -1966,7 +2000,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, get_alias_set (lhs), TREE_TYPE (lhs), lhs_ops); if (lhs_ref_ok - && !refs_may_alias_p_1 (ref, &lhs_ref, true)) + && !refs_may_alias_p_1 (ref, &lhs_ref, data->tbaa_p)) { *disambiguate_only = true; return NULL; @@ -2055,7 +2089,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, } } - if (*disambiguate_only) + /* If we are looking for redundant stores do not create new hashtable + entries from aliasing defs with made up alias-sets. */ + if (*disambiguate_only || !data->tbaa_p) return (void *)-1; /* If we cannot constrain the size of the reference we cannot @@ -2186,7 +2222,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, &offset2, &size2, &maxsize2, &reverse); if (known_size_p (maxsize2) && known_eq (maxsize2, size2) - && operand_equal_p (base, base2, 0) + && adjust_offsets_for_equal_base_address (base, &offset, + base2, &offset2) && known_subrange_p (offset, maxsize, offset2, size2)) { tree val = build_zero_cst (vr->type); @@ -2213,15 +2250,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, && is_gimple_min_invariant (SSA_VAL (gimple_assign_rhs1 (def_stmt)))))) { tree base2; - HOST_WIDE_INT offset2, size2; + poly_int64 offset2, size2, maxsize2; + HOST_WIDE_INT offset2i; bool reverse; - base2 = get_ref_base_and_extent_hwi (gimple_assign_lhs (def_stmt), - &offset2, &size2, &reverse); + base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt), + &offset2, &size2, &maxsize2, &reverse); if (base2 && !reverse - && size2 % BITS_PER_UNIT == 0 - && offset2 % BITS_PER_UNIT == 0 - && operand_equal_p (base, base2, 0) + && known_eq (maxsize2, size2) + && multiple_p (size2, BITS_PER_UNIT) + && multiple_p (offset2, BITS_PER_UNIT) + && adjust_offsets_for_equal_base_address (base, &offset, + base2, &offset2) + && offset.is_constant (&offseti) + && offset2.is_constant (&offset2i) && known_subrange_p (offseti, maxsizei, offset2, size2)) { /* We support up to 512-bit values (for V8DFmode). */ @@ -2233,12 +2275,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, rhs = SSA_VAL (rhs); len = native_encode_expr (rhs, buffer, sizeof (buffer), - (offseti - offset2) / BITS_PER_UNIT); + (offseti - offset2i) / BITS_PER_UNIT); if (len > 0 && len * BITS_PER_UNIT >= maxsizei) { tree type = vr->type; /* Make sure to interpret in a type that has a range - covering the whole access size. */ + covering the whole access size. */ if (INTEGRAL_TYPE_P (vr->type) && maxsizei != TYPE_PRECISION (vr->type)) type = build_nonstandard_integer_type (maxsizei, @@ -2283,7 +2325,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, if (!reverse && known_size_p (maxsize2) && known_eq (maxsize2, size2) - && operand_equal_p (base, base2, 0) + && adjust_offsets_for_equal_base_address (base, &offset, + base2, &offset2) && known_subrange_p (offset, maxsize, offset2, size2) /* ??? We can't handle bitfield precision extracts without either using an alternate type for the BIT_FIELD_REF and @@ -2653,10 +2696,10 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type, { ao_ref r; unsigned limit = PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS); - vn_walk_cb_data data = { &vr1, NULL, kind }; + vn_walk_cb_data data (&vr1, NULL, kind, true); if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands)) *vnresult = - (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, + (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, true, vn_reference_lookup_2, vn_reference_lookup_3, vuse_valueize, limit, &data); @@ -2693,7 +2736,7 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, vr1.operands = operands = valueize_shared_reference_ops_from_ref (op, &valuezied_anything); vr1.type = TREE_TYPE (op); - vr1.set = tbaa_p ? get_alias_set (op) : 0; + vr1.set = get_alias_set (op); vr1.hashcode = vn_reference_compute_hash (&vr1); if ((cst = fully_constant_vn_reference_p (&vr1))) return cst; @@ -2710,11 +2753,9 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, || !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type, vr1.operands)) ao_ref_init (&r, op); - if (! tbaa_p) - r.ref_alias_set = r.base_alias_set = 0; - vn_walk_cb_data data = { &vr1, last_vuse_ptr, kind }; + vn_walk_cb_data data (&vr1, last_vuse_ptr, kind, tbaa_p); wvnresult = - (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, + (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, tbaa_p, vn_reference_lookup_2, vn_reference_lookup_3, vuse_valueize, limit, &data); diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c index 50413eb..838cf8f 100644 --- a/gcc/tree-ssa-scopedtables.c +++ b/gcc/tree-ssa-scopedtables.c @@ -298,7 +298,7 @@ avail_exprs_stack::lookup_avail_expr (gimple *stmt, bool insert, bool tbaa_p) && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME && (ao_ref_init (&ref, gimple_assign_rhs1 (stmt)), ref.base_alias_set = ref.ref_alias_set = tbaa_p ? -1 : 0, true) - && walk_non_aliased_vuses (&ref, vuse2, vuse_eq, NULL, NULL, + && walk_non_aliased_vuses (&ref, vuse2, true, vuse_eq, NULL, NULL, limit, vuse1) != NULL)) { if (insert) -- cgit v1.1 From 66076dcb60bee1c3d2c41ced5424ada90149d7fc Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 5 Jul 2019 12:53:19 +0000 Subject: tree-ssa-sccvn.c (vn_reference_lookup_3): Valueize RHS when comparing against a store with possibly the same value. 2019-07-05 Richard Biener * tree-ssa-sccvn.c (vn_reference_lookup_3): Valueize RHS when comparing against a store with possibly the same value. * gcc.dg/tree-ssa/ssa-fre-77.c: New testcase. From-SVN: r273136 --- gcc/ChangeLog | 5 +++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-77.c | 13 +++++++++++++ gcc/tree-ssa-sccvn.c | 6 ++++-- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-77.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6dd97ab..15d7919 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2019-07-05 Richard Biener + * tree-ssa-sccvn.c (vn_reference_lookup_3): Valueize RHS + when comparing against a store with possibly the same value. + +2019-07-05 Richard Biener + PR tree-optimization/91091 * tree-ssa-alias.h (get_continuation_for_phi): Add tbaa_p parameter. (walk_non_aliased_vuses): Likewise. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5656a5b2e..a57c230 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-05 Richard Biener + * gcc.dg/tree-ssa/ssa-fre-77.c: New testcase. + +2019-07-05 Richard Biener + PR tree-optimization/91091 * gcc.dg/tree-ssa/pr91091-2.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-70.c: Likewise. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-77.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-77.c new file mode 100644 index 0000000..115f277 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-77.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ + +int foo (int *p, int *q) +{ + int x; + *p = 1; + x = *p; + *q = x; + return *p; +} + +/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */ diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 6d4ad75..67d51bf 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2047,9 +2047,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, if (res && res != (void *)-1) { vn_reference_t vnresult = (vn_reference_t) res; + tree rhs = gimple_assign_rhs1 (def_stmt); + if (TREE_CODE (rhs) == SSA_NAME) + rhs = SSA_VAL (rhs); if (vnresult->result - && operand_equal_p (vnresult->result, - gimple_assign_rhs1 (def_stmt), 0)) + && operand_equal_p (vnresult->result, rhs, 0)) return res; } } -- cgit v1.1 From 2bdc7dcbbd2eee4f114c09443933cc37a546dbff Mon Sep 17 00:00:00 2001 From: Sam Tebbs Date: Fri, 5 Jul 2019 13:16:55 +0000 Subject: [PATCH][GCC][AARCH64] PR target/90712 Fix gcc.dg/rtl/aarch64/subs_adds_sp.c regression gcc/ 2019-07-05 Sam Tebbs PR target/90712 * aarch64/aarch64.c (aarch64_post_cfi_startproc): Replace thunk check with a frame laid out check. From-SVN: r273138 --- gcc/ChangeLog | 6 ++++++ gcc/config/aarch64/aarch64.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 15d7919..53e6714 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-05 Sam Tebbs + + PR target/90712 + * aarch64/aarch64.c (aarch64_post_cfi_startproc): Replace thunk check + with a frame laid out check. + 2019-07-05 Richard Biener * tree-ssa-sccvn.c (vn_reference_lookup_3): Valueize RHS diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 5a923ca..a18fbd0 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -15745,7 +15745,7 @@ aarch64_asm_output_external (FILE *stream, tree decl, const char* name) void aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED) { - if (!cfun->is_thunk && aarch64_return_address_signing_enabled () + if (cfun->machine->frame.laid_out && aarch64_return_address_signing_enabled () && aarch64_ra_sign_key == AARCH64_KEY_B) asm_fprintf (f, "\t.cfi_b_key_frame\n"); } -- cgit v1.1 From 899a199767a1a94812bed0642eca3da0c96c9355 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Fri, 5 Jul 2019 14:45:30 +0000 Subject: DR 1813 PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. DR 1813 PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. * class.c (check_bases): Set CLASSTYPE_NON_STD_LAYOUT for a class if CLASSTYPE_REPEATED_BASE_P is true. * g++.dg/ext/is_std_layout3.C: New test. * g++.dg/ext/is_std_layout4.C: New test. From-SVN: r273139 --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/class.c | 6 +++++- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/g++.dg/ext/is_std_layout3.C | 18 ++++++++++++++++++ gcc/testsuite/g++.dg/ext/is_std_layout4.C | 11 +++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/ext/is_std_layout3.C create mode 100644 gcc/testsuite/g++.dg/ext/is_std_layout4.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c1dfb7c..f24a096 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-07-04 Marek Polacek + + DR 1813 + PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. + * class.c (check_bases): Set CLASSTYPE_NON_STD_LAYOUT for a class if + CLASSTYPE_REPEATED_BASE_P is true. + 2019-07-04 Andrew Stubbs * cp-tree.h (cp_omp_emit_unmappable_type_notes): New prototype. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 73291b3..f77b7f4 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1715,11 +1715,15 @@ check_bases (tree t, && (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field), basetype))) CLASSTYPE_NON_STD_LAYOUT (t) = 1; + /* DR 1813: + ...has at most one base class subobject of any given type... */ + else if (CLASSTYPE_REPEATED_BASE_P (t)) + CLASSTYPE_NON_STD_LAYOUT (t) = 1; else /* ...either has no non-static data members in the most-derived class and at most one base class with non-static data members, or has no base classes with non-static data - members */ + members. FIXME This was reworded in DR 1813. */ for (basefield = TYPE_FIELDS (basetype); basefield; basefield = DECL_CHAIN (basefield)) if (TREE_CODE (basefield) == FIELD_DECL diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a57c230..98ad880 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-07-04 Marek Polacek + + DR 1813 + PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. + * g++.dg/ext/is_std_layout3.C: New test. + * g++.dg/ext/is_std_layout4.C: New test. + 2019-07-05 Richard Biener * gcc.dg/tree-ssa/ssa-fre-77.c: New testcase. diff --git a/gcc/testsuite/g++.dg/ext/is_std_layout3.C b/gcc/testsuite/g++.dg/ext/is_std_layout3.C new file mode 100644 index 0000000..b0555c8 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_std_layout3.C @@ -0,0 +1,18 @@ +// DR 1813 +// PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. +// { dg-do compile { target c++11 } } + +struct B { int i; }; // standard-layout class +struct C : B { }; // standard-layout class +struct D : C { }; // standard-layout class +struct E : D { char : 4; }; // not a standard-layout class +static_assert( __is_standard_layout(B), "" ); +static_assert( __is_standard_layout(C), "" ); +static_assert( __is_standard_layout(D), "" ); +static_assert( ! __is_standard_layout(E), "" ); + +struct Q {}; +struct S : Q { }; +struct T : Q { }; +struct U : S, T { }; // not a standard-layout class +static_assert( ! __is_standard_layout(U), "" ); diff --git a/gcc/testsuite/g++.dg/ext/is_std_layout4.C b/gcc/testsuite/g++.dg/ext/is_std_layout4.C new file mode 100644 index 0000000..09c0098 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_std_layout4.C @@ -0,0 +1,11 @@ +// DR 1813 +// PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. +// { dg-do compile { target c++11 } } + +struct R { }; +struct Q { }; +struct S : R { }; +struct T : Q { }; +struct U : S, T { }; +// No repeated base class subobjects. +static_assert(__is_standard_layout(U), ""); -- cgit v1.1 From 6e158c5fd534a1080dd013ed5d9d3fcc3fe838ff Mon Sep 17 00:00:00 2001 From: Andrew Stubbs Date: Fri, 5 Jul 2019 16:00:46 +0000 Subject: Tweak error message for mapped parameters. 2019-07-05 Andrew Stubbs gcc/fortran/ * openmp.c (resolve_omp_clauses): Add custom error messages for parameters in map clauses. From-SVN: r273143 --- gcc/fortran/ChangeLog | 5 +++++ gcc/fortran/openmp.c | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index a163a1d..14ec845 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,8 @@ +2019-07-05 Andrew Stubbs + + * openmp.c (resolve_omp_clauses): Add custom error messages for + parameters in map clauses. + 2019-07-03 Martin Liska * check.c (gfc_check_c_funloc): Remove diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index 1c7bce6..44fcb9d 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -4208,8 +4208,21 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, continue; } } - gfc_error ("Object %qs is not a variable at %L", n->sym->name, - &n->where); + if (list == OMP_LIST_MAP + && n->sym->attr.flavor == FL_PARAMETER) + { + if (openacc) + gfc_error ("Object %qs is not a variable at %L; parameters" + " cannot be and need not be copied", n->sym->name, + &n->where); + else + gfc_error ("Object %qs is not a variable at %L; parameters" + " cannot be and need not be mapped", n->sym->name, + &n->where); + } + else + gfc_error ("Object %qs is not a variable at %L", n->sym->name, + &n->where); } for (list = 0; list < OMP_LIST_NUM; list++) -- cgit v1.1 From 131138d51d22ea58e95a8f21e75f67aab7881854 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 5 Jul 2019 17:38:28 +0000 Subject: * tree-ssa-loop-manip.c (create_iv): Add missing guard for gsi_end_p. From-SVN: r273145 --- gcc/ChangeLog | 8 ++++++-- gcc/tree-ssa-loop-manip.c | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53e6714..7b1109b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,8 +1,12 @@ +2019-07-05 Eric Botcazou + + * tree-ssa-loop-manip.c (create_iv): Add missing guard for gsi_end_p. + 2019-07-05 Sam Tebbs PR target/90712 - * aarch64/aarch64.c (aarch64_post_cfi_startproc): Replace thunk check - with a frame laid out check. + * config/aarch64/aarch64.c (aarch64_post_cfi_startproc): Replace thunk + check with a frame laid out check. 2019-07-05 Richard Biener diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index f072418..ecbe212 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -139,7 +139,8 @@ create_iv (tree base, tree step, tree var, struct loop *loop, } else { - gimple_set_location (stmt, gimple_location (gsi_stmt (*incr_pos))); + if (!gsi_end_p (*incr_pos)) + gimple_set_location (stmt, gimple_location (gsi_stmt (*incr_pos))); gsi_insert_before (incr_pos, stmt, GSI_NEW_STMT); } -- cgit v1.1 From 26f8363d85fd386430ddb612a2e70624715c2ac3 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Fri, 5 Jul 2019 18:03:05 +0000 Subject: PR c++/67184 (again) /cp 2019-07-05 Paolo Carlini PR c++/67184 (again) PR c++/69445 * call.c (build_over_call): Devirtualize user-defined operators coming from a base too. (build_new_method_call_1): Do not devirtualize here. /testsuite 2019-07-05 Paolo Carlini PR c++/67184 (again) PR c++/69445 * g++.dg/other/final4.C: New. From-SVN: r273147 --- gcc/cp/ChangeLog | 11 ++++++++++- gcc/cp/call.c | 24 ++++++++++-------------- gcc/testsuite/ChangeLog | 9 ++++++++- gcc/testsuite/g++.dg/other/final4.C | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/other/final4.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f24a096..05e4555 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,7 +1,16 @@ +2019-07-05 Paolo Carlini + + PR c++/67184 (again) + PR c++/69445 + * call.c (build_over_call): Devirtualize user-defined operators + coming from a base too. + (build_new_method_call_1): Do not devirtualize here. + 2019-07-04 Marek Polacek DR 1813 - PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. + PR c++/83374 - __is_standard_layout wrong for a class with repeated + bases. * class.c (check_bases): Set CLASSTYPE_NON_STD_LAYOUT for a class if CLASSTYPE_REPEATED_BASE_P is true. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0709325..90116f4 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8241,10 +8241,17 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) return error_mark_node; } - /* See if the function member or the whole class type is declared - final and the call can be devirtualized. */ + /* Optimize away vtable lookup if we know that this + function can't be overridden. We need to check if + the context and the type where we found fn are the same, + actually FN might be defined in a different class + type because of a using-declaration. In this case, we + do not want to perform a non-virtual call. Note that + resolves_to_fixed_type_p checks CLASSTYPE_FINAL too. */ if (DECL_FINAL_P (fn) - || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)))) + || (resolves_to_fixed_type_p (arg, 0) + && same_type_ignoring_top_level_qualifiers_p + (DECL_CONTEXT (fn), BINFO_TYPE (cand->conversion_path)))) flags |= LOOKUP_NONVIRTUAL; /* [class.mfct.nonstatic]: If a nonstatic member function of a class @@ -9845,17 +9852,6 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, if (call != error_mark_node) { - /* Optimize away vtable lookup if we know that this - function can't be overridden. We need to check if - the context and the type where we found fn are the same, - actually FN might be defined in a different class - type because of a using-declaration. In this case, we - do not want to perform a non-virtual call. */ - if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL) - && same_type_ignoring_top_level_qualifiers_p - (DECL_CONTEXT (fn), BINFO_TYPE (binfo)) - && resolves_to_fixed_type_p (instance, 0)) - flags |= LOOKUP_NONVIRTUAL; if (explicit_targs) flags |= LOOKUP_EXPLICIT_TMPL_ARGS; /* Now we know what function is being called. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 98ad880..33645b1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,7 +1,14 @@ +2019-07-05 Paolo Carlini + + PR c++/67184 (again) + PR c++/69445 + * g++.dg/other/final4.C: New. + 2019-07-04 Marek Polacek DR 1813 - PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. + PR c++/83374 - __is_standard_layout wrong for a class with repeated + bases. * g++.dg/ext/is_std_layout3.C: New test. * g++.dg/ext/is_std_layout4.C: New test. diff --git a/gcc/testsuite/g++.dg/other/final4.C b/gcc/testsuite/g++.dg/other/final4.C new file mode 100644 index 0000000..867ef38 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/final4.C @@ -0,0 +1,16 @@ +// PR c++/67184 +// { dg-do compile { target c++11 } } +// { dg-options "-fdump-tree-original" } + +struct B +{ + virtual void operator()(); + virtual operator int(); + virtual int operator++(); +}; + +struct D final : B { }; + +void foo(D& d) { d(); int t = d; ++d; } + +// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } } -- cgit v1.1 From 9eb5f744ae21f805a1e5b80aabc6d86306f3b3d7 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Fri, 5 Jul 2019 18:26:26 +0000 Subject: [Darwin.PPC] Remove dead code. TARGET_LINK_STACK is unused on Darwin, and only relevant to a processor on which the port was never released. 2019-07-05 Iain Sandoe * config/rs6000/rs6000-logue.c: Remove unused code. From-SVN: r273148 --- gcc/ChangeLog | 4 ++++ gcc/config/rs6000/rs6000-logue.c | 23 +++++------------------ 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7b1109b..00a01c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2019-07-05 Iain Sandoe + + * config/rs6000/rs6000-logue.c: Remove unused code. + 2019-07-05 Eric Botcazou * tree-ssa-loop-manip.c (create_iv): Add missing guard for gsi_end_p. diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index 3fe6230..8454f96 100644 --- a/gcc/config/rs6000/rs6000-logue.c +++ b/gcc/config/rs6000/rs6000-logue.c @@ -5100,24 +5100,11 @@ macho_branch_islands (void) #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ if (flag_pic) { - if (TARGET_LINK_STACK) - { - char name[32]; - get_ppc476_thunk_name (name); - strcat (tmp_buf, ":\n\tmflr r0\n\tbl "); - strcat (tmp_buf, name); - strcat (tmp_buf, "\n"); - strcat (tmp_buf, label); - strcat (tmp_buf, "_pic:\n\tmflr r11\n"); - } - else - { - strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); - strcat (tmp_buf, label); - strcat (tmp_buf, "_pic\n"); - strcat (tmp_buf, label); - strcat (tmp_buf, "_pic:\n\tmflr r11\n"); - } + strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic\n"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic:\n\tmflr r11\n"); strcat (tmp_buf, "\taddis r11,r11,ha16("); strcat (tmp_buf, name_buf); -- cgit v1.1 From 99e4ed786384cceafd7db5dbe21d1d36bcaa35a6 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 5 Jul 2019 22:51:44 +0200 Subject: re PR c++/67184 (Missed optimization with C++11 final specifier) PR c++/67184 PR c++/69445 * call.c (build_new_method_call_1): Remove set but not used variable binfo. From-SVN: r273149 --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/call.c | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 05e4555..1967c9b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-07-05 Jakub Jelinek + + PR c++/67184 + PR c++/69445 + * call.c (build_new_method_call_1): Remove set but not used variable + binfo. + 2019-07-05 Paolo Carlini PR c++/67184 (again) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 90116f4..e597d7a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -9564,7 +9564,7 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, struct z_candidate *candidates = 0, *cand; tree explicit_targs = NULL_TREE; tree basetype = NULL_TREE; - tree access_binfo, binfo; + tree access_binfo; tree optype; tree first_mem_arg = NULL_TREE; tree name; @@ -9603,7 +9603,6 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, if (!conversion_path) conversion_path = BASELINK_BINFO (fns); access_binfo = BASELINK_ACCESS_BINFO (fns); - binfo = BASELINK_BINFO (fns); optype = BASELINK_OPTYPE (fns); fns = BASELINK_FUNCTIONS (fns); if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) -- cgit v1.1 From e954337f3ce8e458ffbd7d1539a35413a24c73bf Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 6 Jul 2019 00:16:36 +0000 Subject: Daily bump. From-SVN: r273154 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3b646d6..739e0ea 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190705 +20190706 -- cgit v1.1 From 2dcb0d5b59e05b18694173c4c194bcedc1956ff8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 6 Jul 2019 09:49:59 +0200 Subject: omp-low.c (omp_find_scan): Make static. * omp-low.c (omp_find_scan): Make static. (lower_omp_for_scan): Fix order of merge arguments in input phase of the second loop, var2 represents the first partial sum and so needs to go before rprivb[ivar]. From-SVN: r273155 --- gcc/ChangeLog | 7 +++++++ gcc/omp-low.c | 30 +++++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00a01c7..dc75cbb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-06 Jakub Jelinek + + * omp-low.c (omp_find_scan): Make static. + (lower_omp_for_scan): Fix order of merge arguments in input phase of + the second loop, var2 represents the first partial sum and so needs + to go before rprivb[ivar]. + 2019-07-05 Iain Sandoe * config/rs6000/rs6000-logue.c: Remove unused code. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 7e85d48..52834c9 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -9104,7 +9104,7 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p, /* Callback for walk_gimple_seq. Find #pragma omp scan statement. */ -tree +static tree omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, struct walk_stmt_info *wi) { @@ -9240,8 +9240,8 @@ omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, for (i = 0; i < n; i = i + 1) { { - // For UDRs, this is UDR merge (rprivb[ivar], var2); r = rprivb[ivar]; - r = rprivb[ivar] + var2; + // For UDRs, this is r = var2; UDR merge (r, rprivb[ivar]); + r = var2 + rprivb[ivar]; } { // This is the scan phase from user code. @@ -9394,8 +9394,6 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, { tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c); tree val = var2; - if (new_vard != new_var) - val = build_fold_addr_expr_loc (clause_loc, val); x = lang_hooks.decls.omp_clause_default_ctor (c, var2, build_outer_var_ref (var, ctx)); @@ -9420,6 +9418,9 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, /* Otherwise, assign to it the identity element. */ gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c); tseq = copy_gimple_seq_and_replace_locals (tseq); + + if (new_vard != new_var) + val = build_fold_addr_expr_loc (clause_loc, val); SET_DECL_VALUE_EXPR (new_vard, val); DECL_HAS_VALUE_EXPR_P (new_vard) = 1; SET_DECL_VALUE_EXPR (placeholder, error_mark_node); @@ -9469,11 +9470,19 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); gimplify_and_add (x, &mdlist); + x = unshare_expr (new_var); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + gimplify_and_add (x, &input2_list); + + val = rprivb_ref; + if (new_vard != new_var) + val = build_fold_addr_expr_loc (clause_loc, val); + tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); tseq = copy_gimple_seq_and_replace_locals (tseq); SET_DECL_VALUE_EXPR (new_vard, val); DECL_HAS_VALUE_EXPR_P (new_vard) = 1; - SET_DECL_VALUE_EXPR (placeholder, rprivb_ref); + DECL_HAS_VALUE_EXPR_P (placeholder) = 0; lower_omp (&tseq, ctx); if (y) SET_DECL_VALUE_EXPR (new_vard, y); @@ -9482,12 +9491,11 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, DECL_HAS_VALUE_EXPR_P (new_vard) = 0; SET_DECL_VALUE_EXPR (new_vard, NULL_TREE); } + SET_DECL_VALUE_EXPR (placeholder, new_var); + DECL_HAS_VALUE_EXPR_P (placeholder) = 1; + lower_omp (&tseq, ctx); gimple_seq_add_seq (&input2_list, tseq); - x = unshare_expr (new_var); - x = lang_hooks.decls.omp_clause_assign_op (c, x, rprivb_ref); - gimplify_and_add (x, &input2_list); - x = build_outer_var_ref (var, ctx); x = lang_hooks.decls.omp_clause_assign_op (c, x, rpriva_ref); gimplify_and_add (x, &last_list); @@ -9545,7 +9553,7 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, gimplify_assign (unshare_expr (rpriva_ref), var2, &mdlist); - x = build2 (code, TREE_TYPE (new_var), rprivb_ref, var2); + x = build2 (code, TREE_TYPE (new_var), var2, rprivb_ref); gimplify_assign (new_var, x, &input2_list); gimplify_assign (build_outer_var_ref (var, ctx), rpriva_ref, -- cgit v1.1 From 5d1212877acd3f7a2a6ff23f91dc1a0ed106fdd4 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 6 Jul 2019 09:50:44 +0200 Subject: re PR tree-optimization/91096 (Openmp vector max reduction incorrect) PR tree-optimization/91096 * gcc.dg/vect/vect-simd-10.c (FLT_MIN_VALUE): Define. (bar, main): Use it instead of -__builtin_inff (). * gcc.dg/vect/vect-simd-14.c (FLT_MIN_VALUE): Define. (bar, main): Use it instead of -__builtin_inff (). From-SVN: r273156 --- gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/gcc.dg/vect/vect-simd-10.c | 10 ++++++++-- gcc/testsuite/gcc.dg/vect/vect-simd-14.c | 10 ++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 33645b1..5a848eb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-07-06 Jakub Jelinek + + PR tree-optimization/91096 + * gcc.dg/vect/vect-simd-10.c (FLT_MIN_VALUE): Define. + (bar, main): Use it instead of -__builtin_inff (). + * gcc.dg/vect/vect-simd-14.c (FLT_MIN_VALUE): Define. + (bar, main): Use it instead of -__builtin_inff (). + 2019-07-05 Paolo Carlini PR c++/67184 (again) diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-10.c b/gcc/testsuite/gcc.dg/vect/vect-simd-10.c index d442d6b..e49566a 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-10.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-10.c @@ -7,6 +7,12 @@ #include "tree-vect.h" #endif +#ifdef __FAST_MATH__ +#define FLT_MIN_VALUE (-__FLT_MAX__) +#else +#define FLT_MIN_VALUE (-__builtin_inff ()) +#endif + float r = 1.0f, a[1024], b[1024]; __attribute__((noipa)) void @@ -24,7 +30,7 @@ foo (float *a, float *b) __attribute__((noipa)) float bar (void) { - float s = -__builtin_inff (); + float s = FLT_MIN_VALUE; #pragma omp simd reduction (inscan, max:s) for (int i = 0; i < 1024; i++) { @@ -84,7 +90,7 @@ main () } if (bar () != 592.0f) abort (); - s = -__builtin_inff (); + s = FLT_MIN_VALUE; for (int i = 0; i < 1024; ++i) { if (s < a[i]) diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-14.c b/gcc/testsuite/gcc.dg/vect/vect-simd-14.c index 43663bb..9e73792 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-14.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-14.c @@ -7,6 +7,12 @@ #include "tree-vect.h" #endif +#ifdef __FAST_MATH__ +#define FLT_MIN_VALUE (-__FLT_MAX__) +#else +#define FLT_MIN_VALUE (-__builtin_inff ()) +#endif + float r = 1.0f, a[1024], b[1024]; __attribute__((noipa)) void @@ -24,7 +30,7 @@ foo (float *a, float *b) __attribute__((noipa)) float bar (void) { - float s = -__builtin_inff (); + float s = FLT_MIN_VALUE; #pragma omp simd reduction (inscan, max:s) for (int i = 0; i < 1024; i++) { @@ -82,7 +88,7 @@ main () } if (bar () != 592.0f) abort (); - s = -__builtin_inff (); + s = FLT_MIN_VALUE; for (int i = 0; i < 1024; ++i) { if (b[i] != s) -- cgit v1.1 From 1f52d1a8b52ace2922eb9b97e2c49d2ee7d27410 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 6 Jul 2019 09:53:48 +0200 Subject: omp-low.c (struct omp_context): Add for_simd_scan_phase member. * omp-low.c (struct omp_context): Add for_simd_scan_phase member. (maybe_lookup_ctx): Add forward declaration. (omp_find_scan): Likewise. Walk into body of simd if composited with worksharing loop. (scan_omp_simd_scan): New function. (scan_omp_1_stmt): Call it. (lower_rec_simd_input_clauses): Don't create rvar nor rvar2 if ctx->for_simd_scan_phase. (lower_rec_input_clauses): Do much less work for inscan reductions in ctx->for_simd_scan_phase is_simd regions. (lower_omp_scan): Set is_simd also on simd constructs composited with worksharing loop, unless ctx->for_simd_scan_phase. Never emit a sorry message. Don't change GIMPLE_OMP_SCAN stmts into nops and emit their body after in simd constructs composited with worksharing loop. (lower_omp_for_scan): Handle worksharing loop composited with simd. * c-c++-common/gomp/scan-4.c: Don't expect sorry message. * testsuite/libgomp.c/scan-11.c: New test. * testsuite/libgomp.c/scan-12.c: New test. * testsuite/libgomp.c/scan-13.c: New test. * testsuite/libgomp.c/scan-14.c: New test. * testsuite/libgomp.c/scan-15.c: New test. * testsuite/libgomp.c/scan-16.c: New test. * testsuite/libgomp.c/scan-17.c: New test. * testsuite/libgomp.c/scan-18.c: New test. * testsuite/libgomp.c++/scan-9.C: New test. * testsuite/libgomp.c++/scan-10.C: New test. * testsuite/libgomp.c++/scan-11.C: New test. * testsuite/libgomp.c++/scan-12.C: New test. * testsuite/libgomp.c++/scan-13.C: New test. * testsuite/libgomp.c++/scan-14.C: New test. * testsuite/libgomp.c++/scan-15.C: New test. * testsuite/libgomp.c++/scan-16.C: New test. From-SVN: r273157 --- gcc/ChangeLog | 17 ++ gcc/omp-low.c | 329 ++++++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 2 + gcc/testsuite/c-c++-common/gomp/scan-4.c | 2 +- 4 files changed, 295 insertions(+), 55 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dc75cbb..3ce8b90 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2019-07-06 Jakub Jelinek + * omp-low.c (struct omp_context): Add for_simd_scan_phase member. + (maybe_lookup_ctx): Add forward declaration. + (omp_find_scan): Likewise. Walk into body of simd if composited + with worksharing loop. + (scan_omp_simd_scan): New function. + (scan_omp_1_stmt): Call it. + (lower_rec_simd_input_clauses): Don't create rvar nor rvar2 if + ctx->for_simd_scan_phase. + (lower_rec_input_clauses): Do much less work for inscan reductions + in ctx->for_simd_scan_phase is_simd regions. + (lower_omp_scan): Set is_simd also on simd constructs composited + with worksharing loop, unless ctx->for_simd_scan_phase. Never emit + a sorry message. Don't change GIMPLE_OMP_SCAN stmts into nops and + emit their body after in simd constructs composited with worksharing + loop. + (lower_omp_for_scan): Handle worksharing loop composited with simd. + * omp-low.c (omp_find_scan): Make static. (lower_omp_for_scan): Fix order of merge arguments in input phase of the second loop, var2 represents the first partial sum and so needs diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 52834c9..5d5fb6a 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -147,6 +147,9 @@ struct omp_context /* True if there is nested scan context with exclusive clause. */ bool scan_exclusive; + + /* True in the second simd loop of for simd with inscan reductions. */ + bool for_simd_scan_phase; }; static splay_tree all_contexts; @@ -2421,6 +2424,85 @@ scan_omp_simd (gimple_stmt_iterator *gsi, gomp_for *stmt, scan_omp_for (stmt, outer_ctx)->simt_stmt = new_stmt; } +static tree omp_find_scan (gimple_stmt_iterator *, bool *, + struct walk_stmt_info *); +static omp_context *maybe_lookup_ctx (gimple *); + +/* Duplicate #pragma omp simd, one for the scan input phase loop and one + for scan phase loop. */ + +static void +scan_omp_simd_scan (gimple_stmt_iterator *gsi, gomp_for *stmt, + omp_context *outer_ctx) +{ + /* The only change between inclusive and exclusive scan will be + within the first simd loop, so just use inclusive in the + worksharing loop. */ + outer_ctx->scan_inclusive = true; + tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_INCLUSIVE); + OMP_CLAUSE_DECL (c) = integer_zero_node; + + gomp_scan *input_stmt = gimple_build_omp_scan (NULL, NULL_TREE); + gomp_scan *scan_stmt = gimple_build_omp_scan (NULL, c); + gsi_replace (gsi, input_stmt, false); + gimple_seq input_body = NULL; + gimple_seq_add_stmt (&input_body, stmt); + gsi_insert_after (gsi, scan_stmt, GSI_NEW_STMT); + + gimple_stmt_iterator input1_gsi = gsi_none (); + struct walk_stmt_info wi; + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input1_gsi; + walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), omp_find_scan, NULL, &wi); + gcc_assert (!gsi_end_p (input1_gsi)); + + gimple *input_stmt1 = gsi_stmt (input1_gsi); + gsi_next (&input1_gsi); + gimple *scan_stmt1 = gsi_stmt (input1_gsi); + gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN); + c = gimple_omp_scan_clauses (as_a (scan_stmt1)); + if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE) + std::swap (input_stmt1, scan_stmt1); + + gimple_seq input_body1 = gimple_omp_body (input_stmt1); + gimple_omp_set_body (input_stmt1, NULL); + + gimple_seq scan_body = copy_gimple_seq_and_replace_locals (stmt); + gomp_for *new_stmt = as_a (scan_body); + + gimple_omp_set_body (input_stmt1, input_body1); + gimple_omp_set_body (scan_stmt1, NULL); + + gimple_stmt_iterator input2_gsi = gsi_none (); + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input2_gsi; + walk_gimple_seq_mod (gimple_omp_body_ptr (new_stmt), omp_find_scan, + NULL, &wi); + gcc_assert (!gsi_end_p (input2_gsi)); + + gimple *input_stmt2 = gsi_stmt (input2_gsi); + gsi_next (&input2_gsi); + gimple *scan_stmt2 = gsi_stmt (input2_gsi); + gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN); + if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE) + std::swap (input_stmt2, scan_stmt2); + + gimple_omp_set_body (input_stmt2, NULL); + + gimple_omp_set_body (input_stmt, input_body); + gimple_omp_set_body (scan_stmt, scan_body); + + omp_context *ctx = new_omp_context (input_stmt, outer_ctx); + scan_omp (gimple_omp_body_ptr (input_stmt), ctx); + + ctx = new_omp_context (scan_stmt, outer_ctx); + scan_omp (gimple_omp_body_ptr (scan_stmt), ctx); + + maybe_lookup_ctx (new_stmt)->for_simd_scan_phase = true; +} + /* Scan an OpenMP sections directive. */ static void @@ -3321,6 +3403,19 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, case GIMPLE_OMP_FOR: if ((gimple_omp_for_kind (as_a (stmt)) == GF_OMP_FOR_KIND_SIMD) + && gimple_omp_for_combined_into_p (stmt) + && gimple_code (ctx->stmt) != GIMPLE_OMP_SCAN) + { + tree clauses = gimple_omp_for_clauses (as_a (stmt)); + tree c = omp_find_clause (clauses, OMP_CLAUSE_REDUCTION); + if (c && OMP_CLAUSE_REDUCTION_INSCAN (c) && !seen_error ()) + { + scan_omp_simd_scan (gsi, as_a (stmt), ctx); + break; + } + } + if ((gimple_omp_for_kind (as_a (stmt)) + == GF_OMP_FOR_KIND_SIMD) && omp_maybe_offloaded_ctx (ctx) && omp_max_simt_vf ()) scan_omp_simd (gsi, as_a (stmt), ctx); @@ -3757,7 +3852,7 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, DECL_ATTRIBUTES (avar)); gimple_add_tmp_var (avar); tree iavar = avar; - if (rvar) + if (rvar && !ctx->for_simd_scan_phase) { /* For inscan reductions, create another array temporary, which will hold the reduced value. */ @@ -5213,7 +5308,16 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, x = lang_hooks.decls.omp_clause_default_ctor (c, unshare_expr (ivar), build_outer_var_ref (var, ctx)); - if (rvarp) + if (rvarp && ctx->for_simd_scan_phase) + { + if (x) + gimplify_and_add (x, &llist[0]); + x = lang_hooks.decls.omp_clause_dtor (c, ivar); + if (x) + gimplify_and_add (x, &llist[1]); + break; + } + else if (rvarp) { if (x) { @@ -5371,6 +5475,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION && OMP_CLAUSE_REDUCTION_INSCAN (c)) { + if (ctx->for_simd_scan_phase) + goto do_dtor; if (x || (!is_simd && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))) { @@ -5532,6 +5638,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (rvarp) { + if (ctx->for_simd_scan_phase) + break; gimplify_assign (ivar, ref, &llist[0]); ref = build_outer_var_ref (var, ctx); gimplify_assign (ref, rvar, &llist[3]); @@ -8629,11 +8737,13 @@ lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx) bool input_phase = has_clauses ^ octx->scan_inclusive; bool is_simd = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (octx->stmt) & GF_OMP_FOR_SIMD) - && !gimple_omp_for_combined_into_p (octx->stmt)); + && (gimple_omp_for_kind (octx->stmt) & GF_OMP_FOR_SIMD)); bool is_for = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_FOR && !gimple_omp_for_combined_p (octx->stmt)); + bool is_for_simd = is_simd && gimple_omp_for_combined_into_p (octx->stmt); + if (is_for_simd && octx->for_simd_scan_phase) + is_simd = false; if (is_simd) if (tree c = omp_find_clause (gimple_omp_for_clauses (octx->stmt), OMP_CLAUSE__SIMDUID_)) @@ -8866,10 +8976,7 @@ lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx) } } } - else if (has_clauses) - sorry_at (gimple_location (stmt), - "%<#pragma omp scan%> not supported yet"); - if (!is_for) + if (is_simd && !is_for_simd) { gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT); gsi_insert_seq_after (gsi_p, before, GSI_SAME_STMT); @@ -9115,6 +9222,12 @@ omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, { WALK_SUBSTMTS; + case GIMPLE_OMP_FOR: + if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_combined_into_p (stmt)) + *handled_ops_p = false; + break; + case GIMPLE_OMP_SCAN: *(gimple_stmt_iterator *) (wi->info) = *gsi_p; return integer_zero_node; @@ -9255,6 +9368,7 @@ static void lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, struct omp_for_data *fd, omp_context *ctx) { + bool is_for_simd = gimple_omp_for_combined_p (stmt); gcc_assert (ctx->scan_inclusive || ctx->scan_exclusive); gimple_seq body = gimple_omp_body (stmt); @@ -9299,6 +9413,45 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN); gimple_omp_set_body (scan_stmt2, scan_body); + gimple_stmt_iterator input3_gsi = gsi_none (); + gimple_stmt_iterator scan3_gsi = gsi_none (); + gimple_stmt_iterator input4_gsi = gsi_none (); + gimple_stmt_iterator scan4_gsi = gsi_none (); + gimple *input_stmt3 = NULL, *scan_stmt3 = NULL; + gimple *input_stmt4 = NULL, *scan_stmt4 = NULL; + omp_context *input_simd_ctx = NULL, *scan_simd_ctx = NULL; + if (is_for_simd) + { + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input3_gsi; + walk_gimple_seq_mod (&input_body, omp_find_scan, NULL, &wi); + gcc_assert (!gsi_end_p (input3_gsi)); + + input_stmt3 = gsi_stmt (input3_gsi); + gsi = input3_gsi; + gsi_next (&gsi); + scan3_gsi = gsi; + scan_stmt3 = gsi_stmt (gsi); + gcc_assert (scan_stmt3 && gimple_code (scan_stmt3) == GIMPLE_OMP_SCAN); + + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &input4_gsi; + walk_gimple_seq_mod (&scan_body, omp_find_scan, NULL, &wi); + gcc_assert (!gsi_end_p (input4_gsi)); + + input_stmt4 = gsi_stmt (input4_gsi); + gsi = input4_gsi; + gsi_next (&gsi); + scan4_gsi = gsi; + scan_stmt4 = gsi_stmt (gsi); + gcc_assert (scan_stmt4 && gimple_code (scan_stmt4) == GIMPLE_OMP_SCAN); + + input_simd_ctx = maybe_lookup_ctx (input_stmt3)->outer; + scan_simd_ctx = maybe_lookup_ctx (input_stmt4)->outer; + } + tree num_threads = create_tmp_var (integer_type_node); tree thread_num = create_tmp_var (integer_type_node); tree nthreads_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS); @@ -9390,6 +9543,18 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rprivb), rprivb, x); tree rprivb_ref = build_simple_mem_ref_loc (clause_loc, x); + tree var4 = is_for_simd ? new_var : var2; + tree var5 = NULL_TREE, var6 = NULL_TREE; + if (is_for_simd) + { + var5 = lookup_decl (var, input_simd_ctx); + var6 = lookup_decl (var, scan_simd_ctx); + if (new_vard != new_var) + { + var5 = build_simple_mem_ref_loc (clause_loc, var5); + var6 = build_simple_mem_ref_loc (clause_loc, var6); + } + } if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) { tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c); @@ -9401,16 +9566,19 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, gimplify_and_add (x, &clist); x = build_outer_var_ref (var, ctx); - x = lang_hooks.decls.omp_clause_assign_op (c, var2, x); + x = lang_hooks.decls.omp_clause_assign_op (c, unshare_expr (var4), + x); gimplify_and_add (x, &thr01_list); tree y = (DECL_HAS_VALUE_EXPR_P (new_vard) ? DECL_VALUE_EXPR (new_vard) : NULL_TREE); if (var3) { - x = lang_hooks.decls.omp_clause_assign_op (c, var2, var3); + x = unshare_expr (var4); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var3); gimplify_and_add (x, &thrn1_list); - x = lang_hooks.decls.omp_clause_assign_op (c, var2, var3); + x = unshare_expr (var4); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var3); gimplify_and_add (x, &thr02_list); } else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)) @@ -9418,11 +9586,13 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, /* Otherwise, assign to it the identity element. */ gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c); tseq = copy_gimple_seq_and_replace_locals (tseq); - - if (new_vard != new_var) - val = build_fold_addr_expr_loc (clause_loc, val); - SET_DECL_VALUE_EXPR (new_vard, val); - DECL_HAS_VALUE_EXPR_P (new_vard) = 1; + if (!is_for_simd) + { + if (new_vard != new_var) + val = build_fold_addr_expr_loc (clause_loc, val); + SET_DECL_VALUE_EXPR (new_vard, val); + DECL_HAS_VALUE_EXPR_P (new_vard) = 1; + } SET_DECL_VALUE_EXPR (placeholder, error_mark_node); DECL_HAS_VALUE_EXPR_P (placeholder) = 1; lower_omp (&tseq, ctx); @@ -9442,47 +9612,64 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, } } - x = lang_hooks.decls.omp_clause_assign_op (c, var2, rprivam1_ref); + x = unshare_expr (var4); + x = lang_hooks.decls.omp_clause_assign_op (c, x, rprivam1_ref); gimplify_and_add (x, &thrn2_list); - if (ctx->scan_exclusive) + if (is_for_simd) { x = unshare_expr (rprivb_ref); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var5); gimplify_and_add (x, &scan1_list); } + else + { + if (ctx->scan_exclusive) + { + x = unshare_expr (rprivb_ref); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + gimplify_and_add (x, &scan1_list); + } - gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); - tseq = copy_gimple_seq_and_replace_locals (tseq); - SET_DECL_VALUE_EXPR (placeholder, var2); - DECL_HAS_VALUE_EXPR_P (placeholder) = 1; - lower_omp (&tseq, ctx); - gimple_seq_add_seq (&scan1_list, tseq); + gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); + tseq = copy_gimple_seq_and_replace_locals (tseq); + SET_DECL_VALUE_EXPR (placeholder, var2); + DECL_HAS_VALUE_EXPR_P (placeholder) = 1; + lower_omp (&tseq, ctx); + gimple_seq_add_seq (&scan1_list, tseq); - if (ctx->scan_inclusive) - { - x = unshare_expr (rprivb_ref); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); - gimplify_and_add (x, &scan1_list); + if (ctx->scan_inclusive) + { + x = unshare_expr (rprivb_ref); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + gimplify_and_add (x, &scan1_list); + } } x = unshare_expr (rpriva_ref); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + x = lang_hooks.decls.omp_clause_assign_op (c, x, + unshare_expr (var4)); gimplify_and_add (x, &mdlist); - x = unshare_expr (new_var); - x = lang_hooks.decls.omp_clause_assign_op (c, x, var2); + x = unshare_expr (is_for_simd ? var6 : new_var); + x = lang_hooks.decls.omp_clause_assign_op (c, x, var4); gimplify_and_add (x, &input2_list); val = rprivb_ref; if (new_vard != new_var) val = build_fold_addr_expr_loc (clause_loc, val); - tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); + gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c); tseq = copy_gimple_seq_and_replace_locals (tseq); SET_DECL_VALUE_EXPR (new_vard, val); DECL_HAS_VALUE_EXPR_P (new_vard) = 1; - DECL_HAS_VALUE_EXPR_P (placeholder) = 0; + if (is_for_simd) + { + SET_DECL_VALUE_EXPR (placeholder, var6); + DECL_HAS_VALUE_EXPR_P (placeholder) = 1; + } + else + DECL_HAS_VALUE_EXPR_P (placeholder) = 0; lower_omp (&tseq, ctx); if (y) SET_DECL_VALUE_EXPR (new_vard, y); @@ -9491,9 +9678,12 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, DECL_HAS_VALUE_EXPR_P (new_vard) = 0; SET_DECL_VALUE_EXPR (new_vard, NULL_TREE); } - SET_DECL_VALUE_EXPR (placeholder, new_var); - DECL_HAS_VALUE_EXPR_P (placeholder) = 1; - lower_omp (&tseq, ctx); + if (!is_for_simd) + { + SET_DECL_VALUE_EXPR (placeholder, new_var); + DECL_HAS_VALUE_EXPR_P (placeholder) = 1; + lower_omp (&tseq, ctx); + } gimple_seq_add_seq (&input2_list, tseq); x = build_outer_var_ref (var, ctx); @@ -9532,29 +9722,38 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, else { x = build_outer_var_ref (var, ctx); - gimplify_assign (var2, x, &thr01_list); + gimplify_assign (unshare_expr (var4), x, &thr01_list); x = omp_reduction_init (c, TREE_TYPE (new_var)); - gimplify_assign (var2, unshare_expr (x), &thrn1_list); - gimplify_assign (var2, x, &thr02_list); + gimplify_assign (unshare_expr (var4), unshare_expr (x), + &thrn1_list); + gimplify_assign (unshare_expr (var4), x, &thr02_list); - gimplify_assign (var2, rprivam1_ref, &thrn2_list); + gimplify_assign (unshare_expr (var4), rprivam1_ref, &thrn2_list); enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c); if (code == MINUS_EXPR) code = PLUS_EXPR; - if (ctx->scan_exclusive) - gimplify_assign (unshare_expr (rprivb_ref), var2, &scan1_list); - x = build2 (code, TREE_TYPE (new_var), var2, new_var); - gimplify_assign (var2, x, &scan1_list); - if (ctx->scan_inclusive) - gimplify_assign (unshare_expr (rprivb_ref), var2, &scan1_list); + if (is_for_simd) + gimplify_assign (unshare_expr (rprivb_ref), var5, &scan1_list); + else + { + if (ctx->scan_exclusive) + gimplify_assign (unshare_expr (rprivb_ref), var2, + &scan1_list); + x = build2 (code, TREE_TYPE (new_var), var2, new_var); + gimplify_assign (var2, x, &scan1_list); + if (ctx->scan_inclusive) + gimplify_assign (unshare_expr (rprivb_ref), var2, + &scan1_list); + } - gimplify_assign (unshare_expr (rpriva_ref), var2, &mdlist); + gimplify_assign (unshare_expr (rpriva_ref), unshare_expr (var4), + &mdlist); - x = build2 (code, TREE_TYPE (new_var), var2, rprivb_ref); - gimplify_assign (new_var, x, &input2_list); + x = build2 (code, TREE_TYPE (new_var), var4, rprivb_ref); + gimplify_assign (is_for_simd ? var6 : new_var, x, &input2_list); gimplify_assign (build_outer_var_ref (var, ctx), rpriva_ref, &last_list); @@ -9568,7 +9767,8 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node); gimple_seq_add_stmt (&scan1_list, g); g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node); - gimple_seq_add_stmt (gimple_omp_body_ptr (scan_stmt2), g); + gimple_seq_add_stmt (gimple_omp_body_ptr (is_for_simd + ? scan_stmt4 : scan_stmt2), g); tree controlb = create_tmp_var (boolean_type_node); tree controlp = create_tmp_var (ptr_type_node); @@ -9598,8 +9798,29 @@ lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt, *cp2 = gimple_omp_for_clauses (new_stmt); gimple_omp_for_set_clauses (new_stmt, new_clauses2); - gimple_omp_set_body (scan_stmt1, scan1_list); - gimple_omp_set_body (input_stmt2, input2_list); + if (is_for_simd) + { + gimple_seq_add_seq (gimple_omp_body_ptr (scan_stmt3), scan1_list); + gimple_seq_add_seq (gimple_omp_body_ptr (input_stmt4), input2_list); + + gsi_insert_seq_after (&input3_gsi, gimple_omp_body (input_stmt3), + GSI_SAME_STMT); + gsi_remove (&input3_gsi, true); + gsi_insert_seq_after (&scan3_gsi, gimple_omp_body (scan_stmt3), + GSI_SAME_STMT); + gsi_remove (&scan3_gsi, true); + gsi_insert_seq_after (&input4_gsi, gimple_omp_body (input_stmt4), + GSI_SAME_STMT); + gsi_remove (&input4_gsi, true); + gsi_insert_seq_after (&scan4_gsi, gimple_omp_body (scan_stmt4), + GSI_SAME_STMT); + gsi_remove (&scan4_gsi, true); + } + else + { + gimple_omp_set_body (scan_stmt1, scan1_list); + gimple_omp_set_body (input_stmt2, input2_list); + } gsi_insert_seq_after (&input1_gsi, gimple_omp_body (input_stmt1), GSI_SAME_STMT); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5a848eb..cc0661a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2019-07-06 Jakub Jelinek + * c-c++-common/gomp/scan-4.c: Don't expect sorry message. + PR tree-optimization/91096 * gcc.dg/vect/vect-simd-10.c (FLT_MIN_VALUE): Define. (bar, main): Use it instead of -__builtin_inff (). diff --git a/gcc/testsuite/c-c++-common/gomp/scan-4.c b/gcc/testsuite/c-c++-common/gomp/scan-4.c index 32d4006..b2e22e8 100644 --- a/gcc/testsuite/c-c++-common/gomp/scan-4.c +++ b/gcc/testsuite/c-c++-common/gomp/scan-4.c @@ -8,7 +8,7 @@ f1 (int *c, int *d) for (i = 0; i < 64; i++) { d[i] = a; - #pragma omp scan exclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */ + #pragma omp scan exclusive (a) a += c[i]; } } -- cgit v1.1 From 193bee751a607fac9d85e0ce8e6462fb5de1b515 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 6 Jul 2019 08:25:26 +0000 Subject: [arm] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. I think this is a genuine bugfix for Thumb-1, since previously the LDREX width was taken from the SImode success result rather than the memory mode: -#define HAVE_atomic_compare_and_swapt1qi_1 ((TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER) && (TARGET_THUMB1)) -#define HAVE_atomic_compare_and_swapt1hi_1 ((TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER) && (TARGET_THUMB1)) -#define HAVE_atomic_compare_and_swapt1di_1 ((TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER) && (TARGET_THUMB1)) +#define HAVE_atomic_compare_and_swapt1qi_1 ((TARGET_HAVE_LDREXBH && TARGET_HAVE_MEMORY_BARRIER) && (TARGET_THUMB1)) +#define HAVE_atomic_compare_and_swapt1hi_1 ((TARGET_HAVE_LDREXBH && TARGET_HAVE_MEMORY_BARRIER) && (TARGET_THUMB1)) +#define HAVE_atomic_compare_and_swapt1di_1 ((TARGET_HAVE_LDREXD && ARM_DOUBLEWORD_ALIGN \ + && TARGET_HAVE_MEMORY_BARRIER) && (TARGET_THUMB1)) The same goes for the predicate and constraints in @atomic_compare_and_swapt1di_1, which previously used the SI values from the success result. 2019-07-06 Richard Sandiford gcc/ * config/arm/sync.md (@atomic_compare_and_swap_1): Use instead of (implicitly) . (@atomic_compare_and_swap_1): Likewise . Use and . From-SVN: r273158 --- gcc/ChangeLog | 9 +++++++++ gcc/config/arm/sync.md | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3ce8b90..1ae6b1c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-06 Richard Sandiford + + * config/arm/sync.md + (@atomic_compare_and_swap_1): Use + instead of (implicitly) . + (@atomic_compare_and_swap_1): Likewise + . Use and + . + 2019-07-06 Jakub Jelinek * omp-low.c (struct omp_context): Add for_simd_scan_phase member. diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md index 3d49aef..ed857d6 100644 --- a/gcc/config/arm/sync.md +++ b/gcc/config/arm/sync.md @@ -201,7 +201,7 @@ (match_operand:SI 7 "const_int_operand")] ;; mod_f VUNSPEC_ATOMIC_CAS)) (clobber (match_scratch:SI 8 "=&r,X,X,X"))] - "" + "" "#" "&& reload_completed" [(const_int 0)] @@ -225,14 +225,14 @@ (match_operand:SIDI 2 "mem_noofs_operand" "+Ua,Ua,Ua,Ua")) ;; memory (set (match_dup 2) (unspec_volatile:SIDI - [(match_operand:SIDI 3 "" ",lIL*h,J,*r") ;; expect + [(match_operand:SIDI 3 "" ",lIL*h,J,*r") ;; expect (match_operand:SIDI 4 "s_register_operand" "r,r,r,r") ;; desired (match_operand:SI 5 "const_int_operand") ;; is_weak (match_operand:SI 6 "const_int_operand") ;; mod_s (match_operand:SI 7 "const_int_operand")] ;; mod_f VUNSPEC_ATOMIC_CAS)) (clobber (match_scratch:SI 8 "=&r,X,X,X"))] - "" + "" "#" "&& reload_completed" [(const_int 0)] -- cgit v1.1 From 96eb1765a38dd4074fdbaedef76b8b1fe1d7e175 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 6 Jul 2019 08:26:02 +0000 Subject: [amdgcn] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. I think this is a genuine bugfix for the case in which the 1REG_MODE and 1REG_ALT are different, since previously we would use the 1REG_MODE for both the comparison and the select, even though the operands being compared are 1REG_ALT rather than 1REG_MODE. 2019-07-06 Richard Sandiford gcc/ * config/gcn/gcn-valu.md (vcond): Use gen_vec_cmpdi rather than (implicitly) gen_vec_cmpdi. Explicitly use gen_vcond_mask_di. (vcond_exec): Likewise, but using the _exec comparison patterns. (vcondu): Use gen_vec_cmpdi rather than (implicitly) gen_vec_cmpdi. Explicitly use gen_vcond_mask_di. (vcondu_exec): Likewise, but using the _exec comparison patterns. From-SVN: r273159 --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/config/gcn/gcn-valu.md | 32 ++++++++++++++++---------------- 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1ae6b1c..9dc0e09 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,21 @@ 2019-07-06 Richard Sandiford + * config/gcn/gcn-valu.md + (vcond): Use + gen_vec_cmpdi rather than (implicitly) + gen_vec_cmpdi. Explicitly use + gen_vcond_mask_di. + (vcond_exec): Likewise, + but using the _exec comparison patterns. + (vcondu): Use + gen_vec_cmpdi rather than (implicitly) + gen_vec_cmpdi. Explicitly use + gen_vcond_mask_di. + (vcondu_exec): Likewise, + but using the _exec comparison patterns. + +2019-07-06 Richard Sandiford + * config/arm/sync.md (@atomic_compare_and_swap_1): Use instead of (implicitly) . diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md index 3cc59dd..c7e8b16 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -2574,10 +2574,10 @@ "" { rtx tmp = gen_reg_rtx (DImode); - emit_insn (gen_vec_cmpdi (tmp, operands[3], operands[4], - operands[5])); - emit_insn (gen_vcond_mask_di (operands[0], operands[1], operands[2], - tmp)); + emit_insn (gen_vec_cmpdi + (tmp, operands[3], operands[4], operands[5])); + emit_insn (gen_vcond_mask_di + (operands[0], operands[1], operands[2], tmp)); DONE; }) @@ -2592,10 +2592,10 @@ "" { rtx tmp = gen_reg_rtx (DImode); - emit_insn (gen_vec_cmpdi_exec (tmp, operands[3], operands[4], - operands[5], operands[6])); - emit_insn (gen_vcond_mask_di (operands[0], operands[1], operands[2], - tmp)); + emit_insn (gen_vec_cmpdi_exec + (tmp, operands[3], operands[4], operands[5], operands[6])); + emit_insn (gen_vcond_mask_di + (operands[0], operands[1], operands[2], tmp)); DONE; }) @@ -2609,10 +2609,10 @@ "" { rtx tmp = gen_reg_rtx (DImode); - emit_insn (gen_vec_cmpdi (tmp, operands[3], operands[4], - operands[5])); - emit_insn (gen_vcond_mask_di (operands[0], operands[1], operands[2], - tmp)); + emit_insn (gen_vec_cmpdi + (tmp, operands[3], operands[4], operands[5])); + emit_insn (gen_vcond_mask_di + (operands[0], operands[1], operands[2], tmp)); DONE; }) @@ -2627,10 +2627,10 @@ "" { rtx tmp = gen_reg_rtx (DImode); - emit_insn (gen_vec_cmpdi_exec (tmp, operands[3], operands[4], - operands[5], operands[6])); - emit_insn (gen_vcond_mask_di (operands[0], operands[1], operands[2], - tmp)); + emit_insn (gen_vec_cmpdi_exec + (tmp, operands[3], operands[4], operands[5], operands[6])); + emit_insn (gen_vcond_mask_di + (operands[0], operands[1], operands[2], tmp)); DONE; }) -- cgit v1.1 From 212ecf90de89e3fde0704753dc2b1268a7062f1b Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 6 Jul 2019 08:26:11 +0000 Subject: [h8300] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. No behavioural change -- produces the same code as before. 2019-07-06 Richard Sandiford gcc/ * config/h8300/h8300.md (*push1_h8300hs_): Explicitly specify the mode iterator referenced by , giving... (*push1_h8300hs_): ...this. From-SVN: r273160 --- gcc/ChangeLog | 6 ++++++ gcc/config/h8300/h8300.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9dc0e09..262244db 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-07-06 Richard Sandiford + * config/h8300/h8300.md (*push1_h8300hs_): Explicitly + specify the mode iterator referenced by , giving... + (*push1_h8300hs_): ...this. + +2019-07-06 Richard Sandiford + * config/gcn/gcn-valu.md (vcond): Use gen_vec_cmpdi rather than (implicitly) diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 42610fd..778d3e1 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -728,7 +728,7 @@ "mov.w\\t%T0,@-r7" [(set_attr "length" "2")]) -(define_insn "*push1_h8300hs_" +(define_insn "*push1_h8300hs_" [(set (mem:QHI (pre_modify:P (reg:P SP_REG) -- cgit v1.1 From a0cb70b7ea2b522f02a2384fbe1103d69904f916 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 6 Jul 2019 08:26:33 +0000 Subject: [i386] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. No behavioural change except for dropping the unused *andnot3_bcst permutations. 2019-07-06 Richard Sandiford gcc/ * config/i386/i386.md (*fop__3_i387) (l2): Fix ambiguous uses of .md attributes. * config/i386/sse.md (*avx512pf_gatherpfsf_mask) (*avx512pf_gatherpfdf_mask, *avx512pf_scatterpfsf_mask) (*avx512pf_scatterpfdf_mask, *avx2_gathersi) (*avx2_gathersi_2, *avx2_gatherdi) (*avx2_gatherdi_2, *avx2_gatherdi_3): Likewise. (*avx2_gatherdi_4, *avx512f_gathersi): Likewise. (*avx512f_gathersi_2, *avx512f_gatherdi): Likewise. (*avx512f_gatherdi_2, *avx512f_scattersi): Likewise. (*avx512f_scatterdi): Likewise. (*andnot3_bcst): Fix VI/VI48_AVX512VL typo. From-SVN: r273161 --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/config/i386/i386.md | 4 ++-- gcc/config/i386/sse.md | 42 +++++++++++++++++++++--------------------- 3 files changed, 39 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 262244db..1b318b9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,21 @@ 2019-07-06 Richard Sandiford + * config/i386/i386.md (*fop__3_i387) + (l2): Fix ambiguous uses + of .md attributes. + * config/i386/sse.md (*avx512pf_gatherpfsf_mask) + (*avx512pf_gatherpfdf_mask, *avx512pf_scatterpfsf_mask) + (*avx512pf_scatterpfdf_mask, *avx2_gathersi) + (*avx2_gathersi_2, *avx2_gatherdi) + (*avx2_gatherdi_2, *avx2_gatherdi_3): Likewise. + (*avx2_gatherdi_4, *avx512f_gathersi): Likewise. + (*avx512f_gathersi_2, *avx512f_gatherdi): Likewise. + (*avx512f_gatherdi_2, *avx512f_scattersi): Likewise. + (*avx512f_scatterdi): Likewise. + (*andnot3_bcst): Fix VI/VI48_AVX512VL typo. + +2019-07-06 Richard Sandiford + * config/h8300/h8300.md (*push1_h8300hs_): Explicitly specify the mode iterator referenced by , giving... (*push1_h8300hs_): ...this. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c401deb..db5fa9a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -14755,7 +14755,7 @@ ] (const_string "fop"))) (set_attr "fp_int_src" "true") - (set_attr "mode" "")]) + (set_attr "mode" "")]) (define_insn "*fop_xf_4_i387" [(set (match_operand:XF 0 "register_operand" "=f,f") @@ -16457,7 +16457,7 @@ { rtx tmp = gen_reg_rtx (mode); - emit_insn (gen_sse4_1_round2 + emit_insn (gen_sse4_1_round2 (tmp, operands[1], GEN_INT (ROUND_ | ROUND_NO_EXC))); emit_insn (gen_fix_trunc2 diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 3fa4560..3ce2239 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -12702,8 +12702,8 @@ (const_string "")))]) (define_insn "*andnot3_bcst" - [(set (match_operand:VI 0 "register_operand" "=v") - (and:VI + [(set (match_operand:VI48_AVX512VL 0 "register_operand" "=v") + (and:VI48_AVX512VL (not:VI48_AVX512VL (match_operand:VI48_AVX512VL 1 "register_operand" "v")) (vec_duplicate:VI48_AVX512VL @@ -18084,7 +18084,7 @@ operands[3]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512pf_gatherpfsf_mask" +(define_insn "*avx512pf_gatherpfsf_mask" [(unspec [(match_operand: 0 "register_operand" "Yk") (match_operator: 5 "vsib_mem_operator" @@ -18131,7 +18131,7 @@ operands[3]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512pf_gatherpfdf_mask" +(define_insn "*avx512pf_gatherpfdf_mask" [(unspec [(match_operand: 0 "register_operand" "Yk") (match_operator:V8DF 5 "vsib_mem_operator" @@ -18178,7 +18178,7 @@ operands[3]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512pf_scatterpfsf_mask" +(define_insn "*avx512pf_scatterpfsf_mask" [(unspec [(match_operand: 0 "register_operand" "Yk") (match_operator: 5 "vsib_mem_operator" @@ -18227,7 +18227,7 @@ operands[3]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512pf_scatterpfdf_mask" +(define_insn "*avx512pf_scatterpfdf_mask" [(unspec [(match_operand: 0 "register_operand" "Yk") (match_operator:V8DF 5 "vsib_mem_operator" @@ -21016,7 +21016,7 @@ operands[5]), UNSPEC_VSIBADDR); }) -(define_insn "*avx2_gathersi" +(define_insn "*avx2_gathersi" [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=&x") (unspec:VEC_GATHER_MODE [(match_operand:VEC_GATHER_MODE 2 "register_operand" "0") @@ -21036,7 +21036,7 @@ (set_attr "prefix" "vex") (set_attr "mode" "")]) -(define_insn "*avx2_gathersi_2" +(define_insn "*avx2_gathersi_2" [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=&x") (unspec:VEC_GATHER_MODE [(pc) @@ -21077,7 +21077,7 @@ operands[5]), UNSPEC_VSIBADDR); }) -(define_insn "*avx2_gatherdi" +(define_insn "*avx2_gatherdi" [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=&x") (unspec:VEC_GATHER_MODE [(match_operand: 2 "register_operand" "0") @@ -21097,7 +21097,7 @@ (set_attr "prefix" "vex") (set_attr "mode" "")]) -(define_insn "*avx2_gatherdi_2" +(define_insn "*avx2_gatherdi_2" [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=&x") (unspec:VEC_GATHER_MODE [(pc) @@ -21113,7 +21113,7 @@ (clobber (match_scratch:VEC_GATHER_MODE 1 "=&x"))] "TARGET_AVX2" { - if (mode != mode) + if (mode != mode) return "%M2vgatherq\t{%4, %6, %x0|%x0, %6, %4}"; return "%M2vgatherq\t{%4, %6, %0|%0, %6, %4}"; } @@ -21121,7 +21121,7 @@ (set_attr "prefix" "vex") (set_attr "mode" "")]) -(define_insn "*avx2_gatherdi_3" +(define_insn "*avx2_gatherdi_3" [(set (match_operand: 0 "register_operand" "=&x") (vec_select: (unspec:VI4F_256 @@ -21144,7 +21144,7 @@ (set_attr "prefix" "vex") (set_attr "mode" "")]) -(define_insn "*avx2_gatherdi_4" +(define_insn "*avx2_gatherdi_4" [(set (match_operand: 0 "register_operand" "=&x") (vec_select: (unspec:VI4F_256 @@ -21186,7 +21186,7 @@ operands[5]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512f_gathersi" +(define_insn "*avx512f_gathersi" [(set (match_operand:VI48F 0 "register_operand" "=&v") (unspec:VI48F [(match_operand:VI48F 1 "register_operand" "0") @@ -21207,7 +21207,7 @@ (set_attr "prefix" "evex") (set_attr "mode" "")]) -(define_insn "*avx512f_gathersi_2" +(define_insn "*avx512f_gathersi_2" [(set (match_operand:VI48F 0 "register_operand" "=&v") (unspec:VI48F [(pc) @@ -21248,7 +21248,7 @@ operands[5]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512f_gatherdi" +(define_insn "*avx512f_gatherdi" [(set (match_operand:VI48F 0 "register_operand" "=&v") (unspec:VI48F [(match_operand: 1 "register_operand" "0") @@ -21269,7 +21269,7 @@ (set_attr "prefix" "evex") (set_attr "mode" "")]) -(define_insn "*avx512f_gatherdi_2" +(define_insn "*avx512f_gatherdi_2" [(set (match_operand:VI48F 0 "register_operand" "=&v") (unspec:VI48F [(pc) @@ -21286,9 +21286,9 @@ { /* %X5 so that we don't emit any *WORD PTR for -masm=intel, as gas changed what it requires incompatibly. */ - if (mode != mode) + if (mode != mode) { - if ( != 64) + if ( != 64) return "%M3vgatherq\t{%5, %x0%{%1%}|%x0%{%1%}, %X5}"; else return "%M3vgatherq\t{%5, %t0%{%1%}|%t0%{%1%}, %X5}"; @@ -21317,7 +21317,7 @@ operands[4]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512f_scattersi" +(define_insn "*avx512f_scattersi" [(set (match_operator:VI48F 5 "vsib_mem_operator" [(unspec:P [(match_operand:P 0 "vsib_address_operand" "Tv") @@ -21355,7 +21355,7 @@ operands[4]), UNSPEC_VSIBADDR); }) -(define_insn "*avx512f_scatterdi" +(define_insn "*avx512f_scatterdi" [(set (match_operator:VI48F 5 "vsib_mem_operator" [(unspec:P [(match_operand:P 0 "vsib_address_operand" "Tv") -- cgit v1.1 From ef2df51671bb6c755302ffe8e36eae0755882ad2 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 6 Jul 2019 08:26:44 +0000 Subject: [s390] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. The vx-builtins.md part changes the choice of from the implicit to an explicit (i.e. from the mode of the comparison result to the mode of the operands being compared). That seemed like the intended behaviour given later patterns like vec_cmpeq_cc. The use of BFP in the s390.md LNDFR pattern looks like a typo, since the operand to (abs ...) has to have the same mode as the result. The only effect before this series was to create some extra variants that would never match, making it harmless apart from very minor code bloat. 2019-07-06 Richard Sandiford gcc/ * config/s390/s390.md (*negabs2_nocc): Use FP for operand 1. * config/s390/vx-builtins.md (*vec_cmp_cconly): Make the choice of explicit, giving... (*vec_cmp_cconly): ...this. From-SVN: r273162 --- gcc/ChangeLog | 8 ++++++++ gcc/config/s390/s390.md | 4 ++-- gcc/config/s390/vx-builtins.md | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b318b9..3694a77 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2019-07-06 Richard Sandiford + * config/s390/s390.md (*negabs2_nocc): Use FP for + operand 1. + * config/s390/vx-builtins.md (*vec_cmp_cconly): + Make the choice of explicit, giving... + (*vec_cmp_cconly): ...this. + +2019-07-06 Richard Sandiford + * config/i386/i386.md (*fop__3_i387) (l2): Fix ambiguous uses of .md attributes. diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index d06aea9..79451d7 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -8821,8 +8821,8 @@ ; lndfr (define_insn "*negabs2_nocc" - [(set (match_operand:FP 0 "register_operand" "=f") - (neg:FP (abs:FP (match_operand:BFP 1 "register_operand" ""))))] + [(set (match_operand:FP 0 "register_operand" "=f") + (neg:FP (abs:FP (match_operand:FP 1 "register_operand" ""))))] "TARGET_DFP" "lndfr\t%0,%1" [(set_attr "op_type" "RRE") diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md index 3020bc9..c71aae0 100644 --- a/gcc/config/s390/vx-builtins.md +++ b/gcc/config/s390/vx-builtins.md @@ -2046,7 +2046,7 @@ ;; ; vfcesbs, vfcedbs, wfcexbs, vfchsbs, vfchdbs, wfchxbs, vfchesbs, vfchedbs, wfchexbs -(define_insn "*vec_cmp_cconly" +(define_insn "*vec_cmp_cconly" [(set (reg:VFCMP CC_REGNUM) (compare:VFCMP (match_operand:VF_HW 0 "register_operand" "v") (match_operand:VF_HW 1 "register_operand" "v"))) -- cgit v1.1 From 94e14f2e90e3c13894f3b1df39cd1f28f1081d3b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 6 Jul 2019 23:56:46 +0200 Subject: omp-low.c (struct omp_context): Rename combined_into_simd_safelen0 member to combined_into_simd_safelen1. * omp-low.c (struct omp_context): Rename combined_into_simd_safelen0 member to combined_into_simd_safelen1. (lower_rec_input_clauses, lower_omp_1): Adjust uses. (lower_lastprivate_clauses): Likewise. For conditional lastprivate clauses if ctx->combined_into_simd_safelen1 put statements after the predicate conditionalized block rather than into it. From-SVN: r273168 --- gcc/ChangeLog | 9 +++++++++ gcc/omp-low.c | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3694a77..ae3fbe4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-06 Jakub Jelinek + + * omp-low.c (struct omp_context): Rename combined_into_simd_safelen0 + member to combined_into_simd_safelen1. + (lower_rec_input_clauses, lower_omp_1): Adjust uses. + (lower_lastprivate_clauses): Likewise. For conditional lastprivate + clauses if ctx->combined_into_simd_safelen1 put statements after the + predicate conditionalized block rather than into it. + 2019-07-06 Richard Sandiford * config/s390/s390.md (*negabs2_nocc): Use FP for diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 5d5fb6a..b687fe1 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -140,7 +140,7 @@ struct omp_context /* True if lower_omp_1 should look up lastprivate conditional in parent context. */ - bool combined_into_simd_safelen0; + bool combined_into_simd_safelen1; /* True if there is nested scan context with inclusive clause. */ bool scan_inclusive; @@ -5703,7 +5703,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (gimple_omp_for_combined_into_p (ctx->stmt)) { /* Signal to lower_omp_1 that it should use parent context. */ - ctx->combined_into_simd_safelen0 = true; + ctx->combined_into_simd_safelen1 = true; for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)) @@ -6018,6 +6018,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p, bool par_clauses = false; tree simduid = NULL, lastlane = NULL, simtcond = NULL, simtlast = NULL; unsigned HOST_WIDE_INT conditional_off = 0; + gimple_seq post_stmt_list = NULL; /* Early exit if there are no lastprivate or linear clauses. */ for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses)) @@ -6107,7 +6108,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p, if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && ctx->lastprivate_conditional_map - && !ctx->combined_into_simd_safelen0) + && !ctx->combined_into_simd_safelen1) { gcc_assert (body_p); if (simduid) @@ -6144,6 +6145,12 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p, gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab1)); gimplify_assign (mem2, v, this_stmt_list); } + else if (predicate + && ctx->combined_into_simd_safelen1 + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE + && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) + && ctx->lastprivate_conditional_map) + this_stmt_list = &post_stmt_list; if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR @@ -6274,6 +6281,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p, if (label) gimple_seq_add_stmt (stmt_list, gimple_build_label (label)); + gimple_seq_add_seq (stmt_list, post_stmt_list); } /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL @@ -12412,7 +12420,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx) if (tree *v = up->lastprivate_conditional_map->get (lhs)) { tree clauses; - if (up->combined_into_simd_safelen0) + if (up->combined_into_simd_safelen1) up = up->outer; if (gimple_code (up->stmt) == GIMPLE_OMP_FOR) clauses = gimple_omp_for_clauses (up->stmt); -- cgit v1.1 From 6f67abcdb04285553226b82f689f876222f0d38b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 6 Jul 2019 23:58:01 +0200 Subject: omp-low.c (lower_rec_input_clauses): For lastprivate clauses in ctx->for_simd_scan_phase simd copy the outer var to... * omp-low.c (lower_rec_input_clauses): For lastprivate clauses in ctx->for_simd_scan_phase simd copy the outer var to the privatized variable(s). For conditional lastprivate look through outer GIMPLE_OMP_SCAN context. (lower_omp_1): For conditional lastprivate look through outer GIMPLE_OMP_SCAN context. * testsuite/libgomp.c/scan-19.c: New test. * testsuite/libgomp.c/scan-20.c: New test. From-SVN: r273169 --- gcc/ChangeLog | 7 +++++++ gcc/omp-low.c | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ae3fbe4..edb8df5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2019-07-06 Jakub Jelinek + * omp-low.c (lower_rec_input_clauses): For lastprivate clauses in + ctx->for_simd_scan_phase simd copy the outer var to the privatized + variable(s). For conditional lastprivate look through outer + GIMPLE_OMP_SCAN context. + (lower_omp_1): For conditional lastprivate look through outer + GIMPLE_OMP_SCAN context. + * omp-low.c (struct omp_context): Rename combined_into_simd_safelen0 member to combined_into_simd_safelen1. (lower_rec_input_clauses, lower_omp_1): Adjust uses. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index b687fe1..3fe466f 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -5006,6 +5006,17 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, lower_omp (&tseq, ctx->outer); gimple_seq_add_seq (&llist[1], tseq); } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE + && ctx->for_simd_scan_phase) + { + x = unshare_expr (ivar); + tree orig_v + = build_outer_var_ref (var, ctx, + OMP_CLAUSE_LASTPRIVATE); + x = lang_hooks.decls.omp_clause_assign_op (c, x, + orig_v); + gimplify_and_add (x, &llist[0]); + } if (y) { y = lang_hooks.decls.omp_clause_dtor (c, ivar); @@ -5035,6 +5046,16 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, } if (nx) gimplify_and_add (nx, ilist); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE + && is_simd + && ctx->for_simd_scan_phase) + { + tree orig_v = build_outer_var_ref (var, ctx, + OMP_CLAUSE_LASTPRIVATE); + x = lang_hooks.decls.omp_clause_assign_op (c, new_var, + orig_v); + gimplify_and_add (x, ilist); + } /* FALLTHRU */ do_dtor: @@ -5709,11 +5730,12 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)) { tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx); - tree *v - = ctx->lastprivate_conditional_map->get (o); - tree po = lookup_decl (OMP_CLAUSE_DECL (c), ctx->outer); - tree *pv - = ctx->outer->lastprivate_conditional_map->get (po); + omp_context *outer = ctx->outer; + if (gimple_code (outer->stmt) == GIMPLE_OMP_SCAN) + outer = outer->outer; + tree *v = ctx->lastprivate_conditional_map->get (o); + tree po = lookup_decl (OMP_CLAUSE_DECL (c), outer); + tree *pv = outer->lastprivate_conditional_map->get (po); *v = *pv; } } @@ -12421,7 +12443,11 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx) { tree clauses; if (up->combined_into_simd_safelen1) - up = up->outer; + { + up = up->outer; + if (gimple_code (up->stmt) == GIMPLE_OMP_SCAN) + up = up->outer; + } if (gimple_code (up->stmt) == GIMPLE_OMP_FOR) clauses = gimple_omp_for_clauses (up->stmt); else -- cgit v1.1 From 389aba0d2d8b437002017f9636676a81241140eb Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 7 Jul 2019 00:16:21 +0000 Subject: Daily bump. From-SVN: r273173 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 739e0ea..d85bcc5 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190706 +20190707 -- cgit v1.1 From f40ce450f3c4b1cfd0a7e9c68e0c2a60d04b2a03 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 7 Jul 2019 09:49:14 +0000 Subject: Fix uninitialised use in mips_split_move While testing the fix for PR91068, I hit an rtl checking failure while building newlib. mips_split_move was decomposing an address that happened to be symbolic and then tried to access the REGNO of the base register field, which wasn't initialised but which by chance pointed to valid memory. 2019-07-07 Richard Sandiford gcc/ * config/mips/mips.c (mips_split_move): Zero-initialize addr and check whether addr.reg is nonnull before using it. From-SVN: r273174 --- gcc/ChangeLog | 5 +++++ gcc/config/mips/mips.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index edb8df5..13622c8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-07 Richard Sandiford + + * config/mips/mips.c (mips_split_move): Zero-initialize addr + and check whether addr.reg is nonnull before using it. + 2019-07-06 Jakub Jelinek * omp-low.c (lower_rec_input_clauses): For lastprivate clauses in diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index cbebb45..e0535b1 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -4849,7 +4849,7 @@ mips_split_move (rtx dest, rtx src, enum mips_split_type split_type, rtx insn_) can forward SRC for DEST. This is most useful if the next insn is a simple store. */ rtx_insn *insn = (rtx_insn *)insn_; - struct mips_address_info addr; + struct mips_address_info addr = {}; if (insn) { rtx_insn *next = next_nonnote_nondebug_insn_bb (insn); @@ -4862,7 +4862,7 @@ mips_split_move (rtx dest, rtx src, enum mips_split_type split_type, rtx insn_) { rtx tmp = XEXP (src, 0); mips_classify_address (&addr, tmp, GET_MODE (tmp), true); - if (REGNO (addr.reg) != REGNO (dest)) + if (addr.reg && REGNO (addr.reg) != REGNO (dest)) validate_change (next, &SET_SRC (set), src, false); } else -- cgit v1.1 From 0b3839a4b267858948f0d2fe9ec600129d5d14b4 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 7 Jul 2019 09:49:24 +0000 Subject: PR91068: Fix MIPS fallout from IRA matched operand changes PR91068 is a case in which we have (ignoring non-LRA alternatives): [(set (match_operand:SI 0 "register_operand" "=l,d?") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "register_operand" "d,d")) (match_operand:SI 3 "register_operand" "0,d"))) (clobber (match_scratch:SI 4 "=X,l")) (clobber (match_scratch:SI 5 "=X,&d"))] where the first alternative is one instruction but the second is two. This is very similar to the case that my recent IRA patches were supposed to help. The crucial difference is that the cheap alternative requires a single-register class while the expensive alternative uses general registers. This makes a difference when one of operand 0 or 3 can naturally be allocated to LO but the other can't. If IRA makes that allocation, both alternatives require one reload of equal cost and so the first alternative clearly wins. However, if we say that tying operands 0 and 3 saves the cost of a full move, then all other things being equal, IRA will prefer to allocate both registers to the same GPR. The registers will then naturally fit the second alternative. This has a more drastic effect in the MIPS case than it should because using the GPR alternative is much more expensive there than it appears to the RA. But that's really a separate problem and something we were able to live with before my IRA patch. What makes tying less useful here is the fact that the tied register is a single-register class. I think in those circumstances it's better not to use tied operands at all and instead use "l" for the inputs. Allocating the input to LO, and allocating the output to LO, then depend naturally on class costs. If we decide to allocate at least one of them to LO, we'll use the cheap alternative, otherwise we'll (correctly) use the expensive alternative. This effectively restores the situation before my IRA patch, but this time making the preference on the input register more explicit. I originally wrote the patterns in the early days of IRA, and certainly well before LRA. I think they were largely influened by reload rather than RA proper (see the comment above *mul_acc_si, which is all about the reload behaviour). LRA copes with the two-"l" case just fine. The patch may well cause problems for -mno-lra, but I think we should cull that option anyway. 2019-07-07 Richard Sandiford gcc/ PR target/91068 * config/mips/mips.md (*mul_acc_si, *mul_acc_si_r3900, *macc) (*msac, *msac_using_macc, *mul_sub_si): Use "l" for input operands instead of matching them to "l" output operands. From-SVN: r273175 --- gcc/ChangeLog | 7 +++++++ gcc/config/mips/mips.md | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 13622c8..802cdb8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2019-07-07 Richard Sandiford + PR target/91068 + * config/mips/mips.md (*mul_acc_si, *mul_acc_si_r3900, *macc) + (*msac, *msac_using_macc, *mul_sub_si): Use "l" for input operands + instead of matching them to "l" output operands. + +2019-07-07 Richard Sandiford + * config/mips/mips.c (mips_split_move): Zero-initialize addr and check whether addr.reg is nonnull before using it. diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index d260cf9..e17b1d5 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1749,7 +1749,7 @@ [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d?") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") (match_operand:SI 2 "register_operand" "d,d,d")) - (match_operand:SI 3 "register_operand" "0,0,d"))) + (match_operand:SI 3 "register_operand" "l,l,d"))) (clobber (match_scratch:SI 4 "=X,X,l")) (clobber (match_scratch:SI 5 "=X,X,&d"))] "GENERATE_MADD_MSUB && !TARGET_MIPS16" @@ -1778,7 +1778,7 @@ [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d*?,d?") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d,d") (match_operand:SI 2 "register_operand" "d,d,d,d")) - (match_operand:SI 3 "register_operand" "0,0,l,d"))) + (match_operand:SI 3 "register_operand" "l,l,l,d"))) (clobber (match_scratch:SI 4 "=X,X,3,l")) (clobber (match_scratch:SI 5 "=X,X,X,&d"))] "TARGET_MIPS3900 && !TARGET_MIPS16" @@ -1822,7 +1822,7 @@ [(set (match_operand:SI 0 "register_operand" "=l,d") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "register_operand" "d,d")) - (match_operand:SI 3 "register_operand" "0,l"))) + (match_operand:SI 3 "register_operand" "l,l"))) (clobber (match_scratch:SI 4 "=X,3"))] "ISA_HAS_MACC" { @@ -1842,7 +1842,7 @@ (define_insn "*msac" [(set (match_operand:SI 0 "register_operand" "=l,d") - (minus:SI (match_operand:SI 1 "register_operand" "0,l") + (minus:SI (match_operand:SI 1 "register_operand" "l,l") (mult:SI (match_operand:SI 2 "register_operand" "d,d") (match_operand:SI 3 "register_operand" "d,d")))) (clobber (match_scratch:SI 4 "=X,1"))] @@ -1862,7 +1862,7 @@ ;; An msac-like instruction implemented using negation and a macc. (define_insn_and_split "*msac_using_macc" [(set (match_operand:SI 0 "register_operand" "=l,d") - (minus:SI (match_operand:SI 1 "register_operand" "0,l") + (minus:SI (match_operand:SI 1 "register_operand" "l,l") (mult:SI (match_operand:SI 2 "register_operand" "d,d") (match_operand:SI 3 "register_operand" "d,d")))) (clobber (match_scratch:SI 4 "=X,1")) @@ -2005,7 +2005,7 @@ ;; See the comment above *mul_add_si for details. (define_insn "*mul_sub_si" [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d?") - (minus:SI (match_operand:SI 1 "register_operand" "0,0,d") + (minus:SI (match_operand:SI 1 "register_operand" "l,l,d") (mult:SI (match_operand:SI 2 "register_operand" "d,d,d") (match_operand:SI 3 "register_operand" "d,d,d")))) (clobber (match_scratch:SI 4 "=X,X,l")) -- cgit v1.1 From 94f3d11cfaa27dbac96f5edd48839b884a5c1ef5 Mon Sep 17 00:00:00 2001 From: Paul Thomas Date: Sun, 7 Jul 2019 10:53:37 +0000 Subject: re PR fortran/91077 (Wrong indexing when using a pointer) 2019-07-07 Paul Thomas PR fortran/91077 * trans-array.c (gfc_conv_scalarized_array_ref) Delete code that gave symbol backend decl for subref arrays and deferred length variables. 2019-07-07 Paul Thomas PR fortran/91077 * gfortran.dg/pointer_array_11.f90 : New test. From-SVN: r273176 --- gcc/fortran/ChangeLog | 11 +++- gcc/fortran/trans-array.c | 17 +---- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gfortran.dg/pointer_array_11.f90 | 90 ++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/pointer_array_11.f90 (limited to 'gcc') diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 14ec845..0376f00 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,10 @@ +2019-07-07 Paul Thomas + + PR fortran/91077 + * trans-array.c (gfc_conv_scalarized_array_ref) Delete code + that gave symbol backend decl for subref arrays and deferred + length variables. + 2019-07-05 Andrew Stubbs * openmp.c (resolve_omp_clauses): Add custom error messages for @@ -33,9 +40,9 @@ ChangeLog forgotten with revision 272667 * decl.c (access_attr_decl): Use temporary variable to reduce unreadability of code. Normalize jumping to return. - (gfc_match_protected): Fix parsing error. Add comments to + (gfc_match_protected): Fix parsing error. Add comments to explain code. Remove dead code. - (gfc_match_private): Use temporary variable to reduce unreadability + (gfc_match_private): Use temporary variable to reduce unreadability of code. Fix parsing error. Move code to test for blank PRIVATE. Remove dead code. (gfc_match_public): Move code to test for blank PUBLIC. Fix diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 1ab0361..c8d74e5 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -3502,19 +3502,7 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar) return; if (get_CFI_desc (NULL, expr, &decl, ar)) - { - decl = build_fold_indirect_ref_loc (input_location, decl); - goto done; - } - - if (expr && ((is_subref_array (expr) - && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor))) - || (expr->ts.deferred && (expr->expr_type == EXPR_VARIABLE - || expr->expr_type == EXPR_FUNCTION)))) - decl = expr->symtree->n.sym->backend_decl; - - if (decl && GFC_DECL_PTR_ARRAY_P (decl)) - goto done; + decl = build_fold_indirect_ref_loc (input_location, decl); /* A pointer array component can be detected from its field decl. Fix the descriptor, mark the resulting variable decl and pass it to @@ -3532,7 +3520,6 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar) decl = info->descriptor; } -done: se->expr = gfc_build_array_ref (base, index, decl); } @@ -7865,7 +7852,7 @@ array_parameter_size (tree desc, gfc_expr *expr, tree *size) } /* Helper function - return true if the argument is a pointer. */ - + static bool is_pointer (gfc_expr *e) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cc0661a..12e5bc1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-07 Paul Thomas + + PR fortran/91077 + * gfortran.dg/pointer_array_11.f90 : New test. + 2019-07-06 Jakub Jelinek * c-c++-common/gomp/scan-4.c: Don't expect sorry message. diff --git a/gcc/testsuite/gfortran.dg/pointer_array_11.f90 b/gcc/testsuite/gfortran.dg/pointer_array_11.f90 new file mode 100644 index 0000000..11885ae --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pointer_array_11.f90 @@ -0,0 +1,90 @@ +! { dg-do run } +! +! Test the fix for PR91077 - both the original test and that in comment #4 of the PR. +! +! Contribute by Ygal Klein +! +program test + implicit none + call original + call comment_4 +contains + subroutine original + integer, parameter :: length = 9 + real(8), dimension(2) :: a, b + integer :: i + type point + real(8) :: x + end type point + + type stored + type(point), dimension(:), allocatable :: np + end type stored + type(stored), dimension(:), pointer :: std =>null() + allocate(std(1)) + allocate(std(1)%np(length)) + std(1)%np(1)%x = 0.3d0 + std(1)%np(2)%x = 0.3555d0 + std(1)%np(3)%x = 0.26782d0 + std(1)%np(4)%x = 0d0 + std(1)%np(5)%x = 1.555d0 + std(1)%np(6)%x = 7.3d0 + std(1)%np(7)%x = 7.8d0 + std(1)%np(8)%x = 6.3d0 + std(1)%np(9)%x = 5.5d0 +! do i = 1, 2 +! write(*, "('std(1)%np(',i1,')%x = ',1e22.14)") i, std(1)%np(i)%x +! end do +! do i = 1, 2 +! write(*, "('std(1)%np(1:',i1,') = ',9e22.14)") i, std(1)%np(1:i)%x +! end do + a = std(1)%np(1:2)%x + b = [std(1)%np(1)%x, std(1)%np(2)%x] +! print *,a +! print *,b + if (allocated (std(1)%np)) deallocate (std(1)%np) + if (associated (std)) deallocate (std) + if (norm2(a - b) .gt. 1d-3) stop 1 + end subroutine + + subroutine comment_4 + integer, parameter :: length = 2 + real(8), dimension(length) :: a, b + integer :: i + + type point + real(8) :: x + end type point + + type points + type(point), dimension(:), pointer :: np=>null() + end type points + + type stored + integer :: l + type(points), pointer :: nfpoint=>null() + end type stored + + type(stored), dimension(:), pointer :: std=>null() + + + allocate(std(1)) + allocate(std(1)%nfpoint) + allocate(std(1)%nfpoint%np(length)) + std(1)%nfpoint%np(1)%x = 0.3d0 + std(1)%nfpoint%np(2)%x = 0.3555d0 + +! do i = 1, length +! write(*, "('std(1)%nfpoint%np(',i1,')%x = ',1e22.14)") i, std(1)%nfpoint%np(i)%x +! end do +! do i = 1, length +! write(*, "('std(1)%nfpoint%np(1:',i1,')%x = ',2e22.14)") i, std(1)%nfpoint%np(1:i)%x +! end do + a = std(1)%nfpoint%np(1:2)%x + b = [std(1)%nfpoint%np(1)%x, std(1)%nfpoint%np(2)%x] + if (associated (std(1)%nfpoint%np)) deallocate (std(1)%nfpoint%np) + if (associated (std(1)%nfpoint)) deallocate (std(1)%nfpoint) + if (associated (std)) deallocate (std) + if (norm2(a - b) .gt. 1d-3) stop 2 + end subroutine +end program test -- cgit v1.1 From 2ea649341aa927c126f26642490147871d10a00f Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sun, 7 Jul 2019 16:29:32 +0000 Subject: [Darwin] Don't jam symbol stubs on for kernel code. For PPC Darwin, we need the JBSR long jump code to be enabled when generating kernel code. Now we have that handled in rs6000.c, we can drop the conflated setting in the common code. Symbol stubs are not generated for any X86 case. 2019-07-07 Iain Sandoe * config/darwin.c (darwin_override_options): Don't jam symbol stubs on for kernel code. From-SVN: r273180 --- gcc/ChangeLog | 5 +++++ gcc/config/darwin.c | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 802cdb8..39da4f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-07 Iain Sandoe + + * config/darwin.c (darwin_override_options): Don't jam symbol stubs + on for kernel code. + 2019-07-07 Richard Sandiford PR target/91068 diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index ef6e389..02bcf01 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -3232,8 +3232,6 @@ darwin_override_options (void) /* so no tables either.. */ flag_unwind_tables = 0; flag_asynchronous_unwind_tables = 0; - /* We still need to emit branch islands for kernel context. */ - darwin_picsymbol_stubs = true; } if (flag_var_tracking_uninit == 0 -- cgit v1.1 From 21f94af93a884ba2393b3877d7259922ca7522f3 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sun, 7 Jul 2019 16:34:15 +0000 Subject: [Darwin] Make a final check on PIC options. Final check on PCI options; for Darwin these are not dependent on the PIE ones, although PIE does require PIC to support it. Specifically, for Darwin, "fPIC fno-PIE" should result in the same as "-fno-PIE -fPIC". 2019-07-07 Iain Sandoe * config/darwin.c (darwin_override_options): Make a final check on PIC options. From-SVN: r273181 --- gcc/ChangeLog | 5 +++++ gcc/config/darwin.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 39da4f2..0ef7eb6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2019-07-07 Iain Sandoe + * config/darwin.c (darwin_override_options): Make a final check on PIC + options. + +2019-07-07 Iain Sandoe + * config/darwin.c (darwin_override_options): Don't jam symbol stubs on for kernel code. diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 02bcf01..5ac0925 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -3241,6 +3241,8 @@ darwin_override_options (void) && write_symbols == DWARF2_DEBUG) flag_var_tracking_uninit = flag_var_tracking; + /* Final check on PCI options; for Darwin these are not dependent on the PIE + ones, although PIE does require PIC to support it. */ if (MACHO_DYNAMIC_NO_PIC_P) { if (flag_pic) @@ -3249,9 +3251,11 @@ darwin_override_options (void) " %<-fpie%> or %<-fPIE%>"); flag_pic = 0; } - else if (flag_pic == 1) + else if (flag_pic == 1 + || (flag_pic == 0 && !(flag_mkernel || flag_apple_kext))) { - /* Darwin's -fpic is -fPIC. */ + /* Darwin's -fpic is -fPIC. + We only support "static" code in the kernel and kernel exts. */ flag_pic = 2; } -- cgit v1.1 From 6ce4dac81392bb6f144c34a06e9be157c20f31da Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sun, 7 Jul 2019 18:37:36 +0200 Subject: rs6000: Delete Ffre It is unused. * config/rs6000/rs6000.md (Ffre): Delete. From-SVN: r273182 --- gcc/config/rs6000/rs6000.md | 1 - 1 file changed, 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 503f91a..e1f0b0a 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -545,7 +545,6 @@ (define_mode_attr Fisa [(SF "p8v") (DF "*") (DI "*")]) ; FRE/FRES support -(define_mode_attr Ffre [(SF "fres") (DF "fre")]) (define_mode_attr FFRE [(SF "FRES") (DF "FRE")]) ; Conditional returns. -- cgit v1.1 From 0411f1d6cb283b68e85d41fae7601d6a3e0a9954 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Sun, 7 Jul 2019 12:42:45 -0600 Subject: re PR tree-optimization/91090 (A suspicious code in tree-ssa-dom.c) PR tree-optimization/91090 * tree-ssa-dom.c (simplify_stmt_for_jump_threading): Fix logic error in handling of ranges to simplify switch statements. From-SVN: r273184 --- gcc/ChangeLog | 6 ++++++ gcc/tree-ssa-dom.c | 11 ++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0ef7eb6..9f83f75 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-07 Jeff Law + + PR tree-optimization/91090 + * tree-ssa-dom.c (simplify_stmt_for_jump_threading): Fix logic error + in handling of ranges to simplify switch statements. + 2019-07-07 Iain Sandoe * config/darwin.c (darwin_override_options): Make a final check on PIC diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index b0d56fc..17c852d 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -913,21 +913,26 @@ simplify_stmt_for_jump_threading (gimple *stmt, find_case_label_range (switch_stmt, vr->min (), vr->max (), &i, &j); + /* Is there only one such label? */ if (i == j) { tree label = gimple_switch_label (switch_stmt, i); tree singleton; + /* The i'th label will only be taken if the value range of the + operand is entirely within the bounds of this label. */ if (CASE_HIGH (label) != NULL_TREE ? (tree_int_cst_compare (CASE_LOW (label), vr->min ()) <= 0 && tree_int_cst_compare (CASE_HIGH (label), vr->max ()) >= 0) : (vr->singleton_p (&singleton) && tree_int_cst_equal (CASE_LOW (label), singleton))) return label; - - if (i > j) - return gimple_switch_label (switch_stmt, 0); } + + /* If there are no such labels, then the default label + will be taken. */ + if (i > j) + return gimple_switch_label (switch_stmt, 0); } if (vr->kind () == VR_ANTI_RANGE) -- cgit v1.1 From 0b1949603c401f6ad07c0641b6db59efe3140c0e Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 8 Jul 2019 00:16:22 +0000 Subject: Daily bump. From-SVN: r273190 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d85bcc5..fd804b8 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190707 +20190708 -- cgit v1.1 From 7ef004023510d0c88e1a8bb718ee2848c1358ea4 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 8 Jul 2019 06:20:55 +0000 Subject: [riscv] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. No behavioural change -- produces the same code as before. 2019-07-08 Richard Sandiford gcc/ * config/riscv/pic.md (*local_pic_load_s) (*local_pic_load_u): Explicitly specify the mode iterator referenced by , giving... (*local_pic_load_s, *local_pic_load_u): ...these. * config/riscv/riscv.md (*sge_) (*slt_, *sle_): Explicitly use for the mode attribute. From-SVN: r273191 --- gcc/ChangeLog | 10 ++++++++++ gcc/config/riscv/pic.md | 4 ++-- gcc/config/riscv/riscv.md | 6 +++--- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9f83f75..96ae53a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-07-08 Richard Sandiford + + * config/riscv/pic.md (*local_pic_load_s) + (*local_pic_load_u): Explicitly specify the mode iterator + referenced by , giving... + (*local_pic_load_s, *local_pic_load_u): ...these. + * config/riscv/riscv.md (*sge_) + (*slt_, *sle_): Explicitly + use for the mode attribute. + 2019-07-07 Jeff Law PR tree-optimization/91090 diff --git a/gcc/config/riscv/pic.md b/gcc/config/riscv/pic.md index da303e4..f16f054 100644 --- a/gcc/config/riscv/pic.md +++ b/gcc/config/riscv/pic.md @@ -29,14 +29,14 @@ "\t%0,%1" [(set (attr "length") (const_int 8))]) -(define_insn "*local_pic_load_s" +(define_insn "*local_pic_load_s" [(set (match_operand:SUPERQI 0 "register_operand" "=r") (sign_extend:SUPERQI (mem:SUBX (match_operand 1 "absolute_symbolic_operand" ""))))] "USE_LOAD_ADDRESS_MACRO (operands[1])" "\t%0,%1" [(set (attr "length") (const_int 8))]) -(define_insn "*local_pic_load_u" +(define_insn "*local_pic_load_u" [(set (match_operand:SUPERQI 0 "register_operand" "=r") (zero_extend:SUPERQI (mem:SUBX (match_operand 1 "absolute_symbolic_operand" ""))))] "USE_LOAD_ADDRESS_MACRO (operands[1])" diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 309c109..0f46266 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -2054,7 +2054,7 @@ "" "slt%i2\t%0,zero,%1" [(set_attr "type" "slt") - (set_attr "mode" "")]) + (set_attr "mode" "")]) (define_insn "*slt_" [(set (match_operand:GPR 0 "register_operand" "= r") @@ -2063,7 +2063,7 @@ "" "slt%i2\t%0,%1,%2" [(set_attr "type" "slt") - (set_attr "mode" "")]) + (set_attr "mode" "")]) (define_insn "*sle_" [(set (match_operand:GPR 0 "register_operand" "=r") @@ -2075,7 +2075,7 @@ return "slt%i2\t%0,%1,%2"; } [(set_attr "type" "slt") - (set_attr "mode" "")]) + (set_attr "mode" "")]) ;; ;; .................... -- cgit v1.1 From 0de175b8d6722cca2221bbb52772f975058ac183 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 8 Jul 2019 06:21:05 +0000 Subject: Make guality.h handle Yama restricted ptrace mode guality.exp is silently skipped on Linux systems with kernel.yama.ptrace_scope=1 because gdb fails to attach to the sanity check test. This patch uses PR_SET_PTRACER (where available) to avoid this. prctl was apparently added in Linux 2.1.57, so I don't think we need any tests other than __linux for the #include. 2019-07-08 Richard Sandiford gcc/testsuite/ * gcc.dg/guality/guality.h: Include on Linux targets. (main): Use PR_SET_PTRACER where available. From-SVN: r273192 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/guality/guality.h | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 12e5bc1..911dc21 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Richard Sandiford + + * gcc.dg/guality/guality.h: Include on Linux targets. + (main): Use PR_SET_PTRACER where available. + 2019-07-07 Paul Thomas PR fortran/91077 diff --git a/gcc/testsuite/gcc.dg/guality/guality.h b/gcc/testsuite/gcc.dg/guality/guality.h index 7a16475..d41327c 100644 --- a/gcc/testsuite/gcc.dg/guality/guality.h +++ b/gcc/testsuite/gcc.dg/guality/guality.h @@ -23,6 +23,9 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#ifdef __linux +#include +#endif /* This is a first cut at checking that debug information matches run-time. The idea is to annotate programs with GUALCHK* macros @@ -214,6 +217,10 @@ main (int argc, char *argv[]) int i; char *argv0 = argv[0]; +#if defined(PR_SET_PTRACER_ANY) + prctl (PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); +#endif + guality_gdb_command = getenv ("GUALITY_GDB"); if (!guality_gdb_command) { -- cgit v1.1 From 8849d5034c5ab5c2e6f3fc17209504576e7c6dd4 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 8 Jul 2019 06:21:11 +0000 Subject: Add a build config for bootstrapping at -Og Although BOOT_CFLAGS can be used to bootstrap with -Og, having a dedicated build config is sometimes more convenient. 2019-07-08 Richard Sandiford config/ * bootstrap-Og.mk: New file. gcc/ * doc/install.texi (bootstrap-Og): Document. From-SVN: r273193 --- gcc/ChangeLog | 4 ++++ gcc/doc/install.texi | 1 + 2 files changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 96ae53a..145b7b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2019-07-08 Richard Sandiford + * doc/install.texi (bootstrap-Og): Document. + +2019-07-08 Richard Sandiford + * config/riscv/pic.md (*local_pic_load_s) (*local_pic_load_u): Explicitly specify the mode iterator referenced by , giving... diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 852aa8f..2598713 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -2535,6 +2535,7 @@ Removes any @option{-O}-started option from @code{BOOT_CFLAGS}, and adds @samp{BOOT_CFLAGS='-g -O1'}. @item @samp{bootstrap-O3} +@itemx @samp{bootstrap-Og} Analogous to @code{bootstrap-O1}. @item @samp{bootstrap-lto} -- cgit v1.1 From 38988cbf9ebaa96fb1e891a46aa063f0c298a2e2 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 8 Jul 2019 07:09:24 +0000 Subject: re PR tree-optimization/83518 (Missing optimization: useless instructions should be dropped) 2019-07-08 Richard Biener PR tree-optimization/83518 * tree-ssa-sccvn.c: Include splay-tree.h. (struct pd_range, struct pd_data): New. (struct vn_walk_cb_data): Add data to track partial definitions. (vn_walk_cb_data::~vn_walk_cb_data): New. (vn_walk_cb_data::push_partial_def): New. (pd_tree_alloc, pd_tree_dealloc, pd_range_compare): New. (vn_reference_lookup_2): When partial defs are registered give up. (vn_reference_lookup_3): Track partial defs for memset and constructor zeroing and for defs from constants. * gcc.dg/tree-ssa/ssa-fre-73.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-74.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-75.c: Likewise. * gcc.dg/tree-ssa/ssa-fre-76.c: Likewise. * g++.dg/tree-ssa/pr83518.C: Likewise. From-SVN: r273194 --- gcc/ChangeLog | 13 + gcc/testsuite/ChangeLog | 9 + gcc/testsuite/g++.dg/tree-ssa/pr83518.C | 27 ++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-73.c | 14 ++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-74.c | 16 ++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-75.c | 34 +++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-76.c | 16 ++ gcc/tree-ssa-sccvn.c | 389 +++++++++++++++++++++++++---- 8 files changed, 469 insertions(+), 49 deletions(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr83518.C create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-73.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-74.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-75.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-76.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 145b7b2..74a9890 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2019-07-08 Richard Biener + + PR tree-optimization/83518 + * tree-ssa-sccvn.c: Include splay-tree.h. + (struct pd_range, struct pd_data): New. + (struct vn_walk_cb_data): Add data to track partial definitions. + (vn_walk_cb_data::~vn_walk_cb_data): New. + (vn_walk_cb_data::push_partial_def): New. + (pd_tree_alloc, pd_tree_dealloc, pd_range_compare): New. + (vn_reference_lookup_2): When partial defs are registered give up. + (vn_reference_lookup_3): Track partial defs for memset and + constructor zeroing and for defs from constants. + 2019-07-08 Richard Sandiford * doc/install.texi (bootstrap-Og): Document. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 911dc21..db493b3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2019-07-08 Richard Biener + + PR tree-optimization/83518 + * gcc.dg/tree-ssa/ssa-fre-73.c: New testcase. + * gcc.dg/tree-ssa/ssa-fre-74.c: Likewise. + * gcc.dg/tree-ssa/ssa-fre-75.c: Likewise. + * gcc.dg/tree-ssa/ssa-fre-76.c: Likewise. + * g++.dg/tree-ssa/pr83518.C: Likewise. + 2019-07-08 Richard Sandiford * gcc.dg/guality/guality.h: Include on Linux targets. diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr83518.C b/gcc/testsuite/g++.dg/tree-ssa/pr83518.C new file mode 100644 index 0000000..3e153c5 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr83518.C @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-optimized" } */ + +unsigned test() +{ + int arr[] = {5,4,3,2,1}; + int sum = 0; + + for(int i = 0;i < 5;++i) + { + for(int j = 0; j < 5; ++j) + { + int t = arr[i]; + arr[i] = arr[j]; + arr[j] = t; + } + } + + for(int i = 0; i < 5; ++i) + { + sum += arr[i]; + } + + return sum; +} + +/* { dg-final { scan-tree-dump "return 15;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-73.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-73.c new file mode 100644 index 0000000..f138203 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-73.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1" } */ + +typedef int v2si __attribute__((vector_size(__SIZEOF_INT__ * 2))); +int foo (int *a) +{ + a[0] = 1; + a[1] = 2; + v2si x = *(v2si *)a; + *(v2si *)&a[2] = x; + return a[3]; +} + +/* { dg-final { scan-tree-dump "return 2;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-74.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-74.c new file mode 100644 index 0000000..4439d83 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-74.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1" } */ + +typedef int v4si __attribute__((vector_size(__SIZEOF_INT__ * 4))); +int foo (int *a) +{ + a[2] = 2; + a[0] = 0; + a[1] = 1; + a[3] = 4; + v4si x = *(v4si *)a; + *(v4si *)&a[4] = x; + return a[4] + a[7]; +} + +/* { dg-final { scan-tree-dump "return 4;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-75.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-75.c new file mode 100644 index 0000000..54bfe73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-75.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target int32plus } */ +/* { dg-options "-O -fgimple -fdump-tree-fre1" } */ + +typedef int v4si __attribute__((vector_size(__SIZEOF_INT__ * 4))); +#if __SIZEOF_INT__ == 4 +__GIMPLE (ssa) int foo (int *a) +{ + v4si _2; + int _3; + int _4; + int _5; + int _6; + int _7; + int _8; + int _9; + +__BB(2): + __MEM ((char *)a_1(D) + 4) = _Literal (unsigned char[3 * __SIZEOF_INT__]) {}; + __MEM (a_1(D) + 8) = 2; + __MEM (a_1(D)) = 1; + _2 = __MEM (a_1(D)); + _3 = __BIT_FIELD_REF (_2, 32, 0); + _4 = __BIT_FIELD_REF (_2, 32, 32); + _5 = __BIT_FIELD_REF (_2, 32, 64); + _6 = __BIT_FIELD_REF (_2, 32, 96); + _7 = _3 + _4; + _8 = _7 + _5; + _9 = _8 + _6; + return _9; +} +#endif + +/* { dg-final { scan-tree-dump "return 3;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-76.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-76.c new file mode 100644 index 0000000..7a1eede --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-76.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1" } */ + +typedef int v4si __attribute__((vector_size(__SIZEOF_INT__ * 4))); +int foo (int *a) +{ + __builtin_memset (a, 0, 2 * __SIZEOF_INT__); + a[2] = 2; + a[0] = 1; + a[3] = 3; + v4si x = *(v4si *)a; + *(v4si *)&a[4] = x; + return a[4] + a[5] + a[7]; +} + +/* { dg-final { scan-tree-dump "return 4;" "fre1" } } */ diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 67d51bf..3c45adc 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "splay-tree.h" #include "backend.h" #include "rtl.h" #include "tree.h" @@ -360,6 +361,8 @@ static void init_vn_nary_op_from_stmt (vn_nary_op_t, gimple *); static void init_vn_nary_op_from_pieces (vn_nary_op_t, unsigned int, enum tree_code, tree, tree *); static tree vn_lookup_simplify_result (gimple_match_op *); +static vn_reference_t vn_reference_lookup_or_insert_for_pieces + (tree, alias_set_type, tree, vec, tree); /* Return whether there is value numbering information for a given SSA name. */ @@ -1646,20 +1649,245 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult) return NULL_TREE; } + +/* Partial definition tracking support. */ + +struct pd_range +{ + HOST_WIDE_INT offset; + HOST_WIDE_INT size; +}; + +struct pd_data +{ + tree rhs; + HOST_WIDE_INT offset; + HOST_WIDE_INT size; +}; + +/* Context for alias walking. */ + struct vn_walk_cb_data { vn_walk_cb_data (vn_reference_t vr_, tree *last_vuse_ptr_, - vn_lookup_kind vn_walk_kind_, bool tbaa_p_) + vn_lookup_kind vn_walk_kind_, bool tbaa_p_) : vr (vr_), last_vuse_ptr (last_vuse_ptr_), vn_walk_kind (vn_walk_kind_), - tbaa_p (tbaa_p_) - {} + tbaa_p (tbaa_p_), known_ranges (NULL) + {} + ~vn_walk_cb_data (); + void *push_partial_def (const pd_data& pd, tree, HOST_WIDE_INT); vn_reference_t vr; tree *last_vuse_ptr; vn_lookup_kind vn_walk_kind; bool tbaa_p; + + /* The VDEFs of partial defs we come along. */ + auto_vec partial_defs; + /* The first defs range to avoid splay tree setup in most cases. */ + pd_range first_range; + tree first_vuse; + splay_tree known_ranges; + obstack ranges_obstack; }; +vn_walk_cb_data::~vn_walk_cb_data () +{ + if (known_ranges) + { + splay_tree_delete (known_ranges); + obstack_free (&ranges_obstack, NULL); + } +} + +/* pd_range splay-tree helpers. */ + +static int +pd_range_compare (splay_tree_key offset1p, splay_tree_key offset2p) +{ + HOST_WIDE_INT offset1 = *(HOST_WIDE_INT *)offset1p; + HOST_WIDE_INT offset2 = *(HOST_WIDE_INT *)offset2p; + if (offset1 < offset2) + return -1; + else if (offset1 > offset2) + return 1; + return 0; +} + +static void * +pd_tree_alloc (int size, void *data_) +{ + vn_walk_cb_data *data = (vn_walk_cb_data *)data_; + return obstack_alloc (&data->ranges_obstack, size); +} + +static void +pd_tree_dealloc (void *, void *) +{ +} + +/* Push PD to the vector of partial definitions returning a + value when we are ready to combine things with VUSE and MAXSIZEI, + NULL when we want to continue looking for partial defs or -1 + on failure. */ + +void * +vn_walk_cb_data::push_partial_def (const pd_data &pd, tree vuse, + HOST_WIDE_INT maxsizei) +{ + if (partial_defs.is_empty ()) + { + partial_defs.safe_push (pd); + first_range.offset = pd.offset; + first_range.size = pd.size; + first_vuse = vuse; + last_vuse_ptr = NULL; + } + else + { + if (!known_ranges) + { + /* ??? Optimize the case where the second partial def + completes things. */ + gcc_obstack_init (&ranges_obstack); + known_ranges + = splay_tree_new_with_allocator (pd_range_compare, 0, 0, + pd_tree_alloc, + pd_tree_dealloc, this); + splay_tree_insert (known_ranges, + (splay_tree_key)&first_range.offset, + (splay_tree_value)&first_range); + } + if (known_ranges) + { + pd_range newr = { pd.offset, pd.size }; + splay_tree_node n; + pd_range *r; + /* Lookup the predecessor of offset + 1 and see if + we need to merge with it. */ + HOST_WIDE_INT loffset = newr.offset + 1; + if ((n = splay_tree_predecessor (known_ranges, + (splay_tree_key)&loffset)) + && ((r = (pd_range *)n->value), true) + && ranges_known_overlap_p (r->offset, r->size + 1, + newr.offset, newr.size)) + { + /* Ignore partial defs already covered. */ + if (known_subrange_p (newr.offset, newr.size, + r->offset, r->size)) + return NULL; + r->size = MAX (r->offset + r->size, + newr.offset + newr.size) - r->offset; + } + else + { + /* newr.offset wasn't covered yet, insert the + range. */ + r = XOBNEW (&ranges_obstack, pd_range); + *r = newr; + splay_tree_insert (known_ranges, + (splay_tree_key)&r->offset, + (splay_tree_value)r); + } + /* Merge r which now contains newr and is a member + of the splay tree with adjacent overlapping ranges. */ + pd_range *rafter; + while ((n = splay_tree_successor (known_ranges, + (splay_tree_key)&r->offset)) + && ((rafter = (pd_range *)n->value), true) + && ranges_known_overlap_p (r->offset, r->size + 1, + rafter->offset, rafter->size)) + { + r->size = MAX (r->offset + r->size, + rafter->offset + rafter->size) - r->offset; + splay_tree_remove (known_ranges, + (splay_tree_key)&rafter->offset); + } + partial_defs.safe_push (pd); + + /* Now we have merged newr into the range tree. + When we have covered [offseti, sizei] then the + tree will contain exactly one node which has + the desired properties and it will be 'r'. */ + if (known_subrange_p (0, maxsizei / BITS_PER_UNIT, + r->offset, r->size)) + { + /* Now simply native encode all partial defs + in reverse order. */ + unsigned ndefs = partial_defs.length (); + /* We support up to 512-bit values (for V8DFmode). */ + unsigned char buffer[64]; + int len; + + while (!partial_defs.is_empty ()) + { + pd_data pd = partial_defs.pop (); + if (TREE_CODE (pd.rhs) == CONSTRUCTOR) + /* Empty CONSTRUCTOR. */ + memset (buffer + MAX (0, pd.offset), + 0, MIN ((HOST_WIDE_INT)sizeof (buffer), pd.size)); + else + { + len = native_encode_expr (pd.rhs, + buffer + MAX (0, pd.offset), + sizeof (buffer - MAX (0, pd.offset)), + MAX (0, -pd.offset)); + if (len <= 0 + || len < (pd.size - MAX (0, -pd.offset))) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Failed to encode %u " + "partial definitions\n", ndefs); + return (void *)-1; + } + } + } + + tree type = vr->type; + /* Make sure to interpret in a type that has a range + covering the whole access size. */ + if (INTEGRAL_TYPE_P (vr->type) + && maxsizei != TYPE_PRECISION (vr->type)) + type = build_nonstandard_integer_type (maxsizei, + TYPE_UNSIGNED (type)); + tree val = native_interpret_expr (type, buffer, + maxsizei / BITS_PER_UNIT); + /* If we chop off bits because the types precision doesn't + match the memory access size this is ok when optimizing + reads but not when called from the DSE code during + elimination. */ + if (val + && type != vr->type) + { + if (! int_fits_type_p (val, vr->type)) + val = NULL_TREE; + else + val = fold_convert (vr->type, val); + } + + if (val) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Successfully combined %u " + "partial definitions\n", ndefs); + return vn_reference_lookup_or_insert_for_pieces + (first_vuse, + vr->set, vr->type, vr->operands, val); + } + else + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Failed to interpret %u " + "encoded partial definitions\n", ndefs); + return (void *)-1; + } + } + } + } + /* Continue looking for partial defs. */ + return NULL; +} + /* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_ with the current VUSE and performs the expression lookup. */ @@ -1671,6 +1899,11 @@ vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *data_) vn_reference_s **slot; hashval_t hash; + /* If we have partial definitions recorded we have to go through + vn_reference_lookup_3. */ + if (!data->partial_defs.is_empty ()) + return NULL; + if (data->last_vuse_ptr) *data->last_vuse_ptr = vuse; @@ -2179,8 +2412,10 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, else return (void *)-1; tree len = gimple_call_arg (def_stmt, 2); - if (known_subrange_p (offset, maxsize, offset2, - wi::to_poly_offset (len) << LOG2_BITS_PER_UNIT)) + HOST_WIDE_INT leni, offset2i, offseti; + if (data->partial_defs.is_empty () + && known_subrange_p (offset, maxsize, offset2, + wi::to_poly_offset (len) << LOG2_BITS_PER_UNIT)) { tree val; if (integer_zerop (gimple_call_arg (def_stmt, 1))) @@ -2209,6 +2444,19 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, return vn_reference_lookup_or_insert_for_pieces (vuse, vr->set, vr->type, vr->operands, val); } + /* For now handle clearing memory with partial defs. */ + else if (integer_zerop (gimple_call_arg (def_stmt, 1)) + && tree_to_poly_int64 (len).is_constant (&leni) + && offset.is_constant (&offseti) + && offset2.is_constant (&offset2i) + && maxsize.is_constant (&maxsizei)) + { + pd_data pd; + pd.rhs = build_constructor (NULL_TREE, NULL); + pd.offset = offset2i - offseti; + pd.size = leni; + return data->push_partial_def (pd, vuse, maxsizei); + } } /* 2) Assignment from an empty CONSTRUCTOR. */ @@ -2219,18 +2467,37 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, { tree base2; poly_int64 offset2, size2, maxsize2; + HOST_WIDE_INT offset2i, size2i; bool reverse; base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt), &offset2, &size2, &maxsize2, &reverse); if (known_size_p (maxsize2) && known_eq (maxsize2, size2) && adjust_offsets_for_equal_base_address (base, &offset, - base2, &offset2) - && known_subrange_p (offset, maxsize, offset2, size2)) + base2, &offset2)) { - tree val = build_zero_cst (vr->type); - return vn_reference_lookup_or_insert_for_pieces - (vuse, vr->set, vr->type, vr->operands, val); + if (data->partial_defs.is_empty () + && known_subrange_p (offset, maxsize, offset2, size2)) + { + tree val = build_zero_cst (vr->type); + return vn_reference_lookup_or_insert_for_pieces + (vuse, vr->set, vr->type, vr->operands, val); + } + else if (maxsize.is_constant (&maxsizei) + && maxsizei % BITS_PER_UNIT == 0 + && offset.is_constant (&offseti) + && offseti % BITS_PER_UNIT == 0 + && offset2.is_constant (&offset2i) + && offset2i % BITS_PER_UNIT == 0 + && size2.is_constant (&size2i) + && size2i % BITS_PER_UNIT == 0) + { + pd_data pd; + pd.rhs = gimple_assign_rhs1 (def_stmt); + pd.offset = (offset2i - offseti) / BITS_PER_UNIT; + pd.size = size2i / BITS_PER_UNIT; + return data->push_partial_def (pd, vuse, maxsizei); + } } } @@ -2253,7 +2520,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, { tree base2; poly_int64 offset2, size2, maxsize2; - HOST_WIDE_INT offset2i; + HOST_WIDE_INT offset2i, size2i; bool reverse; base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt), &offset2, &size2, &maxsize2, &reverse); @@ -2266,45 +2533,60 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, base2, &offset2) && offset.is_constant (&offseti) && offset2.is_constant (&offset2i) - && known_subrange_p (offseti, maxsizei, offset2, size2)) + && size2.is_constant (&size2i)) { - /* We support up to 512-bit values (for V8DFmode). */ - unsigned char buffer[64]; - int len; - - tree rhs = gimple_assign_rhs1 (def_stmt); - if (TREE_CODE (rhs) == SSA_NAME) - rhs = SSA_VAL (rhs); - len = native_encode_expr (rhs, - buffer, sizeof (buffer), - (offseti - offset2i) / BITS_PER_UNIT); - if (len > 0 && len * BITS_PER_UNIT >= maxsizei) + if (data->partial_defs.is_empty () + && known_subrange_p (offseti, maxsizei, offset2, size2)) { - tree type = vr->type; - /* Make sure to interpret in a type that has a range - covering the whole access size. */ - if (INTEGRAL_TYPE_P (vr->type) - && maxsizei != TYPE_PRECISION (vr->type)) - type = build_nonstandard_integer_type (maxsizei, - TYPE_UNSIGNED (type)); - tree val = native_interpret_expr (type, buffer, - maxsizei / BITS_PER_UNIT); - /* If we chop off bits because the types precision doesn't - match the memory access size this is ok when optimizing - reads but not when called from the DSE code during - elimination. */ - if (val - && type != vr->type) + /* We support up to 512-bit values (for V8DFmode). */ + unsigned char buffer[64]; + int len; + + tree rhs = gimple_assign_rhs1 (def_stmt); + if (TREE_CODE (rhs) == SSA_NAME) + rhs = SSA_VAL (rhs); + len = native_encode_expr (rhs, + buffer, sizeof (buffer), + (offseti - offset2i) / BITS_PER_UNIT); + if (len > 0 && len * BITS_PER_UNIT >= maxsizei) { - if (! int_fits_type_p (val, vr->type)) - val = NULL_TREE; - else - val = fold_convert (vr->type, val); - } + tree type = vr->type; + /* Make sure to interpret in a type that has a range + covering the whole access size. */ + if (INTEGRAL_TYPE_P (vr->type) + && maxsizei != TYPE_PRECISION (vr->type)) + type = build_nonstandard_integer_type (maxsizei, + TYPE_UNSIGNED (type)); + tree val = native_interpret_expr (type, buffer, + maxsizei / BITS_PER_UNIT); + /* If we chop off bits because the types precision doesn't + match the memory access size this is ok when optimizing + reads but not when called from the DSE code during + elimination. */ + if (val + && type != vr->type) + { + if (! int_fits_type_p (val, vr->type)) + val = NULL_TREE; + else + val = fold_convert (vr->type, val); + } - if (val) - return vn_reference_lookup_or_insert_for_pieces - (vuse, vr->set, vr->type, vr->operands, val); + if (val) + return vn_reference_lookup_or_insert_for_pieces + (vuse, vr->set, vr->type, vr->operands, val); + } + } + else if (ranges_known_overlap_p (offseti, maxsizei, offset2i, size2i)) + { + pd_data pd; + tree rhs = gimple_assign_rhs1 (def_stmt); + if (TREE_CODE (rhs) == SSA_NAME) + rhs = SSA_VAL (rhs); + pd.rhs = rhs; + pd.offset = (offset2i - offseti) / BITS_PER_UNIT; + pd.size = size2i / BITS_PER_UNIT; + return data->push_partial_def (pd, vuse, maxsizei); } } } @@ -2315,7 +2597,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, && is_gimple_reg_type (vr->type) && !contains_storage_order_barrier_p (vr->operands) && gimple_assign_single_p (def_stmt) - && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME) + && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME + /* A subset of partial defs from non-constants can be handled + by for example inserting a CONSTRUCTOR, a COMPLEX_EXPR or + even a (series of) BIT_INSERT_EXPR hoping for simplifications + downstream, not so much for actually doing the insertion. */ + && data->partial_defs.is_empty ()) { tree base2; poly_int64 offset2, size2, maxsize2; @@ -2363,7 +2650,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, && gimple_assign_single_p (def_stmt) && (DECL_P (gimple_assign_rhs1 (def_stmt)) || TREE_CODE (gimple_assign_rhs1 (def_stmt)) == MEM_REF - || handled_component_p (gimple_assign_rhs1 (def_stmt)))) + || handled_component_p (gimple_assign_rhs1 (def_stmt))) + /* Handling this is more complicated, give up for now. */ + && data->partial_defs.is_empty ()) { tree base2; int i, j, k; @@ -2497,7 +2786,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, || TREE_CODE (gimple_call_arg (def_stmt, 0)) == SSA_NAME) && (TREE_CODE (gimple_call_arg (def_stmt, 1)) == ADDR_EXPR || TREE_CODE (gimple_call_arg (def_stmt, 1)) == SSA_NAME) - && poly_int_tree_p (gimple_call_arg (def_stmt, 2), ©_size)) + && poly_int_tree_p (gimple_call_arg (def_stmt, 2), ©_size) + /* Handling this is more complicated, give up for now. */ + && data->partial_defs.is_empty ()) { tree lhs, rhs; ao_ref r; -- cgit v1.1 From e87f67eb5d8671bc7c98dbf10106fda34114b293 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 8 Jul 2019 08:12:46 +0000 Subject: [Ada] Spurious visibility error on dynamic_predicate aspect in generic This patch fixes a spurious error when verifying that the visibility of the expression of an aspect has not changed between the freeze point of the entity to which it applies, and the end of the enclosing declarative part. If the entity is a composite type its components must be made directly visible for the analysis of the expression. In a generic context this must be done explicitly at the end of the declarative part. 2019-07-08 Ed Schonberg gcc/ada/ * sem_ch13.adb (Check_Aspect_At_End_Of_Declarations): For an unanalized aspect in a generic context that has not been analyzed yet, if the aspect applies to a type, place the type on the scope stack to make its components visible, before checking conformance with the version of the expression analyzed at the freeze point. gcc/testsuite/ * gnat.dg/predicate8.adb, gnat.dg/predicate8_pkg.adb, gnat.dg/predicate8_pkg.ads: New testcase. From-SVN: r273197 --- gcc/ada/ChangeLog | 9 ++++ gcc/ada/sem_ch13.adb | 18 +++++-- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gnat.dg/predicate8.adb | 15 ++++++ gcc/testsuite/gnat.dg/predicate8_pkg.adb | 64 +++++++++++++++++++++++++ gcc/testsuite/gnat.dg/predicate8_pkg.ads | 81 ++++++++++++++++++++++++++++++++ 6 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/predicate8.adb create mode 100644 gcc/testsuite/gnat.dg/predicate8_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/predicate8_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8a729d1..687c4ab 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-08 Ed Schonberg + + * sem_ch13.adb (Check_Aspect_At_End_Of_Declarations): For an + unanalized aspect in a generic context that has not been + analyzed yet, if the aspect applies to a type, place the type on + the scope stack to make its components visible, before checking + conformance with the version of the expression analyzed at the + freeze point. + 2019-07-05 Justin Squirek * checks.adb (Apply_Accessibility_Check): Add logic to fetch the diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 4c74366..b62e297 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -3491,7 +3491,9 @@ package body Sem_Ch13 is -- Build the precondition/postcondition pragma - -- Add note about why we do NOT need Copy_Tree here??? + -- We use Relocate_Node here rather than New_Copy_Tree + -- because subsequent visibility analysis of the aspect + -- depends on this sharing. This should be cleaned up??? Make_Aitem_Pragma (Pragma_Argument_Associations => New_List ( @@ -9358,10 +9360,20 @@ package body Sem_Ch13 is else -- In a generic context freeze nodes are not always generated, so - -- analyze the expression now. + -- analyze the expression now. If the aspect is for a type, this + -- makes its potential components accessible. if not Analyzed (Freeze_Expr) and then Inside_A_Generic then - Preanalyze (Freeze_Expr); + if A_Id = Aspect_Dynamic_Predicate + or else A_Id = Aspect_Predicate + or else A_Id = Aspect_Priority + then + Push_Type (Ent); + Preanalyze (Freeze_Expr); + Pop_Type (Ent); + else + Preanalyze (Freeze_Expr); + end if; end if; -- Indicate that the expression comes from an aspect specification, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index db493b3..a5a44a5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Ed Schonberg + + * gnat.dg/predicate8.adb, gnat.dg/predicate8_pkg.adb, + gnat.dg/predicate8_pkg.ads: New testcase. + 2019-07-08 Richard Biener PR tree-optimization/83518 diff --git a/gcc/testsuite/gnat.dg/predicate8.adb b/gcc/testsuite/gnat.dg/predicate8.adb new file mode 100644 index 0000000..0019699 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate8.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } + +pragma Spark_Mode (On); + +with Predicate8_Pkg; + +procedure Predicate8 is + package Ring_Buffer is new Predicate8_Pkg (Element_Type => Integer); + use Ring_Buffer; + + X : Ring_Buffer_Type (4); + +begin + Put (X, 1); +end Predicate8; diff --git a/gcc/testsuite/gnat.dg/predicate8_pkg.adb b/gcc/testsuite/gnat.dg/predicate8_pkg.adb new file mode 100644 index 0000000..20626d9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate8_pkg.adb @@ -0,0 +1,64 @@ +pragma Spark_Mode (On); + +package body Predicate8_Pkg is + function Empty + (Buffer : in Ring_Buffer_Type) return Boolean + is (Size (Buffer) = 0); + + function Full + (Buffer : in Ring_Buffer_Type) return Boolean + is (Size (Buffer) = Buffer.Max_Size); + + function Size + (Buffer : in Ring_Buffer_Type) return Natural + is (Buffer.Count); + + function Free + (Buffer : in Ring_Buffer_Type) return Natural + is (Buffer.Max_Size - Size (Buffer)); + + function First + (Buffer : in Ring_Buffer_Type) return Element_Type + is (Buffer.Items (Buffer.Head)); + + function Last + (Buffer : in Ring_Buffer_Type) return Element_Type + is (Buffer.Items (Buffer.Tail)); + + procedure Get + (Buffer : in out Ring_Buffer_Type; + Element : out Element_Type) + is + begin + Element := Buffer.Items (Buffer.Head); + Buffer := + Buffer'Update + (Head => + (if Buffer.Head = Buffer.Max_Size then 1 else Buffer.Head + 1), + Count => Buffer.Count - 1); + end Get; + + procedure Put + (Buffer : in out Ring_Buffer_Type; + Element : in Element_Type) + is + begin + if Buffer.Tail = Buffer.Max_Size then + Buffer.Tail := 1; + else + Buffer.Tail := Buffer.Tail + 1; + end if; + + Buffer.Items (Buffer.Tail) := Element; + Buffer.Count := Buffer.Count + 1; + end Put; + + procedure Clear + (Buffer : in out Ring_Buffer_Type) + is + begin + Buffer.Head := 1; + Buffer.Tail := Buffer.Max_Size; + Buffer.Count := 0; + end Clear; +end Predicate8_Pkg; diff --git a/gcc/testsuite/gnat.dg/predicate8_pkg.ads b/gcc/testsuite/gnat.dg/predicate8_pkg.ads new file mode 100644 index 0000000..fd25294 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate8_pkg.ads @@ -0,0 +1,81 @@ +pragma Spark_Mode (On); + +generic + type Element_Type is private; + +package Predicate8_Pkg is + pragma Annotate (GNATprove, Terminating, Predicate8_Pkg); + + subtype Small_Natural is Natural range 0 .. Natural'Last / 2; + subtype Small_Positive is Natural range 1 .. Natural'Last / 2; + + type Element_Array_Type is array (Small_Positive range <>) of Element_Type; + + type Ring_Buffer_Type (Max_Size : Small_Positive) is private + with Default_Initial_Condition => Empty (Ring_Buffer_Type); + + function Empty + (Buffer : in Ring_Buffer_Type) return Boolean; + + function Full + (Buffer : in Ring_Buffer_Type) return Boolean; + + function Size + (Buffer : in Ring_Buffer_Type) return Natural; + + function Free + (Buffer : in Ring_Buffer_Type) return Natural; + + function First + (Buffer : in Ring_Buffer_Type) return Element_Type + with + Pre => not Empty (Buffer); + + function Last + (Buffer : in Ring_Buffer_Type) return Element_Type + with + Pre => not Empty (Buffer); + + procedure Get + (Buffer : in out Ring_Buffer_Type; + Element : out Element_Type) + with + Pre => not Empty (Buffer) and + Size (Buffer) >= 1, + Post => not Full (Buffer) and then + Element = First (Buffer'Old) and then + Size (Buffer) = Size (Buffer'Old) - 1; + + procedure Put + (Buffer : in out Ring_Buffer_Type; + Element : in Element_Type) + with + Pre => not Full (Buffer), + Post => not Empty (Buffer) and then + Last (Buffer) = Element and then + Size (Buffer) = Size (Buffer'Old) + 1; + + procedure Clear + (Buffer : in out Ring_Buffer_Type) + with + Post => Empty (Buffer) and then + not Full (Buffer) and then + Size (Buffer) = 0; + +private + type Ring_Buffer_Type (Max_Size : Small_Positive) is record + Count : Small_Natural := 0; + Head : Small_Positive := 1; + Tail : Small_Positive := Max_Size; + Items : Element_Array_Type (1 .. Max_Size); + end record + with Dynamic_Predicate => + (Max_Size <= Small_Positive'Last and + Count <= Max_Size and + Head <= Max_Size and + Tail <= Max_Size and + ((Count = 0 and Tail = Max_Size and Head = 1) or + (Count = Max_Size + Tail - Head + 1) or + (Count = Tail - Head + 1))); + +end Predicate8_Pkg; -- cgit v1.1 From 0a90412010e4bd535df8c35d4bce95f321ebb6be Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Mon, 8 Jul 2019 08:12:51 +0000 Subject: [Ada] GNAT.Sockets: remove default level in Get/Set_Socket_Option 2019-07-08 Dmitriy Anisimkov gcc/ada/ * libgnat/g-socket.ads, libgnat/g-socket.adb: Improve documentation. (Get_Socket_Option, Set_Socket_Option): Remove default value for the Level formal. From-SVN: r273198 --- gcc/ada/ChangeLog | 7 +++ gcc/ada/libgnat/g-socket.adb | 4 +- gcc/ada/libgnat/g-socket.ads | 133 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 115 insertions(+), 29 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 687c4ab..b1b2e48 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-08 Dmitriy Anisimkov + + * libgnat/g-socket.ads, libgnat/g-socket.adb: Improve + documentation. + (Get_Socket_Option, Set_Socket_Option): Remove default value for + the Level formal. + 2019-07-08 Ed Schonberg * sem_ch13.adb (Check_Aspect_At_End_Of_Declarations): For an diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb index ef6071b..2c9b8c7 100644 --- a/gcc/ada/libgnat/g-socket.adb +++ b/gcc/ada/libgnat/g-socket.adb @@ -1369,7 +1369,7 @@ package body GNAT.Sockets is function Get_Socket_Option (Socket : Socket_Type; - Level : Level_Type := Socket_Level; + Level : Level_Type; Name : Option_Name; Optname : Interfaces.C.int := -1) return Option_Type is @@ -2539,7 +2539,7 @@ package body GNAT.Sockets is procedure Set_Socket_Option (Socket : Socket_Type; - Level : Level_Type := Socket_Level; + Level : Level_Type; Option : Option_Type) is use type C.unsigned; diff --git a/gcc/ada/libgnat/g-socket.ads b/gcc/ada/libgnat/g-socket.ads index 3024433..6db3c54 100644 --- a/gcc/ada/libgnat/g-socket.ads +++ b/gcc/ada/libgnat/g-socket.ads @@ -775,34 +775,113 @@ package GNAT.Sockets is IP_Protocol_For_TCP_Level); -- There are several options available to manipulate sockets. Each option - -- has a name and several values available. Most of the time, the value is - -- a boolean to enable or disable this option. + -- has a name and several values available. Most of the time, the value + -- is a boolean to enable or disable this option. Each socket option is + -- provided with an appropriate C name taken from the sockets API comments. + -- The C name can be used to find a detailed description in the OS-specific + -- documentation. The options are grouped by main Level_Type value, which + -- can be used together with this option in calls to the Set_Socket_Option + -- and Get_Socket_Option routines. Note that some options can be used with + -- more than one level. type Option_Name is (Generic_Option, - Keep_Alive, -- Enable sending of keep-alive messages - Reuse_Address, -- Allow bind to reuse local address - Broadcast, -- Enable datagram sockets to recv/send broadcasts - Send_Buffer, -- Set/get the maximum socket send buffer in bytes - Receive_Buffer, -- Set/get the maximum socket recv buffer in bytes - Linger, -- Shutdown wait for msg to be sent or timeout occur - Error, -- Get and clear the pending socket error - No_Delay, -- Do not delay send to coalesce data (TCP_NODELAY) - Add_Membership_V4, -- Join a multicast group - Add_Membership_V6, -- Idem for IPv6 socket - Drop_Membership_V4, -- Leave a multicast group - Drop_Membership_V6, -- Idem for IPv6 socket - Multicast_If_V4, -- Set default out interface for multicast packets - Multicast_If_V6, -- Idem for IPv6 socket - Multicast_Loop_V4, -- Sent multicast packets are looped to local socket - Multicast_Loop_V6, -- Idem for IPv6 socket - Multicast_TTL, -- Set the time-to-live of sent multicast packets - Multicast_Hops, -- Set the multicast hop limit for the IPv6 socket - Receive_Packet_Info, -- Receive low level packet info as ancillary data - Send_Timeout, -- Set timeout value for output - Receive_Timeout, -- Set timeout value for input - IPv6_Only, -- Restricted to IPv6 communications only - Busy_Polling); -- Set busy polling mode + -- Can be used to set/get any socket option via an OS-specific option + -- code with an integer value. + + ------------------ + -- Socket_Level -- + ------------------ + + Keep_Alive, -- SO_KEEPALIVE + -- Enable sending of keep-alive messages on connection-oriented sockets + + Reuse_Address, -- SO_REUSEADDR + -- Enable binding to an address and port already in use + + Broadcast, -- SO_BROADCAST + -- Enable sending broadcast datagrams on the socket + + Send_Buffer, -- SO_SNDBUF + -- Set/get the maximum socket send buffer in bytes + + Receive_Buffer, -- SO_RCVBUF + -- Set/get the maximum socket receive buffer in bytes + + Linger, -- SO_LINGER + -- When enabled, a Close_Socket or Shutdown_Socket will wait until all + -- queued messages for the socket have been successfully sent or the + -- linger timeout has been reached. + + Error, -- SO_ERROR + -- Get and clear the pending socket error integer code + + Send_Timeout, -- SO_SNDTIMEO + -- Specify sending timeout until reporting an error + + Receive_Timeout, -- SO_RCVTIMEO + -- Specify receiving timeout until reporting an error + + Busy_Polling, -- SO_BUSY_POLL + -- Sets the approximate time in microseconds to busy poll on a blocking + -- receive when there is no data. + + ------------------------------- + -- IP_Protocol_For_TCP_Level -- + ------------------------------- + + No_Delay, -- TCP_NODELAY + -- Disable the Nagle algorithm. This means that output buffer content + -- is always sent as soon as possible, even if there is only a small + -- amount of data. + + ------------------------------ + -- IP_Protocol_For_IP_Level -- + ------------------------------ + + Add_Membership_V4, -- IP_ADD_MEMBERSHIP + -- Join a multicast group + + Drop_Membership_V4, -- IP_DROP_MEMBERSHIP + -- Leave a multicast group + + Multicast_If_V4, -- IP_MULTICAST_IF + -- Set/Get outgoing interface for sending multicast packets + + Multicast_Loop_V4, -- IP_MULTICAST_LOOP + -- This boolean option determines whether sent multicast packets should + -- be looped back to the local sockets. + + Multicast_TTL, -- IP_MULTICAST_TTL + -- Set/Get the time-to-live of sent multicast packets + + Receive_Packet_Info, -- IP_PKTINFO + -- Receive low-level packet info as ancillary data + + -------------------------------- + -- IP_Protocol_For_IPv6_Level -- + -------------------------------- + + Add_Membership_V6, -- IPV6_ADD_MEMBERSHIP + -- Join IPv6 multicast group + + Drop_Membership_V6, -- IPV6_DROP_MEMBERSHIP + -- Leave IPv6 multicast group + + Multicast_If_V6, -- IPV6_MULTICAST_IF + -- Set/Get outgoing interface index for sending multicast packets + + Multicast_Loop_V6, -- IPV6_MULTICAST_LOOP + -- This boolean option determines whether sent multicast IPv6 packets + -- should be looped back to the local sockets. + + IPv6_Only, -- IPV6_V6ONLY + -- Restricted to IPv6 communications only + + Multicast_Hops -- IPV6_MULTICAST_HOPS + -- Set the multicast hop limit for the IPv6 socket + ); + subtype Specific_Option_Name is Option_Name range Keep_Alive .. Option_Name'Last; @@ -1084,7 +1163,7 @@ package GNAT.Sockets is function Get_Socket_Option (Socket : Socket_Type; - Level : Level_Type := Socket_Level; + Level : Level_Type; Name : Option_Name; Optname : Interfaces.C.int := -1) return Option_Type; -- Get the options associated with a socket. Raises Socket_Error on error. @@ -1199,7 +1278,7 @@ package GNAT.Sockets is procedure Set_Socket_Option (Socket : Socket_Type; - Level : Level_Type := Socket_Level; + Level : Level_Type; Option : Option_Type); -- Manipulate socket options. Raises Socket_Error on error -- cgit v1.1 From ffec45e390555f4881c841271464a9c264adbbca Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Mon, 8 Jul 2019 08:12:55 +0000 Subject: [Ada] Crash on Image and Value attributes This patch fixes an issue whereby the creation of an enumeration within package where Default_Scalar_Storage_Order is in effect may lead to a crash when the attributes Image or Value are applied to objects of said type or the type directly. 2019-07-08 Justin Squirek gcc/ada/ * exp_imgv.adb (Build_Enumeration_Image_Tables): Default SSO for the building of image tables. (Expand_Image_Attribute): Minor cleanup. gcc/testsuite/ * gnat.dg/sso16.adb: New testcase. From-SVN: r273199 --- gcc/ada/ChangeLog | 6 +++++ gcc/ada/exp_imgv.adb | 38 +++++++++++++++++++++------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gnat.dg/sso16.adb | 55 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/sso16.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b1b2e48..528556a 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Justin Squirek + + * exp_imgv.adb (Build_Enumeration_Image_Tables): Default SSO for + the building of image tables. + (Expand_Image_Attribute): Minor cleanup. + 2019-07-08 Dmitriy Anisimkov * libgnat/g-socket.ads, libgnat/g-socket.adb: Improve diff --git a/gcc/ada/exp_imgv.adb b/gcc/ada/exp_imgv.adb index 6a8d626..a47de2f 100644 --- a/gcc/ada/exp_imgv.adb +++ b/gcc/ada/exp_imgv.adb @@ -69,18 +69,23 @@ package body Exp_Imgv is ------------------------------------ procedure Build_Enumeration_Image_Tables (E : Entity_Id; N : Node_Id) is - Loc : constant Source_Ptr := Sloc (E); - Str : String_Id; + Loc : constant Source_Ptr := Sloc (E); + + Eind : Entity_Id; + Estr : Entity_Id; Ind : List_Id; + Ityp : Node_Id; + Len : Nat; Lit : Entity_Id; Nlit : Nat; - Len : Nat; - Estr : Entity_Id; - Eind : Entity_Id; - Ityp : Node_Id; + Str : String_Id; + + Saved_SSO : constant Character := Opt.Default_SSO; + -- Used to save the current scalar storage order during the generation + -- of the literal lookup table. begin - -- Nothing to do for other than a root enumeration type + -- Nothing to do for types other than a root enumeration type if E /= Root_Type (E) then return; @@ -138,6 +143,15 @@ package body Exp_Imgv is Set_Lit_Strings (E, Estr); Set_Lit_Indexes (E, Eind); + -- Temporarily set the current scalar storage order to the default + -- during the generation of the literals table, since both the Image and + -- Value attributes rely on runtime routines for interpreting table + -- values. + + Opt.Default_SSO := ' '; + + -- Generate literal table + Insert_Actions (N, New_List ( Make_Object_Declaration (Loc, @@ -168,6 +182,10 @@ package body Exp_Imgv is Make_Aggregate (Loc, Expressions => Ind))), Suppress => All_Checks); + + -- Reset the scalar storage order to the saved value + + Opt.Default_SSO := Saved_SSO; end Build_Enumeration_Image_Tables; ---------------------------- @@ -433,13 +451,13 @@ package body Exp_Imgv is -- Local variables + Enum_Case : Boolean; Imid : RE_Id; + Proc_Ent : Entity_Id; Ptyp : Entity_Id; Rtyp : Entity_Id; Tent : Entity_Id := Empty; Ttyp : Entity_Id; - Proc_Ent : Entity_Id; - Enum_Case : Boolean; Arg_List : List_Id; -- List of arguments for run-time procedure call @@ -450,6 +468,8 @@ package body Exp_Imgv is Snn : constant Entity_Id := Make_Temporary (Loc, 'S'); Pnn : constant Entity_Id := Make_Temporary (Loc, 'P'); + -- Start of processing for Expand_Image_Attribute + begin if Is_Object_Image (Pref) then Rewrite_Object_Image (N, Pref, Name_Image, Standard_String); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a5a44a5..744f782 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Justin Squirek + + * gnat.dg/sso16.adb: New testcase. + 2019-07-08 Ed Schonberg * gnat.dg/predicate8.adb, gnat.dg/predicate8_pkg.adb, diff --git a/gcc/testsuite/gnat.dg/sso16.adb b/gcc/testsuite/gnat.dg/sso16.adb new file mode 100644 index 0000000..0480d9162 --- /dev/null +++ b/gcc/testsuite/gnat.dg/sso16.adb @@ -0,0 +1,55 @@ +-- { dg-do run } + +with Ada.Text_IO; use Ada.Text_IO; + +procedure SSO16 is + + pragma Default_Scalar_Storage_Order (High_Order_First); + + type Enum_T is + (Event_0, + Event_1, + Event_2, + Event_3, + Event_4, + Event_5, + Event_11, + Event_12, + Event_13, + Event_14, + Event_15, + Event_21, + Event_22, + Event_23, + Event_24, + Event_25, + Event_31, + Event_32, + Event_33, + Event_34, + Event_35, + Event_41, + Event_42, + Event_43, + Event_44, + Event_45); + + Var : Enum_T := Event_0; + +begin + if Var'Image /= "EVENT_0" then + raise Program_Error; + end if; + + if Enum_T'Value ("Event_4")'Image /= "EVENT_4" then + raise Program_Error; + end if; + + if Enum_T'Val (20)'Image /= "EVENT_35" then + raise Program_Error; + end if; + + if Enum_T'Pos (Enum_T'Value ("Event_45"))'Image /= " 25" then + raise Program_Error; + end if; +end; -- cgit v1.1 From b91cdf756caafddf48433e6f93c4cc0049d292f8 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Mon, 8 Jul 2019 08:13:00 +0000 Subject: [Ada] Spurious error reported by pragma Compile_Time_Error The compiler may trigger spurious errors on pragmas Compile_Time_Error and Compile_Time_Warning when their boolean expression computes the size of a type. After this patch the following test compiles fine. with Interfaces; use Interfaces; package Types is type Arr is array (1 .. 6) of Unsigned_8 with Size => 48, Alignment => 1; type Rec is record Comp_1 : Unsigned_32; Comp_2 : Unsigned_16; end record with Size => 48, Alignment => 1; end Types; with Types; use Types; package Main is pragma Compile_Time_Error (Arr'Size = 12, "ERROR: Arr'Size is 48, not 12"); pragma Compile_Time_Error (Arr'Size = 48, "OK: Arr"); pragma Compile_Time_Error (Arr'Size /= 48, "ERROR: Arr'Size is 48"); pragma Compile_Time_Error (Rec'Size = 34, "ERROR: Rec'Size is 48, not 34"); pragma Compile_Time_Error (Rec'Size = 48, "OK: Rec"); pragma Compile_Time_Error (Rec'Size /= 48, "ERROR: Rec'Size is 48"); end Main; Command: gcc -c main.ads Output: main.ads:7:07: OK: Arr main.ads:14:07: OK: Rec 2019-07-08 Javier Miranda gcc/ada/ * sem_attr.adb (Analyze_Attribute [Attribute_Size]): For pragmas used to report user defined compile time warning or errors handle 'Size for types with known static RM size. From-SVN: r273200 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/sem_attr.adb | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 528556a..9a86909 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Javier Miranda + + * sem_attr.adb (Analyze_Attribute [Attribute_Size]): For pragmas + used to report user defined compile time warning or errors + handle 'Size for types with known static RM size. + 2019-07-08 Justin Squirek * exp_imgv.adb (Build_Enumeration_Image_Tables): Default SSO for diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index a3f9ffd..4c6cba6 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -5848,8 +5848,19 @@ package body Sem_Attr is or else Ekind (Entity (P)) = E_Enumeration_Literal) and then Size_Known_At_Compile_Time (Entity (P)) then - Rewrite (N, Make_Integer_Literal (Sloc (N), Esize (Entity (P)))); - Analyze (N); + declare + Siz : Uint; + + begin + if Known_Static_RM_Size (Entity (P)) then + Siz := RM_Size (Entity (P)); + else + Siz := Esize (Entity (P)); + end if; + + Rewrite (N, Make_Integer_Literal (Sloc (N), Siz)); + Analyze (N); + end; end if; ----------- -- cgit v1.1 From 5291985c00302036cc6d5932fdffb9acab3043cf Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 8 Jul 2019 08:13:04 +0000 Subject: [Ada] Crash on named actual in postcondition for generic subprogram This patch fixes a crash on compiling the postcondtion for a generic subprogram, when the postcondition is a call with both positional and named parameter associations. 2019-07-08 Ed Schonberg gcc/ada/ * sem_ch13.adb (Analyze_Aspect_Specifications): For a pre/postcondition of a generic subprogram declaration, do not use Relocate_Node on the aspect expression to construct the corresponding attribute specification, to prevent tree anomalies when the expression is a call with named actual parameters. gcc/testsuite/ * gnat.dg/predicate9.adb: New testcase. From-SVN: r273201 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/sem_ch13.adb | 28 ++++++++++++++++++++++------ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/predicate9.adb | 21 +++++++++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/predicate9.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9a86909..d651ff0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-08 Ed Schonberg + + * sem_ch13.adb (Analyze_Aspect_Specifications): For a + pre/postcondition of a generic subprogram declaration, do not + use Relocate_Node on the aspect expression to construct the + corresponding attribute specification, to prevent tree anomalies + when the expression is a call with named actual parameters. + 2019-07-08 Javier Miranda * sem_attr.adb (Analyze_Attribute [Attribute_Size]): For pragmas diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index b62e297..8467f75 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -3495,12 +3495,28 @@ package body Sem_Ch13 is -- because subsequent visibility analysis of the aspect -- depends on this sharing. This should be cleaned up??? - Make_Aitem_Pragma - (Pragma_Argument_Associations => New_List ( - Make_Pragma_Argument_Association (Eloc, - Chars => Name_Check, - Expression => Relocate_Node (Expr))), - Pragma_Name => Pname); + -- If the context is generic or involves ASIS, we want + -- to preserve the original tree, and simply share it + -- between aspect and generated attribute. This parallels + -- what is done in sem_prag.adb (see Get_Argument). + + declare + New_Expr : Node_Id; + + begin + if ASIS_Mode or else Inside_A_Generic then + New_Expr := Expr; + else + New_Expr := Relocate_Node (Expr); + end if; + + Make_Aitem_Pragma + (Pragma_Argument_Associations => New_List ( + Make_Pragma_Argument_Association (Eloc, + Chars => Name_Check, + Expression => New_Expr)), + Pragma_Name => Pname); + end; -- Add message unless exception messages are suppressed diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 744f782..94ad86f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Ed Schonberg + + * gnat.dg/predicate9.adb: New testcase. + 2019-07-08 Justin Squirek * gnat.dg/sso16.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/predicate9.adb b/gcc/testsuite/gnat.dg/predicate9.adb new file mode 100644 index 0000000..ebcfca7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate9.adb @@ -0,0 +1,21 @@ +-- { dg-do compile } +procedure Predicate9 is + function Num (x : Integer) return Integer is (X + 1); + function name (X : String) return Integer is (X'Size); + function Post (One : Integer; Two : Integer) return Boolean; + + generic + type T is private; + procedure Pro (Z : Integer) with Post => + Post (Num (5), Two => Name ("yeah")); + + function Post (One : Integer; Two : Integer) return Boolean + is (True); + + procedure Pro (Z : Integer) is + begin + null; + end Pro; +begin + null; +end Predicate9; -- cgit v1.1 From f56e04e89e809dc34d3f7fd3137f7d35c26e8fee Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Mon, 8 Jul 2019 08:13:11 +0000 Subject: [Ada] Code reorganization This patch performs a code reorganization of the implementation of pragma Compile_Time_Error. No functional change. No test required. 2019-07-08 Javier Miranda gcc/ada/ * gnat1drv.adb (Post_Compilation_Validation_Checks: Validate_Compile_Time_Warning_Errors is now located in sem_prag (instead of sem_ch13). * sem_ch13.ads (Validate_Compile_Time_Warning_Error, Validate_Compile_Time_Warning_Errors): Move to sem_prag. * sem_ch13.adb (Compile_Time_Warnings_Errors): Move to sem_prag. (Initialize): Remove initialization of table Compile_Time_Warning_Errors. (Validate_Compile_Time_Warning_Error, Validate_Compile_Time_Warning_Errors): Move to sem_prag. * sem_prag.ads (Validate_Compile_Time_Warning_Errors): New procedure. * sem_prag.adb (Initialize): Initialize table Compile_Time_Warning_Errors. From-SVN: r273202 --- gcc/ada/ChangeLog | 18 ++++++++ gcc/ada/gnat1drv.adb | 3 +- gcc/ada/sem_ch13.adb | 110 ----------------------------------------------- gcc/ada/sem_ch13.ads | 12 ------ gcc/ada/sem_prag.adb | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++- gcc/ada/sem_prag.ads | 6 +++ 6 files changed, 143 insertions(+), 124 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d651ff0..bec3306 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,21 @@ +2019-07-08 Javier Miranda + + * gnat1drv.adb (Post_Compilation_Validation_Checks: + Validate_Compile_Time_Warning_Errors is now located in sem_prag + (instead of sem_ch13). + * sem_ch13.ads (Validate_Compile_Time_Warning_Error, + Validate_Compile_Time_Warning_Errors): Move to sem_prag. + * sem_ch13.adb + (Compile_Time_Warnings_Errors): Move to sem_prag. + (Initialize): Remove initialization of table + Compile_Time_Warning_Errors. + (Validate_Compile_Time_Warning_Error, + Validate_Compile_Time_Warning_Errors): Move to sem_prag. + * sem_prag.ads (Validate_Compile_Time_Warning_Errors): New + procedure. + * sem_prag.adb (Initialize): Initialize table + Compile_Time_Warning_Errors. + 2019-07-08 Ed Schonberg * sem_ch13.adb (Analyze_Aspect_Specifications): For a diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index ded754d..572ce3d 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -61,6 +61,7 @@ with Sem_Ch12; with Sem_Ch13; with Sem_Elim; with Sem_Eval; +with Sem_Prag; with Sem_SPARK; use Sem_SPARK; with Sem_Type; with Set_Targ; @@ -990,7 +991,7 @@ procedure Gnat1drv is Atree.Unlock; Nlists.Unlock; Sem.Unlock; - Sem_Ch13.Validate_Compile_Time_Warning_Errors; + Sem_Prag.Validate_Compile_Time_Warning_Errors; Sem.Lock; Nlists.Lock; Atree.Lock; diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 8467f75..76639cd 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -30,7 +30,6 @@ with Debug; use Debug; with Einfo; use Einfo; with Elists; use Elists; with Errout; use Errout; -with Expander; use Expander; with Exp_Disp; use Exp_Disp; with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; @@ -247,41 +246,6 @@ package body Sem_Ch13 is -- Remove visibility to the discriminants of type entity E and pop the -- scope stack if E has discriminants and is not a subtype. - --------------------------------------------------- - -- Table for Validate_Compile_Time_Warning_Error -- - --------------------------------------------------- - - -- The following table collects pragmas Compile_Time_Error and Compile_ - -- Time_Warning for validation. Entries are made by calls to subprogram - -- Validate_Compile_Time_Warning_Error, and the call to the procedure - -- Validate_Compile_Time_Warning_Errors does the actual error checking - -- and posting of warning and error messages. The reason for this delayed - -- processing is to take advantage of back-annotations of attributes size - -- and alignment values performed by the back end. - - -- Note: the reason we store a Source_Ptr value instead of a Node_Id is - -- that by the time Validate_Unchecked_Conversions is called, Sprint will - -- already have modified all Sloc values if the -gnatD option is set. - - type CTWE_Entry is record - Eloc : Source_Ptr; - -- Source location used in warnings and error messages - - Prag : Node_Id; - -- Pragma Compile_Time_Error or Compile_Time_Warning - - Scope : Node_Id; - -- The scope which encloses the pragma - end record; - - package Compile_Time_Warnings_Errors is new Table.Table ( - Table_Component_Type => CTWE_Entry, - Table_Index_Type => Int, - Table_Low_Bound => 1, - Table_Initial => 50, - Table_Increment => 200, - Table_Name => "Compile_Time_Warnings_Errors"); - ---------------------------------------------- -- Table for Validate_Unchecked_Conversions -- ---------------------------------------------- @@ -11830,7 +11794,6 @@ package body Sem_Ch13 is procedure Initialize is begin Address_Clause_Checks.Init; - Compile_Time_Warnings_Errors.Init; Unchecked_Conversions.Init; -- ??? Might be needed in the future for some non GCC back-ends @@ -13937,79 +13900,6 @@ package body Sem_Ch13 is end loop; end Validate_Address_Clauses; - ----------------------------------------- - -- Validate_Compile_Time_Warning_Error -- - ----------------------------------------- - - procedure Validate_Compile_Time_Warning_Error (N : Node_Id) is - begin - Compile_Time_Warnings_Errors.Append - (New_Val => CTWE_Entry'(Eloc => Sloc (N), - Scope => Current_Scope, - Prag => N)); - end Validate_Compile_Time_Warning_Error; - - ------------------------------------------ - -- Validate_Compile_Time_Warning_Errors -- - ------------------------------------------ - - procedure Validate_Compile_Time_Warning_Errors is - procedure Set_Scope (S : Entity_Id); - -- Install all enclosing scopes of S along with S itself - - procedure Unset_Scope (S : Entity_Id); - -- Uninstall all enclosing scopes of S along with S itself - - --------------- - -- Set_Scope -- - --------------- - - procedure Set_Scope (S : Entity_Id) is - begin - if S /= Standard_Standard then - Set_Scope (Scope (S)); - end if; - - Push_Scope (S); - end Set_Scope; - - ----------------- - -- Unset_Scope -- - ----------------- - - procedure Unset_Scope (S : Entity_Id) is - begin - if S /= Standard_Standard then - Unset_Scope (Scope (S)); - end if; - - Pop_Scope; - end Unset_Scope; - - -- Start of processing for Validate_Compile_Time_Warning_Errors - - begin - Expander_Mode_Save_And_Set (False); - In_Compile_Time_Warning_Or_Error := True; - - for N in Compile_Time_Warnings_Errors.First .. - Compile_Time_Warnings_Errors.Last - loop - declare - T : CTWE_Entry renames Compile_Time_Warnings_Errors.Table (N); - - begin - Set_Scope (T.Scope); - Reset_Analyzed_Flags (T.Prag); - Process_Compile_Time_Warning_Or_Error (T.Prag, T.Eloc); - Unset_Scope (T.Scope); - end; - end loop; - - In_Compile_Time_Warning_Or_Error := False; - Expander_Mode_Restore; - end Validate_Compile_Time_Warning_Errors; - --------------------------- -- Validate_Independence -- --------------------------- diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads index 3773a12..eb95e2b 100644 --- a/gcc/ada/sem_ch13.ads +++ b/gcc/ada/sem_ch13.ads @@ -189,18 +189,6 @@ package Sem_Ch13 is -- change. A False result is possible only for array, enumeration or -- record types. - procedure Validate_Compile_Time_Warning_Error (N : Node_Id); - -- N is a pragma Compile_Time_Error or Compile_Warning_Error whose boolean - -- expression is not known at compile time. This procedure makes an entry - -- in a table. The actual checking is performed by Validate_Compile_Time_ - -- Warning_Errors, which is invoked after calling the back end. - - procedure Validate_Compile_Time_Warning_Errors; - -- This routine is called after calling the back end to validate pragmas - -- Compile_Time_Error and Compile_Time_Warning for size and alignment - -- appropriateness. The reason it is called that late is to take advantage - -- of any back-annotation of size and alignment performed by the back end. - procedure Validate_Unchecked_Conversion (N : Node_Id; Act_Unit : Entity_Id); diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index d841426..7f20221 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -41,6 +41,7 @@ with Elists; use Elists; with Errout; use Errout; with Exp_Dist; use Exp_Dist; with Exp_Util; use Exp_Util; +with Expander; use Expander; with Freeze; use Freeze; with Ghost; use Ghost; with Gnatvsn; use Gnatvsn; @@ -298,6 +299,12 @@ package body Sem_Prag is -- pragma. Entity name for unit and its parents is taken from item in -- previous with_clause that mentions the unit. + procedure Validate_Compile_Time_Warning_Error (N : Node_Id); + -- N is a pragma Compile_Time_Error or Compile_Warning_Error whose boolean + -- expression is not known at compile time. This procedure makes an entry + -- in a table. The actual checking is performed by Validate_Compile_Time_ + -- Warning_Errors, which is invoked after calling the back end. + Dummy : Integer := 0; pragma Volatile (Dummy); -- Dummy volatile integer used in bodies of ip/rv to prevent optimization @@ -316,6 +323,41 @@ package body Sem_Prag is -- pragma in the source program, a breakpoint on rv catches this place in -- the source, allowing convenient stepping to the point of interest. + --------------------------------------------------- + -- Table for Validate_Compile_Time_Warning_Error -- + --------------------------------------------------- + + -- The following table collects pragmas Compile_Time_Error and Compile_ + -- Time_Warning for validation. Entries are made by calls to subprogram + -- Validate_Compile_Time_Warning_Error, and the call to the procedure + -- Validate_Compile_Time_Warning_Errors does the actual error checking + -- and posting of warning and error messages. The reason for this delayed + -- processing is to take advantage of back-annotations of attributes size + -- and alignment values performed by the back end. + + -- Note: the reason we store a Source_Ptr value instead of a Node_Id is + -- that by the time Validate_Unchecked_Conversions is called, Sprint will + -- already have modified all Sloc values if the -gnatD option is set. + + type CTWE_Entry is record + Eloc : Source_Ptr; + -- Source location used in warnings and error messages + + Prag : Node_Id; + -- Pragma Compile_Time_Error or Compile_Time_Warning + + Scope : Node_Id; + -- The scope which encloses the pragma + end record; + + package Compile_Time_Warnings_Errors is new Table.Table ( + Table_Component_Type => CTWE_Entry, + Table_Index_Type => Int, + Table_Low_Bound => 1, + Table_Initial => 50, + Table_Increment => 200, + Table_Name => "Compile_Time_Warnings_Errors"); + ------------------------------- -- Adjust_External_Name_Case -- ------------------------------- @@ -7605,7 +7647,7 @@ package body Sem_Prag is Check_Expression (Arg1x); if Validation_Needed then - Sem_Ch13.Validate_Compile_Time_Warning_Error (N); + Validate_Compile_Time_Warning_Error (N); end if; end if; end Process_Compile_Time_Warning_Or_Error; @@ -30724,6 +30766,7 @@ package body Sem_Prag is procedure Initialize is begin Externals.Init; + Compile_Time_Warnings_Errors.Init; end Initialize; -------- @@ -32066,4 +32109,77 @@ package body Sem_Prag is return Empty; end Test_Case_Arg; + ----------------------------------------- + -- Validate_Compile_Time_Warning_Error -- + ----------------------------------------- + + procedure Validate_Compile_Time_Warning_Error (N : Node_Id) is + begin + Compile_Time_Warnings_Errors.Append + (New_Val => CTWE_Entry'(Eloc => Sloc (N), + Scope => Current_Scope, + Prag => N)); + end Validate_Compile_Time_Warning_Error; + + ------------------------------------------ + -- Validate_Compile_Time_Warning_Errors -- + ------------------------------------------ + + procedure Validate_Compile_Time_Warning_Errors is + procedure Set_Scope (S : Entity_Id); + -- Install all enclosing scopes of S along with S itself + + procedure Unset_Scope (S : Entity_Id); + -- Uninstall all enclosing scopes of S along with S itself + + --------------- + -- Set_Scope -- + --------------- + + procedure Set_Scope (S : Entity_Id) is + begin + if S /= Standard_Standard then + Set_Scope (Scope (S)); + end if; + + Push_Scope (S); + end Set_Scope; + + ----------------- + -- Unset_Scope -- + ----------------- + + procedure Unset_Scope (S : Entity_Id) is + begin + if S /= Standard_Standard then + Unset_Scope (Scope (S)); + end if; + + Pop_Scope; + end Unset_Scope; + + -- Start of processing for Validate_Compile_Time_Warning_Errors + + begin + Expander_Mode_Save_And_Set (False); + In_Compile_Time_Warning_Or_Error := True; + + for N in Compile_Time_Warnings_Errors.First .. + Compile_Time_Warnings_Errors.Last + loop + declare + T : CTWE_Entry renames Compile_Time_Warnings_Errors.Table (N); + + begin + Set_Scope (T.Scope); + Reset_Analyzed_Flags (T.Prag); + Process_Compile_Time_Warning_Or_Error (T.Prag, T.Eloc); + Unset_Scope (T.Scope); + end; + end loop; + + In_Compile_Time_Warning_Or_Error := False; + Expander_Mode_Restore; + end Validate_Compile_Time_Warning_Errors; + end Sem_Prag; diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads index f2f6d0c..25353b7 100644 --- a/gcc/ada/sem_prag.ads +++ b/gcc/ada/sem_prag.ads @@ -555,4 +555,10 @@ package Sem_Prag is -- -- Empty if there is no such argument + procedure Validate_Compile_Time_Warning_Errors; + -- This routine is called after calling the back end to validate pragmas + -- Compile_Time_Error and Compile_Time_Warning for size and alignment + -- appropriateness. The reason it is called that late is to take advantage + -- of any back-annotation of size and alignment performed by the back end. + end Sem_Prag; -- cgit v1.1 From 23eb3cb2b4fb900398461410c6c31294fc77cfc6 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Mon, 8 Jul 2019 08:13:16 +0000 Subject: [Ada] Document handling of preprocessor directives in GNATpp 2019-07-08 Bob Duff gcc/ada/ * doc/gnat_ugn/gnat_utility_programs.rst: Document handling of preprocessor directives in GNATpp. From-SVN: r273203 --- gcc/ada/ChangeLog | 5 +++ gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst | 61 ++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index bec3306..72cb892 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Bob Duff + + * doc/gnat_ugn/gnat_utility_programs.rst: Document handling of + preprocessor directives in GNATpp. + 2019-07-08 Javier Miranda * gnat1drv.adb (Post_Compilation_Validation_Checks: diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst index 53904b1..b6a1d18 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst @@ -3933,6 +3933,67 @@ Alternatively, you may run the script using the following command line: Name2_NAME3_Name4 := Name4_NAME3_Name2 > NAME1; end Test; + .. _Preprocessor_directives: + + Preprocessor Directives + ^^^^^^^^^^^^^^^^^^^^^^^ + + ``gnatpp`` has some support for preprocessor directives. + You can use preprocessor symbols, as in ``$symbol``. + In addition, you can use conditional compilation, + so long as the program text is syntactically legal Ada code + after removing all the preprocessor directives (lines starting + with ``#``). For example, ``gnatpp`` can format the following: + + .. code-block:: ada + + package P is + #IF SOMETHING + X : constant Integer := 123; + #ELSE + X : constant Integer := 456; + #END IF; + end P; + + which will be formatted as if it were: + + .. code-block:: ada + + package P is + X : constant Integer := 123; + X : constant Integer := 456; + end P; + + except that the ``#`` lines will be preserved. + However, ``gnatpp`` cannot format the following: + + .. code-block:: ada + + procedure P is + begin + #IF SOMETHING + if X = 0 then + #ELSE + if X = 1 then + #END IF; + null; + end if; + end P; + + because removing the ``#`` lines gives: + + .. code-block:: ada + + procedure P is + begin + if X = 0 then + if X = 1 then + null; + end if; + end P; + + which is not syntactically legal. + Legacy Switches ^^^^^^^^^^^^^^^ -- cgit v1.1 From 4a0e6ac18f731f41f7ddfa05c370186cd32bef52 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Mon, 8 Jul 2019 08:13:20 +0000 Subject: [Ada] Crash in interface derivation with null primitive The frontend crashes processing the derivation of a tagged type whose ultimate ancestor is an interface type I1 that has a null primitive, implements another interface I2 derived from I2, and does not override the null primitive. 2019-07-08 Javier Miranda gcc/ada/ * exp_disp.adb (Register_Primitive): When registering a primitive in the secondary dispatch table, handle primitive inherited through several levels of type derivation (required to properly handle inherited 'null' primitive). gcc/testsuite/ * gnat.dg/interface9.adb, gnat.dg/interface9_root-child.ads, gnat.dg/interface9_root.ads: New testcase. From-SVN: r273204 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/exp_disp.adb | 2 +- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/interface9.adb | 10 ++++++++++ gcc/testsuite/gnat.dg/interface9_root-child.ads | 7 +++++++ gcc/testsuite/gnat.dg/interface9_root.ads | 10 ++++++++++ 6 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/interface9.adb create mode 100644 gcc/testsuite/gnat.dg/interface9_root-child.ads create mode 100644 gcc/testsuite/gnat.dg/interface9_root.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 72cb892..969e933 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-08 Javier Miranda + + * exp_disp.adb (Register_Primitive): When registering a + primitive in the secondary dispatch table, handle primitive + inherited through several levels of type derivation (required to + properly handle inherited 'null' primitive). + 2019-07-08 Bob Duff * doc/gnat_ugn/gnat_utility_programs.rst: Document handling of diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index 1b21234..a659594 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -7637,7 +7637,7 @@ package body Exp_Disp is Unchecked_Convert_To (RTE (RE_Prim_Ptr), Make_Attribute_Reference (Loc, Prefix => - New_Occurrence_Of (Alias (Prim), Loc), + New_Occurrence_Of (Ultimate_Alias (Prim), Loc), Attribute_Name => Name_Unrestricted_Access)))); end if; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 94ad86f..14d127f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Javier Miranda + + * gnat.dg/interface9.adb, gnat.dg/interface9_root-child.ads, + gnat.dg/interface9_root.ads: New testcase. + 2019-07-08 Ed Schonberg * gnat.dg/predicate9.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/interface9.adb b/gcc/testsuite/gnat.dg/interface9.adb new file mode 100644 index 0000000..ec46e20 --- /dev/null +++ b/gcc/testsuite/gnat.dg/interface9.adb @@ -0,0 +1,10 @@ +-- { dg-do compile } + +with Interface9_Root.Child; +procedure Interface9 is + package R is new Interface9_Root (Real => Float); + package RC is new R.Child; + +begin + null; +end Interface9; diff --git a/gcc/testsuite/gnat.dg/interface9_root-child.ads b/gcc/testsuite/gnat.dg/interface9_root-child.ads new file mode 100644 index 0000000..0440ddb --- /dev/null +++ b/gcc/testsuite/gnat.dg/interface9_root-child.ads @@ -0,0 +1,7 @@ +generic +package Interface9_Root.Child is + type Base_Type is abstract new Base_Interface with null record; + + type Derived_Type is abstract new Base_Type and Derived_Interface + with null record; -- Test +end Interface9_Root.Child; diff --git a/gcc/testsuite/gnat.dg/interface9_root.ads b/gcc/testsuite/gnat.dg/interface9_root.ads new file mode 100644 index 0000000..2e64e5b --- /dev/null +++ b/gcc/testsuite/gnat.dg/interface9_root.ads @@ -0,0 +1,10 @@ +generic + type Real is digits <>; +package Interface9_Root is + type Base_Interface is limited interface; + + procedure Primitive1 (B : in out Base_Interface) is abstract; + procedure Primitive2 (B : in out Base_Interface) is null; + + type Derived_Interface is limited interface and Base_Interface; +end Interface9_Root; -- cgit v1.1 From 4962dc441d317b6f28ab4ee3bf6b0d83f7c61837 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 8 Jul 2019 08:13:25 +0000 Subject: [Ada] Semantics of Delete for fixed strings This patch corrects a bug in the implementation of Delete in an unusual boundary case: the RM describes the semantics of Delete as equivalent to that of Replace_String with a null argument. As a result, deleting a null string that starts past the end of its argument is a noop and must not raise Index_Error. 2019-07-08 Ed Schonberg gcc/ada/ * libgnat/a-strfix.adb (Delete): The RM describes the semantics of Delete as equivalent to that of Replace_String with a null argument. As a result, deleting a null string that starts past the end of its argument is a noop and must not raise Index_Error. gcc/testsuite/ * gnat.dg/fixed_delete.adb: New testcase. From-SVN: r273205 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/libgnat/a-strfix.adb | 10 +++++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/fixed_delete.adb | 17 +++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/fixed_delete.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 969e933..2f97ab9 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-08 Ed Schonberg + + * libgnat/a-strfix.adb (Delete): The RM describes the semantics + of Delete as equivalent to that of Replace_String with a null + argument. As a result, deleting a null string that starts past + the end of its argument is a noop and must not raise + Index_Error. + 2019-07-08 Javier Miranda * exp_disp.adb (Register_Primitive): When registering a diff --git a/gcc/ada/libgnat/a-strfix.adb b/gcc/ada/libgnat/a-strfix.adb index 6bf825b..b8b5f42 100644 --- a/gcc/ada/libgnat/a-strfix.adb +++ b/gcc/ada/libgnat/a-strfix.adb @@ -192,7 +192,15 @@ package body Ada.Strings.Fixed is elsif From not in Source'Range or else Through > Source'Last then - raise Index_Error; + -- In most cases this raises an exception, but the case of deleting + -- a null string at the end of the current one is a special-case, and + -- reflects the equivalence with Replace_String (RM A.4.3 (86/3)). + + if From = Source'Last + 1 and then From = Through then + return Source; + else + raise Index_Error; + end if; else declare diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 14d127f..a0b6bb4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Ed Schonberg + + * gnat.dg/fixed_delete.adb: New testcase. + 2019-07-08 Javier Miranda * gnat.dg/interface9.adb, gnat.dg/interface9_root-child.ads, diff --git a/gcc/testsuite/gnat.dg/fixed_delete.adb b/gcc/testsuite/gnat.dg/fixed_delete.adb new file mode 100644 index 0000000..c13c71c --- /dev/null +++ b/gcc/testsuite/gnat.dg/fixed_delete.adb @@ -0,0 +1,17 @@ +-- { dg-do run } + +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Fixed; use Ada.Strings.Fixed; + +procedure Fixed_Delete is + Str : String := "a"; + Str1 : String := Replace_Slice (Str, 2, 2, ""); + Str2 : String := Delete (Str, 2, 2); +begin + if Str1 /= "a" then + raise Program_Error; + end if; + if Str2 /= "a" then + raise Program_Error; + end if; +end Fixed_Delete; -- cgit v1.1 From abbc45464b1be9895a4842903a5c75b6dd085b9a Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 8 Jul 2019 08:13:30 +0000 Subject: [Ada] Fix crash on extension of private type with -gnatRj This fixes a crash (or an assertion failure) during the processing done for -gnatRj on the declaration of an extension of a private type. Generally speaking, extension declarations are delicate in this context because the front-end does not duplicate the structure of the parent type, so the processing required to output the structural layout needs to go up to the declaration of the parent type, which may or may not be available or usable. The change also makes the processing more robust by falling back to the flat layout if the declaration of the parent type cannot be processed. 2019-07-08 Eric Botcazou gcc/ada/ * repinfo.adb (List_Record_Info): Declare Incomplete_Layout and Not_In_Extended_Main local exceptions. (List_Structural_Record_Layout): For an extension, raise the former if the parent subtype has not been built and the latter if it is not declared in the main source unit. Fall back to the flat layout if either exception has been raised. From-SVN: r273206 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/repinfo.adb | 42 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2f97ab9..198db54 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-08 Eric Botcazou + + * repinfo.adb (List_Record_Info): Declare Incomplete_Layout and + Not_In_Extended_Main local exceptions. + (List_Structural_Record_Layout): For an extension, raise the + former if the parent subtype has not been built and the latter + if it is not declared in the main source unit. Fall back to the + flat layout if either exception has been raised. + 2019-07-08 Ed Schonberg * libgnat/a-strfix.adb (Delete): The RM describes the semantics diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 007fe39..4bf3351 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -1125,6 +1125,12 @@ package body Repinfo is Indent : Natural := 0); -- Internal recursive procedure to display the structural layout + Incomplete_Layout : exception; + -- Exception raised if the layout is incomplete in -gnatc mode + + Not_In_Extended_Main : exception; + -- Exception raised when an ancestor is not declared in the main unit + Max_Name_Length : Natural := 0; Max_Spos_Length : Natural := 0; @@ -1564,14 +1570,29 @@ package body Repinfo is Disc : Entity_Id; Listed_Disc : Entity_Id; + Parent_Type : Entity_Id; begin -- If this is an extension, first list the layout of the parent -- and then proceed to the extension part, if any. if Is_Extension then - List_Structural_Record_Layout - (Base_Type (Parent_Subtype (Ent)), Outer_Ent); + Parent_Type := Parent_Subtype (Ent); + if No (Parent_Type) then + raise Incomplete_Layout; + end if; + + if Is_Private_Type (Parent_Type) then + Parent_Type := Full_View (Parent_Type); + pragma Assert (Present (Parent_Type)); + end if; + + Parent_Type := Base_Type (Parent_Type); + if not In_Extended_Main_Source_Unit (Parent_Type) then + raise Not_In_Extended_Main; + end if; + + List_Structural_Record_Layout (Parent_Type, Outer_Ent); First := False; if Present (Record_Extension_Part (Definition)) then @@ -1733,8 +1754,23 @@ package body Repinfo is Write_Line (","); Write_Str (" ""record"": ["); + -- ??? We can output structural layout only for base types fully + -- declared in the extended main source unit for the time being, + -- because otherwise declarations might not be processed at all. + if Is_Base_Type (Ent) then - List_Structural_Record_Layout (Ent, Ent); + begin + List_Structural_Record_Layout (Ent, Ent); + + exception + when Incomplete_Layout + | Not_In_Extended_Main + => + List_Record_Layout (Ent); + + when others => + raise Program_Error; + end; else List_Record_Layout (Ent); end if; -- cgit v1.1 From 19d9ce464afc12f95951de2a3be3398e1d2f292d Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 8 Jul 2019 08:13:34 +0000 Subject: [Ada] Arrange not to set DECL_ARTIFICIAL on elab procs Unlike, say, clones created internally by the compiler, elab procs materialize specific user code and flagging them artificial now takes elab code away from gcov's analysis, a regression compared to previous releases. On the testcase below: package Gcov_Q is function F (X : Integer) return Integer is (X + 1); end; with Gcov_Q; package Gcov_P is Y : Integer := Gcov_Q.F (X => 1); end; with Gcov_P; procedure Gcov_Test is begin if Gcov_P.Y /= 2 then raise Program_Error; end if; end; After compiling with: gnatmake -f -g gcov_test.adb \ -cargs -ftest-coverage -fprofile-arcs \ -largs -fprofile-generate and executing with ./gcov_test We expect gcov gcov_p to produce a gcov_p.ads.gcov report. 2019-07-08 Olivier Hainque gcc/ada/ * gcc-interface/trans.c (Compilation_Unit_to_gnu): Don't request DECL_ARTIFICIAL_P on elab proc declarations. From-SVN: r273207 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/gcc-interface/trans.c | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 198db54..81ef99e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Olivier Hainque + + * gcc-interface/trans.c (Compilation_Unit_to_gnu): Don't request + DECL_ARTIFICIAL_P on elab proc declarations. + 2019-07-08 Eric Botcazou * repinfo.adb (List_Record_Info): Declare Incomplete_Layout and diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 32dd132..6cd3759 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -6276,13 +6276,17 @@ Compilation_Unit_to_gnu (Node_Id gnat_node) Node_Id gnat_pragma; /* Make the decl for the elaboration procedure. Emit debug info for it, so that users can break into their elaboration code in debuggers. Kludge: - don't consider it as a definition so that we have a line map for its body, - but no subprogram description in debug info. */ + don't consider it as a definition so that we have a line map for its + body, but no subprogram description in debug info. In addition, don't + qualify it as artificial, even though it is not a user subprogram per se, + in particular for specs. Unlike, say, clones created internally by the + compiler, this subprogram materializes specific user code and flagging it + artificial would take elab code away from gcov's analysis. */ tree gnu_elab_proc_decl = create_subprog_decl (create_concat_name (gnat_unit_entity, body_p ? "elabb" : "elabs"), NULL_TREE, void_ftype, NULL_TREE, - is_default, true, false, true, true, false, NULL, gnat_unit); + is_default, true, false, false, true, false, NULL, gnat_unit); struct elab_info *info; vec_safe_push (gnu_elab_proc_stack, gnu_elab_proc_decl); -- cgit v1.1 From 79ee9e32b17be333e6c70a104c7049c8cab40834 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Mon, 8 Jul 2019 08:13:38 +0000 Subject: [Ada] More data rates supported on Linux This patch adds additional data rates to the GNAT.Serial_Communications package (Linux version). 2019-07-08 Bob Duff gcc/ada/ * libgnat/g-sercom.ads, libgnat/g-sercom__linux.adb (Data_Rate): Support additional data rates. From-SVN: r273208 --- gcc/ada/ChangeLog | 5 ++++ gcc/ada/libgnat/g-sercom.ads | 48 +++++++++++++++++++++++++------------ gcc/ada/libgnat/g-sercom__linux.adb | 39 ++++++++++++++++++++---------- 3 files changed, 64 insertions(+), 28 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 81ef99e..3bbc1cf 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Bob Duff + + * libgnat/g-sercom.ads, libgnat/g-sercom__linux.adb (Data_Rate): + Support additional data rates. + 2019-07-08 Olivier Hainque * gcc-interface/trans.c (Compilation_Unit_to_gnu): Don't request diff --git a/gcc/ada/libgnat/g-sercom.ads b/gcc/ada/libgnat/g-sercom.ads index 8550e8d..e807dab 100644 --- a/gcc/ada/libgnat/g-sercom.ads +++ b/gcc/ada/libgnat/g-sercom.ads @@ -100,8 +100,13 @@ package GNAT.Serial_Communications is -- cases, an explicit port name can be passed directly to Open. type Data_Rate is - (B75, B110, B150, B300, B600, B1200, B2400, B4800, B9600, - B19200, B38400, B57600, B115200); + (B75, B110, B150, B300, B600, B1200, + B2400, B4800, B9600, + B19200, B38400, B57600, B115200, + B230400, B460800, B500000, B576000, B921600, + B1000000, B1152000, B1500000, + B2000000, B2500000, B3000000, + B3500000, B4000000); -- Speed of the communication type Data_Bits is (CS8, CS7); @@ -173,18 +178,31 @@ private end record; Data_Rate_Value : constant array (Data_Rate) of Interfaces.C.unsigned := - (B75 => 75, - B110 => 110, - B150 => 150, - B300 => 300, - B600 => 600, - B1200 => 1_200, - B2400 => 2_400, - B4800 => 4_800, - B9600 => 9_600, - B19200 => 19_200, - B38400 => 38_400, - B57600 => 57_600, - B115200 => 115_200); + (B75 => 75, + B110 => 110, + B150 => 150, + B300 => 300, + B600 => 600, + B1200 => 1_200, + B2400 => 2_400, + B4800 => 4_800, + B9600 => 9_600, + B19200 => 19_200, + B38400 => 38_400, + B57600 => 57_600, + B115200 => 115_200, + B230400 => 230_400, + B460800 => 460_800, + B500000 => 500_000, + B576000 => 576_000, + B921600 => 921_600, + B1000000 => 1_000_000, + B1152000 => 1_152_000, + B1500000 => 1_500_000, + B2000000 => 2_000_000, + B2500000 => 2_500_000, + B3000000 => 3_000_000, + B3500000 => 3_500_000, + B4000000 => 4_000_000); end GNAT.Serial_Communications; diff --git a/gcc/ada/libgnat/g-sercom__linux.adb b/gcc/ada/libgnat/g-sercom__linux.adb index 93bc793..f116aea 100644 --- a/gcc/ada/libgnat/g-sercom__linux.adb +++ b/gcc/ada/libgnat/g-sercom__linux.adb @@ -58,19 +58,32 @@ package body GNAT.Serial_Communications is pragma Import (C, fcntl, "fcntl"); C_Data_Rate : constant array (Data_Rate) of unsigned := - (B75 => OSC.B75, - B110 => OSC.B110, - B150 => OSC.B150, - B300 => OSC.B300, - B600 => OSC.B600, - B1200 => OSC.B1200, - B2400 => OSC.B2400, - B4800 => OSC.B4800, - B9600 => OSC.B9600, - B19200 => OSC.B19200, - B38400 => OSC.B38400, - B57600 => OSC.B57600, - B115200 => OSC.B115200); + (B75 => OSC.B75, + B110 => OSC.B110, + B150 => OSC.B150, + B300 => OSC.B300, + B600 => OSC.B600, + B1200 => OSC.B1200, + B2400 => OSC.B2400, + B4800 => OSC.B4800, + B9600 => OSC.B9600, + B19200 => OSC.B19200, + B38400 => OSC.B38400, + B57600 => OSC.B57600, + B115200 => OSC.B115200, + B230400 => OSC.B230400, + B460800 => OSC.B460800, + B500000 => OSC.B500000, + B576000 => OSC.B576000, + B921600 => OSC.B921600, + B1000000 => OSC.B1000000, + B1152000 => OSC.B1152000, + B1500000 => OSC.B1500000, + B2000000 => OSC.B2000000, + B2500000 => OSC.B2500000, + B3000000 => OSC.B3000000, + B3500000 => OSC.B3500000, + B4000000 => OSC.B4000000); C_Bits : constant array (Data_Bits) of unsigned := (CS7 => OSC.CS7, CS8 => OSC.CS8); -- cgit v1.1 From 92c7734db7af1395be571c5ec023a38fb7b42adf Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Mon, 8 Jul 2019 08:13:43 +0000 Subject: [Ada] New algorithm for Elaboration order v4.0 This patch introduces several changes to the new elaboration order mechanism: * The concept of "strong" and "weak" edges is introduced. Strong edges are the byproduct of language-defined relations between units, such as with clauses. Weak edges are the byproduct of specilative invocations at elaboration time, which may or may not take place depending on control flow. * The elaboration order algorithm has been heavily modified to make use of the strong and weak edges, and operate on units compiled with different elaboration models. * The elaboration order algorithm employs the following logic: - Maintain two sets of vertices, one for all elaborable vertices, and one for all waiting vertices. - Pick the best elaborable vertex, and elaborate its component. - If no such elaborable vertex is available, pick the best weakly elaborable vertex whose unit has been compiled with the dynamic model, and elaborate its component. - If no such weakly elaborable vertex is available, then either all vertices were already elaborated, or the graph contains a cycle. The elaboration of a component employs the same logic, with an added step where all successors of some predecessor currently being elaborated are notified that they have one fewer predecessor to wait on. This may cause certain successors to become elaborable, in which case they are moved from the set of waiting vertices to the set of elaborable vertices. * Three new GNATbind debug switches are introduced, -d_a, -d_b, and -d_e, to eliminate the effects of pragmas Elaborate_All, Elaborate_Body, and Elaborate respectively. * The section on terminology is updated to include new entries. 2019-07-08 Hristian Kirtchev gcc/ada/ * bindo.adb: Update the section on terminology to include new concepts. Update the section on switches to include new entries. * bindo.ads: Add type Precedence_Kind. * bindo-builders.adb: Add with and use clauses for Debug and Bindo.Validators. Add use clauses for Bindo.Validators.Invocation_Graph_Validators and Bindo.Validators.Library_Graph_Validators. (Build_Invocation_Graph): Validate the graph immediately after it was built. (Build_Library_Graph): Update the parameter profile. The creation of the graph is now elaboration model-agnostic. Validate the graph immediately after it was built. (Create_With_Edge): Create regular with edges for Elaborate and Elaborate_All edges when the appropriate debug switches are in effect. * bindo-builders.ads (Build_Library_Graph): Update the parameter profile. * bindo-diagnostics.adb (Diagnose_Cycle): Track the presence of an Elaborate_All edge throughout the inspection of the cycle's edges. (Output_Dynamic_Model_Suggestions): Output the suggestion only when the cycle contains at least one weak edge where the successor was statically elaborated. (Output_Elaborate_Body_Transition, Output_Forced_Transition, Output_With_Transition): Update the assertions. * bindo-elaborators.adb: Remove use clauses for Bindo.Validators.Invocation_Graph_Validators and Bindo.Validators.Library_Graph_Validators. Remove strings Add_To_All_Candidates_Msg and Add_To_Comp_Candidates_Msg. Remove type String_Ptr. (Add_Vertex, Add_Vertex_If_Elaborable, Create_All_Candidates_Set Create_Component_Candidates_Set): Remove. (Create_Component_Vertex_Sets, Create_Vertex_Sets): New routine. (Elaborate_Component): Update the parameter profile and the comment on usage. Reimplement the elaboration of a component. The algorithm will now attempt to elaborate as many vertices possible. If this is not possible, and a weakly elaborable vertex is available use unit was compiled using the dynamic model, the algorithm will elaborate it. (Elaborate_Library_Graph): Reimplement the elaboration of the graph. The algorithm will now attempt to elaborate as many vertices along with their components as possible. If this is not possible, and a weakly elaborable vertex is available use unit was compiled using the dynamic model, the algorithm will elaborate it along with its component. (Elaborate_Units): Merge with the functionality of Elaborate_Units_Common. (Elaborate_Units_Common, Elaborate_Units_Dynamic, Elaborate_Units_Static): Remove. (Elaborate_Vertex): Update the parameter profile and the comment on usage. Reimplemented. (Find_Best_Candidate): Remove. (Find_Best_Elaborable_Vertex, Find_Best_Vertex, Find_Best_Weakly_Elaborable_Vertex, Has_Elaborable_Body, Insert_Elaborable_Successor, Insert_Vertex): New routines. (Is_Better_Candidate): Remove. (Is_Better_Elaborable_Vertex, Is_Better_Weakly_Elaborable_Vertex, Is_Suitable_Elaborable_Vertex, Is_Suitable_Weakly_Elaborable_Vertex): New routines. (Trace_Candidate_Vertices): Remove. (Trace_Component): Output the number of strong and weak predecessors. (Trace_Unelaborated_Vertices): Remove. (Trace_Vertex): Output the number of strong and weak predecessors. (Trace_Vertices): New routine. (Update_Successor, Update_Successors): Update the parameter profile and the comment on usage. * bindo-graphs.adb: Remove type Precedence_Kind. (Add_Edge_With_Return): Update the increment of pending predecessors. (Add_Vertex): Provide default values for strong and weak predecessors. (Complementary_Vertex): Move the initial declaration to the spec. Update the parameter profile and the comment on usage. (Contains_Weak_Static_Successor): New routine. (Create): Update the parameter profile. The creation of the graph is now elaboration model-agnostic. (Decrement_Pending_Predecessors): Update the parameter profile and the comment on usage. Reimplemented. (Delete_Edge): Update the decrement of pending predecesors. (Has_Elaborate_Body): Do not treat a vertex as being subject to Elaborate_Body when a debug switch is in effect. (Increment_Pending_Predecessors): Update the parameter profile and the comment on usage. Reimplemented. (Is_Elaborable_Component): Reimplemented. (Is_Elaborable_Vertex): Move the initial declaration to the spec. Reimplemented. (Is_Elaborate_Body_Pair): New routine. (Is_Dynamically_Elaborated): Update the parameter profile. Reimplemented. (Is_Weakly_Elaborable_Vertex): New routine. (Pending_Predecessors): Removed. (Pending_Predecessors_For_Elaboration, Pending_Strong_Predecessors, Pending_Weak_Predecessors, Update_Pending_Predecessors): New routines. (Update_Pending_Predecessors_Of_Components): Update the increment of pending predecessors. * bindo-graphs.ads: Update the components of type Component_Attributes. Update the components of type Library_Graph_Attributes. Update the components of type Library_Graph_Vertex_Attributes. Update the initialization of No_Component_Attributes. Update the initialization of No_Library_Graph_Vertex_Attributes. (Complementary_Vertex, Contains_Weak_Static_Successor): New routines. (Create): Update the parameter profile and the comment on usage. (Decrement_Pending_Predecessors, Is_Dynamically_Elaborated): Update the parameter profile and the comment on usage. (Is_Elaborate_Body_Pair, Is_Weakly_Elaborable_Vertex): New routines. (Pending_Predecessors): Removed. (Pending_Predecessors_For_Elaboration, Pending_Strong_Predecessors, Pending_Weak_Predecessors): New routines. * bindo-writers.adb (Write_Components): Moved from the spec. (Write_Component): Output the strong and weak predecessors. (Write_Library_Graph): Output the components as part of the graph. (Write_Library_Graph_Vertex): Output the strong and weak predecessors. * bindo-writers.ads (Write_Components): Moved to the body. * debug.adb: Add and document new GNATbind switches -d_a, -d_b, -d_e. * bindo-validators.adb: Minor reformattings. From-SVN: r273209 --- gcc/ada/ChangeLog | 130 +++ gcc/ada/bindo-builders.adb | 36 +- gcc/ada/bindo-builders.ads | 6 +- gcc/ada/bindo-diagnostics.adb | 45 +- gcc/ada/bindo-elaborators.adb | 1907 +++++++++++++++++++++++------------------ gcc/ada/bindo-graphs.adb | 527 ++++++++---- gcc/ada/bindo-graphs.ads | 156 +++- gcc/ada/bindo-validators.adb | 12 +- gcc/ada/bindo-writers.adb | 23 +- gcc/ada/bindo-writers.ads | 3 - gcc/ada/bindo.adb | 48 +- gcc/ada/bindo.ads | 10 + gcc/ada/debug.adb | 17 +- 13 files changed, 1845 insertions(+), 1075 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 3bbc1cf..e6eac08 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,133 @@ +2019-07-08 Hristian Kirtchev + + * bindo.adb: Update the section on terminology to include new + concepts. Update the section on switches to include new + entries. + * bindo.ads: Add type Precedence_Kind. + * bindo-builders.adb: Add with and use clauses for Debug and + Bindo.Validators. Add use clauses for + Bindo.Validators.Invocation_Graph_Validators and + Bindo.Validators.Library_Graph_Validators. + (Build_Invocation_Graph): Validate the graph immediately after + it was built. + (Build_Library_Graph): Update the parameter profile. The + creation of the graph is now elaboration model-agnostic. + Validate the graph immediately after it was built. + (Create_With_Edge): Create regular with edges for Elaborate and + Elaborate_All edges when the appropriate debug switches are in + effect. + * bindo-builders.ads (Build_Library_Graph): Update the parameter + profile. + * bindo-diagnostics.adb (Diagnose_Cycle): Track the presence of + an Elaborate_All edge throughout the inspection of the cycle's + edges. + (Output_Dynamic_Model_Suggestions): Output the suggestion only + when the cycle contains at least one weak edge where the + successor was statically elaborated. + (Output_Elaborate_Body_Transition, Output_Forced_Transition, + Output_With_Transition): Update the assertions. + * bindo-elaborators.adb: Remove use clauses for + Bindo.Validators.Invocation_Graph_Validators and + Bindo.Validators.Library_Graph_Validators. Remove strings + Add_To_All_Candidates_Msg and Add_To_Comp_Candidates_Msg. + Remove type String_Ptr. + (Add_Vertex, Add_Vertex_If_Elaborable, Create_All_Candidates_Set + Create_Component_Candidates_Set): Remove. + (Create_Component_Vertex_Sets, Create_Vertex_Sets): New routine. + (Elaborate_Component): Update the parameter profile and the + comment on usage. Reimplement the elaboration of a component. + The algorithm will now attempt to elaborate as many vertices + possible. If this is not possible, and a weakly elaborable + vertex is available use unit was compiled using the dynamic + model, the algorithm will elaborate it. + (Elaborate_Library_Graph): Reimplement the elaboration of the + graph. The algorithm will now attempt to elaborate as many + vertices along with their components as possible. If this is not + possible, and a weakly elaborable vertex is available use unit + was compiled using the dynamic model, the algorithm will + elaborate it along with its component. + (Elaborate_Units): Merge with the functionality of + Elaborate_Units_Common. + (Elaborate_Units_Common, Elaborate_Units_Dynamic, + Elaborate_Units_Static): Remove. + (Elaborate_Vertex): Update the parameter profile and the comment + on usage. Reimplemented. + (Find_Best_Candidate): Remove. + (Find_Best_Elaborable_Vertex, Find_Best_Vertex, + Find_Best_Weakly_Elaborable_Vertex, Has_Elaborable_Body, + Insert_Elaborable_Successor, Insert_Vertex): New routines. + (Is_Better_Candidate): Remove. + (Is_Better_Elaborable_Vertex, + Is_Better_Weakly_Elaborable_Vertex, + Is_Suitable_Elaborable_Vertex, + Is_Suitable_Weakly_Elaborable_Vertex): New routines. + (Trace_Candidate_Vertices): Remove. + (Trace_Component): Output the number of strong and weak + predecessors. + (Trace_Unelaborated_Vertices): Remove. + (Trace_Vertex): Output the number of strong and weak + predecessors. + (Trace_Vertices): New routine. + (Update_Successor, Update_Successors): Update the parameter + profile and the comment on usage. + * bindo-graphs.adb: Remove type Precedence_Kind. + (Add_Edge_With_Return): Update the increment of pending + predecessors. + (Add_Vertex): Provide default values for strong and weak + predecessors. + (Complementary_Vertex): Move the initial declaration to the + spec. Update the parameter profile and the comment on usage. + (Contains_Weak_Static_Successor): New routine. + (Create): Update the parameter profile. The creation of the + graph is now elaboration model-agnostic. + (Decrement_Pending_Predecessors): Update the parameter profile + and the comment on usage. Reimplemented. + (Delete_Edge): Update the decrement of pending predecesors. + (Has_Elaborate_Body): Do not treat a vertex as being subject to + Elaborate_Body when a debug switch is in effect. + (Increment_Pending_Predecessors): Update the parameter profile + and the comment on usage. Reimplemented. + (Is_Elaborable_Component): Reimplemented. + (Is_Elaborable_Vertex): Move the initial declaration to the + spec. Reimplemented. + (Is_Elaborate_Body_Pair): New routine. + (Is_Dynamically_Elaborated): Update the parameter profile. + Reimplemented. + (Is_Weakly_Elaborable_Vertex): New routine. + (Pending_Predecessors): Removed. + (Pending_Predecessors_For_Elaboration, + Pending_Strong_Predecessors, Pending_Weak_Predecessors, + Update_Pending_Predecessors): New routines. + (Update_Pending_Predecessors_Of_Components): Update the + increment of pending predecessors. + * bindo-graphs.ads: Update the components of type + Component_Attributes. Update the components of type + Library_Graph_Attributes. Update the components of type + Library_Graph_Vertex_Attributes. Update the initialization of + No_Component_Attributes. Update the initialization of + No_Library_Graph_Vertex_Attributes. + (Complementary_Vertex, Contains_Weak_Static_Successor): New + routines. + (Create): Update the parameter profile and the comment on usage. + (Decrement_Pending_Predecessors, Is_Dynamically_Elaborated): + Update the parameter profile and the comment on usage. + (Is_Elaborate_Body_Pair, Is_Weakly_Elaborable_Vertex): New + routines. + (Pending_Predecessors): Removed. + (Pending_Predecessors_For_Elaboration, + Pending_Strong_Predecessors, Pending_Weak_Predecessors): New + routines. + * bindo-writers.adb (Write_Components): Moved from the spec. + (Write_Component): Output the strong and weak predecessors. + (Write_Library_Graph): Output the components as part of the + graph. + (Write_Library_Graph_Vertex): Output the strong and weak + predecessors. + * bindo-writers.ads (Write_Components): Moved to the body. + * debug.adb: Add and document new GNATbind switches -d_a, -d_b, + -d_e. + * bindo-validators.adb: Minor reformattings. + 2019-07-08 Bob Duff * libgnat/g-sercom.ads, libgnat/g-sercom__linux.adb (Data_Rate): diff --git a/gcc/ada/bindo-builders.adb b/gcc/ada/bindo-builders.adb index f4b8e42..233891d 100644 --- a/gcc/ada/bindo-builders.adb +++ b/gcc/ada/bindo-builders.adb @@ -25,12 +25,18 @@ with Binderr; use Binderr; with Butil; use Butil; +with Debug; use Debug; with Opt; use Opt; with Output; use Output; with Types; use Types; with Bindo.Units; use Bindo.Units; +with Bindo.Validators; +use Bindo.Validators; +use Bindo.Validators.Invocation_Graph_Validators; +use Bindo.Validators.Library_Graph_Validators; + with GNAT; use GNAT; with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables; @@ -104,6 +110,8 @@ package body Bindo.Builders is For_Each_Elaborable_Unit (Create_Vertices'Access); For_Each_Elaborable_Unit (Create_Edges'Access); + Validate_Invocation_Graph (Inv_Graph); + return Inv_Graph; end Build_Invocation_Graph; @@ -365,24 +373,22 @@ package body Bindo.Builders is -- Build_Library_Graph -- ------------------------- - function Build_Library_Graph - (Dynamically_Elaborated : Boolean) return Library_Graph - is + function Build_Library_Graph return Library_Graph is begin -- Prepare the global data Lib_Graph := Create - (Initial_Vertices => Number_Of_Elaborable_Units, - Initial_Edges => Number_Of_Elaborable_Units, - Dynamically_Elaborated => Dynamically_Elaborated); + (Initial_Vertices => Number_Of_Elaborable_Units, + Initial_Edges => Number_Of_Elaborable_Units); For_Each_Elaborable_Unit (Create_Vertex'Access); For_Each_Elaborable_Unit (Create_Spec_And_Body_Edge'Access); For_Each_Elaborable_Unit (Create_With_Edges'Access); - Create_Forced_Edges; + Validate_Library_Graph (Lib_Graph); + return Lib_Graph; end Build_Library_Graph; @@ -549,9 +555,13 @@ package body Bindo.Builders is Withed_Vertex := Corresponding_Vertex (Lib_Graph, Withed_U_Id); - -- The with comes with pragma Elaborate + -- The with comes with pragma Elaborate. Treat the edge as a with + -- edge when switch -d_e (ignore the effects of pragma Elaborate) + -- is in effect. - if Withed_Rec.Elaborate then + if Withed_Rec.Elaborate + and then not Debug_Flag_Underscore_E + then Kind := Elaborate_Edge; -- The withed unit is a spec with a completing body. Add an edge @@ -568,9 +578,13 @@ package body Bindo.Builders is Kind => Kind); end if; - -- The with comes with pragma Elaborate_All + -- The with comes with pragma Elaborate_All. Treat the edge as a with + -- edge when switch -d_a (ignore the effects of pragma Elaborate_All) + -- is in effect. - elsif Withed_Rec.Elaborate_All then + elsif Withed_Rec.Elaborate_All + and then not Debug_Flag_Underscore_A + then Kind := Elaborate_All_Edge; -- Otherwise this is a regular with diff --git a/gcc/ada/bindo-builders.ads b/gcc/ada/bindo-builders.ads index 0e8519f..54c39e4 100644 --- a/gcc/ada/bindo-builders.ads +++ b/gcc/ada/bindo-builders.ads @@ -56,11 +56,9 @@ package Bindo.Builders is ---------------------------- package Library_Graph_Builders is - function Build_Library_Graph - (Dynamically_Elaborated : Boolean) return Library_Graph; + function Build_Library_Graph return Library_Graph; -- Return a new library graph that reflects the dependencies between - -- all units of the bind. Flag Dynamically_Elaborated must be set when - -- the main library unit was compiled using the dynamic model. + -- all units of the bind. end Library_Graph_Builders; diff --git a/gcc/ada/bindo-diagnostics.adb b/gcc/ada/bindo-diagnostics.adb index 0c9da46..0c1a924 100644 --- a/gcc/ada/bindo-diagnostics.adb +++ b/gcc/ada/bindo-diagnostics.adb @@ -285,9 +285,9 @@ package body Bindo.Diagnostics is end loop; end Diagnose_All_Cycles; - -------------------------- + ---------------------------- -- Diagnose_Circularities -- - -------------------------- + ---------------------------- procedure Diagnose_Circularities (Inv_Graph : Invocation_Graph; @@ -374,6 +374,12 @@ package body Bindo.Diagnostics is -- taking into account the predecessors and successors involved, as -- well as the nature of the edge. + Elaborate_All_Active := + Elaborate_All_Active + or else Is_Elaborate_All_Edge + (G => Lib_Graph, + Edge => Current_Edge); + Output_Transition (Inv_Graph => Inv_Graph, Lib_Graph => Lib_Graph, @@ -533,12 +539,12 @@ package body Bindo.Diagnostics is pragma Assert (Present (G)); pragma Assert (Present (Cycle)); - -- The cycle contains at least one invocation edge and the main library - -- unit was compiled with the static model. Using the dynamic model may - -- eliminate the invocation edge, and thus the cycle. + -- The cycle contains at least one invocation edge where the successor + -- was statically elaborated. Using the dynamic model may eliminate an + -- invocation edge, and thus the cycle. if Invocation_Edge_Count (G, Cycle) > 0 - and then not Is_Dynamically_Elaborated (G) + and then Contains_Weak_Static_Successor (G, Cycle) then Error_Msg_Info (" use the dynamic elaboration model (compiler switch -gnatE)"); @@ -703,10 +709,11 @@ package body Bindo.Diagnostics is -- Expected_Destination else - pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); - pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); pragma Assert - (Proper_Body (G, Actual_Destination) = Expected_Destination); + (Is_Elaborate_Body_Pair + (G => G, + Spec_Vertex => Actual_Destination, + Body_Vertex => Expected_Destination)); Error_Msg_Unit_1 := Name (G, Source); Error_Msg_Unit_2 := Name (G, Actual_Destination); @@ -922,13 +929,11 @@ package body Bindo.Diagnostics is -- Expected_Destination else - pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); - pragma Assert (Is_Spec_With_Elaborate_Body (G, Actual_Destination)); - pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); - pragma Assert - (Is_Body_Of_Spec_With_Elaborate_Body (G, Expected_Destination)); pragma Assert - (Proper_Body (G, Actual_Destination) = Expected_Destination); + (Is_Elaborate_Body_Pair + (G => G, + Spec_Vertex => Actual_Destination, + Body_Vertex => Expected_Destination)); Error_Msg_Unit_1 := Name (G, Source); Error_Msg_Unit_2 := Name (G, Actual_Destination); @@ -1392,13 +1397,11 @@ package body Bindo.Diagnostics is -- Expected_Destination else - pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); - pragma Assert (Is_Spec_With_Elaborate_Body (G, Actual_Destination)); - pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); - pragma Assert - (Is_Body_Of_Spec_With_Elaborate_Body (G, Expected_Destination)); pragma Assert - (Proper_Body (G, Actual_Destination) = Expected_Destination); + (Is_Elaborate_Body_Pair + (G => G, + Spec_Vertex => Actual_Destination, + Body_Vertex => Expected_Destination)); Error_Msg_Unit_1 := Name (G, Source); Error_Msg_Unit_2 := Name (G, Actual_Destination); diff --git a/gcc/ada/bindo-elaborators.adb b/gcc/ada/bindo-elaborators.adb index 762198b..192e4a2 100644 --- a/gcc/ada/bindo-elaborators.adb +++ b/gcc/ada/bindo-elaborators.adb @@ -46,8 +46,6 @@ use Bindo.Units; with Bindo.Validators; use Bindo.Validators; use Bindo.Validators.Elaboration_Order_Validators; -use Bindo.Validators.Invocation_Graph_Validators; -use Bindo.Validators.Library_Graph_Validators; with Bindo.Writers; use Bindo.Writers; @@ -76,76 +74,61 @@ package body Bindo.Elaborators is ---------------------------------------------- package body Invocation_And_Library_Graph_Elaborators is - Add_To_All_Candidates_Msg : aliased String := - "add vertex to all candidates"; - Add_To_Comp_Candidates_Msg : aliased String := - "add vertex to component candidates"; - - ----------- - -- Types -- - ----------- - - type String_Ptr is access all String; ----------------------- -- Local subprograms -- ----------------------- - procedure Add_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Msg : String; - Step : Elaboration_Order_Step; - Indent : Indentation_Level); - pragma Inline (Add_Vertex); - -- Add vertex Vertex of library graph G to membership set Set. Msg is - -- a message emitted for tracing purposes. Step is the current step in - -- the elaboration order. Indent is the desired indentation level for - -- tracing. - - procedure Add_Vertex_If_Elaborable - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Msg : String; - Step : Elaboration_Order_Step; - Indent : Indentation_Level); - pragma Inline (Add_Vertex_If_Elaborable); - -- Add vertex Vertex of library graph G to membership set Set if it can - -- be elaborated. Msg is a message emitted for tracing purposes. Step is - -- the current step in the elaboration order. Indent is the desired - -- indentation level for tracing. - - function Create_All_Candidates_Set - (G : Library_Graph; - Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set; - pragma Inline (Create_All_Candidates_Set); - -- Collect all elaborable candidate vertices of library graph G in a - -- set. Step is the current step in the elaboration order. - - function Create_Component_Candidates_Set - (G : Library_Graph; - Comp : Component_Id; - Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set; - pragma Inline (Create_Component_Candidates_Set); - -- Collect all elaborable candidate vertices that appear in component - -- Comp of library graph G in a set. Step is the current step in the - -- elaboration order. + procedure Create_Component_Vertex_Sets + (G : Library_Graph; + Comp : Component_Id; + Elaborable_Vertices : out LGV_Sets.Membership_Set; + Waiting_Vertices : out LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step); + pragma Inline (Create_Component_Vertex_Sets); + -- Split all vertices of component Comp of library graph G as follows: + -- + -- * Elaborable vertices are added to set Elaborable_Vertices. + -- + -- * Vertices that are still waiting on their predecessors to be + -- elaborated are added to set Waiting_Vertices. + -- + -- Step is the current step in the elaboration order. + + procedure Create_Vertex_Sets + (G : Library_Graph; + Elaborable_Vertices : out LGV_Sets.Membership_Set; + Waiting_Vertices : out LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step); + pragma Inline (Create_Vertex_Sets); + -- Split all vertices of library graph G as follows: + -- + -- * Elaborable vertices are added to set Elaborable_Vertices. + -- + -- * Vertices that are still waiting on their predecessors to be + -- elaborated are added to set Waiting_Vertices. + -- + -- Step is the current step in the elaboration order. procedure Elaborate_Component - (G : Library_Graph; - Comp : Component_Id; - All_Candidates : LGV_Sets.Membership_Set; - Remaining_Vertices : in out Natural; - Order : in out Unit_Id_Table; - Step : Elaboration_Order_Step); + (G : Library_Graph; + Comp : Component_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Order : in out Unit_Id_Table; + Step : Elaboration_Order_Step); pragma Inline (Elaborate_Component); - -- Elaborate as many vertices as possible that appear in component - -- Comp of library graph G. All_Candidates is the set of all elaborable - -- vertices across the whole library graph. Remaining_Vertices is the - -- number of vertices that remain to be elaborated. Order denotes the - -- elaboration order. Step is the current step in the elaboration order. + -- Elaborate as many vertices as possible that appear in component Comp + -- of library graph G. The sets contain vertices arranged as follows: + -- + -- * All_Elaborable_Vertices - all elaborable vertices in the library + -- graph. + -- + -- * All_Waiting_Vertices - all vertices in the library graph that are + -- waiting on predecessors to be elaborated. + -- + -- Order is the elaboration order. Step denotes the current step in the + -- elaboration order. procedure Elaborate_Library_Graph (G : Library_Graph; @@ -156,81 +139,149 @@ package body Bindo.Elaborators is -- the elaboration order. Status is the condition of the elaboration -- order. - procedure Elaborate_Units_Common - (Use_Inv_Graph : Boolean; - Is_Dyn_Elab : Boolean; - Inv_Graph : out Invocation_Graph; - Lib_Graph : out Library_Graph; - Order : out Unit_Id_Table; - Status : out Elaboration_Order_Status); - pragma Inline (Elaborate_Units_Common); - -- Find the elaboration order of all units in the bind. Use_Inv_Graph - -- should be set when library graph Lib_Graph is to be augmented with - -- information from invocation graph Inv_Graph. Is_Dyn_Elab should be - -- set when the main library unit was compiled using the dynamic model. - -- Order is the elaboration order. Status is the condition of the - -- elaboration order. - - procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table); - pragma Inline (Elaborate_Units_Dynamic); - -- Find the elaboration order of all units in the bind using the dynamic - -- model. Order is the elaboration order. In the event where no ordering - -- is possible, this routine diagnoses the issue(s) and raises exception - -- Unrecoverable_Error. - - procedure Elaborate_Units_Static (Order : out Unit_Id_Table); - pragma Inline (Elaborate_Units_Static); - -- Find the elaboration order of all units in the bind using the static - -- model. Order is the elaboration order. In the event where no ordering - -- is possible, this routine diagnoses the issue(s) and raises exception - -- Unrecoverable_Error. - procedure Elaborate_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - All_Candidates : LGV_Sets.Membership_Set; - Comp_Candidates : LGV_Sets.Membership_Set; - Remaining_Vertices : in out Natural; - Order : in out Unit_Id_Table; - Step : Elaboration_Order_Step; - Indent : Indentation_Level); + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Order : in out Unit_Id_Table; + Step : Elaboration_Order_Step; + Indent : Indentation_Level); pragma Inline (Elaborate_Vertex); -- Elaborate vertex Vertex of library graph G by adding its unit to -- elaboration order Order. The routine updates awaiting successors - -- where applicable. All_Candidates denotes the set of all elaborable - -- vertices across the whole library graph. Comp_Candidates is the set - -- of all elaborable vertices in the component of Vertex. Parameter - -- Remaining_Vertices denotes the number of vertices that remain to - -- be elaborated. Step is the current step in the elaboration order. + -- where applicable. The sets contain vertices arranged as follows: + -- + -- * All_Elaborable_Vertices - all elaborable vertices in the library + -- graph. + -- + -- * All_Waiting_Vertices - all vertices in the library graph that are + -- waiting on predecessors to be elaborated. + -- + -- * Comp_Elaborable_Vertices - all elaborable vertices found in the + -- component of Vertex. + -- + -- * Comp_Waiting_Vertices - all vertices found in the component of + -- Vertex that are still waiting on predecessors to be elaborated. + -- + -- Order denotes the elaboration order. Step is the current step in the + -- elaboration order. Indent denotes the desired indentation level for + -- tracing. + + function Find_Best_Elaborable_Vertex + (G : Library_Graph; + Set : LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) return Library_Graph_Vertex_Id; + pragma Inline (Find_Best_Elaborable_Vertex); + -- Find the best vertex of library graph G from membership set S that + -- can be elaborated. Step is the current step in the elaboration order. -- Indent is the desired indentation level for tracing. - function Find_Best_Candidate + type Comparator_Ptr is access function + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; + + type Predicate_Ptr is access function + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + + function Find_Best_Vertex + (G : Library_Graph; + Set : LGV_Sets.Membership_Set; + Is_Suitable_Vertex : Predicate_Ptr; + Compare_Vertices : Comparator_Ptr; + Initial_Best_Msg : String; + Subsequent_Best_Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) + return Library_Graph_Vertex_Id; + pragma Inline (Find_Best_Vertex); + -- Find the best vertex of library graph G from membership set S which + -- satisfies predicate Is_Suitable_Vertex and is preferred by comparator + -- Compare_Vertices. Initial_Best_Msg is emitted on the first candidate + -- vertex. Subsequent_Best_Msg is emitted whenever a better vertex is + -- discovered. Step is the current step in the elaboration order. Indent + -- is the desired indentation level for tracing. + + function Find_Best_Weakly_Elaborable_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id; - pragma Inline (Find_Best_Candidate); - -- Find the most suitable vertex of library graph G for elaboration from - -- membership set Set. Step denotes the current step in the elaboration + pragma Inline (Find_Best_Weakly_Elaborable_Vertex); + -- Find the best vertex of library graph G from membership set S that + -- can be weakly elaborated. Step is the current step in the elaboration -- order. Indent is the desired indentation level for tracing. - function Is_Better_Candidate - (G : Library_Graph; - Best_Candidate : Library_Graph_Vertex_Id; - New_Candidate : Library_Graph_Vertex_Id) return Boolean; - pragma Inline (Is_Better_Candidate); - -- Determine whether new candidate vertex New_Candidate of library graph - -- G is a more suitable choice for elaboration compared to the current - -- best candidate Best_Candidate. + function Has_Elaborable_Body + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Has_Elaborable_Body); + -- Determine whether vertex Vertex of library graph G has a body that is + -- elaborable. It is assumed that the vertex has been elaborated. + + procedure Insert_Elaborable_Successor + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level); + pragma Inline (Insert_Elaborable_Successor); + -- Add elaborable successor Vertex of library graph G to membership set + -- Elaborable_Vertices and remove it from both All_Waiting_Vertices and + -- Comp_Waiting_Vertices. Msg is a message emitted for tracing purposes. + -- Step is the current step in the elaboration order. Indent denotes the + -- desired indentation level for tracing. + + procedure Insert_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; + Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level); + pragma Inline (Insert_Vertex); + -- Add vertex Vertex of library graph G to membership set Set. Msg is + -- a message emitted for tracing purposes. Step is the current step in + -- the elaboration order. Indent is the desired indentation level for + -- tracing. - procedure Trace_Candidate_Vertices - (G : Library_Graph; - Set : LGV_Sets.Membership_Set; - Step : Elaboration_Order_Step); - pragma Inline (Trace_Candidate_Vertices); - -- Write the candidate vertices of library graph G present in membership - -- set Set to standard output. Formal Step denotes the current step in - -- the elaboration order. + function Is_Better_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; + pragma Inline (Is_Better_Elaborable_Vertex); + -- Determine whether vertex Vertex of library graph G is a better choice + -- for elaboration compared to vertex Compared_To. + + function Is_Better_Weakly_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; + pragma Inline (Is_Better_Weakly_Elaborable_Vertex); + -- Determine whether vertex Vertex of library graph G is a better choice + -- for weak elaboration compared to vertex Compared_To. + + function Is_Suitable_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Is_Suitable_Elaborable_Vertex); + -- Determine whether vertex Vertex of library graph G is suitable for + -- elaboration. + + function Is_Suitable_Weakly_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Is_Suitable_Weakly_Elaborable_Vertex); + -- Determine whether vertex Vertex of library graph G is suitable for + -- weak elaboration. procedure Trace_Component (G : Library_Graph; @@ -246,15 +297,6 @@ package body Bindo.Elaborators is pragma Inline (Trace_Step); -- Write current step Step of the elaboration order to standard output - procedure Trace_Unelaborated_Vertices - (G : Library_Graph; - Count : Natural; - Step : Elaboration_Order_Step); - pragma Inline (Trace_Unelaborated_Vertices); - -- Write the remaining unelaborated vertices of library graph G to - -- standard output. Count is the number of vertices that remain to - -- be elaborated. Step is the current step in the elaboration order. - procedure Trace_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; @@ -267,220 +309,202 @@ package body Bindo.Elaborators is -- current step in the elaboration order. Indent denotes the desired -- indentation level for tracing. + procedure Trace_Vertices + (G : Library_Graph; + Set : LGV_Sets.Membership_Set; + Set_Msg : String; + Vertex_Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level); + pragma Inline (Trace_Vertices); + -- Write the candidate vertices of library graph G present in membership + -- set Set to standard output, starting with message Set_Msg. Vertex_Msg + -- is the message emitted prior to each vertex. Step denotes the current + -- step in the elaboration order. Indent denotes the desired indentation + -- level for tracing. + procedure Update_Successor - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - Succ : Library_Graph_Vertex_Id; - All_Candidates : LGV_Sets.Membership_Set; - Comp_Candidates : LGV_Sets.Membership_Set; - Step : Elaboration_Order_Step; - Indent : Indentation_Level); + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step; + Indent : Indentation_Level); pragma Inline (Update_Successor); - -- Notify successor vertex Succ of library graph G along with its - -- component that their predecessor Pred has just been elaborated. - -- This may cause new vertices to become elaborable, and thus be added - -- to one of the two sets. All_Candidates is the set of all elaborable - -- vertices across the whole library graph. Comp_Candidates is the set - -- of all elaborable vertices in the component of Pred. Step is the - -- current step in the elaboration order. Indent denotes the desired - -- indentation level for tracing. + -- Notify the successor of edge Edge of library graph G along with its + -- component that their predecessor has just been elaborated. This may + -- cause new vertices to become elaborable. The sets contain vertices + -- arranged as follows: + -- + -- * All_Elaborable_Vertices - all elaborable vertices in the library + -- graph. + -- + -- * All_Waiting_Vertices - all vertices in the library graph that are + -- waiting on predecessors to be elaborated. + -- + -- * Comp_Elaborable_Vertices - all elaborable vertices found in the + -- component of Vertex. + -- + -- * Comp_Waiting_Vertices - all vertices found in the component of + -- Vertex that are still waiting on predecessors to be elaborated. + -- + -- Step is the current step in the elaboration order. Indent denotes the + -- desired indentation level for tracing. procedure Update_Successors - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - All_Candidates : LGV_Sets.Membership_Set; - Comp_Candidates : LGV_Sets.Membership_Set; - Step : Elaboration_Order_Step; - Indent : Indentation_Level); + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step; + Indent : Indentation_Level); pragma Inline (Update_Successors); - -- Notify all successors along with their components that their - -- predecessor vertex Pred of ligrary graph G has just been elaborated. - -- This may cause new vertices to become elaborable, and thus be added - -- to one of the two sets. All_Candidates is the set of all elaborable - -- vertices across the whole library graph. Comp_Candidates is the set - -- of all elaborable vertices in the component of Pred. Step is the - -- current step in the elaboration order. Indent denotes the desired - -- indentation level for tracing. - - ---------------- - -- Add_Vertex -- - ---------------- - - procedure Add_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Msg : String; - Step : Elaboration_Order_Step; - Indent : Indentation_Level) + -- Notify all successors of vertex Vertex of library graph G along with + -- their components that their predecessor has just been elaborated. + -- This may cause new vertices to become elaborable. The sets contain + -- vertices arranged as follows: + -- + -- * All_Elaborable_Vertices - all elaborable vertices in the library + -- graph. + -- + -- * All_Waiting_Vertices - all vertices in the library graph that are + -- waiting on predecessors to be elaborated. + -- + -- * Comp_Elaborable_Vertices - all elaborable vertices found in the + -- component of Vertex. + -- + -- * Comp_Waiting_Vertices - all vertices found in the component of + -- Vertex that are still waiting on predecessors to be elaborated. + -- + -- Step is the current step in the elaboration order. Indent denotes the + -- desired indentation level for tracing. + + ---------------------------------- + -- Create_Component_Vertex_Sets -- + ---------------------------------- + + procedure Create_Component_Vertex_Sets + (G : Library_Graph; + Comp : Component_Id; + Elaborable_Vertices : out LGV_Sets.Membership_Set; + Waiting_Vertices : out LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step) is - begin - pragma Assert (Present (Vertex)); - pragma Assert (Needs_Elaboration (G, Vertex)); - pragma Assert (LGV_Sets.Present (Set)); - - -- Add vertex only when it is not present in the set. This is not - -- strictly necessary because the set implementation handles this - -- case, however the check eliminates spurious traces. - - if not LGV_Sets.Contains (Set, Vertex) then - Trace_Vertex - (G => G, - Vertex => Vertex, - Msg => Msg, - Step => Step, - Indent => Indent); - - LGV_Sets.Insert (Set, Vertex); - end if; - end Add_Vertex; + pragma Assert (Present (G)); + pragma Assert (Present (Comp)); - ------------------------------ - -- Add_Vertex_If_Elaborable -- - ------------------------------ + Num_Of_Vertices : constant Natural := + Number_Of_Component_Vertices (G, Comp); - procedure Add_Vertex_If_Elaborable - (G : Library_Graph; + Iter : Component_Vertex_Iterator; Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Msg : String; - Step : Elaboration_Order_Step; - Indent : Indentation_Level) - is - Extra_Vertex : Library_Graph_Vertex_Id; begin - pragma Assert (Present (G)); - pragma Assert (Present (Vertex)); - pragma Assert (Needs_Elaboration (G, Vertex)); - pragma Assert (LGV_Sets.Present (Set)); - - if Is_Elaborable_Vertex (G, Vertex) then - Add_Vertex - (G => G, - Vertex => Vertex, - Set => Set, - Msg => Msg, - Step => Step, - Indent => Indent); - - -- Assume that there is no extra vertex that needs to be added + Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices); + Waiting_Vertices := LGV_Sets.Create (Num_Of_Vertices); - Extra_Vertex := No_Library_Graph_Vertex; - - -- A spec-body pair where the spec carries pragma Elaborate_Body - -- must be treated as one vertex for elaboration purposes. If one - -- of them is elaborable, then the other is also elaborable. This - -- property is guaranteed by predicate Is_Elaborable_Vertex. - - if Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then - Extra_Vertex := Proper_Spec (G, Vertex); - pragma Assert (Present (Extra_Vertex)); + Iter := Iterate_Component_Vertices (G, Comp); + while Has_Next (Iter) loop + Next (Iter, Vertex); - elsif Is_Spec_With_Elaborate_Body (G, Vertex) then - Extra_Vertex := Proper_Body (G, Vertex); - pragma Assert (Present (Extra_Vertex)); - end if; + -- Add the vertex to the proper set depending on whether it can be + -- elaborated. - if Present (Extra_Vertex) then - pragma Assert (Needs_Elaboration (G, Extra_Vertex)); + if Is_Elaborable_Vertex (G, Vertex) then + Insert_Vertex + (G => G, + Vertex => Vertex, + Set => Elaborable_Vertices, + Msg => "add elaborable component vertex", + Step => Step, + Indent => No_Indentation); - Add_Vertex + else + Insert_Vertex (G => G, - Vertex => Extra_Vertex, - Set => Set, - Msg => Msg, + Vertex => Vertex, + Set => Waiting_Vertices, + Msg => "add waiting component vertex", Step => Step, - Indent => Indent); + Indent => No_Indentation); end if; - end if; - end Add_Vertex_If_Elaborable; + end loop; + end Create_Component_Vertex_Sets; - ------------------------------- - -- Create_All_Candidates_Set -- - ------------------------------- + ------------------------ + -- Create_Vertex_Sets -- + ------------------------ - function Create_All_Candidates_Set - (G : Library_Graph; - Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set + procedure Create_Vertex_Sets + (G : Library_Graph; + Elaborable_Vertices : out LGV_Sets.Membership_Set; + Waiting_Vertices : out LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step) is + pragma Assert (Present (G)); + + Num_Of_Vertices : constant Natural := Number_Of_Vertices (G); + Iter : Library_Graphs.All_Vertex_Iterator; - Set : LGV_Sets.Membership_Set; Vertex : Library_Graph_Vertex_Id; begin - pragma Assert (Present (G)); + Elaborable_Vertices := LGV_Sets.Create (Num_Of_Vertices); + Waiting_Vertices := LGV_Sets.Create (Num_Of_Vertices); - Set := LGV_Sets.Create (Number_Of_Vertices (G)); Iter := Iterate_All_Vertices (G); while Has_Next (Iter) loop Next (Iter, Vertex); - Add_Vertex_If_Elaborable - (G => G, - Vertex => Vertex, - Set => Set, - Msg => Add_To_All_Candidates_Msg, - Step => Step, - Indent => No_Indentation); - end loop; - - return Set; - end Create_All_Candidates_Set; - - ------------------------------------- - -- Create_Component_Candidates_Set -- - ------------------------------------- - - function Create_Component_Candidates_Set - (G : Library_Graph; - Comp : Component_Id; - Step : Elaboration_Order_Step) return LGV_Sets.Membership_Set - is - Iter : Component_Vertex_Iterator; - Set : LGV_Sets.Membership_Set; - Vertex : Library_Graph_Vertex_Id; - - begin - pragma Assert (Present (G)); - pragma Assert (Present (Comp)); + -- Add the vertex to the proper set depending on whether it can be + -- elaborated. - Set := LGV_Sets.Create (Number_Of_Component_Vertices (G, Comp)); - Iter := Iterate_Component_Vertices (G, Comp); - while Has_Next (Iter) loop - Next (Iter, Vertex); + if Is_Elaborable_Vertex (G, Vertex) then + Insert_Vertex + (G => G, + Vertex => Vertex, + Set => Elaborable_Vertices, + Msg => "add elaborable vertex", + Step => Step, + Indent => No_Indentation); - Add_Vertex_If_Elaborable - (G => G, - Vertex => Vertex, - Set => Set, - Msg => Add_To_Comp_Candidates_Msg, - Step => Step, - Indent => No_Indentation); + else + Insert_Vertex + (G => G, + Vertex => Vertex, + Set => Waiting_Vertices, + Msg => "add waiting vertex", + Step => Step, + Indent => No_Indentation); + end if; end loop; - - return Set; - end Create_Component_Candidates_Set; + end Create_Vertex_Sets; ------------------------- -- Elaborate_Component -- ------------------------- procedure Elaborate_Component - (G : Library_Graph; - Comp : Component_Id; - All_Candidates : LGV_Sets.Membership_Set; - Remaining_Vertices : in out Natural; - Order : in out Unit_Id_Table; - Step : Elaboration_Order_Step) + (G : Library_Graph; + Comp : Component_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Order : in out Unit_Id_Table; + Step : Elaboration_Order_Step) is - Candidate : Library_Graph_Vertex_Id; - Comp_Candidates : LGV_Sets.Membership_Set; + Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Vertex : Library_Graph_Vertex_Id; begin pragma Assert (Present (G)); pragma Assert (Present (Comp)); - pragma Assert (LGV_Sets.Present (All_Candidates)); + pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); Trace_Component (G => G, @@ -488,35 +512,81 @@ package body Bindo.Elaborators is Msg => "elaborating component", Step => Step); - Comp_Candidates := Create_Component_Candidates_Set (G, Comp, Step); + -- Divide all vertices of the component into an elaborable and + -- waiting vertex set. + + Create_Component_Vertex_Sets + (G => G, + Comp => Comp, + Elaborable_Vertices => Comp_Elaborable_Vertices, + Waiting_Vertices => Comp_Waiting_Vertices, + Step => Step); loop - Candidate := - Find_Best_Candidate + Trace_Vertices + (G => G, + Set => Comp_Elaborable_Vertices, + Set_Msg => "elaborable component vertices", + Vertex_Msg => "elaborable component vertex", + Step => Step, + Indent => Nested_Indentation); + + Trace_Vertices + (G => G, + Set => Comp_Waiting_Vertices, + Set_Msg => "waiting component vertices", + Vertex_Msg => "waiting component vertex", + Step => Step, + Indent => Nested_Indentation); + + Vertex := + Find_Best_Elaborable_Vertex (G => G, - Set => Comp_Candidates, + Set => Comp_Elaborable_Vertices, Step => Step, Indent => Nested_Indentation); - -- Stop the elaboration of the component when there is no suitable - -- candidate. This indicates that either all vertices within the - -- component have been elaborated, or the library graph contains a - -- circularity. + -- The component lacks an elaborable vertex. This indicates that + -- either all vertices of the component have been elaborated or + -- the graph has a circularity. Locate the best weak vertex that + -- was compiled with the dynamic model to elaborate from the set + -- waiting vertices. This action assumes that certain invocations + -- will not take place at elaboration time. An order produced in + -- this fashion may fail an ABE check at run time. + + if not Present (Vertex) then + Vertex := + Find_Best_Weakly_Elaborable_Vertex + (G => G, + Set => Comp_Waiting_Vertices, + Step => Step, + Indent => Nested_Indentation); + end if; + + -- Stop the elaboration when either all vertices of the component + -- have been elaborated, or the graph contains a circularity. + + exit when not Present (Vertex); - exit when not Present (Candidate); + -- Try to elaborate as many vertices within the component as + -- possible. Each successful elaboration signals the appropriate + -- successors and components that they have one less predecessor + -- to wait on. Elaborate_Vertex - (G => G, - Vertex => Candidate, - All_Candidates => All_Candidates, - Comp_Candidates => Comp_Candidates, - Remaining_Vertices => Remaining_Vertices, - Order => Order, - Step => Step, - Indent => Nested_Indentation); + (G => G, + Vertex => Vertex, + All_Elaborable_Vertices => All_Elaborable_Vertices, + All_Waiting_Vertices => All_Waiting_Vertices, + Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, + Comp_Waiting_Vertices => Comp_Waiting_Vertices, + Order => Order, + Step => Step, + Indent => Nested_Indentation); end loop; - LGV_Sets.Destroy (Comp_Candidates); + LGV_Sets.Destroy (Comp_Elaborable_Vertices); + LGV_Sets.Destroy (Comp_Waiting_Vertices); end Elaborate_Component; ----------------------------- @@ -528,73 +598,97 @@ package body Bindo.Elaborators is Order : out Unit_Id_Table; Status : out Elaboration_Order_Status) is - All_Candidates : LGV_Sets.Membership_Set; - Candidate : Library_Graph_Vertex_Id; - Remaining_Vertices : Natural; - Step : Elaboration_Order_Step; + Elaborable_Vertices : LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step; + Vertex : Library_Graph_Vertex_Id; + Waiting_Vertices : LGV_Sets.Membership_Set; begin pragma Assert (Present (G)); Step := Initial_Step; - All_Candidates := Create_All_Candidates_Set (G, Step); - Remaining_Vertices := Number_Of_Vertices (G); + -- Divide all vertices of the library graph into an elaborable and + -- waiting vertex set. + + Create_Vertex_Sets + (G => G, + Elaborable_Vertices => Elaborable_Vertices, + Waiting_Vertices => Waiting_Vertices, + Step => Step); loop Step := Step + 1; - Trace_Candidate_Vertices - (G => G, - Set => All_Candidates, - Step => Step); - - Trace_Unelaborated_Vertices - (G => G, - Count => Remaining_Vertices, - Step => Step); - - Candidate := - Find_Best_Candidate + Trace_Vertices + (G => G, + Set => Elaborable_Vertices, + Set_Msg => "elaborable vertices", + Vertex_Msg => "elaborable vertex", + Step => Step, + Indent => No_Indentation); + + Trace_Vertices + (G => G, + Set => Waiting_Vertices, + Set_Msg => "waiting vertices", + Vertex_Msg => "waiting vertex", + Step => Step, + Indent => No_Indentation); + + Vertex := + Find_Best_Elaborable_Vertex (G => G, - Set => All_Candidates, + Set => Elaborable_Vertices, Step => Step, Indent => No_Indentation); - -- Stop the elaboration when there is no suitable candidate. This - -- indicates that either all units were elaborated or the library - -- graph contains a circularity. + -- The graph lacks an elaborable vertex. This indicates that + -- either all vertices have been elaborated or the graph has a + -- circularity. Find the best weak vertex that was compiled with + -- the dynamic model to elaborate from set of waiting vertices. + -- This action assumes that certain invocations will not take + -- place at elaboration time. An order produced in this fashion + -- may fail an ABE check at run time. + + if not Present (Vertex) then + Vertex := + Find_Best_Weakly_Elaborable_Vertex + (G => G, + Set => Waiting_Vertices, + Step => Step, + Indent => No_Indentation); + end if; + + -- Stop the elaboration when either all vertices of the graph have + -- been elaborated, or the graph contains a circularity. - exit when not Present (Candidate); + exit when not Present (Vertex); - -- Elaborate the component of the candidate vertex by trying to - -- elaborate as many vertices within the component as possible. - -- Each successful elaboration signals the appropriate successors - -- and their components that they have one less predecessor to - -- wait on. This may add new candidates to set All_Candidates. + -- Elaborate the component of the vertex by trying to elaborate as + -- many vertices within the component as possible. Each successful + -- elaboration signals the appropriate successors and components + -- that they have one less predecessor to wait on. Elaborate_Component - (G => G, - Comp => Component (G, Candidate), - All_Candidates => All_Candidates, - Remaining_Vertices => Remaining_Vertices, - Order => Order, - Step => Step); + (G => G, + Comp => Component (G, Vertex), + All_Elaborable_Vertices => Elaborable_Vertices, + All_Waiting_Vertices => Waiting_Vertices, + Order => Order, + Step => Step); end loop; - LGV_Sets.Destroy (All_Candidates); - - -- The library graph contains an Elaborate_All circularity when - -- at least one edge subject to the related pragma appears in a - -- component. + -- The graph contains an Elaborate_All circularity when at least one + -- edge subject to the related pragma appears in a component. if Has_Elaborate_All_Cycle (G) then Status := Order_Has_Elaborate_All_Circularity; - -- The library contains a circularity when at least one vertex failed + -- The graph contains a circularity when at least one vertex failed -- to elaborate. - elsif Remaining_Vertices /= 0 then + elsif LGV_Sets.Size (Waiting_Vertices) /= 0 then Status := Order_Has_Circularity; -- Otherwise the elaboration order is satisfactory @@ -602,6 +696,9 @@ package body Bindo.Elaborators is else Status := Order_OK; end if; + + LGV_Sets.Destroy (Elaborable_Vertices); + LGV_Sets.Destroy (Waiting_Vertices); end Elaborate_Library_Graph; --------------------- @@ -612,271 +709,114 @@ package body Bindo.Elaborators is (Order : out Unit_Id_Table; Main_Lib_File : File_Name_Type) is - Main_Lib_Unit : constant Unit_Id := - Corresponding_Unit (Unit_Name_Type (Main_Lib_File)); + pragma Unreferenced (Main_Lib_File); - begin - pragma Assert (Present (Main_Lib_Unit)); + Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Status : Elaboration_Order_Status; + begin -- Initialize all unit-related data structures and gather all units -- that need elaboration. Initialize_Units; Collect_Elaborable_Units; - Write_ALI_Tables; - - -- Choose the proper elaboration strategy based on whether the main - -- library unit was compiled using the dynamic model. - - if Is_Dynamically_Elaborated (Main_Lib_Unit) then - Elaborate_Units_Dynamic (Order); - else - Elaborate_Units_Static (Order); - end if; - - Validate_Elaboration_Order (Order); - Write_Elaboration_Order (Order); - - -- Enumerate the sources referenced in the closure of the order - - Write_Unit_Closure (Order); - - -- Destroy all unit-delated data structures - - Finalize_Units; - - exception - when others => - Finalize_Units; - raise; - end Elaborate_Units; - - ---------------------------- - -- Elaborate_Units_Common -- - ---------------------------- - - procedure Elaborate_Units_Common - (Use_Inv_Graph : Boolean; - Is_Dyn_Elab : Boolean; - Inv_Graph : out Invocation_Graph; - Lib_Graph : out Library_Graph; - Order : out Unit_Id_Table; - Status : out Elaboration_Order_Status) - is - begin - -- Create, validate, and output the library graph that captures the - -- dependencies between library items. - - Lib_Graph := Build_Library_Graph (Is_Dyn_Elab); - Validate_Library_Graph (Lib_Graph); - Write_Library_Graph (Lib_Graph); - - -- Create, validate, output, and use the invocation graph that - -- represents the flow of execusion only when requested by the - -- caller. + -- Create the library graph that captures the dependencies between + -- library items. - if Use_Inv_Graph then - Inv_Graph := Build_Invocation_Graph (Lib_Graph); - Validate_Invocation_Graph (Inv_Graph); - Write_Invocation_Graph (Inv_Graph); + Lib_Graph := Build_Library_Graph; - -- Otherwise the invocation graph is not used. Create a dummy graph - -- as this allows for a uniform behavior on the caller side. + -- Create the invocation graph that represents the flow of execution - else - Inv_Graph := - Invocation_Graphs.Create - (Initial_Vertices => 1, - Initial_Edges => 1); - end if; + Inv_Graph := Build_Invocation_Graph (Lib_Graph); -- Traverse the invocation graph starting from elaboration code in -- order to discover transitions of the execution flow from a unit -- to a unit that result in extra edges within the library graph. Augment_Library_Graph (Inv_Graph, Lib_Graph); - Write_Library_Graph (Lib_Graph); - -- Create and output the component graph by collapsing all library - -- items into library units and traversing the library graph. + -- Create the component graph by collapsing all library items into + -- library units and traversing the library graph. - Find_Components (Lib_Graph); - Write_Components (Lib_Graph); + Find_Components (Lib_Graph); - -- Traverse the library graph to determine the elaboration order of - -- units. + -- Output the contents of the ALI tables and both graphs to standard + -- output now that they have been fully decorated. - Elaborate_Library_Graph - (G => Lib_Graph, - Order => Order, - Status => Status); - end Elaborate_Units_Common; - - ----------------------------- - -- Elaborate_Units_Dynamic -- - ----------------------------- + Write_ALI_Tables; + Write_Invocation_Graph (Inv_Graph); + Write_Library_Graph (Lib_Graph); - procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table) is - Dyn_Inv_Graph : Invocation_Graph; - Dyn_Lib_Graph : Library_Graph; - Dyn_Order : Unit_Id_Table; - Mix_Inv_Graph : Invocation_Graph; - Mix_Lib_Graph : Library_Graph; - Mix_Order : Unit_Id_Table; - Status : Elaboration_Order_Status; + -- Traverse the library graph to determine the elaboration order of + -- units. - begin - -- Attempt to elaborate the units in the library graph by mixing in - -- the information from the invocation graph. This assumes that all - -- invocations will take place at elaboration time. - - Elaborate_Units_Common - (Use_Inv_Graph => True, - Is_Dyn_Elab => True, - Inv_Graph => Mix_Inv_Graph, - Lib_Graph => Mix_Lib_Graph, - Order => Mix_Order, - Status => Status); + Elaborate_Library_Graph (Lib_Graph, Order, Status); -- The elaboration order is satisfactory if Status = Order_OK then - Order := Mix_Order; + Validate_Elaboration_Order (Order); - -- Output the dependencies of vertices when switch -e (output + -- Output the dependencies among units when switch -e (output -- complete list of elaboration order dependencies) is active. - Write_Dependencies (Mix_Lib_Graph); - - -- The library graph contains an Elaborate_All circularity. There is - -- no point in re-elaborating the units without the information from - -- the invocation graph because the circularity will persist. - - elsif Status = Order_Has_Elaborate_All_Circularity then - Diagnose_Circularities - (Inv_Graph => Mix_Inv_Graph, - Lib_Graph => Mix_Lib_Graph); - - -- Otherwise the library graph contains a circularity, or the extra - -- information provided by the invocation graph caused a circularity. - -- Re-elaborate the units without using the invocation graph. This - -- assumes that all invocations will not take place at elaboration - -- time. - - else - pragma Assert (Status = Order_Has_Circularity); - - Elaborate_Units_Common - (Use_Inv_Graph => False, - Is_Dyn_Elab => True, - Inv_Graph => Dyn_Inv_Graph, - Lib_Graph => Dyn_Lib_Graph, - Order => Dyn_Order, - Status => Status); - - -- The elaboration order is satisfactory. The elaboration of the - -- program may still fail at runtime with an ABE. - - if Status = Order_OK then - Order := Dyn_Order; - - -- Output the dependencies of vertices when switch -e (output - -- complete list of elaboration order dependencies) is active. - - Write_Dependencies (Dyn_Lib_Graph); - - -- Otherwise the library graph contains a circularity without the - -- extra information provided by the invocation graph. Diagnose - -- the circularity. - - else - Diagnose_Circularities - (Inv_Graph => Dyn_Inv_Graph, - Lib_Graph => Dyn_Lib_Graph); - end if; - - Destroy (Dyn_Inv_Graph); - Destroy (Dyn_Lib_Graph); - end if; - - Destroy (Mix_Inv_Graph); - Destroy (Mix_Lib_Graph); - - -- Halt the bind as there is no satisfactory elaboration order - - if Status /= Order_OK then - raise Unrecoverable_Error; - end if; - end Elaborate_Units_Dynamic; + Write_Dependencies (Lib_Graph); - ---------------------------- - -- Elaborate_Units_Static -- - ---------------------------- + -- Output the elaboration order when switch -l (output chosen + -- elaboration order) is in effect. - procedure Elaborate_Units_Static (Order : out Unit_Id_Table) is - Inv_Graph : Invocation_Graph; - Lib_Graph : Library_Graph; - Status : Elaboration_Order_Status; + Write_Elaboration_Order (Order); - begin - -- Attempt to elaborate the units in the library graph by mixing in - -- the information from the invocation graph. This assumes that all - -- invocations will take place at elaboration time. - - Elaborate_Units_Common - (Use_Inv_Graph => True, - Is_Dyn_Elab => False, - Inv_Graph => Inv_Graph, - Lib_Graph => Lib_Graph, - Order => Order, - Status => Status); - - -- The elaboration order is satisfactory. Output the dependencies of - -- vertices when switch -e (output complete list of elaboration order - -- dependencies) is active. + -- Output the sources referenced in the closure of the order when + -- switch -R (list sources referenced in closure) is in effect. - if Status = Order_OK then - Write_Dependencies (Lib_Graph); + Write_Unit_Closure (Order); - -- Otherwise the augmented library graph contains a circularity + -- Otherwise the library graph contains at least one circularity else - Diagnose_Circularities - (Inv_Graph => Inv_Graph, - Lib_Graph => Lib_Graph); + Diagnose_Circularities (Inv_Graph, Lib_Graph); end if; Destroy (Inv_Graph); Destroy (Lib_Graph); - -- Halt the bind as there is no satisfactory elaboration order + -- Destroy all unit-related data structures + + Finalize_Units; + + -- Halt the bind when there is no satisfactory elaboration order if Status /= Order_OK then raise Unrecoverable_Error; end if; - end Elaborate_Units_Static; + end Elaborate_Units; ---------------------- -- Elaborate_Vertex -- ---------------------- procedure Elaborate_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - All_Candidates : LGV_Sets.Membership_Set; - Comp_Candidates : LGV_Sets.Membership_Set; - Remaining_Vertices : in out Natural; - Order : in out Unit_Id_Table; - Step : Elaboration_Order_Step; - Indent : Indentation_Level) + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Order : in out Unit_Id_Table; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) is begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); pragma Assert (Needs_Elaboration (G, Vertex)); - pragma Assert (LGV_Sets.Present (All_Candidates)); - pragma Assert (LGV_Sets.Present (Comp_Candidates)); + pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); + pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); Trace_Vertex (G => G, @@ -885,14 +825,20 @@ package body Bindo.Elaborators is Step => Step, Indent => Indent); - -- Remove the vertex from both candidate sets. This is needed when + -- Remove the vertex from both elaborable sets. This is needed when -- the vertex is both an overall best candidate among all vertices, - -- and the best candidate within the component. There is no need to - -- check that the vertex is present in either set because the set - -- implementation handles this case. + -- and the best candidate within the component. + + LGV_Sets.Delete (All_Elaborable_Vertices, Vertex); + LGV_Sets.Delete (Comp_Elaborable_Vertices, Vertex); - LGV_Sets.Delete (All_Candidates, Vertex); - LGV_Sets.Delete (Comp_Candidates, Vertex); + -- Remove the vertex from both waiting sets. This is needed when a + -- weakly elaborable vertex is both an overall best candidate among + -- all waiting vertices and the best waiting candidate within the + -- component. + + LGV_Sets.Delete (All_Waiting_Vertices, Vertex); + LGV_Sets.Delete (Comp_Waiting_Vertices, Vertex); -- Mark the vertex as elaborated in order to prevent further attempts -- to re-elaborate it. @@ -903,202 +849,469 @@ package body Bindo.Elaborators is Unit_Id_Tables.Append (Order, Unit (G, Vertex)); - -- There is now one fewer vertex to elaborate - - Remaining_Vertices := Remaining_Vertices - 1; - -- Notify all successors and their components that they have one -- fewer predecessor to wait on. This may cause some successors to -- be included in one of the sets. Update_Successors - (G => G, - Pred => Vertex, - All_Candidates => All_Candidates, - Comp_Candidates => Comp_Candidates, - Step => Step, - Indent => Indent + Nested_Indentation); - - -- The vertex denotes a spec with a completing body, and is subject - -- to pragma Elaborate_Body. Elaborate the body in order to satisfy - -- the semantics of the pragma. - - if Is_Spec_With_Elaborate_Body (G, Vertex) then + (G => G, + Vertex => Vertex, + All_Elaborable_Vertices => All_Elaborable_Vertices, + All_Waiting_Vertices => All_Waiting_Vertices, + Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, + Comp_Waiting_Vertices => Comp_Waiting_Vertices, + Step => Step, + Indent => Indent + Nested_Indentation); + + -- Elaborate an eligible completing body immediately after its spec. + -- This action satisfies the semantics of pragma Elaborate_Body. In + -- addition, it ensures that a body will not "drift" too far from its + -- spec in case invocation edges are removed from the library graph. + + if Has_Elaborable_Body (G, Vertex) then Elaborate_Vertex - (G => G, - Vertex => Proper_Body (G, Vertex), - All_Candidates => All_Candidates, - Comp_Candidates => Comp_Candidates, - Remaining_Vertices => Remaining_Vertices, - Order => Order, - Step => Step, - Indent => Indent); + (G => G, + Vertex => Proper_Body (G, Vertex), + All_Elaborable_Vertices => All_Elaborable_Vertices, + All_Waiting_Vertices => All_Waiting_Vertices, + Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, + Comp_Waiting_Vertices => Comp_Waiting_Vertices, + Order => Order, + Step => Step, + Indent => Indent); end if; end Elaborate_Vertex; - ------------------------- - -- Find_Best_Candidate -- - ------------------------- + --------------------------------- + -- Find_Best_Elaborable_Vertex -- + --------------------------------- - function Find_Best_Candidate + function Find_Best_Elaborable_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; Step : Elaboration_Order_Step; Indent : Indentation_Level) return Library_Graph_Vertex_Id is - Best : Library_Graph_Vertex_Id; - Current : Library_Graph_Vertex_Id; - Iter : LGV_Sets.Iterator; + begin + pragma Assert (Present (G)); + pragma Assert (LGV_Sets.Present (Set)); + + return + Find_Best_Vertex + (G => G, + Set => Set, + Is_Suitable_Vertex => + Is_Suitable_Elaborable_Vertex'Access, + Compare_Vertices => + Is_Better_Elaborable_Vertex'Access, + Initial_Best_Msg => "initial best elaborable vertex", + Subsequent_Best_Msg => "better elaborable vertex", + Step => Step, + Indent => Indent); + end Find_Best_Elaborable_Vertex; + + ---------------------- + -- Find_Best_Vertex -- + ---------------------- + + function Find_Best_Vertex + (G : Library_Graph; + Set : LGV_Sets.Membership_Set; + Is_Suitable_Vertex : Predicate_Ptr; + Compare_Vertices : Comparator_Ptr; + Initial_Best_Msg : String; + Subsequent_Best_Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) + return Library_Graph_Vertex_Id + is + Best_Vertex : Library_Graph_Vertex_Id; + Current_Vertex : Library_Graph_Vertex_Id; + Iter : LGV_Sets.Iterator; begin pragma Assert (Present (G)); pragma Assert (LGV_Sets.Present (Set)); + pragma Assert (Is_Suitable_Vertex /= null); + pragma Assert (Compare_Vertices /= null); -- Assume that there is no candidate - Best := No_Library_Graph_Vertex; + Best_Vertex := No_Library_Graph_Vertex; - -- Inspect all vertices in the set, looking for the best candidate to - -- elaborate. + -- Inspect all vertices in the set, looking for the best candidate + -- according to the comparator. Iter := LGV_Sets.Iterate (Set); while LGV_Sets.Has_Next (Iter) loop - LGV_Sets.Next (Iter, Current); - pragma Assert (Needs_Elaboration (G, Current)); + LGV_Sets.Next (Iter, Current_Vertex); + pragma Assert (Needs_Elaboration (G, Current_Vertex)); + + if Is_Suitable_Vertex.all (G, Current_Vertex) then + + -- A previous iteration already picked the best candidate. + -- Update the best candidate when the current vertex is a + -- better choice. + + if Present (Best_Vertex) then + if Compare_Vertices.all + (G => G, + Vertex => Current_Vertex, + Compared_To => Best_Vertex) = Higher_Precedence + then + Best_Vertex := Current_Vertex; + + Trace_Vertex + (G => G, + Vertex => Best_Vertex, + Msg => Subsequent_Best_Msg, + Step => Step, + Indent => Indent); + end if; + + -- Otherwise this is the first candidate + + else + Best_Vertex := Current_Vertex; + + Trace_Vertex + (G => G, + Vertex => Best_Vertex, + Msg => Initial_Best_Msg, + Step => Step, + Indent => Indent); + end if; + end if; + end loop; - -- Update the best candidate when there is no such candidate + return Best_Vertex; + end Find_Best_Vertex; - if not Present (Best) then - Best := Current; + ---------------------------------------- + -- Find_Best_Weakly_Elaborable_Vertex -- + ---------------------------------------- - Trace_Vertex - (G => G, - Vertex => Best, - Msg => "initial best candidate vertex", - Step => Step, - Indent => Indent); + function Find_Best_Weakly_Elaborable_Vertex + (G : Library_Graph; + Set : LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) return Library_Graph_Vertex_Id + is + begin + pragma Assert (Present (G)); + pragma Assert (LGV_Sets.Present (Set)); - -- Update the best candidate when the current vertex is a better - -- choice. + return + Find_Best_Vertex + (G => G, + Set => Set, + Is_Suitable_Vertex => + Is_Suitable_Weakly_Elaborable_Vertex'Access, + Compare_Vertices => + Is_Better_Weakly_Elaborable_Vertex'Access, + Initial_Best_Msg => "initial best weakly elaborable vertex", + Subsequent_Best_Msg => "better weakly elaborable vertex", + Step => Step, + Indent => Indent); + end Find_Best_Weakly_Elaborable_Vertex; - elsif Is_Better_Candidate - (G => G, - Best_Candidate => Best, - New_Candidate => Current) - then - Best := Current; + ------------------------- + -- Has_Elaborable_Body -- + ------------------------- - Trace_Vertex - (G => G, - Vertex => Best, - Msg => "best candidate vertex", - Step => Step, - Indent => Indent); - end if; - end loop; + function Has_Elaborable_Body + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); - return Best; - end Find_Best_Candidate; + -- The body of an already-elaborated spec subject to Elaborate_Body + -- is always elaborable. - ------------------------- - -- Is_Better_Candidate -- - ------------------------- + if Is_Spec_With_Elaborate_Body (G, Vertex) then + return True; + + elsif Is_Spec_With_Body (G, Vertex) then + return Is_Elaborable_Vertex (G, Proper_Body (G, Vertex)); + end if; + + return False; + end Has_Elaborable_Body; + + --------------------------------- + -- Insert_Elaborable_Successor -- + --------------------------------- + + procedure Insert_Elaborable_Successor + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) + is + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + pragma Assert (LGV_Sets.Present (Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); + pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); + + Complement : constant Library_Graph_Vertex_Id := + Complementary_Vertex + (G => G, + Vertex => Vertex, + Force_Complement => False); + + begin + -- Remove the successor from both waiting vertex sets because it may + -- be the best vertex to elaborate across the whole graph and within + -- its component. + + LGV_Sets.Delete (All_Waiting_Vertices, Vertex); + LGV_Sets.Delete (Comp_Waiting_Vertices, Vertex); + + Insert_Vertex + (G => G, + Vertex => Vertex, + Set => Elaborable_Vertices, + Msg => Msg, + Step => Step, + Indent => Indent); + + if Present (Complement) then + + -- Remove the complement of the successor from both waiting vertex + -- sets because it may be the best vertex to elaborate across the + -- whole graph and within its component. + + LGV_Sets.Delete (All_Waiting_Vertices, Complement); + LGV_Sets.Delete (Comp_Waiting_Vertices, Complement); + + Insert_Vertex + (G => G, + Vertex => Complement, + Set => Elaborable_Vertices, + Msg => Msg, + Step => Step, + Indent => Indent); + end if; + end Insert_Elaborable_Successor; + + ------------------- + -- Insert_Vertex -- + ------------------- + + procedure Insert_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Set : LGV_Sets.Membership_Set; + Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + pragma Assert (Needs_Elaboration (G, Vertex)); + pragma Assert (LGV_Sets.Present (Set)); + + -- Nothing to do when the vertex is already present in the set - function Is_Better_Candidate - (G : Library_Graph; - Best_Candidate : Library_Graph_Vertex_Id; - New_Candidate : Library_Graph_Vertex_Id) return Boolean + if LGV_Sets.Contains (Set, Vertex) then + return; + end if; + + Trace_Vertex + (G => G, + Vertex => Vertex, + Msg => Msg, + Step => Step, + Indent => Indent); + + -- Add the vertex to the set + + LGV_Sets.Insert (Set, Vertex); + end Insert_Vertex; + + --------------------------------- + -- Is_Better_Elaborable_Vertex -- + --------------------------------- + + function Is_Better_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind is begin pragma Assert (Present (G)); - pragma Assert (Present (Best_Candidate)); - pragma Assert (Present (New_Candidate)); + pragma Assert (Present (Vertex)); + pragma Assert (Present (Compared_To)); + + -- Prefer a spec with Elaborate_Body over its corresponding body + + if Is_Elaborate_Body_Pair + (G => G, + Spec_Vertex => Vertex, + Body_Vertex => Compared_To) + then + return Higher_Precedence; + + elsif Is_Elaborate_Body_Pair + (G => G, + Spec_Vertex => Compared_To, + Body_Vertex => Vertex) + then + return Lower_Precedence; -- Prefer a predefined unit over a non-predefined unit - if Is_Predefined_Unit (G, Best_Candidate) - and then not Is_Predefined_Unit (G, New_Candidate) + elsif Is_Predefined_Unit (G, Vertex) + and then not Is_Predefined_Unit (G, Compared_To) then - return False; + return Higher_Precedence; - elsif not Is_Predefined_Unit (G, Best_Candidate) - and then Is_Predefined_Unit (G, New_Candidate) + elsif not Is_Predefined_Unit (G, Vertex) + and then Is_Predefined_Unit (G, Compared_To) then - return True; + return Lower_Precedence; - -- Prefer an internal unit over a non-iternal unit + -- Prefer an internal unit over a non-internal unit - elsif Is_Internal_Unit (G, Best_Candidate) - and then not Is_Internal_Unit (G, New_Candidate) + elsif Is_Internal_Unit (G, Vertex) + and then not Is_Internal_Unit (G, Compared_To) then - return False; + return Higher_Precedence; - elsif not Is_Internal_Unit (G, Best_Candidate) - and then Is_Internal_Unit (G, New_Candidate) + elsif not Is_Internal_Unit (G, Vertex) + and then Is_Internal_Unit (G, Compared_To) then - return True; + return Lower_Precedence; -- Prefer a preelaborated unit over a non-preelaborated unit - elsif Is_Preelaborated_Unit (G, Best_Candidate) - and then not Is_Preelaborated_Unit (G, New_Candidate) + elsif Is_Preelaborated_Unit (G, Vertex) + and then not Is_Preelaborated_Unit (G, Compared_To) then - return False; + return Higher_Precedence; - elsif not Is_Preelaborated_Unit (G, Best_Candidate) - and then Is_Preelaborated_Unit (G, New_Candidate) + elsif not Is_Preelaborated_Unit (G, Vertex) + and then Is_Preelaborated_Unit (G, Compared_To) then - return True; + return Lower_Precedence; -- Otherwise default to lexicographical order to ensure deterministic -- behavior. + elsif Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then + return Higher_Precedence; + else - return - Uname_Less (Name (G, Best_Candidate), Name (G, New_Candidate)); + return Lower_Precedence; end if; - end Is_Better_Candidate; + end Is_Better_Elaborable_Vertex; - ------------------------------ - -- Trace_Candidate_Vertices -- - ------------------------------ + ---------------------------------------- + -- Is_Better_Weakly_Elaborable_Vertex -- + ---------------------------------------- - procedure Trace_Candidate_Vertices - (G : Library_Graph; - Set : LGV_Sets.Membership_Set; - Step : Elaboration_Order_Step) + function Is_Better_Weakly_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind is - Iter : LGV_Sets.Iterator; - Vertex : Library_Graph_Vertex_Id; + Comp_Strong_Preds : Natural; + Comp_Weak_Preds : Natural; + Vertex_Strong_Preds : Natural; + Vertex_Weak_Preds : Natural; begin pragma Assert (Present (G)); - pragma Assert (LGV_Sets.Present (Set)); + pragma Assert (Present (Vertex)); + pragma Assert (Present (Compared_To)); - -- Nothing to do when switch -d_T (output elaboration order and cycle - -- detection trace information) is not in effect. + -- Obtain the number of pending predecessors for both candidates, + -- taking into account Elaborate_Body pairs. - if not Debug_Flag_Underscore_TT then - return; + Pending_Predecessors_For_Elaboration + (G => G, + Vertex => Vertex, + Strong_Preds => Vertex_Strong_Preds, + Weak_Preds => Vertex_Weak_Preds); + + Pending_Predecessors_For_Elaboration + (G => G, + Vertex => Compared_To, + Strong_Preds => Comp_Strong_Preds, + Weak_Preds => Comp_Weak_Preds); + + -- Neither candidate should be waiting on strong predecessors, + -- otherwise the candidate cannot be weakly elaborated. + + pragma Assert (Vertex_Strong_Preds = 0); + pragma Assert (Comp_Strong_Preds = 0); + + -- Prefer a unit with fewer weak predecessors over a unit with more + -- weak predecessors. + + if Vertex_Weak_Preds < Comp_Weak_Preds then + return Higher_Precedence; + + elsif Vertex_Weak_Preds > Comp_Weak_Preds then + return Lower_Precedence; + + -- Otherwise default to lexicographical order to ensure deterministic + -- behavior. + + elsif Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then + return Higher_Precedence; + + else + return Lower_Precedence; end if; + end Is_Better_Weakly_Elaborable_Vertex; - Trace_Step (Step); - Write_Str ("candidate vertices: "); - Write_Int (Int (LGV_Sets.Size (Set))); - Write_Eol; + ----------------------------------- + -- Is_Suitable_Elaborable_Vertex -- + ----------------------------------- - Iter := LGV_Sets.Iterate (Set); - while LGV_Sets.Has_Next (Iter) loop - LGV_Sets.Next (Iter, Vertex); + function Is_Suitable_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); - Trace_Vertex - (G => G, - Vertex => Vertex, - Msg => "candidate vertex", - Step => Step, - Indent => Nested_Indentation); - end loop; - end Trace_Candidate_Vertices; + -- A vertex is suitable for elaboration as long it is not waiting on + -- any predecessors, ignoring the static or dynamic model. + + return Is_Elaborable_Vertex (G, Vertex); + end Is_Suitable_Elaborable_Vertex; + + ------------------------------------------ + -- Is_Suitable_Weakly_Elaborable_Vertex -- + ------------------------------------------ + + function Is_Suitable_Weakly_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + -- A vertex is suitable for weak elaboration when it is waiting on + -- weak predecessors only, and the unit it represents was compiled + -- using the dynamic model. + + return + Is_Dynamically_Elaborated (G, Vertex) + and then Is_Weakly_Elaborable_Vertex (G, Vertex); + end Is_Suitable_Weakly_Elaborable_Vertex; --------------------- -- Trace_Component -- @@ -1130,8 +1343,14 @@ package body Bindo.Elaborators is Trace_Step (Step); Indent_By (Nested_Indentation); - Write_Str ("pending predecessors: "); - Write_Num (Int (Pending_Predecessors (G, Comp))); + Write_Str ("pending strong predecessors: "); + Write_Num (Int (Pending_Strong_Predecessors (G, Comp))); + Write_Eol; + + Trace_Step (Step); + Indent_By (Nested_Indentation); + Write_Str ("pending weak predecessors : "); + Write_Num (Int (Pending_Weak_Predecessors (G, Comp))); Write_Eol; end Trace_Component; @@ -1154,50 +1373,6 @@ package body Bindo.Elaborators is Write_Str (": "); end Trace_Step; - --------------------------------- - -- Trace_Unelaborated_Vertices -- - --------------------------------- - - procedure Trace_Unelaborated_Vertices - (G : Library_Graph; - Count : Natural; - Step : Elaboration_Order_Step) - is - Iter : Library_Graphs.All_Vertex_Iterator; - Vertex : Library_Graph_Vertex_Id; - - begin - pragma Assert (Present (G)); - - -- Nothing to do when switch -d_T (output elaboration order and cycle - -- detection trace information) is not in effect. - - if not Debug_Flag_Underscore_TT then - return; - end if; - - Trace_Step (Step); - Write_Str ("remaining unelaborated vertices: "); - Write_Int (Int (Count)); - Write_Eol; - - Iter := Iterate_All_Vertices (G); - while Has_Next (Iter) loop - Next (Iter, Vertex); - - if Needs_Elaboration (G, Vertex) - and then not In_Elaboration_Order (G, Vertex) - then - Trace_Vertex - (G => G, - Vertex => Vertex, - Msg => "remaining vertex", - Step => Step, - Indent => Nested_Indentation); - end if; - end loop; - end Trace_Unelaborated_Vertices; - ------------------ -- Trace_Vertex -- ------------------ @@ -1247,37 +1422,104 @@ package body Bindo.Elaborators is Trace_Step (Step); Indent_By (Attr_Indent); - Write_Str ("pending predecessors: "); - Write_Num (Int (Pending_Predecessors (G, Vertex))); + Write_Str ("pending strong predecessors: "); + Write_Num (Int (Pending_Strong_Predecessors (G, Vertex))); + Write_Eol; + + Trace_Step (Step); + Indent_By (Attr_Indent); + Write_Str ("pending weak predecessors : "); + Write_Num (Int (Pending_Weak_Predecessors (G, Vertex))); Write_Eol; Trace_Step (Step); Indent_By (Attr_Indent); - Write_Str ("pending components : "); - Write_Num (Int (Pending_Predecessors (G, Comp))); + Write_Str ("pending strong components : "); + Write_Num (Int (Pending_Strong_Predecessors (G, Comp))); + Write_Eol; + + Trace_Step (Step); + Indent_By (Attr_Indent); + Write_Str ("pending weak components : "); + Write_Num (Int (Pending_Weak_Predecessors (G, Comp))); Write_Eol; end Trace_Vertex; + -------------------- + -- Trace_Vertices -- + -------------------- + + procedure Trace_Vertices + (G : Library_Graph; + Set : LGV_Sets.Membership_Set; + Set_Msg : String; + Vertex_Msg : String; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) + is + Vertex_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + + Iter : LGV_Sets.Iterator; + Vertex : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (LGV_Sets.Present (Set)); + + -- Nothing to do when switch -d_T (output elaboration order and cycle + -- detection trace information) is not in effect. + + if not Debug_Flag_Underscore_TT then + return; + end if; + + Trace_Step (Step); + Indent_By (Indent); + Write_Str (Set_Msg); + Write_Str (": "); + Write_Int (Int (LGV_Sets.Size (Set))); + Write_Eol; + + Iter := LGV_Sets.Iterate (Set); + while LGV_Sets.Has_Next (Iter) loop + LGV_Sets.Next (Iter, Vertex); + + Trace_Vertex + (G => G, + Vertex => Vertex, + Msg => Vertex_Msg, + Step => Step, + Indent => Vertex_Indent); + end loop; + end Trace_Vertices; + ---------------------- -- Update_Successor -- ---------------------- procedure Update_Successor - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - Succ : Library_Graph_Vertex_Id; - All_Candidates : LGV_Sets.Membership_Set; - Comp_Candidates : LGV_Sets.Membership_Set; - Step : Elaboration_Order_Step; - Indent : Indentation_Level) + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) is pragma Assert (Present (G)); - pragma Assert (Present (Pred)); + pragma Assert (Present (Edge)); + pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); + pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); + + Pred : constant Library_Graph_Vertex_Id := Predecessor (G, Edge); + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); + pragma Assert (Needs_Elaboration (G, Pred)); - pragma Assert (Present (Succ)); pragma Assert (Needs_Elaboration (G, Succ)); - pragma Assert (LGV_Sets.Present (All_Candidates)); - pragma Assert (LGV_Sets.Present (Comp_Candidates)); In_Different_Components : constant Boolean := not In_Same_Component @@ -1289,10 +1531,8 @@ package body Bindo.Elaborators is Vertex_Indent : constant Indentation_Level := Indent + Nested_Indentation; - Candidate : Library_Graph_Vertex_Id; - Iter : Component_Vertex_Iterator; - Msg : String_Ptr; - Set : LGV_Sets.Membership_Set; + Iter : Component_Vertex_Iterator; + Vertex : Library_Graph_Vertex_Id; begin Trace_Vertex @@ -1305,45 +1545,61 @@ package body Bindo.Elaborators is -- Notify the successor that it has one less predecessor to wait on. -- This effectively eliminates the edge that links the two. - Decrement_Pending_Predecessors (G, Succ); + Decrement_Pending_Predecessors + (G => G, + Vertex => Succ, + Edge => Edge); -- The predecessor and successor reside in different components. -- Notify the successor component it has one fewer components to -- wait on. if In_Different_Components then - Decrement_Pending_Predecessors (G, Succ_Comp); + Decrement_Pending_Predecessors + (G => G, + Comp => Succ_Comp, + Edge => Edge); end if; -- At this point the successor may become elaborable when its final - -- predecessor or final predecessor component is elaborated. - - -- The predecessor and successor reside in different components. - -- The successor must not be added to the candidates of Pred's - -- component because this will mix units from the two components. - -- Instead, the successor is added to the set of all candidates - -- that must be elaborated. + -- predecessor or final predecessor component has been elaborated. + + if Is_Elaborable_Vertex (G, Succ) then + + -- The predecessor and successor reside in different components. + -- The successor must not be added to the candidates of Pred's + -- component because this will mix units from the two components. + -- Instead, the successor is added to the set of all elaborable + -- vertices. + + if In_Different_Components then + Insert_Elaborable_Successor + (G => G, + Vertex => Succ, + Elaborable_Vertices => All_Elaborable_Vertices, + All_Waiting_Vertices => All_Waiting_Vertices, + Comp_Waiting_Vertices => Comp_Waiting_Vertices, + Msg => "add elaborable successor", + Step => Step, + Indent => Vertex_Indent); + + -- Otherwise the predecessor and successor reside within the same + -- component. Pred's component gains another elaborable vertex. - if In_Different_Components then - Msg := Add_To_All_Candidates_Msg'Access; - Set := All_Candidates; - - -- Otherwise the predecessor and successor reside within the same - -- component. Pred's component gains another elaborable node. - - else - Msg := Add_To_Comp_Candidates_Msg'Access; - Set := Comp_Candidates; + else + Insert_Elaborable_Successor + (G => G, + Vertex => Succ, + Elaborable_Vertices => Comp_Elaborable_Vertices, + All_Waiting_Vertices => All_Waiting_Vertices, + Comp_Waiting_Vertices => Comp_Waiting_Vertices, + Msg => + "add elaborable component successor", + Step => Step, + Indent => Vertex_Indent); + end if; end if; - Add_Vertex_If_Elaborable - (G => G, - Vertex => Succ, - Set => Set, - Msg => Msg.all, - Step => Step, - Indent => Vertex_Indent); - -- At this point the successor component may become elaborable when -- its final predecessor component is elaborated. This in turn may -- allow vertices of the successor component to be elaborated. @@ -1353,15 +1609,19 @@ package body Bindo.Elaborators is then Iter := Iterate_Component_Vertices (G, Succ_Comp); while Has_Next (Iter) loop - Next (Iter, Candidate); - - Add_Vertex_If_Elaborable - (G => G, - Vertex => Candidate, - Set => All_Candidates, - Msg => Add_To_All_Candidates_Msg, - Step => Step, - Indent => Vertex_Indent); + Next (Iter, Vertex); + + if Is_Elaborable_Vertex (G, Vertex) then + Insert_Elaborable_Successor + (G => G, + Vertex => Vertex, + Elaborable_Vertices => All_Elaborable_Vertices, + All_Waiting_Vertices => All_Waiting_Vertices, + Comp_Waiting_Vertices => Comp_Waiting_Vertices, + Msg => "add elaborable vertex", + Step => Step, + Indent => Vertex_Indent); + end if; end loop; end if; end Update_Successor; @@ -1371,36 +1631,41 @@ package body Bindo.Elaborators is ----------------------- procedure Update_Successors - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - All_Candidates : LGV_Sets.Membership_Set; - Comp_Candidates : LGV_Sets.Membership_Set; - Step : Elaboration_Order_Step; - Indent : Indentation_Level) + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + All_Elaborable_Vertices : LGV_Sets.Membership_Set; + All_Waiting_Vertices : LGV_Sets.Membership_Set; + Comp_Elaborable_Vertices : LGV_Sets.Membership_Set; + Comp_Waiting_Vertices : LGV_Sets.Membership_Set; + Step : Elaboration_Order_Step; + Indent : Indentation_Level) is Edge : Library_Graph_Edge_Id; Iter : Edges_To_Successors_Iterator; begin pragma Assert (Present (G)); - pragma Assert (Present (Pred)); - pragma Assert (Needs_Elaboration (G, Pred)); - pragma Assert (LGV_Sets.Present (All_Candidates)); - pragma Assert (LGV_Sets.Present (Comp_Candidates)); + pragma Assert (Present (Vertex)); + pragma Assert (Needs_Elaboration (G, Vertex)); + pragma Assert (LGV_Sets.Present (All_Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (All_Waiting_Vertices)); + pragma Assert (LGV_Sets.Present (Comp_Elaborable_Vertices)); + pragma Assert (LGV_Sets.Present (Comp_Waiting_Vertices)); - Iter := Iterate_Edges_To_Successors (G, Pred); + Iter := Iterate_Edges_To_Successors (G, Vertex); while Has_Next (Iter) loop Next (Iter, Edge); - pragma Assert (Predecessor (G, Edge) = Pred); + pragma Assert (Predecessor (G, Edge) = Vertex); Update_Successor - (G => G, - Pred => Pred, - Succ => Successor (G, Edge), - All_Candidates => All_Candidates, - Comp_Candidates => Comp_Candidates, - Step => Step, - Indent => Indent); + (G => G, + Edge => Edge, + All_Elaborable_Vertices => All_Elaborable_Vertices, + All_Waiting_Vertices => All_Waiting_Vertices, + Comp_Elaborable_Vertices => Comp_Elaborable_Vertices, + Comp_Waiting_Vertices => Comp_Waiting_Vertices, + Step => Step, + Indent => Indent); end loop; end Update_Successors; end Invocation_And_Library_Graph_Elaborators; diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index c68e367..387d969 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -205,7 +205,7 @@ package body Bindo.Graphs is (G : Invocation_Graph; Rel : Source_Target_Relation) return Boolean; pragma Inline (Is_Existing_Source_Target_Relation); - -- Determine whether a source vertex and a target vertex desctibed by + -- Determine whether a source vertex and a target vertex described by -- relation Rel are already related in invocation graph G. procedure Save_Elaboration_Root @@ -226,7 +226,7 @@ package body Bindo.Graphs is Rel : Source_Target_Relation; Val : Boolean := True); pragma Inline (Set_Is_Existing_Source_Target_Relation); - -- Mark a source vertex and a target vertex desctibed by relation Rel as + -- Mark a source vertex and a target vertex described by relation Rel as -- already related in invocation graph G depending on value Val. procedure Set_IGE_Attributes @@ -1026,18 +1026,6 @@ package body Bindo.Graphs is package body Library_Graphs is - ----------- - -- Types -- - ----------- - - -- The following type represents the various kinds of precedence between - -- two items. - - type Precedence_Kind is - (Lower_Precedence, - Equal_Precedence, - Higher_Precedence); - ----------------------- -- Local subprograms -- ----------------------- @@ -1064,7 +1052,7 @@ package body Bindo.Graphs is Attrs : Library_Graph_Cycle_Attributes; Indent : Indentation_Level); pragma Inline (Add_Cycle); - -- Store a cycle described by attribytes Attrs in library graph G, + -- Store a cycle described by attributes Attrs in library graph G, -- unless a prior rotation of it already exists. The edges of the cycle -- must be in normalized form. Indent is the desired indentation level -- for tracing. @@ -1090,15 +1078,6 @@ package body Bindo.Graphs is -- part of an Elaborate_Body pair, or flag Do_Complement is set, add -- the complementary vertex to the set. - function Complementary_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Do_Complement : Boolean) return Library_Graph_Vertex_Id; - pragma Inline (Complementary_Vertex); - -- If vertex Vertex of library graph G is part of an Elaborate_Body - -- pair, or flag Do_Complement is set, return the spec when Vertex is - -- a body, the body when Vertex is a spec, or No_Library_Graph_Vertex. - function Copy_Cycle_Path (Cycle_Path : LGE_Lists.Doubly_Linked_List) return LGE_Lists.Doubly_Linked_List; @@ -1228,17 +1207,21 @@ package body Bindo.Graphs is procedure Increment_Pending_Predecessors (G : Library_Graph; - Comp : Component_Id); + Comp : Component_Id; + Edge : Library_Graph_Edge_Id); pragma Inline (Increment_Pending_Predecessors); - -- Increment the number of pending precedessors component Comp of - -- library graph G must wait on before it can be elaborated by one. + -- Increment the number of pending predecessors component Comp which was + -- reached via edge Edge of library graph G must wait on before it can + -- be elaborated by one. procedure Increment_Pending_Predecessors (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id; + Edge : Library_Graph_Edge_Id); pragma Inline (Increment_Pending_Predecessors); - -- Increment the number of pending precedessors vertex Vertex of library - -- graph G must wait on before it can be elaborated by one. + -- Increment the number of pending predecessors vertex Vertex which was + -- reached via edge Edge of library graph G must wait on before it can + -- be elaborated by one. procedure Initialize_Components (G : Library_Graph); pragma Inline (Initialize_Components); @@ -1306,22 +1289,14 @@ package body Bindo.Graphs is Edge : Library_Graph_Edge_Id) return Boolean; pragma Inline (Is_Cyclic_With_Edge); -- Determine whether edge Edge of library graph G participates in a - -- cycle and is the result of awith dependency between its successor + -- cycle and is the result of a with dependency between its successor -- and predecessor. - function Is_Elaborable_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Predecessors : Natural) return Boolean; - pragma Inline (Is_Elaborable_Vertex); - -- Determine whether vertex Vertex of library graph G can be elaborated - -- given that it meets number of predecessors Predecessors. - function Is_Recorded_Cycle (G : Library_Graph; Attrs : Library_Graph_Cycle_Attributes) return Boolean; pragma Inline (Is_Recorded_Cycle); - -- Determine whether a cycle desctibed by its attributes Attrs has + -- Determine whether a cycle described by its attributes Attrs has -- has already been recorded in library graph G. function Is_Recorded_Edge @@ -1329,7 +1304,7 @@ package body Bindo.Graphs is Rel : Predecessor_Successor_Relation) return Boolean; pragma Inline (Is_Recorded_Edge); -- Determine whether a predecessor vertex and a successor vertex - -- desctibed by relation Rel are already linked in library graph G. + -- described by relation Rel are already linked in library graph G. function Links_Vertices_In_Same_Component (G : Library_Graph; @@ -1441,7 +1416,7 @@ package body Bindo.Graphs is Rel : Predecessor_Successor_Relation; Val : Boolean := True); pragma Inline (Set_Is_Recorded_Edge); - -- Mark a predecessor vertex and a successor vertex desctibed by + -- Mark a predecessor vertex and a successor vertex described by -- relation Rel as already linked depending on value Val. procedure Set_LGC_Attributes @@ -1493,6 +1468,16 @@ package body Bindo.Graphs is -- Write the contents of vertex Vertex of library graph G to standard -- output. Indent is the desired indentation level for tracing. + procedure Update_Pending_Predecessors + (Strong_Predecessors : in out Natural; + Weak_Predecessors : in out Natural; + Update_Weak : Boolean; + Value : Integer); + pragma Inline (Update_Pending_Predecessors); + -- Update the number of pending strong or weak predecessors denoted by + -- Strong_Predecessors and Weak_Predecessors respectively depending on + -- flag Update_Weak by adding value Value. + procedure Update_Pending_Predecessors_Of_Components (G : Library_Graph); pragma Inline (Update_Pending_Predecessors_Of_Components); -- Update the number of pending predecessors all components of library @@ -1523,7 +1508,7 @@ package body Bindo.Graphs is pragma Assert (LGE_Lists.Present (Edges)); -- A vertex requires a special Body_Before_Spec edge to its - -- Corresponging_Item when it either denotes a + -- Corresponding_Item when it either denotes a -- -- * Body that completes a previous spec -- @@ -1717,7 +1702,10 @@ package body Bindo.Graphs is -- Update the number of pending predecessors the successor must wait -- on before it is elaborated. - Increment_Pending_Predecessors (G, Succ); + Increment_Pending_Predecessors + (G => G, + Vertex => Succ, + Edge => Edge); -- Update the edge statistics @@ -1757,10 +1745,12 @@ package body Bindo.Graphs is Set_LGV_Attributes (G => G, Vertex => Vertex, - Val => (Corresponding_Item => No_Library_Graph_Vertex, - In_Elaboration_Order => False, - Pending_Predecessors => 0, - Unit => U_Id)); + Val => + (Corresponding_Item => No_Library_Graph_Vertex, + In_Elaboration_Order => False, + Pending_Strong_Predecessors => 0, + Pending_Weak_Predecessors => 0, + Unit => U_Id)); -- Associate the unit with its corresponding vertex @@ -1783,9 +1773,9 @@ package body Bindo.Graphs is Complement : constant Library_Graph_Vertex_Id := Complementary_Vertex - (G => G, - Vertex => Vertex, - Do_Complement => Do_Complement); + (G => G, + Vertex => Vertex, + Force_Complement => Do_Complement); begin LGV_Sets.Insert (Set, Vertex); @@ -1800,9 +1790,9 @@ package body Bindo.Graphs is -------------------------- function Complementary_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Do_Complement : Boolean) return Library_Graph_Vertex_Id + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Force_Complement : Boolean) return Library_Graph_Vertex_Id is Complement : Library_Graph_Vertex_Id; @@ -1816,7 +1806,7 @@ package body Bindo.Graphs is -- The caller requests the complement explicitly - if Do_Complement then + if Force_Complement then Complement := Corresponding_Item (G, Vertex); -- The vertex is a completing body of a spec subject to pragma @@ -1850,6 +1840,46 @@ package body Bindo.Graphs is return DG.Component (G.Graph, Vertex); end Component; + ------------------------------------ + -- Contains_Weak_Static_Successor -- + ------------------------------------ + + function Contains_Weak_Static_Successor + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Boolean + is + Edge : Library_Graph_Edge_Id; + Iter : Edges_Of_Cycle_Iterator; + Seen : Boolean; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- Assume that no weak static successor has been seen + + Seen := False; + + -- IMPORTANT: + -- + -- * The iteration must run to completion in order to unlock the + -- edges of the cycle. + + Iter := Iterate_Edges_Of_Cycle (G, Cycle); + while Has_Next (Iter) loop + Next (Iter, Edge); + + if not Seen + and then Is_Invocation_Edge (G, Edge) + and then not Is_Dynamically_Elaborated (G, Successor (G, Edge)) + then + Seen := True; + end if; + end loop; + + return Seen; + end Contains_Weak_Static_Successor; + --------------------- -- Copy_Cycle_Path -- --------------------- @@ -1911,15 +1941,12 @@ package body Bindo.Graphs is ------------ function Create - (Initial_Vertices : Positive; - Initial_Edges : Positive; - Dynamically_Elaborated : Boolean) return Library_Graph + (Initial_Vertices : Positive; + Initial_Edges : Positive) return Library_Graph is G : constant Library_Graph := new Library_Graph_Attributes; begin - G.Dynamically_Elaborated := Dynamically_Elaborated; - G.Component_Attributes := Component_Tables.Create (Initial_Vertices); G.Cycle_Attributes := LGC_Tables.Create (Initial_Vertices); G.Cycles := LGC_Lists.Create; @@ -1990,7 +2017,8 @@ package body Bindo.Graphs is procedure Decrement_Pending_Predecessors (G : Library_Graph; - Comp : Component_Id) + Comp : Component_Id; + Edge : Library_Graph_Edge_Id) is Attrs : Component_Attributes; @@ -1999,7 +2027,13 @@ package body Bindo.Graphs is pragma Assert (Present (Comp)); Attrs := Get_Component_Attributes (G, Comp); - Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1; + + Update_Pending_Predecessors + (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, + Weak_Predecessors => Attrs.Pending_Weak_Predecessors, + Update_Weak => Is_Invocation_Edge (G, Edge), + Value => -1); + Set_Component_Attributes (G, Comp, Attrs); end Decrement_Pending_Predecessors; @@ -2009,7 +2043,8 @@ package body Bindo.Graphs is procedure Decrement_Pending_Predecessors (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id; + Edge : Library_Graph_Edge_Id) is Attrs : Library_Graph_Vertex_Attributes; @@ -2018,7 +2053,13 @@ package body Bindo.Graphs is pragma Assert (Present (Vertex)); Attrs := Get_LGV_Attributes (G, Vertex); - Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1; + + Update_Pending_Predecessors + (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, + Weak_Predecessors => Attrs.Pending_Weak_Predecessors, + Update_Weak => Is_Invocation_Edge (G, Edge), + Value => -1); + Set_LGV_Attributes (G, Vertex, Attrs); end Decrement_Pending_Predecessors; @@ -2071,7 +2112,10 @@ package body Bindo.Graphs is -- Update the number of pending predecessors the successor must wait -- on before it is elaborated. - Decrement_Pending_Predecessors (G, Succ); + Decrement_Pending_Predecessors + (G => G, + Vertex => Succ, + Edge => Edge); -- Delete the link between the predecessor and successor. This allows -- for further attempts to link the same predecessor and successor. @@ -2298,9 +2342,9 @@ package body Bindo.Graphs is (G => G, Vertex => Complementary_Vertex - (G => G, - Vertex => Vertex, - Do_Complement => Spec_And_Body_Together), + (G => G, + Vertex => Vertex, + Force_Complement => Spec_And_Body_Together), End_Vertices => End_Vertices, Most_Significant_Edge => Most_Significant_Edge, Invocation_Edge_Count => Invocation_Edge_Count, @@ -2343,7 +2387,7 @@ package body Bindo.Graphs is Trace_Edge (G, Initial_Edge, Indent); -- Use a set to represent the end vertices of the cycle. The set is - -- needed to accomodate the Elaborate_All and Elaborate_Body cases + -- needed to accommodate the Elaborate_All and Elaborate_Body cases -- where a cycle may terminate on either a spec or a body vertex. End_Vertices := LGV_Sets.Create (2); @@ -2650,7 +2694,10 @@ package body Bindo.Graphs is U_Rec : Unit_Record renames ALI.Units.Table (U_Id); begin - return U_Rec.Elaborate_Body; + -- Treat the spec and body as decoupled when switch -d_b (ignore the + -- effects of pragma Elaborate_Body) is in effect. + + return U_Rec.Elaborate_Body and not Debug_Flag_Underscore_B; end Has_Elaborate_Body; -------------- @@ -2884,7 +2931,8 @@ package body Bindo.Graphs is procedure Increment_Pending_Predecessors (G : Library_Graph; - Comp : Component_Id) + Comp : Component_Id; + Edge : Library_Graph_Edge_Id) is Attrs : Component_Attributes; @@ -2893,7 +2941,13 @@ package body Bindo.Graphs is pragma Assert (Present (Comp)); Attrs := Get_Component_Attributes (G, Comp); - Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1; + + Update_Pending_Predecessors + (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, + Weak_Predecessors => Attrs.Pending_Weak_Predecessors, + Update_Weak => Is_Invocation_Edge (G, Edge), + Value => 1); + Set_Component_Attributes (G, Comp, Attrs); end Increment_Pending_Predecessors; @@ -2903,7 +2957,8 @@ package body Bindo.Graphs is procedure Increment_Pending_Predecessors (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id) + Vertex : Library_Graph_Vertex_Id; + Edge : Library_Graph_Edge_Id) is Attrs : Library_Graph_Vertex_Attributes; @@ -2912,7 +2967,13 @@ package body Bindo.Graphs is pragma Assert (Present (Vertex)); Attrs := Get_LGV_Attributes (G, Vertex); - Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1; + + Update_Pending_Predecessors + (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, + Weak_Predecessors => Attrs.Pending_Weak_Predecessors, + Update_Weak => Is_Invocation_Edge (G, Edge), + Value => 1); + Set_LGV_Attributes (G, Vertex, Attrs); end Increment_Pending_Predecessors; @@ -2925,7 +2986,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); -- The graph already contains a set of components. Reinitialize - -- them in order to accomodate the new set of components about to + -- them in order to accommodate the new set of components about to -- be computed. if Number_Of_Components (G) > 0 then @@ -3216,11 +3277,15 @@ package body Bindo.Graphs is -- Is_Dynamically_Elaborated -- ------------------------------- - function Is_Dynamically_Elaborated (G : Library_Graph) return Boolean is + function Is_Dynamically_Elaborated + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is begin pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); - return G.Dynamically_Elaborated; + return Is_Dynamically_Elaborated (Unit (G, Vertex)); end Is_Dynamically_Elaborated; ----------------------------- @@ -3235,12 +3300,14 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Comp)); - -- A component can be elaborated when + -- A component is elaborable when: -- - -- * The component is no longer wanting on any of its predecessors - -- to be elaborated. + -- * It is not waiting on strong predecessors, and + -- * It is not waiting on weak predecessors - return Pending_Predecessors (G, Comp) = 0; + return + Pending_Strong_Predecessors (G, Comp) = 0 + and then Pending_Weak_Predecessors (G, Comp) = 0; end Is_Elaborable_Component; -------------------------- @@ -3251,80 +3318,47 @@ package body Bindo.Graphs is (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean is - Check_Vertex : Library_Graph_Vertex_Id; - - begin pragma Assert (Present (G)); pragma Assert (Present (Vertex)); - Check_Vertex := Vertex; - - -- A spec-body pair where the spec carries pragma Elaborate_Body must - -- be treated as one vertex for elaboration purposes. Use the spec as - -- the point of reference for the composite vertex. - - if Is_Body_Of_Spec_With_Elaborate_Body (G, Check_Vertex) then - Check_Vertex := Proper_Spec (G, Check_Vertex); - end if; - - return - Is_Elaborable_Vertex - (G => G, - Vertex => Check_Vertex, - Predecessors => 0); - end Is_Elaborable_Vertex; - - -------------------------- - -- Is_Elaborable_Vertex -- - -------------------------- + Complement : constant Library_Graph_Vertex_Id := + Complementary_Vertex + (G => G, + Vertex => Vertex, + Force_Complement => False); - function Is_Elaborable_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Predecessors : Natural) return Boolean - is - Body_Vertex : Library_Graph_Vertex_Id; + Strong_Preds : Natural; + Weak_Preds : Natural; begin - pragma Assert (Present (G)); - pragma Assert (Present (Vertex)); - - -- The vertex must not be re-elaborated once it has been elaborated + -- A vertex is elaborable when: + -- + -- * It has not been elaborated yet, and + -- * The complement vertex of an Elaborate_Body pair has not been + -- elaborated yet, and + -- * It resides within an elaborable component, and + -- * It is not waiting on strong predecessors, and + -- * It is not waiting on weak predecessors if In_Elaboration_Order (G, Vertex) then return False; - -- The vertex must not be waiting on more precedessors than requested - -- to be elaborated. - - elsif Pending_Predecessors (G, Vertex) /= Predecessors then + elsif Present (Complement) + and then In_Elaboration_Order (G, Complement) + then return False; - -- The component where the vertex resides must not be waiting on any - -- of its precedessors to be elaborated. - elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then return False; - - -- The vertex denotes a spec with a completing body, and is subject - -- to pragma Elaborate_Body. The body must be elaborable for the - -- vertex to be elaborated. Account for the sole predecessor of the - -- body which is the vertex itself. - - elsif Is_Spec_With_Elaborate_Body (G, Vertex) then - Body_Vertex := Proper_Body (G, Vertex); - pragma Assert (Present (Body_Vertex)); - - return - Is_Elaborable_Vertex - (G => G, - Vertex => Body_Vertex, - Predecessors => 1); end if; - -- At this point it is known that the vertex can be elaborated + Pending_Predecessors_For_Elaboration + (G => G, + Vertex => Vertex, + Strong_Preds => Strong_Preds, + Weak_Preds => Weak_Preds); - return True; + return Strong_Preds = 0 and then Weak_Preds = 0; end Is_Elaborable_Vertex; --------------------------- @@ -3378,6 +3412,26 @@ package body Bindo.Graphs is return Kind (G, Edge) = Elaborate_Edge; end Is_Elaborate_Edge; + ---------------------------- + -- Is_Elaborate_Body_Pair -- + ---------------------------- + + function Is_Elaborate_Body_Pair + (G : Library_Graph; + Spec_Vertex : Library_Graph_Vertex_Id; + Body_Vertex : Library_Graph_Vertex_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Spec_Vertex)); + pragma Assert (Present (Body_Vertex)); + + return + Is_Spec_With_Elaborate_Body (G, Spec_Vertex) + and then Is_Body_Of_Spec_With_Elaborate_Body (G, Body_Vertex) + and then Proper_Body (G, Spec_Vertex) = Body_Vertex; + end Is_Elaborate_Body_Pair; + -------------------- -- Is_Forced_Edge -- -------------------- @@ -3539,6 +3593,57 @@ package body Bindo.Graphs is and then Has_Elaborate_Body (G, Vertex); end Is_Spec_With_Elaborate_Body; + --------------------------------- + -- Is_Weakly_Elaborable_Vertex -- + ---------------------------------- + + function Is_Weakly_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + Complement : constant Library_Graph_Vertex_Id := + Complementary_Vertex + (G => G, + Vertex => Vertex, + Force_Complement => False); + + Strong_Preds : Natural; + Weak_Preds : Natural; + + begin + -- A vertex is weakly elaborable when: + -- + -- * It has not been elaborated yet, and + -- * The complement vertex of an Elaborate_Body pair has not been + -- elaborated yet, and + -- * It resides within an elaborable component, and + -- * It is not waiting on strong predecessors, and + -- * It is waiting on at least one weak predecessor + + if In_Elaboration_Order (G, Vertex) then + return False; + + elsif Present (Complement) + and then In_Elaboration_Order (G, Complement) + then + return False; + + elsif not Is_Elaborable_Component (G, Component (G, Vertex)) then + return False; + end if; + + Pending_Predecessors_For_Elaboration + (G => G, + Vertex => Vertex, + Strong_Preds => Strong_Preds, + Weak_Preds => Weak_Preds); + + return Strong_Preds = 0 and then Weak_Preds >= 1; + end Is_Weakly_Elaborable_Vertex; + ------------------ -- Is_With_Edge -- ------------------ @@ -4044,11 +4149,72 @@ package body Bindo.Graphs is return Get_LGC_Attributes (G, Cycle).Path; end Path; - -------------------------- - -- Pending_Predecessors -- - -------------------------- + ------------------------------------------ + -- Pending_Predecessors_For_Elaboration -- + ------------------------------------------ - function Pending_Predecessors + procedure Pending_Predecessors_For_Elaboration + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Strong_Preds : out Natural; + Weak_Preds : out Natural) + is + Complement : Library_Graph_Vertex_Id; + Spec_Vertex : Library_Graph_Vertex_Id; + Total_Strong_Preds : Natural; + Total_Weak_Preds : Natural; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + Total_Strong_Preds := Pending_Strong_Predecessors (G, Vertex); + Total_Weak_Preds := Pending_Weak_Predecessors (G, Vertex); + + -- Assume that there is no complementary vertex that needs to be + -- examined. + + Complement := No_Library_Graph_Vertex; + Spec_Vertex := No_Library_Graph_Vertex; + + if Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex) then + Complement := Proper_Spec (G, Vertex); + Spec_Vertex := Complement; + + elsif Is_Spec_With_Elaborate_Body (G, Vertex) then + Complement := Proper_Body (G, Vertex); + Spec_Vertex := Vertex; + end if; + + -- The vertex is part of an Elaborate_Body pair. Take into account + -- the strong and weak predecessors of the complementary vertex. + + if Present (Complement) then + Total_Strong_Preds := + Pending_Strong_Predecessors (G, Complement) + Total_Strong_Preds; + Total_Weak_Preds := + Pending_Weak_Predecessors (G, Complement) + Total_Weak_Preds; + + -- The body of an Elaborate_Body pair is the successor of a strong + -- edge where the predecessor is the spec. This edge must not be + -- considered for elaboration purposes because the pair is treated + -- as one vertex. Account for the edge only when the spec has not + -- been elaborated yet. + + if not In_Elaboration_Order (G, Spec_Vertex) then + Total_Strong_Preds := Total_Strong_Preds - 1; + end if; + end if; + + Strong_Preds := Total_Strong_Preds; + Weak_Preds := Total_Weak_Preds; + end Pending_Predecessors_For_Elaboration; + + --------------------------------- + -- Pending_Strong_Predecessors -- + --------------------------------- + + function Pending_Strong_Predecessors (G : Library_Graph; Comp : Component_Id) return Natural is @@ -4056,14 +4222,14 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Comp)); - return Get_Component_Attributes (G, Comp).Pending_Predecessors; - end Pending_Predecessors; + return Get_Component_Attributes (G, Comp).Pending_Strong_Predecessors; + end Pending_Strong_Predecessors; - -------------------------- - -- Pending_Predecessors -- - -------------------------- + --------------------------------- + -- Pending_Strong_Predecessors -- + --------------------------------- - function Pending_Predecessors + function Pending_Strong_Predecessors (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Natural is @@ -4071,8 +4237,38 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Vertex)); - return Get_LGV_Attributes (G, Vertex).Pending_Predecessors; - end Pending_Predecessors; + return Get_LGV_Attributes (G, Vertex).Pending_Strong_Predecessors; + end Pending_Strong_Predecessors; + + ------------------------------- + -- Pending_Weak_Predecessors -- + ------------------------------- + + function Pending_Weak_Predecessors + (G : Library_Graph; + Comp : Component_Id) return Natural + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Comp)); + + return Get_Component_Attributes (G, Comp).Pending_Weak_Predecessors; + end Pending_Weak_Predecessors; + + ------------------------------- + -- Pending_Weak_Predecessors -- + ------------------------------- + + function Pending_Weak_Predecessors + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Natural + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + return Get_LGV_Attributes (G, Vertex).Pending_Weak_Predecessors; + end Pending_Weak_Predecessors; ---------------- -- Precedence -- @@ -4306,9 +4502,9 @@ package body Bindo.Graphs is Complement : constant Library_Graph_Vertex_Id := Complementary_Vertex - (G => G, - Vertex => Vertex, - Do_Complement => Do_Complement); + (G => G, + Vertex => Vertex, + Force_Complement => Do_Complement); begin LGV_Sets.Delete (Set, Vertex); @@ -4702,6 +4898,24 @@ package body Bindo.Graphs is return Get_LGV_Attributes (G, Vertex).Unit; end Unit; + --------------------------------- + -- Update_Pending_Predecessors -- + --------------------------------- + + procedure Update_Pending_Predecessors + (Strong_Predecessors : in out Natural; + Weak_Predecessors : in out Natural; + Update_Weak : Boolean; + Value : Integer) + is + begin + if Update_Weak then + Weak_Predecessors := Weak_Predecessors + Value; + else + Strong_Predecessors := Strong_Predecessors + Value; + end if; + end Update_Pending_Predecessors; + ----------------------------------------------- -- Update_Pending_Predecessors_Of_Components -- ----------------------------------------------- @@ -4748,7 +4962,10 @@ package body Bindo.Graphs is -- must wait on another predecessor until it can be elaborated. if Pred_Comp /= Succ_Comp then - Increment_Pending_Predecessors (G, Succ_Comp); + Increment_Pending_Predecessors + (G => G, + Comp => Succ_Comp, + Edge => Edge); end if; end Update_Pending_Predecessors_Of_Components; end Library_Graphs; @@ -4835,7 +5052,7 @@ package body Bindo.Graphs is -------------------------- LGC_Sequencer : Library_Graph_Cycle_Id := First_Library_Graph_Cycle; - -- The couhnter for library graph cycles. Do not directly manipulate its + -- The counter for library graph cycles. Do not directly manipulate its -- value. function Sequence_Next_Cycle return Library_Graph_Cycle_Id is diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads index 02f8e52..3c2fef01 100644 --- a/gcc/ada/bindo-graphs.ads +++ b/gcc/ada/bindo-graphs.ads @@ -668,7 +668,7 @@ package Bindo.Graphs is -- The following type represents the various kinds of library graph -- cycles. The ordering of kinds is significant, where a literal with - -- lower ordinal has a higner precedence than one with higher ordinal. + -- lower ordinal has a higher precedence than one with higher ordinal. type Library_Graph_Cycle_Kind is (Elaborate_Body_Cycle, @@ -753,13 +753,11 @@ package Bindo.Graphs is -- describes. function Create - (Initial_Vertices : Positive; - Initial_Edges : Positive; - Dynamically_Elaborated : Boolean) return Library_Graph; + (Initial_Vertices : Positive; + Initial_Edges : Positive) return Library_Graph; pragma Inline (Create); -- Create a new empty graph with vertex capacity Initial_Vertices and - -- edge capacity Initial_Edges. Flag Dynamically_Elaborated must be set - -- when the main library unit was compiled using the dynamic model. + -- edge capacity Initial_Edges. procedure Destroy (G : in out Library_Graph); pragma Inline (Destroy); @@ -809,10 +807,12 @@ package Bindo.Graphs is procedure Decrement_Pending_Predecessors (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id); + Vertex : Library_Graph_Vertex_Id; + Edge : Library_Graph_Edge_Id); pragma Inline (Decrement_Pending_Predecessors); - -- Decrease the number of pending predecessors vertex Vertex of library - -- graph G must wait on until it can be elaborated. + -- Decrease the number of pending predecessors vertex Vertex which was + -- reached via edge Edge of library graph G must wait until it can be + -- elaborated. function File_Name (G : Library_Graph; @@ -844,12 +844,30 @@ package Bindo.Graphs is -- Obtain the name of the unit which vertex Vertex of library graph G -- represents. - function Pending_Predecessors + procedure Pending_Predecessors_For_Elaboration + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Strong_Preds : out Natural; + Weak_Preds : out Natural); + pragma Inline (Pending_Predecessors_For_Elaboration); + -- Obtain the number of pending strong and weak predecessors of vertex + -- Vertex of library graph G, taking into account Elaborate_Body pairs. + -- Strong predecessors are returned in Strong_Preds. Weak predecessors + -- are returned in Weak_Preds. + + function Pending_Strong_Predecessors + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Natural; + pragma Inline (Pending_Strong_Predecessors); + -- Obtain the number of pending strong predecessors vertex Vertex of + -- library graph G must wait on until it can be elaborated. + + function Pending_Weak_Predecessors (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Natural; - pragma Inline (Pending_Predecessors); - -- Obtain the number of pending predecessors vertex Vertex of library - -- graph G must wait on until it can be elaborated. + pragma Inline (Pending_Weak_Predecessors); + -- Obtain the number of pending weak predecessors vertex Vertex of + -- library graph G must wait on until it can be elaborated. procedure Set_Corresponding_Item (G : Library_Graph; @@ -901,17 +919,26 @@ package Bindo.Graphs is procedure Decrement_Pending_Predecessors (G : Library_Graph; - Comp : Component_Id); + Comp : Component_Id; + Edge : Library_Graph_Edge_Id); pragma Inline (Decrement_Pending_Predecessors); - -- Decrease the number of pending predecessors component Comp of library - -- graph G must wait on until it can be elaborated. + -- Decrease the number of pending predecessors component Comp which was + -- reached via edge Edge of library graph G must wait on until it can be + -- elaborated. - function Pending_Predecessors + function Pending_Strong_Predecessors (G : Library_Graph; Comp : Component_Id) return Natural; - pragma Inline (Pending_Predecessors); - -- Obtain the number of pending predecessors component Comp of library - -- graph G must wait on until it can be elaborated. + pragma Inline (Pending_Strong_Predecessors); + -- Obtain the number of pending strong predecessors component Comp of + -- library graph G must wait on until it can be elaborated. + + function Pending_Weak_Predecessors + (G : Library_Graph; + Comp : Component_Id) return Natural; + pragma Inline (Pending_Weak_Predecessors); + -- Obtain the number of pending weak predecessors component Comp of + -- library graph G must wait on until it can be elaborated. ---------------------- -- Cycle attributes -- @@ -940,6 +967,26 @@ package Bindo.Graphs is -- Semantics -- --------------- + function Complementary_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Force_Complement : Boolean) return Library_Graph_Vertex_Id; + pragma Inline (Complementary_Vertex); + -- Obtain the complementary vertex of vertex Vertex of library graph G + -- as follows: + -- + -- * If Vertex is the spec of an Elaborate_Body pair, return the body + -- * If Vertex is the body of an Elaborate_Body pair, return the spec + -- + -- This behavior can be forced by setting flag Force_Complement to True. + + function Contains_Weak_Static_Successor + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Boolean; + pragma Inline (Contains_Weak_Static_Successor); + -- Determine whether cycle Cycle of library graph G contains a weak edge + -- where the successor was compiled using the static model. + function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean; pragma Inline (Has_Elaborate_All_Cycle); -- Determine whether library graph G contains a cycle involving pragma @@ -973,22 +1020,26 @@ package Bindo.Graphs is -- Determine whether vertex Vertex of library graph G denotes a body -- with a corresponding spec. - function Is_Dynamically_Elaborated (G : Library_Graph) return Boolean; + function Is_Dynamically_Elaborated + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Dynamically_Elaborated); - -- Determine whether library graph G was created from a set of units - -- where the main library unit was compiled using the dynamic model. + -- Determine whether vertex Vertex of library graph G was compiled + -- using the dynamic model. function Is_Elaborable_Component (G : Library_Graph; Comp : Component_Id) return Boolean; pragma Inline (Is_Elaborable_Component); - -- Determine whether component Comp of library graph G can be elaborated + -- Determine whether component Comp of library graph G is not waiting on + -- any predecessors, and can thus be elaborated. function Is_Elaborable_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Elaborable_Vertex); - -- Determine whether vertex Vertex of library graph G can be elaborated + -- Determine whether vertex Vertex of library graph G is not waiting on + -- any predecessors, and can thus be elaborated. function Is_Elaborate_All_Edge (G : Library_Graph; @@ -1012,6 +1063,15 @@ package Bindo.Graphs is -- Determine whether edge Edge of library graph G is an edge whose -- predecessor is subject to pragma Elaborate. + function Is_Elaborate_Body_Pair + (G : Library_Graph; + Spec_Vertex : Library_Graph_Vertex_Id; + Body_Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Is_Elaborate_Body_Pair); + -- Determine whether vertices Spec_Vertex and Body_Vertex of library + -- graph G denote a spec subject to Elaborate_Body and its completing + -- body. + function Is_Forced_Edge (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Boolean; @@ -1045,7 +1105,7 @@ package Bindo.Graphs is Vertex : Library_Graph_Vertex_Id) return Boolean; pragma Inline (Is_Preelaborated_Unit); -- Determine whether vertex Vertex of library graph G denotes a unit - -- subjec to pragma Pure or Preelaborable. + -- subject to pragma Pure or Preelaborable. function Is_Spec (G : Library_Graph; @@ -1067,6 +1127,14 @@ package Bindo.Graphs is -- Determine whether vertex Vertex of library graph G denotes a spec -- with a corresponding body, and is subject to pragma Elaborate_Body. + function Is_Weakly_Elaborable_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Is_Weakly_Elaborable_Vertex); + -- Determine whether vertex Vertex of library graph G is waiting on + -- weak predecessors only, in which case it can be elaborated assuming + -- that the weak edges will not be exercised at elaboration time. + function Is_With_Edge (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Boolean; @@ -1320,9 +1388,13 @@ package Bindo.Graphs is In_Elaboration_Order : Boolean := False; -- Set when this vertex is elaborated - Pending_Predecessors : Natural := 0; - -- The number of pending predecessor vertices this vertex must wait - -- on before it can be elaborated. + Pending_Strong_Predecessors : Natural := 0; + -- The number of pending strong predecessor vertices this vertex must + -- wait on before it can be elaborated. + + Pending_Weak_Predecessors : Natural := 0; + -- The number of weak predecessor vertices this vertex must wait on + -- before it can be elaborated. Unit : Unit_Id := No_Unit_Id; -- The reference to unit this vertex represents @@ -1330,10 +1402,11 @@ package Bindo.Graphs is No_Library_Graph_Vertex_Attributes : constant Library_Graph_Vertex_Attributes := - (Corresponding_Item => No_Library_Graph_Vertex, - In_Elaboration_Order => False, - Pending_Predecessors => 0, - Unit => No_Unit_Id); + (Corresponding_Item => No_Library_Graph_Vertex, + In_Elaboration_Order => False, + Pending_Strong_Predecessors => 0, + Pending_Weak_Predecessors => 0, + Unit => No_Unit_Id); procedure Destroy_Library_Graph_Vertex_Attributes (Attrs : in out Library_Graph_Vertex_Attributes); @@ -1391,13 +1464,18 @@ package Bindo.Graphs is -- The following type represents the attributes of a component type Component_Attributes is record - Pending_Predecessors : Natural := 0; - -- The number of pending predecessor components this component must - -- wait on before it can be elaborated. + Pending_Strong_Predecessors : Natural := 0; + -- The number of pending strong predecessor components this component + -- must wait on before it can be elaborated. + + Pending_Weak_Predecessors : Natural := 0; + -- The number of pending weak predecessor components this component + -- must wait on before it can be elaborated. end record; No_Component_Attributes : constant Component_Attributes := - (Pending_Predecessors => 0); + (Pending_Strong_Predecessors => 0, + Pending_Weak_Predecessors => 0); procedure Destroy_Component_Attributes (Attrs : in out Component_Attributes); @@ -1560,10 +1638,6 @@ package Bindo.Graphs is Cycles : LGC_Lists.Doubly_Linked_List := LGC_Lists.Nil; -- The list of all cycles in the graph, sorted based on precedence - Dynamically_Elaborated : Boolean := False; - -- Set when the main library unit was compiled using the dynamic - -- model. - Edge_Attributes : LGE_Tables.Dynamic_Hash_Table := LGE_Tables.Nil; -- The map of edge -> edge attributes for all edges in the graph diff --git a/gcc/ada/bindo-validators.adb b/gcc/ada/bindo-validators.adb index aed4960..88be2e8 100644 --- a/gcc/ada/bindo-validators.adb +++ b/gcc/ada/bindo-validators.adb @@ -140,7 +140,7 @@ package body Bindo.Validators is Edges := LGE_Sets.Create (Length (G, Cycle)); - -- Inspect the edges of the cucle, trying to catch duplicates + -- Inspect the edges of the cycle, trying to catch duplicates Iter := Iterate_Edges_Of_Cycle (G, Cycle); while Has_Next (Iter) loop @@ -155,7 +155,7 @@ package body Bindo.Validators is Write_Str (" library graph edge (LGE_Id_"); Write_Int (Int (Edge)); - Write_Str (") is repeaded in cycle (LGC_Id_"); + Write_Str (") is repeated in cycle (LGC_Id_"); Write_Int (Int (Cycle)); Write_Str (")"); Write_Eol; @@ -421,7 +421,7 @@ package body Bindo.Validators is (G : Invocation_Graph; Vertex : Invocation_Graph_Vertex_Id); pragma Inline (Validate_Invocation_Graph_Vertex); - -- Verify that the attributes of vertex Vertex of inbocation graph G are + -- Verify that the attributes of vertex Vertex of invocation graph G are -- properly set. procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph); @@ -468,7 +468,7 @@ package body Bindo.Validators is if not Present (Edge) then Write_Error (Msg, Has_Invalid_Data); - Write_Str (" emply invocation graph edge"); + Write_Str (" empty invocation graph edge"); Write_Eol; Write_Eol; return; @@ -530,7 +530,7 @@ package body Bindo.Validators is if not Present (Vertex) then Write_Error (Msg, Has_Invalid_Data); - Write_Str (" emply invocation graph vertex"); + Write_Str (" empty invocation graph vertex"); Write_Eol; Write_Eol; return; @@ -662,7 +662,7 @@ package body Bindo.Validators is if not Present (Edge) then Write_Error (Msg, Has_Invalid_Data); - Write_Str (" emply library graph edge"); + Write_Str (" empty library graph edge"); Write_Eol; Write_Eol; return; diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb index a3b45fc..99f93f5 100644 --- a/gcc/ada/bindo-writers.adb +++ b/gcc/ada/bindo-writers.adb @@ -1025,6 +1025,10 @@ package body Bindo.Writers is -- Write all vertices of component Comp of library graph G to standard -- output. + procedure Write_Components (G : Library_Graph); + pragma Inline (Write_Component); + -- Write all components of library graph G to standard output + procedure Write_Edges_To_Successors (G : Library_Graph; Vertex : Library_Graph_Vertex_Id); @@ -1089,8 +1093,12 @@ package body Bindo.Writers is Write_Str (")"); Write_Eol; - Write_Str (" Pending_Predecessors = "); - Write_Int (Int (Pending_Predecessors (G, Comp))); + Write_Str (" Pending_Strong_Predecessors = "); + Write_Int (Int (Pending_Strong_Predecessors (G, Comp))); + Write_Eol; + + Write_Str (" Pending_Weak_Predecessors = "); + Write_Int (Int (Pending_Weak_Predecessors (G, Comp))); Write_Eol; Write_Component_Vertices (G, Comp); @@ -1225,6 +1233,7 @@ package body Bindo.Writers is Write_Statistics (G); Write_Library_Graph_Vertices (G); + Write_Components (G); Write_Str ("Library Graph end"); Write_Eol; @@ -1312,8 +1321,12 @@ package body Bindo.Writers is end if; Write_Eol; - Write_Str (" Pending_Predecessors = "); - Write_Int (Int (Pending_Predecessors (G, Vertex))); + Write_Str (" Pending_Strong_Predecessors = "); + Write_Int (Int (Pending_Strong_Predecessors (G, Vertex))); + Write_Eol; + + Write_Str (" Pending_Weak_Predecessors = "); + Write_Int (Int (Pending_Weak_Predecessors (G, Vertex))); Write_Eol; Write_Str (" Component (Comp_Id_"); @@ -1612,7 +1625,7 @@ package body Bindo.Writers is is function Digits_Indentation return Indentation_Level; pragma Inline (Digits_Indentation); - -- Determine the level of indentation the number requies in order to + -- Determine the level of indentation the number requires in order to -- be right-justified by Val_Indent. ------------------------ diff --git a/gcc/ada/bindo-writers.ads b/gcc/ada/bindo-writers.ads index ff6b9b3..01e48e4 100644 --- a/gcc/ada/bindo-writers.ads +++ b/gcc/ada/bindo-writers.ads @@ -127,9 +127,6 @@ package Bindo.Writers is --------------------------- package Library_Graph_Writers is - procedure Write_Components (G : Library_Graph); - -- Write all components of library graph G to standard output - procedure Write_Library_Graph (G : Library_Graph); -- Write library graph G to standard output diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index b3106ad..897e746 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -74,7 +74,7 @@ package body Bindo is -- -- * Diagnose elaboration circularities between units -- - -- An elaboration circularity arrises when either + -- An elaboration circularity arises when either -- -- - At least one unit cannot be ordered, or -- @@ -95,6 +95,12 @@ package body Bindo is -- * Component - A strongly connected component of a graph. -- + -- * Elaborable component - A component that is not waiting on other + -- components to be elaborated. + -- + -- * Elaborable vertex - A vertex that is not waiting on strong and weak + -- predecessors, and whose component is elaborable. + -- -- * Elaboration circularity - A cycle involving units from the bind. -- -- * Elaboration root - A special invocation construct which denotes the @@ -136,8 +142,23 @@ package body Bindo is -- * Pending predecessor - A vertex that must be elaborated before another -- vertex can be elaborated. -- + -- * Strong edge - A non-invocation library graph edge. Strong edges + -- represent the language-defined relations between units. + -- + -- * Strong predecessor - A library graph vertex reachable via a strong + -- edge. + -- -- * Target - The destination construct of an invocation relation (the -- generic, subprogram, or task type). + -- + -- * Weak edge - An invocation library graph edge. Weak edges represent + -- the speculative flow of execution at elaboration time, which may or + -- may not take place. + -- + -- * Weak predecessor - A library graph vertex reachable via a weak edge. + -- + -- * Weakly elaborable vertex - A vertex that is waiting solely on weak + -- predecessors to be elaborated, and whose component is elaborable. ------------------ -- Architecture -- @@ -233,7 +254,7 @@ package body Bindo is -- bodies as single vertices. -- -- * Try to order as many vertices of the library graph as possible by - -- peforming a topological sort based on the pending predecessors of + -- performing a topological sort based on the pending predecessors of -- vertices across all components and within a single component. -- -- * Validate the consistency of the order, only when switch -d_V is in @@ -251,7 +272,7 @@ package body Bindo is -- The Diagnostics phase has the following objectives: -- -- * Discover, save, and sort all cycles in the library graph. The cycles - -- are sorted based on the following heiristics: + -- are sorted based on the following heuristics: -- -- - A cycle with higher precedence is preferred. -- @@ -268,7 +289,7 @@ package body Bindo is -- * Diagnose the most important cycle, or all cycles when switch -d_C is -- in effect. The diagnostic consists of: -- - -- - The reason for the existance of the cycle, along with the unit + -- - The reason for the existence of the cycle, along with the unit -- whose elaboration cannot be guaranteed. -- -- - A detailed traceback of the cycle, showcasing the transition @@ -276,7 +297,7 @@ package body Bindo is -- information. -- -- - A set of suggestions on how to break the cycle considering the - -- the edges coprising the circuit, the elaboration model used to + -- the edges comprising the circuit, the elaboration model used to -- compile the units, the availability of invocation information, -- and the state of various relevant switches. @@ -284,6 +305,23 @@ package body Bindo is -- Switches -- -------------- + -- -d_a Ignore the effects of pragma Elaborate_All + -- + -- GNATbind creates a regular with edge instead of an Elaborate_All + -- edge in the library graph, thus eliminating the effects of the + -- pragma. + -- + -- -d_b Ignore the effects of pragma Elaborate_Body + -- + -- GNATbind treats a spec and body pair as decoupled. + -- + -- -d_e Ignore the effects of pragma Elaborate + -- + -- GNATbind creates a regular with edge instead of an Elaborate edge + -- in the library graph, thus eliminating the effects of the pragma. + -- In addition, GNATbind does not create an edge to the body of the + -- pragma argument. + -- -- -d_A Output ALI invocation tables -- -- GNATbind outputs the contents of ALI table Invocation_Constructs diff --git a/gcc/ada/bindo.ads b/gcc/ada/bindo.ads index 39cf7a4..940b752 100644 --- a/gcc/ada/bindo.ads +++ b/gcc/ada/bindo.ads @@ -41,4 +41,14 @@ package Bindo is -- exists, it is returned in Order, otherwise Unrecoverable_Error is -- raised. +private + + -- The following type represents the various kinds of precedence between + -- two items. + + type Precedence_Kind is + (Lower_Precedence, + Equal_Precedence, + Higher_Precedence); + end Bindo; diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index da4bea1..680c38f 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -349,11 +349,11 @@ package body Debug is -- d.8 -- d.9 - -- d_a - -- d_b + -- d_a Ignore the effects of pragma Elaborate_All + -- d_b Ignore the effects of pragma Elaborate_Body -- d_c -- d_d - -- d_e + -- d_e Ignore the effects of pragma Elaborate -- d_f -- d_g -- d_h @@ -1141,6 +1141,17 @@ package body Debug is -- dx Force the binder to read (and then ignore) the xref information -- in ali files (used to check that read circuit is working OK). + -- d_a GNATBIND ignores the effects of pragma Elaborate_All in the case of + -- elaboration order and treats the associated dependency as a regular + -- with edge. + + -- d_b GNATBIND ignores the effects of pragma Elaborate_Body in the case + -- of elaboration order and treats the spec and body as decoupled. + + -- d_e GNATBIND ignores the effects of pragma Elaborate in the case of + -- elaboration order and no longer creates an implicit dependency on + -- the body of the argument. + -- d_A GNATBIND output the contents of all ALI invocation-related tables -- in textual format to standard output. -- cgit v1.1 From 1bb2e1d96eb23d2289765cd0fd9ef10b7a3b7ea3 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 8 Jul 2019 08:13:48 +0000 Subject: [Ada] Crash on timed entry call with a delay given by a type conversion This patch fixes a compiler crash in the compiler on a timed entry call whose delay expression is a type conversion, when FLoat_Overflow checks are enabled. 2019-07-08 Ed Schonberg gcc/ada/ * exp_ch9.adb (Expand_N_Timed_Entry_Call): Do not insert twice the assignment statement that computes the delay value, to prevent improper tree sharing when the value is a type conversion and Float_Overflow checks are enabled. gcc/testsuite/ * gnat.dg/entry1.adb, gnat.dg/entry1.ads: New testcase. From-SVN: r273210 --- gcc/ada/ChangeLog | 7 ++++ gcc/ada/exp_ch9.adb | 25 +++++++------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gnat.dg/entry1.adb | 75 ++++++++++++++++++++++++++++++++++++++++ gcc/testsuite/gnat.dg/entry1.ads | 4 +++ 5 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/entry1.adb create mode 100644 gcc/testsuite/gnat.dg/entry1.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e6eac08..1650732 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-08 Ed Schonberg + + * exp_ch9.adb (Expand_N_Timed_Entry_Call): Do not insert twice + the assignment statement that computes the delay value, to + prevent improper tree sharing when the value is a type + conversion and Float_Overflow checks are enabled. + 2019-07-08 Hristian Kirtchev * bindo.adb: Update the section on terminology to include new diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 03f133f..e742ec3 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -3887,6 +3887,7 @@ package body Exp_Ch9 is if Unprotected then Set_Protected_Formal (Formal, Defining_Identifier (New_Param)); + Set_Ekind (Defining_Identifier (New_Param), Ekind (Formal)); end if; Append (New_Param, New_Plist); @@ -10711,7 +10712,7 @@ package body Exp_Ch9 is Make_Defining_Identifier (Eloc, New_External_Name (Chars (Ename), 'A', Num_Accept)); - -- Link the acceptor to the original receiving entry + -- Link the acceptor to the original receiving entry. Set_Ekind (PB_Ent, E_Procedure); Set_Receiving_Entry (PB_Ent, Eent); @@ -12658,14 +12659,6 @@ package body Exp_Ch9 is Object_Definition => New_Occurrence_Of (Standard_Integer, Loc), Expression => D_Disc)); - -- Do the assignment at this stage only because the evaluation of the - -- expression must not occur earlier (see ACVC C97302A). - - Append_To (Stmts, - Make_Assignment_Statement (Loc, - Name => New_Occurrence_Of (D, Loc), - Expression => D_Conv)); - -- Parameter block processing -- Manually create the parameter block for dispatching calls. In the @@ -12673,6 +12666,13 @@ package body Exp_Ch9 is -- to Build_Simple_Entry_Call. if Is_Disp_Select then + -- Compute the delay at this stage because the evaluation of + -- its expression must not occur earlier (see ACVC C97302A). + + Append_To (Stmts, + Make_Assignment_Statement (Loc, + Name => New_Occurrence_Of (D, Loc), + Expression => D_Conv)); -- Tagged kind processing, generate: -- K : Ada.Tags.Tagged_Kind := @@ -12855,8 +12855,8 @@ package body Exp_Ch9 is Next (Stmt); end loop; - -- Do the assignment at this stage only because the evaluation - -- of the expression must not occur earlier (see ACVC C97302A). + -- Compute the delay at this stage because the evaluation of + -- its expression must not occur earlier (see ACVC C97302A). Insert_Before (Stmt, Make_Assignment_Statement (Loc, @@ -14882,7 +14882,8 @@ package body Exp_Ch9 is -- Ditto for a package declaration or a full type declaration, etc. - elsif Nkind (N) = N_Package_Declaration + elsif + (Nkind (N) = N_Package_Declaration and then N /= Specification (N)) or else Nkind (N) in N_Declaration or else Nkind (N) in N_Renaming_Declaration then diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a0b6bb4..25f6636 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-08 Ed Schonberg + * gnat.dg/entry1.adb, gnat.dg/entry1.ads: New testcase. + +2019-07-08 Ed Schonberg + * gnat.dg/fixed_delete.adb: New testcase. 2019-07-08 Javier Miranda diff --git a/gcc/testsuite/gnat.dg/entry1.adb b/gcc/testsuite/gnat.dg/entry1.adb new file mode 100644 index 0000000..7577a26 --- /dev/null +++ b/gcc/testsuite/gnat.dg/entry1.adb @@ -0,0 +1,75 @@ +-- { dg-do compile } +-- { dg-options "-gnateF" } + +PACKAGE BODY Entry1 IS + + PROTECTED TYPE key_buffer IS + + PROCEDURE clear; + + ENTRY incr; + ENTRY put (val : IN Natural); + ENTRY get (val : OUT Natural); + + PRIVATE + + -- Stores Key states (key state controller) + -- purpose: exclusive access + max_len : Natural := 10; + + cnt : Natural := 0; + + END key_buffer; + + PROTECTED BODY key_buffer IS + + PROCEDURE clear IS + BEGIN + cnt := 0; + END clear; + + ENTRY incr WHEN cnt < max_len IS + BEGIN + cnt := cnt + 1; + END; + + ENTRY put (val : IN Natural) WHEN cnt < max_len IS + BEGIN + cnt := val; + END put; + + ENTRY get (val : OUT Natural) WHEN cnt > 0 IS + BEGIN + val := cnt; + END get; + + END key_buffer; + + my_buffer : key_buffer; + + FUNCTION pt2 (t : IN Float) RETURN Natural IS + c : Natural; + t2 : duration := duration (t); + BEGIN + SELECT + my_buffer.get (c); + RETURN c; + OR + DELAY t2; + RETURN 0; + END SELECT; + END pt2; + + FUNCTION pt (t : IN Float) RETURN Natural IS + c : Natural; + BEGIN + SELECT + my_buffer.get (c); + RETURN c; + OR + DELAY Duration (t); + RETURN 0; + END SELECT; + END pt; + +END Entry1; diff --git a/gcc/testsuite/gnat.dg/entry1.ads b/gcc/testsuite/gnat.dg/entry1.ads new file mode 100644 index 0000000..7dcc7b5 --- /dev/null +++ b/gcc/testsuite/gnat.dg/entry1.ads @@ -0,0 +1,4 @@ +PACKAGE Entry1 IS + FUNCTION pt (t : IN Float) RETURN Natural; + FUNCTION pt2 (t : IN Float) RETURN Natural; +END Entry1; -- cgit v1.1 From 7800a8fb04adc60273185de201e9dff51b356952 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Mon, 8 Jul 2019 08:13:52 +0000 Subject: [Ada] Do not erase precise type on fixed-point real literal Real literals of fixed-point type are expected to keep their precise fixed-point type in GNATprove. This is now correctly enforced. There is no impact on compilation. 2019-07-08 Yannick Moy gcc/ada/ * expander.adb (Expand): Do not reset Analyzed flag always. * sem_eval.adb (Fold_Ureal): Mark node as analyzed. From-SVN: r273211 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/expander.adb | 7 ++++++- gcc/ada/sem_eval.adb | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1650732..e278295 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Yannick Moy + + * expander.adb (Expand): Do not reset Analyzed flag always. + * sem_eval.adb (Fold_Ureal): Mark node as analyzed. + 2019-07-08 Ed Schonberg * exp_ch9.adb (Expand_N_Timed_Entry_Call): Do not insert twice diff --git a/gcc/ada/expander.adb b/gcc/ada/expander.adb index 11711b9..aac2e7d 100644 --- a/gcc/ada/expander.adb +++ b/gcc/ada/expander.adb @@ -112,7 +112,12 @@ package body Expander is Expand_SPARK (N); end if; - Set_Analyzed (N, Full_Analysis); + -- Do not reset the Analyzed flag if it has been set on purpose + -- during preanalysis. + + if Full_Analysis then + Set_Analyzed (N); + end if; -- Regular expansion is normally followed by special handling for -- transient scopes for unconstrained results, etc. but this is not diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index 4956ef3..ff3359f 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -4611,10 +4611,14 @@ package body Sem_Eval is -- will cause semantic errors if it is marked as static), and after -- the Resolve step (since Resolve in some cases sets this flag). + -- We mark the node as analyzed so that its type is not erased by + -- calling Analyze_Real_Literal. + Analyze (N); Set_Is_Static_Expression (N, Static); Set_Etype (N, Typ); Resolve (N); + Set_Analyzed (N); Set_Is_Static_Expression (N, Static); end Fold_Ureal; -- cgit v1.1 From 589721afccb7fc7a06fea97c7a2ac6adbc8abb70 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Mon, 8 Jul 2019 08:13:57 +0000 Subject: [Ada] Use g-sercom__linux.adb for all Linuxes 2019-07-08 Dmitriy Anisimkov gcc/ada/ * Makefile.rtl: Use g-sercom__linux.adb for all linuxes. From-SVN: r273212 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/Makefile.rtl | 12 +++++------- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e278295..6c86afb 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Dmitriy Anisimkov + + * Makefile.rtl: Use g-sercom__linux.adb for all linuxes. + 2019-07-08 Yannick Moy * expander.adb (Expand): Do not reset Analyzed flag always. diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 916ae3e..4210018 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -1521,7 +1521,6 @@ ifeq ($(strip $(filter-out %86 linux%,$(target_cpu) $(target_os))),) s-intman.adb Date: Mon, 8 Jul 2019 08:14:01 +0000 Subject: [Ada] New port for x86_64-vx7 2019-07-08 Doug Rupp gcc/ada/ * Makefile.rtl: Handle vxworks7r2 in x86_64 and x86 vxworks7. From-SVN: r273213 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/Makefile.rtl | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6c86afb..288c604 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Doug Rupp + + * Makefile.rtl: Handle vxworks7r2 in x86_64 and x86 vxworks7. + 2019-07-08 Dmitriy Anisimkov * Makefile.rtl: Use g-sercom__linux.adb for all linuxes. diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 4210018..8e906a9 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -1118,7 +1118,7 @@ ifeq ($(strip $(filter-out %86 wrs vxworksae,$(target_cpu) $(target_vendor) $(ta endif # x86/x86_64 VxWorks -ifeq ($(strip $(filter-out %86 x86_64 wrs vxworks vxworks7,$(target_cpu) $(target_vendor) $(target_os))),) +ifeq ($(strip $(filter-out %86 x86_64 wrs vxworks vxworks7%,$(target_cpu) $(target_vendor) $(target_os))),) EH_MECHANISM=-gcc -- cgit v1.1 From 900dd8405fbd327023aa24f856b4535033ebbef0 Mon Sep 17 00:00:00 2001 From: Nicolas Roche Date: Mon, 8 Jul 2019 08:14:06 +0000 Subject: [Ada] Remove dependency on Win32 GDI (Graphical Interface) CommandLineToArgvW drags a dependency on SHELL32.DLL and thus GDI32.DLL. By loading GDI32.DLL some default GDI objects are allocated. On some Windows versions this cause the use of a lock on the graphical interface during process termination. This can impact parallelism significantly as termination of processes is serialized. 2019-07-08 Nicolas Roche gcc/ada/ * rtinit.c (__gnat_runtime_initialize): Remove dependency on CommandLineToArgvW. From-SVN: r273214 --- gcc/ada/ChangeLog | 5 ++ gcc/ada/rtinit.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 197 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 288c604..57869d3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Nicolas Roche + + * rtinit.c (__gnat_runtime_initialize): Remove dependency on + CommandLineToArgvW. + 2019-07-08 Doug Rupp * Makefile.rtl: Handle vxworks7r2 in x86_64 and x86 vxworks7. diff --git a/gcc/ada/rtinit.c b/gcc/ada/rtinit.c index 13bd595..1df98f8 100644 --- a/gcc/ada/rtinit.c +++ b/gcc/ada/rtinit.c @@ -62,7 +62,7 @@ extern "C" { /* __gnat_runtime_initialize (NT-mingw32 Version) */ /**************************************************/ -extern void __gnat_install_handler(void); +extern void __gnat_install_handler (void); int __gnat_wide_text_translation_required = 0; /* wide text translation, 0=none, 1=activated */ @@ -89,6 +89,189 @@ extern HANDLE ProcListEvt; int __gnat_do_argv_expansion = 1; #pragma weak __gnat_do_argv_expansion +/* Assuming we are pointing to the beginning of a quoted part of an +argument, skip until the end of the quoted part. */ +static void skip_quoted_string (const WCHAR **current_in, + WCHAR **current_out) +{ + /* Number of backslashes buffered. */ + int qbs_count = 0; + + /* Pointer to current input character. */ + const WCHAR *ci = *current_in; + + /* Pointer to next output character. */ + WCHAR *co = *current_out; + + /* Skip initial quote. */ + ci++; + + while (*ci) + { + if (*ci == '\\') + { + /* Buffer incoming backslashes. */ + qbs_count++; + } + else if (*ci == '"') + { + /* Append qbs_count / 2 backslahes. */ + for (int i=0; i Date: Mon, 8 Jul 2019 08:14:11 +0000 Subject: [Ada] Suppress warnings on memory representation in CodePeer mode 2019-07-08 Daniel Mercier gcc/ada/ * gnat1drv.adb: Suppress warnings on memory representation in CodePeer compiler mode. From-SVN: r273215 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/gnat1drv.adb | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 57869d3..6ed4339 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Daniel Mercier + + * gnat1drv.adb: Suppress warnings on memory representation in + CodePeer compiler mode. + 2019-07-08 Nicolas Roche * rtinit.c (__gnat_runtime_initialize): Remove dependency on diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 572ce3d..86d6be2 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -82,6 +82,7 @@ with Uname; use Uname; with Urealp; with Usage; with Validsw; use Validsw; +with Warnsw; use Warnsw; with System.Assertions; with System.OS_Lib; @@ -403,7 +404,22 @@ procedure Gnat1drv is Relaxed_RM_Semantics := True; - if not Generate_CodePeer_Messages then + if Generate_CodePeer_Messages then + + -- We do want to emit GNAT warnings when using -gnateC. But, + -- in CodePeer mode, warnings about memory representation are not + -- meaningful, thus, suppress them. + + Warn_On_Biased_Representation := False; -- -gnatw.b + Warn_On_Unrepped_Components := False; -- -gnatw.c + Warn_On_Record_Holes := False; -- -gnatw.h + Warn_On_Unchecked_Conversion := False; -- -gnatwz + Warn_On_Size_Alignment := False; -- -gnatw.z + Warn_On_Questionable_Layout := False; -- -gnatw.q + Warn_On_Overridden_Size := False; -- -gnatw.s + Warn_On_Reverse_Bit_Order := False; -- -gnatw.v + + else -- Suppress compiler warnings by default when generating SCIL for -- CodePeer, except when combined with -gnateC where we do want to -- cgit v1.1 From 56730418631c887e3c20f6529ed9399b80b50915 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 8 Jul 2019 08:14:15 +0000 Subject: [Ada] Set dummy Etype for the fake __HEAP entity in GNATprove GNATprove represents reads and writes via pointers as operations on a fake __HEAP entity. This entity already had various properties set to dummy values (e.g. Scope set to Standard_Standard), so that it can be processed like other entities without crashing and not special-cased everywhere. Now it also has a dummy Etype, so it can be processed with Is_Single_Concurrent_Object. The modified code is only executed by GNATprove; frontend is not affected. 2019-07-08 Piotr Trojanek gcc/ada/ * lib-xref-spark_specific.adb (Create_Heap): Set dummy Etype for the fake __HEAP entity. From-SVN: r273216 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/lib-xref-spark_specific.adb | 1 + 2 files changed, 6 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6ed4339..afa2381 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Piotr Trojanek + + * lib-xref-spark_specific.adb (Create_Heap): Set dummy Etype for + the fake __HEAP entity. + 2019-07-08 Daniel Mercier * gnat1drv.adb: Suppress warnings on memory representation in diff --git a/gcc/ada/lib-xref-spark_specific.adb b/gcc/ada/lib-xref-spark_specific.adb index 36aaefb..0ad7044 100644 --- a/gcc/ada/lib-xref-spark_specific.adb +++ b/gcc/ada/lib-xref-spark_specific.adb @@ -298,6 +298,7 @@ package body SPARK_Specific is Set_Ekind (Heap, E_Variable); Set_Is_Internal (Heap, True); + Set_Etype (Heap, Standard_Void_Type); Set_Scope (Heap, Standard_Standard); Set_Has_Fully_Qualified_Name (Heap); end Create_Heap; -- cgit v1.1 From 47bcd81fe7f8f9251f0777ae5ee77520b615af26 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Mon, 8 Jul 2019 08:14:22 +0000 Subject: [Ada] Diagnostics for Elaboration order v4.0 This patch adds a missing case to the output of cycle diagnostics here a transition from an Elaborate_Body pair may reach a destination which is in the context of an active Elaborate_All. 2019-07-08 Hristian Kirtchev gcc/ada/ * bindo-diagnostics.adb (Diagnose_Cycle): Capture the presence of an Elaborate_All edge before iterating over the edges of the cycle. (Output_Elaborate_Body_Transition): Update the parameter profile and the comment on usage. Add a missing case where the edge is within the context of an Elaborate_All. (Output_Transition): Update the call to Output_Elaborate_Body_Transition. * bindo-graphs.ads, bindo-graphs.adb (Contains_Elaborate_All_Edge): New routine. From-SVN: r273217 --- gcc/ada/ChangeLog | 13 +++++ gcc/ada/bindo-diagnostics.adb | 117 ++++++++++++++++++++++++------------------ gcc/ada/bindo-graphs.adb | 39 ++++++++++++++ gcc/ada/bindo-graphs.ads | 7 +++ 4 files changed, 126 insertions(+), 50 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index afa2381..cc8978d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2019-07-08 Hristian Kirtchev + + * bindo-diagnostics.adb (Diagnose_Cycle): Capture the presence + of an Elaborate_All edge before iterating over the edges of the + cycle. + (Output_Elaborate_Body_Transition): Update the parameter profile + and the comment on usage. Add a missing case where the edge is + within the context of an Elaborate_All. + (Output_Transition): Update the call to + Output_Elaborate_Body_Transition. + * bindo-graphs.ads, bindo-graphs.adb + (Contains_Elaborate_All_Edge): New routine. + 2019-07-08 Piotr Trojanek * lib-xref-spark_specific.adb (Create_Heap): Set dummy Etype for diff --git a/gcc/ada/bindo-diagnostics.adb b/gcc/ada/bindo-diagnostics.adb index 0c1a924..9cd9d68 100644 --- a/gcc/ada/bindo-diagnostics.adb +++ b/gcc/ada/bindo-diagnostics.adb @@ -115,13 +115,15 @@ package body Bindo.Diagnostics is (G : Library_Graph; Source : Library_Graph_Vertex_Id; Actual_Destination : Library_Graph_Vertex_Id; - Expected_Destination : Library_Graph_Vertex_Id); + Expected_Destination : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean); pragma Inline (Output_Elaborate_Body_Transition); -- Output a transition through an edge of library graph G with successor - -- Source and predecessor Actual_Destination. Vertex Source is either a - -- spec subject to pragma Elaborate_Body or denotes the body of such a - -- spec. Expected_Destination denotes the predecessor as specified by the - -- next edge in a cycle. + -- Source and predecessor Actual_Destination. Vertex Source is either + -- a spec subject to pragma Elaborate_Body or denotes the body of such + -- a spec. Expected_Destination denotes the predecessor as specified by + -- the next edge in a cycle. Elaborate_All_Active should be set when the + -- transition occurs within a cycle that involves an Elaborate_All edge. procedure Output_Elaborate_Suggestions (G : Library_Graph; @@ -160,7 +162,8 @@ package body Bindo.Diagnostics is -- Output a transition through a Forced edge of library graph G with -- successor Source and predecessor Actual_Destination. Parameter -- Expected_Destination denotes the predecessor as specified by the - -- next edge in a cycle. + -- next edge in a cycle. Elaborate_All_Active should be set when the + -- transition occurs within a cycle that involves an Elaborate_All edge. procedure Output_Full_Encoding_Suggestions (G : Library_Graph; @@ -328,18 +331,21 @@ package body Bindo.Diagnostics is Lib_Graph : Library_Graph; Cycle : Library_Graph_Cycle_Id) is - Current_Edge : Library_Graph_Edge_Id; - Elaborate_All_Active : Boolean; - First_Edge : Library_Graph_Edge_Id; - Iter : Edges_Of_Cycle_Iterator; - Next_Edge : Library_Graph_Edge_Id; - - begin pragma Assert (Present (Inv_Graph)); pragma Assert (Present (Lib_Graph)); pragma Assert (Present (Cycle)); - Elaborate_All_Active := False; + Elaborate_All_Active : constant Boolean := + Contains_Elaborate_All_Edge + (G => Lib_Graph, + Cycle => Cycle); + + Current_Edge : Library_Graph_Edge_Id; + First_Edge : Library_Graph_Edge_Id; + Iter : Edges_Of_Cycle_Iterator; + Next_Edge : Library_Graph_Edge_Id; + + begin First_Edge := No_Library_Graph_Edge; -- Inspect the edges of the cycle in pairs, emitting diagnostics based @@ -355,11 +361,6 @@ package body Bindo.Diagnostics is Next (Iter, Current_Edge); First_Edge := Current_Edge; - Elaborate_All_Active := - Is_Elaborate_All_Edge - (G => Lib_Graph, - Edge => First_Edge); - Output_Reason_And_Circularity_Header (G => Lib_Graph, First_Edge => First_Edge); @@ -374,12 +375,6 @@ package body Bindo.Diagnostics is -- taking into account the predecessors and successors involved, as -- well as the nature of the edge. - Elaborate_All_Active := - Elaborate_All_Active - or else Is_Elaborate_All_Edge - (G => Lib_Graph, - Edge => Current_Edge); - Output_Transition (Inv_Graph => Inv_Graph, Lib_Graph => Lib_Graph, @@ -590,7 +585,7 @@ package body Bindo.Diagnostics is pragma Assert (Present (Expected_Destination)); -- The actual and expected destination vertices match, and denote the - -- spec of a unit. + -- initial declaration of a unit. -- -- Elaborate_All Actual_Destination -- Source ---------------> spec --> @@ -668,7 +663,8 @@ package body Bindo.Diagnostics is (G : Library_Graph; Source : Library_Graph_Vertex_Id; Actual_Destination : Library_Graph_Vertex_Id; - Expected_Destination : Library_Graph_Vertex_Id) + Expected_Destination : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean) is begin pragma Assert (Present (G)); @@ -676,20 +672,17 @@ package body Bindo.Diagnostics is pragma Assert (Present (Actual_Destination)); pragma Assert (Present (Expected_Destination)); - -- The actual and expected destination vertices match, and denote the - -- spec or body of a unit subject to pragma Elaborate_Body. There is no - -- need to mention the pragma because it does not affect the path of the - -- cycle. Treat the edge as a regular with edge. + -- The actual and expected destination vertices match -- - -- Actual_Destination - -- Source --> spec Elaborate_Body --> - -- Expected_Destination + -- Actual_Destination + -- Source --------> spec --> + -- Elaborate_Body Expected_Destination -- - -- spec Elaborate_Body + -- spec -- - -- Actual_Destination - -- Source --> body --> - -- Expected_Destination + -- Actual_Destination + -- Source --------> body --> + -- Elaborate_Body Expected_Destination if Actual_Destination = Expected_Destination then Error_Msg_Unit_1 := Name (G, Source); @@ -697,16 +690,40 @@ package body Bindo.Diagnostics is Error_Msg_Info (" unit $ has with clause for unit $"); + -- The actual destination vertex denotes the spec of a unit while the + -- expected destination is the corresponding body, and the unit is in + -- the closure of an earlier Elaborate_All pragma. + -- + -- Actual_Destination + -- Source --------> spec + -- Elaborate_Body + -- body --> + -- Expected_Destination + + elsif Elaborate_All_Active then + pragma Assert (Is_Spec_With_Body (G, Actual_Destination)); + pragma Assert (Is_Body_With_Spec (G, Expected_Destination)); + pragma Assert + (Proper_Body (G, Actual_Destination) = Expected_Destination); + + Error_Msg_Unit_1 := Name (G, Source); + Error_Msg_Unit_2 := Name (G, Actual_Destination); + Error_Msg_Info + (" unit $ has with clause for unit $"); + + Error_Msg_Unit_1 := Name (G, Expected_Destination); + Error_Msg_Info + (" unit $ is in the closure of pragma Elaborate_All"); + -- Otherwise the actual destination vertex is the spec of a unit subject -- to pragma Elaborate_Body and the expected destination vertex is the - -- completion body. The pragma must be mentioned because it directs the - -- path of the cycle from the spec to the body. - -- - -- Actual_Destination - -- Source --> spec Elaborate_Body + -- completion body. -- - -- body --> - -- Expected_Destination + -- Actual_Destination + -- Source --------> spec Elaborate_Body + -- Elaborate_Body + -- body --> + -- Expected_Destination else pragma Assert @@ -769,7 +786,7 @@ package body Bindo.Diagnostics is pragma Assert (Present (Expected_Destination)); -- The actual and expected destination vertices match, and denote the - -- spec of a unit. + -- initial declaration of a unit. -- -- Elaborate Actual_Destination -- Source -----------> spec --> @@ -876,8 +893,7 @@ package body Bindo.Diagnostics is pragma Assert (Present (Actual_Destination)); pragma Assert (Present (Expected_Destination)); - -- The actual and expected destination vertices match, and denote the - -- spec of a unit. + -- The actual and expected destination vertices match -- -- Forced Actual_Destination -- Source --------> spec --> @@ -1291,7 +1307,8 @@ package body Bindo.Diagnostics is (G => Lib_Graph, Source => Source, Actual_Destination => Actual_Destination, - Expected_Destination => Expected_Destination); + Expected_Destination => Expected_Destination, + Elaborate_All_Active => Elaborate_All_Active); elsif Is_Elaborate_Edge (Lib_Graph, Current_Edge) then Output_Elaborate_Transition @@ -1345,7 +1362,7 @@ package body Bindo.Diagnostics is pragma Assert (Present (Expected_Destination)); -- The actual and expected destination vertices match, and denote the - -- spec of a unit. + -- initial declaration of a unit. -- -- with Actual_Destination -- Source ------> spec --> diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index 387d969..5443b79 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -1840,6 +1840,45 @@ package body Bindo.Graphs is return DG.Component (G.Graph, Vertex); end Component; + --------------------------------- + -- Contains_Elaborate_All_Edge -- + --------------------------------- + + function Contains_Elaborate_All_Edge + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Boolean + is + Edge : Library_Graph_Edge_Id; + Iter : Edges_Of_Cycle_Iterator; + Seen : Boolean; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- Assume that no Elaborate_All edge has been seen + + Seen := False; + + -- IMPORTANT: + -- + -- * The iteration must run to completion in order to unlock the + -- edges of the cycle. + + Iter := Iterate_Edges_Of_Cycle (G, Cycle); + while Has_Next (Iter) loop + Next (Iter, Edge); + + if not Seen + and then Is_Elaborate_All_Edge (G, Edge) + then + Seen := True; + end if; + end loop; + + return Seen; + end Contains_Elaborate_All_Edge; + ------------------------------------ -- Contains_Weak_Static_Successor -- ------------------------------------ diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads index 3c2fef01..84e83b9 100644 --- a/gcc/ada/bindo-graphs.ads +++ b/gcc/ada/bindo-graphs.ads @@ -980,6 +980,13 @@ package Bindo.Graphs is -- -- This behavior can be forced by setting flag Force_Complement to True. + function Contains_Elaborate_All_Edge + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Boolean; + pragma Inline (Contains_Elaborate_All_Edge); + -- Determine whether cycle Cycle of library graph G contains an + -- Elaborate_All edge. + function Contains_Weak_Static_Successor (G : Library_Graph; Cycle : Library_Graph_Cycle_Id) return Boolean; -- cgit v1.1 From 570d5bbc7b7c5f7eb0eb03660a93687a6698ae7e Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Mon, 8 Jul 2019 08:14:27 +0000 Subject: [Ada] Assertion failure on validity check for Address This patch corrects the verification of 'Address clauses to avoid processing a clause where the prefix of the attribute is a generic formal object. 2019-07-08 Hristian Kirtchev gcc/ada/ * sem_ch13.adb (Analyze_Attribute_Definition_Clause): Do not register an address clause when its prefix denotes a generic formal object. gcc/testsuite/ * gnat.dg/addr13.adb, gnat.dg/addr13.ads: New testcase. From-SVN: r273218 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/sem_ch13.adb | 1 + gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/addr13.adb | 9 +++++++++ gcc/testsuite/gnat.dg/addr13.ads | 5 +++++ 5 files changed, 25 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/addr13.adb create mode 100644 gcc/testsuite/gnat.dg/addr13.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cc8978d..b122428 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,11 @@ 2019-07-08 Hristian Kirtchev + * sem_ch13.adb (Analyze_Attribute_Definition_Clause): Do not + register an address clause when its prefix denotes a generic + formal object. + +2019-07-08 Hristian Kirtchev + * bindo-diagnostics.adb (Diagnose_Cycle): Capture the presence of an Elaborate_All edge before iterating over the edges of the cycle. diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 76639cd..cbae9c8 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -5145,6 +5145,7 @@ package body Sem_Ch13 is -- aspect case properly. if Is_Object (O_Ent) + and then not Is_Generic_Formal (O_Ent) and then not Is_Generic_Type (Etype (U_Ent)) and then Address_Clause_Overlay_Warnings then diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 25f6636..169c7a5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Hristian Kirtchev + + * gnat.dg/addr13.adb, gnat.dg/addr13.ads: New testcase. + 2019-07-08 Ed Schonberg * gnat.dg/entry1.adb, gnat.dg/entry1.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/addr13.adb b/gcc/testsuite/gnat.dg/addr13.adb new file mode 100644 index 0000000..91e44ae --- /dev/null +++ b/gcc/testsuite/gnat.dg/addr13.adb @@ -0,0 +1,9 @@ +-- { dg-do compile } + +package body Addr13 is + procedure Overlay is + Over : Integer with Address => Gen_Obj'Address; + begin + Over := 123; + end Overlay; +end Addr13; diff --git a/gcc/testsuite/gnat.dg/addr13.ads b/gcc/testsuite/gnat.dg/addr13.ads new file mode 100644 index 0000000..f1f1646 --- /dev/null +++ b/gcc/testsuite/gnat.dg/addr13.ads @@ -0,0 +1,5 @@ +generic + Gen_Obj : in out Integer; +package Addr13 is + procedure Overlay; +end Addr13; -- cgit v1.1 From fa2538c77b94a62c657aee31a613ea29e6a46d4d Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Mon, 8 Jul 2019 08:14:32 +0000 Subject: [Ada] Wrong evaluation of membership test The code generated by the compiler erroneously evaluates to True membership tests when their left operand is a a class-wide interface object and the right operand is a tagged type that implements such interface type. 2019-07-08 Javier Miranda gcc/ada/ * exp_ch4.adb (Tagged_Membership): Fix regression silently introduced in r260738 that erroneouslusy causes the evaluation to True of the membership test when the left operand of the membership test is a class-wide interface object and the right operand is a type that implements such interface type. gcc/testsuite/ * gnat.dg/interface10.adb: New testcase. From-SVN: r273219 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/exp_ch4.adb | 3 ++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/interface10.adb | 22 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/interface10.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b122428..2692731 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-08 Javier Miranda + + * exp_ch4.adb (Tagged_Membership): Fix regression silently + introduced in r260738 that erroneouslusy causes the evaluation + to True of the membership test when the left operand of the + membership test is a class-wide interface object and the right + operand is a type that implements such interface type. + 2019-07-08 Hristian Kirtchev * sem_ch13.adb (Analyze_Attribute_Definition_Clause): Do not diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 78b5028..eb35845 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -14156,7 +14156,8 @@ package body Exp_Ch4 is -- Obj1 in DT'Class; -- Compile time error -- Obj1 in Iface'Class; -- Compile time error - if not Is_Class_Wide_Type (Left_Type) + if not Is_Interface (Left_Type) + and then not Is_Class_Wide_Type (Left_Type) and then (Is_Ancestor (Etype (Right_Type), Left_Type, Use_Full_View => True) or else (Is_Interface (Etype (Right_Type)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 169c7a5..ca89951 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Javier Miranda + + * gnat.dg/interface10.adb: New testcase. + 2019-07-08 Hristian Kirtchev * gnat.dg/addr13.adb, gnat.dg/addr13.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/interface10.adb b/gcc/testsuite/gnat.dg/interface10.adb new file mode 100644 index 0000000..7433454 --- /dev/null +++ b/gcc/testsuite/gnat.dg/interface10.adb @@ -0,0 +1,22 @@ +-- { dg-do run } +-- { dg-options "-gnata" } + +with Ada.Text_IO; + +procedure Interface10 is + + type Iface is interface; + + type My_First_Type is new Iface with null record; + type My_Second_Type is new Iface with null record; + + procedure Do_Test (Object : in Iface'Class) is + begin + pragma Assert + ((Object in My_First_Type) = (Object in My_First_Type'Class)); + end; + + V : My_Second_Type; +begin + Do_Test (V); +end Interface10; -- cgit v1.1 From 156187ef87ef07d5004954785f4c0127e64d1a21 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Mon, 8 Jul 2019 08:14:36 +0000 Subject: [Ada] In-place initialization for Initialize_Scalars Update the documentation of pragma Initialize_Scalars in the GNAT Reference Manual. 2019-07-08 Hristian Kirtchev gcc/ada/ * doc/gnat_rm/implementation_defined_pragmas.rst: Update the documentation of pragma Initialize_Scalars. * gnat_rm.texi: Regenerate. From-SVN: r273220 --- gcc/ada/ChangeLog | 6 + .../doc/gnat_rm/implementation_defined_pragmas.rst | 121 ++++++++++------- gcc/ada/gnat_rm.texi | 144 ++++++++++++++------- 3 files changed, 175 insertions(+), 96 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2692731..badbe8f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Hristian Kirtchev + + * doc/gnat_rm/implementation_defined_pragmas.rst: + Update the documentation of pragma Initialize_Scalars. + * gnat_rm.texi: Regenerate. + 2019-07-08 Javier Miranda * exp_ch4.adb (Tagged_Membership): Fix regression silently diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst index c2e4a4e..dff7798 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst @@ -2432,7 +2432,7 @@ with Import and Export pragmas. There are two cases to consider: ``As_Is`` provides the normal default behavior in which the casing is taken from the string provided. -This pragma may appear anywhere that a pragma is valid. In particular, it +This pragma may appear anywhere that a pragma is valid. In particular, it can be used as a configuration pragma in the :file:`gnat.adc` file, in which case it applies to all subsequent compilations, or it can be used as a program unit pragma, in which case it only applies to the current unit, or it can @@ -2999,58 +2999,87 @@ Syntax: .. code-block:: ada - pragma Initialize_Scalars; + pragma Initialize_Scalars + [ ( TYPE_VALUE_PAIR {, TYPE_VALUE_PAIR} ) ]; + TYPE_VALUE_PAIR ::= + SCALAR_TYPE => static_EXPRESSION -This pragma is similar to ``Normalize_Scalars`` conceptually but has -two important differences. First, there is no requirement for the pragma -to be used uniformly in all units of a partition, in particular, it is fine -to use this just for some or all of the application units of a partition, -without needing to recompile the run-time library. + SCALAR_TYPE := + Short_Float + | Float + | Long_Float + | Long_Long_Flat + | Signed_8 + | Signed_16 + | Signed_32 + | Signed_64 + | Unsigned_8 + | Unsigned_16 + | Unsigned_32 + | Unsigned_64 -In the case where some units are compiled with the pragma, and some without, -then a declaration of a variable where the type is defined in package -Standard or is locally declared will always be subject to initialization, -as will any declaration of a scalar variable. For composite variables, -whether the variable is initialized may also depend on whether the package -in which the type of the variable is declared is compiled with the pragma. -The other important difference is that you can control the value used -for initializing scalar objects. At bind time, you can select several -options for initialization. You can -initialize with invalid values (similar to Normalize_Scalars, though for -Initialize_Scalars it is not always possible to determine the invalid -values in complex cases like signed component fields with non-standard -sizes). You can also initialize with high or -low values, or with a specified bit pattern. See the GNAT -User's Guide for binder options for specifying these cases. +This pragma is similar to ``Normalize_Scalars`` conceptually but has two +important differences. -This means that you can compile a program, and then without having to -recompile the program, you can run it with different values being used -for initializing otherwise uninitialized values, to test if your program -behavior depends on the choice. Of course the behavior should not change, -and if it does, then most likely you have an incorrect reference to an -uninitialized value. +First, there is no requirement for the pragma to be used uniformly in all units +of a partition. In particular, it is fine to use this just for some or all of +the application units of a partition, without needing to recompile the run-time +library. In the case where some units are compiled with the pragma, and some +without, then a declaration of a variable where the type is defined in package +Standard or is locally declared will always be subject to initialization, as +will any declaration of a scalar variable. For composite variables, whether the +variable is initialized may also depend on whether the package in which the +type of the variable is declared is compiled with the pragma. -It is even possible to change the value at execution time eliminating even -the need to rebind with a different switch using an environment variable. -See the GNAT User's Guide for details. +The other important difference is that the programmer can control the value +used for initializing scalar objects. This effect can be achieved in several +different ways: + +* At compile time, the programmer can specify the invalid value for a + particular family of scalar types using the optional arguments of the pragma. + + The compile-time approach is intended to optimize the generated code for the + pragma, by possibly using fast operations such as ``memset``. + +* At bind time, the programmer has several options: + + * Initialization with invalid values (similar to Normalize_Scalars, though + for Initialize_Scalars it is not always possible to determine the invalid + values in complex cases like signed component fields with nonstandard + sizes). + + * Initialization with high values. + + * Initialization with low values. + + * Initialization with a specific bit pattern. + + See the GNAT User's Guide for binder options for specifying these cases. + + The bind-time approach is intended to provide fast turnaround for testing + with different values, without having to recompile the program. + +* At execution time, the programmer can speify the invalid values using an + environment variable. See the GNAT User's Guide for details. + + The execution-time approach is intended to provide fast turnaround for + testing with different values, without having to recompile and rebind the + program. + +Note that pragma ``Initialize_Scalars`` is particularly useful in conjunction +with the enhanced validity checking that is now provided in GNAT, which checks +for invalid values under more conditions. Using this feature (see description +of the *-gnatV* flag in the GNAT User's Guide) in conjunction with pragma +``Initialize_Scalars`` provides a powerful new tool to assist in the detection +of problems caused by uninitialized variables. -Note that pragma ``Initialize_Scalars`` is particularly useful in -conjunction with the enhanced validity checking that is now provided -in GNAT, which checks for invalid values under more conditions. -Using this feature (see description of the *-gnatV* flag in the -GNAT User's Guide) in conjunction with -pragma ``Initialize_Scalars`` -provides a powerful new tool to assist in the detection of problems -caused by uninitialized variables. - -Note: the use of ``Initialize_Scalars`` has a fairly extensive -effect on the generated code. This may cause your code to be -substantially larger. It may also cause an increase in the amount -of stack required, so it is probably a good idea to turn on stack -checking (see description of stack checking in the GNAT -User's Guide) when using this pragma. +Note: the use of ``Initialize_Scalars`` has a fairly extensive effect on the +generated code. This may cause your code to be substantially larger. It may +also cause an increase in the amount of stack required, so it is probably a +good idea to turn on stack checking (see description of stack checking in the +GNAT User's Guide) when using this pragma. .. _Pragma-Initializes: diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index e67fb7b..b540e7b 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -3870,7 +3870,7 @@ then the name will be forced to all lowercase letters. A specification of taken from the string provided. @end itemize -This pragma may appear anywhere that a pragma is valid. In particular, it +This pragma may appear anywhere that a pragma is valid. In particular, it can be used as a configuration pragma in the @code{gnat.adc} file, in which case it applies to all subsequent compilations, or it can be used as a program unit pragma, in which case it only applies to the current unit, or it can @@ -4441,58 +4441,102 @@ in the SPARK 2014 Reference Manual, section 7.1.6. Syntax: @example -pragma Initialize_Scalars; +pragma Initialize_Scalars + [ ( TYPE_VALUE_PAIR @{, TYPE_VALUE_PAIR@} ) ]; + +TYPE_VALUE_PAIR ::= + SCALAR_TYPE => static_EXPRESSION + +SCALAR_TYPE := + Short_Float +| Float +| Long_Float +| Long_Long_Flat +| Signed_8 +| Signed_16 +| Signed_32 +| Signed_64 +| Unsigned_8 +| Unsigned_16 +| Unsigned_32 +| Unsigned_64 @end example -This pragma is similar to @code{Normalize_Scalars} conceptually but has -two important differences. First, there is no requirement for the pragma -to be used uniformly in all units of a partition, in particular, it is fine -to use this just for some or all of the application units of a partition, -without needing to recompile the run-time library. - -In the case where some units are compiled with the pragma, and some without, -then a declaration of a variable where the type is defined in package -Standard or is locally declared will always be subject to initialization, -as will any declaration of a scalar variable. For composite variables, -whether the variable is initialized may also depend on whether the package -in which the type of the variable is declared is compiled with the pragma. - -The other important difference is that you can control the value used -for initializing scalar objects. At bind time, you can select several -options for initialization. You can -initialize with invalid values (similar to Normalize_Scalars, though for -Initialize_Scalars it is not always possible to determine the invalid -values in complex cases like signed component fields with non-standard -sizes). You can also initialize with high or -low values, or with a specified bit pattern. See the GNAT -User's Guide for binder options for specifying these cases. - -This means that you can compile a program, and then without having to -recompile the program, you can run it with different values being used -for initializing otherwise uninitialized values, to test if your program -behavior depends on the choice. Of course the behavior should not change, -and if it does, then most likely you have an incorrect reference to an -uninitialized value. - -It is even possible to change the value at execution time eliminating even -the need to rebind with a different switch using an environment variable. -See the GNAT User's Guide for details. +This pragma is similar to @code{Normalize_Scalars} conceptually but has two +important differences. + +First, there is no requirement for the pragma to be used uniformly in all units +of a partition. In particular, it is fine to use this just for some or all of +the application units of a partition, without needing to recompile the run-time +library. In the case where some units are compiled with the pragma, and some +without, then a declaration of a variable where the type is defined in package +Standard or is locally declared will always be subject to initialization, as +will any declaration of a scalar variable. For composite variables, whether the +variable is initialized may also depend on whether the package in which the +type of the variable is declared is compiled with the pragma. + +The other important difference is that the programmer can control the value +used for initializing scalar objects. This effect can be achieved in several +different ways: + + +@itemize * + +@item +At compile time, the programmer can specify the invalid value for a +particular family of scalar types using the optional arguments of the pragma. + +The compile-time approach is intended to optimize the generated code for the +pragma, by possibly using fast operations such as @code{memset}. + +@item +At bind time, the programmer has several options: + + +@itemize * + +@item +Initialization with invalid values (similar to Normalize_Scalars, though +for Initialize_Scalars it is not always possible to determine the invalid +values in complex cases like signed component fields with nonstandard +sizes). + +@item +Initialization with high values. + +@item +Initialization with low values. + +@item +Initialization with a specific bit pattern. +@end itemize + +See the GNAT User's Guide for binder options for specifying these cases. + +The bind-time approach is intended to provide fast turnaround for testing +with different values, without having to recompile the program. + +@item +At execution time, the programmer can speify the invalid values using an +environment variable. See the GNAT User's Guide for details. + +The execution-time approach is intended to provide fast turnaround for +testing with different values, without having to recompile and rebind the +program. +@end itemize + +Note that pragma @code{Initialize_Scalars} is particularly useful in conjunction +with the enhanced validity checking that is now provided in GNAT, which checks +for invalid values under more conditions. Using this feature (see description +of the @emph{-gnatV} flag in the GNAT User's Guide) in conjunction with pragma +@code{Initialize_Scalars} provides a powerful new tool to assist in the detection +of problems caused by uninitialized variables. -Note that pragma @code{Initialize_Scalars} is particularly useful in -conjunction with the enhanced validity checking that is now provided -in GNAT, which checks for invalid values under more conditions. -Using this feature (see description of the @emph{-gnatV} flag in the -GNAT User's Guide) in conjunction with -pragma @code{Initialize_Scalars} -provides a powerful new tool to assist in the detection of problems -caused by uninitialized variables. - -Note: the use of @code{Initialize_Scalars} has a fairly extensive -effect on the generated code. This may cause your code to be -substantially larger. It may also cause an increase in the amount -of stack required, so it is probably a good idea to turn on stack -checking (see description of stack checking in the GNAT -User's Guide) when using this pragma. +Note: the use of @code{Initialize_Scalars} has a fairly extensive effect on the +generated code. This may cause your code to be substantially larger. It may +also cause an increase in the amount of stack required, so it is probably a +good idea to turn on stack checking (see description of stack checking in the +GNAT User's Guide) when using this pragma. @node Pragma Initializes,Pragma Inline_Always,Pragma Initialize_Scalars,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-initializes}@anchor{83}@anchor{gnat_rm/implementation_defined_pragmas id17}@anchor{84} -- cgit v1.1 From b723426575b8a948947cd8b2403c4949edc92dfc Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Mon, 8 Jul 2019 08:14:41 +0000 Subject: [Ada] Remove documentation of ignored GNATpp switch 2019-07-08 Bob Duff gcc/ada/ * doc/gnat_ugn/gnat_utility_programs.rst: Remove documentation of ignored GNATpp switch. From-SVN: r273221 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst | 11 ----------- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index badbe8f..7641688 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Bob Duff + + * doc/gnat_ugn/gnat_utility_programs.rst: Remove documentation + of ignored GNATpp switch. + 2019-07-08 Hristian Kirtchev * doc/gnat_rm/implementation_defined_pragmas.rst: diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst index b6a1d18..e20ea63 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst @@ -3337,12 +3337,6 @@ Alternatively, you may run the script using the following command line: '(' and ':'. This also turns off alignment. - .. index:: --ff-after-pragma-page (gnatpp) - - :switch:`--ff-after-pragma-page` - Insert a Form Feed character after a pragma Page. - - .. index:: --call_threshold (gnatpp) :switch:`--call_threshold={nnn}` @@ -4123,11 +4117,6 @@ Alternatively, you may run the script using the following command line: :switch:`-cl{nnn}` :switch:`--indent-continuation={nnn}` - .. index:: -ff (gnatpp) - - :switch:`-ff` - :switch:`--ff-after-pragma-page` - .. index:: -pipe (gnatpp) :switch:`-pipe` -- cgit v1.1 From 4fe5bbcf30a491a1722fa1752bc0ea9c32dcb2e3 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Mon, 8 Jul 2019 08:14:46 +0000 Subject: [Ada] Remove dead code from Enclosing_Package_Or_Subprogram routine Calls to Scope always return unique entities, i.e. package/subprogram and not their bodies, so there is no need to expect them. Cleanup only; semantics unaffected. (This routine was only used in CCG and GNATprove backends anyway.) 2019-07-08 Piotr Trojanek gcc/ada/ * sem_util.adb (Enclosing_Package_Or_Subprogram): Do not expect package and subprogram bodies. From-SVN: r273222 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_util.adb | 7 +------ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7641688..d38dce0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Piotr Trojanek + + * sem_util.adb (Enclosing_Package_Or_Subprogram): Do not expect + package and subprogram bodies. + 2019-07-08 Bob Duff * doc/gnat_ugn/gnat_utility_programs.rst: Remove documentation diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 67bc4de..0d4ec9c 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -6924,12 +6924,7 @@ package body Sem_Util is S := Scope (E); while Present (S) loop if Is_Package_Or_Generic_Package (S) - or else Ekind (S) = E_Package_Body - then - return S; - - elsif Is_Subprogram_Or_Generic_Subprogram (S) - or else Ekind (S) = E_Subprogram_Body + or else Is_Subprogram_Or_Generic_Subprogram (S) then return S; -- cgit v1.1 From 3a4a60d1d2303f51ea0ed442aa38cc5a9a4201c5 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Mon, 8 Jul 2019 08:14:50 +0000 Subject: [Ada] Os_Lib: do not call __gnat_kill for Invalid_Pid 2019-07-08 Dmitriy Anisimkov gcc/ada/ * libgnat/s-os_lib.adb: Do not call __gnat_kill for Invalid_Pid. From-SVN: r273223 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/libgnat/s-os_lib.adb | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d38dce0..672ac82 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Dmitriy Anisimkov + + * libgnat/s-os_lib.adb: Do not call __gnat_kill for Invalid_Pid. + 2019-07-08 Piotr Trojanek * sem_util.adb (Enclosing_Package_Or_Subprogram): Do not expect diff --git a/gcc/ada/libgnat/s-os_lib.adb b/gcc/ada/libgnat/s-os_lib.adb index 7efddf7..c3c1979 100644 --- a/gcc/ada/libgnat/s-os_lib.adb +++ b/gcc/ada/libgnat/s-os_lib.adb @@ -1629,10 +1629,12 @@ package body System.OS_Lib is pragma Import (C, C_Kill, "__gnat_kill"); begin - if Hard_Kill then - C_Kill (Pid, SIGKILL, 1); - else - C_Kill (Pid, SIGINT, 1); + if Pid /= Invalid_Pid then + if Hard_Kill then + C_Kill (Pid, SIGKILL, 1); + else + C_Kill (Pid, SIGINT, 1); + end if; end if; end Kill; -- cgit v1.1 From aec80f204f01c8c8ccd78a6cc4cfa07ba99ecb9f Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Mon, 8 Jul 2019 08:14:55 +0000 Subject: [Ada] GNAT RM: Update documentation on No_Exceptions restriction 2019-07-08 Arnaud Charlet gcc/ada/ * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst: Update documentation on No_Exceptions restriction. * gnat_rm.texi: Regenerate. From-SVN: r273224 --- gcc/ada/ChangeLog | 6 ++++++ .../gnat_rm/standard_and_implementation_defined_restrictions.rst | 4 +++- gcc/ada/gnat_rm.texi | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 672ac82..af36d68 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Arnaud Charlet + + * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst: + Update documentation on No_Exceptions restriction. + * gnat_rm.texi: Regenerate. + 2019-07-08 Dmitriy Anisimkov * libgnat/s-os_lib.adb: Do not call __gnat_kill for Invalid_Pid. diff --git a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst index cfa6356..56dd6a7 100644 --- a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst +++ b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst @@ -356,7 +356,9 @@ No_Exceptions .. index:: No_Exceptions [RM H.4] This restriction ensures at compile time that there are no -raise statements and no exception handlers. +raise statements and no exception handlers and also suppresses the +generation of language-defined run-time checks. + No_Finalization --------------- diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index b540e7b..91ac523 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -12507,7 +12507,8 @@ of exceptions when they are declared. @geindex No_Exceptions [RM H.4] This restriction ensures at compile time that there are no -raise statements and no exception handlers. +raise statements and no exception handlers and also suppresses the +generation of language-defined run-time checks. @node No_Finalization,No_Fixed_Point,No_Exceptions,Partition-Wide Restrictions @anchor{gnat_rm/standard_and_implementation_defined_restrictions no-finalization}@anchor{1d2} -- cgit v1.1 From 55d4e2ba076049f88c24011f2f63aa226e6c87a0 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Mon, 8 Jul 2019 08:14:59 +0000 Subject: [Ada] GNAT.Serial_Communications: simplify the Serial_Port structure 2019-07-08 Dmitriy Anisimkov gcc/ada/ * libgnat/g-sercom.ads (Serial_Port_Descriptor): New type. (Serial_Port): Add a comment, make it hold a Serial_Port_Descriptor. (To_Ada, To_C): New procedures. (Port_Data, Port_Data_Access): Remove types. * libgnat/g-sercom.adb (To_Ada): New stub. * libgnat/g-sercom__linux.adb, libgnat/g-sercom__mingw.adb: Update implementations accordingly. * s-oscons-tmplt.c: Bind Serial_Port_Descriptor to System.Win32.HANDLE on Windows, and to Interfaces.C.int on Linux. Add "Interfaces.C." prefix for other basic integer type bindings. * xoscons.adb (Output_Info): Remove the "Interfaces.C." prefix for subtypes generation. From-SVN: r273225 --- gcc/ada/ChangeLog | 18 ++++++++++++ gcc/ada/libgnat/g-sercom.adb | 9 ++++++ gcc/ada/libgnat/g-sercom.ads | 25 +++++++++++++--- gcc/ada/libgnat/g-sercom__linux.adb | 49 +++++++++++++++---------------- gcc/ada/libgnat/g-sercom__mingw.adb | 57 ++++++++++++++++++------------------- gcc/ada/s-oscons-tmplt.c | 23 +++++++++------ gcc/ada/xoscons.adb | 3 +- 7 files changed, 114 insertions(+), 70 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index af36d68..7df6448 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,21 @@ +2019-07-08 Dmitriy Anisimkov + + * libgnat/g-sercom.ads + (Serial_Port_Descriptor): New type. + (Serial_Port): Add a comment, make it hold a + Serial_Port_Descriptor. + (To_Ada, To_C): New procedures. + (Port_Data, Port_Data_Access): Remove types. + * libgnat/g-sercom.adb (To_Ada): New stub. + * libgnat/g-sercom__linux.adb, libgnat/g-sercom__mingw.adb: + Update implementations accordingly. + * s-oscons-tmplt.c: Bind Serial_Port_Descriptor to + System.Win32.HANDLE on Windows, and to Interfaces.C.int on + Linux. Add "Interfaces.C." prefix for other basic integer type + bindings. + * xoscons.adb (Output_Info): Remove the "Interfaces.C." prefix + for subtypes generation. + 2019-07-08 Arnaud Charlet * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst: diff --git a/gcc/ada/libgnat/g-sercom.adb b/gcc/ada/libgnat/g-sercom.adb index c3bed83..ccf5239 100644 --- a/gcc/ada/libgnat/g-sercom.adb +++ b/gcc/ada/libgnat/g-sercom.adb @@ -103,6 +103,15 @@ package body GNAT.Serial_Communications is Unimplemented; end Read; + ------------ + -- To_Ada -- + ------------ + + procedure To_Ada (Port : out Serial_Port; Fd : Serial_Port_Descriptor) is + begin + Unimplemented; + end To_Ada; + ----------- -- Write -- ----------- diff --git a/gcc/ada/libgnat/g-sercom.ads b/gcc/ada/libgnat/g-sercom.ads index e807dab..52447db 100644 --- a/gcc/ada/libgnat/g-sercom.ads +++ b/gcc/ada/libgnat/g-sercom.ads @@ -33,6 +33,7 @@ with Ada.Streams; with Interfaces.C; +with System.OS_Constants; package GNAT.Serial_Communications is @@ -122,6 +123,11 @@ package GNAT.Serial_Communications is -- No flow control, hardware flow control, software flow control type Serial_Port is new Ada.Streams.Root_Stream_Type with private; + -- Serial port stream type + + type Serial_Port_Descriptor is + new System.OS_Constants.Serial_Port_Descriptor; + -- OS specific serial port descriptor procedure Open (Port : out Serial_Port; @@ -168,13 +174,21 @@ package GNAT.Serial_Communications is procedure Close (Port : in out Serial_Port); -- Close port -private + procedure To_Ada (Port : out Serial_Port; Fd : Serial_Port_Descriptor) + with Inline; + -- Convert a serial port descriptor to Serial_Port. This is useful when a + -- serial port descriptor is obtained from an external library call. - type Port_Data; - type Port_Data_Access is access Port_Data; + function To_C + (Port : Serial_Port) return Serial_Port_Descriptor with Inline; + -- Return a serial port descriptor to be used by external subprograms. + -- This is useful for C functions that are not yet interfaced in this + -- package. + +private type Serial_Port is new Ada.Streams.Root_Stream_Type with record - H : Port_Data_Access; + H : Serial_Port_Descriptor := -1; end record; Data_Rate_Value : constant array (Data_Rate) of Interfaces.C.unsigned := @@ -205,4 +219,7 @@ private B3500000 => 3_500_000, B4000000 => 4_000_000); + function To_C (Port : Serial_Port) return Serial_Port_Descriptor is + (Port.H); + end GNAT.Serial_Communications; diff --git a/gcc/ada/libgnat/g-sercom__linux.adb b/gcc/ada/libgnat/g-sercom__linux.adb index f116aea..87143e2 100644 --- a/gcc/ada/libgnat/g-sercom__linux.adb +++ b/gcc/ada/libgnat/g-sercom__linux.adb @@ -33,12 +33,10 @@ with Ada.Streams; use Ada.Streams; with Ada; use Ada; -with Ada.Unchecked_Deallocation; with System; use System; with System.Communication; use System.Communication; with System.CRTL; use System.CRTL; -with System.OS_Constants; with GNAT.OS_Lib; use GNAT.OS_Lib; @@ -48,8 +46,6 @@ package body GNAT.Serial_Communications is use type Interfaces.C.unsigned; - type Port_Data is new int; - subtype unsigned is Interfaces.C.unsigned; subtype char is Interfaces.C.char; subtype unsigned_char is Interfaces.C.unsigned_char; @@ -124,20 +120,16 @@ package body GNAT.Serial_Communications is Res : int; begin - if Port.H = null then - Port.H := new Port_Data; - end if; - - Port.H.all := Port_Data (open + Port.H := Serial_Port_Descriptor (open (C_Name (C_Name'First)'Address, int (O_RDWR + O_NOCTTY + O_NDELAY))); - if Port.H.all = -1 then + if Port.H = -1 then Raise_Error ("open: open failed"); end if; -- By default we are in blocking mode - Res := fcntl (int (Port.H.all), F_SETFL, 0); + Res := fcntl (int (Port.H), F_SETFL, 0); if Res = -1 then Raise_Error ("open: fcntl failed"); @@ -169,11 +161,11 @@ package body GNAT.Serial_Communications is Res : ssize_t; begin - if Port.H = null then + if Port.H = -1 then Raise_Error ("read: port not opened", 0); end if; - Res := read (Integer (Port.H.all), Buffer'Address, Len); + Res := read (Integer (Port.H), Buffer'Address, Len); if Res = -1 then Raise_Error ("read failed"); @@ -228,13 +220,13 @@ package body GNAT.Serial_Communications is -- Warnings off, since we don't always test the result begin - if Port.H = null then + if Port.H = -1 then Raise_Error ("set: port not opened", 0); end if; -- Get current port settings - Res := tcgetattr (int (Port.H.all), Current'Address); + Res := tcgetattr (int (Port.H), Current'Address); -- Change settings now @@ -269,18 +261,27 @@ package body GNAT.Serial_Communications is -- Set port settings - Res := tcflush (int (Port.H.all), TCIFLUSH); - Res := tcsetattr (int (Port.H.all), TCSANOW, Current'Address); + Res := tcflush (int (Port.H), TCIFLUSH); + Res := tcsetattr (int (Port.H), TCSANOW, Current'Address); -- Block - Res := fcntl (int (Port.H.all), F_SETFL, (if Block then 0 else FNDELAY)); + Res := fcntl (int (Port.H), F_SETFL, (if Block then 0 else FNDELAY)); if Res = -1 then Raise_Error ("set: fcntl failed"); end if; end Set; + ------------ + -- To_Ada -- + ------------ + + procedure To_Ada (Port : out Serial_Port; Fd : Serial_Port_Descriptor) is + begin + Port.H := Fd; + end To_Ada; + ----------- -- Write -- ----------- @@ -293,11 +294,11 @@ package body GNAT.Serial_Communications is Res : ssize_t; begin - if Port.H = null then + if Port.H = -1 then Raise_Error ("write: port not opened", 0); end if; - Res := write (int (Port.H.all), Buffer'Address, Len); + Res := write (int (Port.H), Buffer'Address, Len); if Res = -1 then Raise_Error ("write failed"); @@ -311,16 +312,12 @@ package body GNAT.Serial_Communications is ----------- procedure Close (Port : in out Serial_Port) is - procedure Unchecked_Free is - new Unchecked_Deallocation (Port_Data, Port_Data_Access); - Res : int; pragma Unreferenced (Res); begin - if Port.H /= null then - Res := close (int (Port.H.all)); - Unchecked_Free (Port.H); + if Port.H /= -1 then + Res := close (int (Port.H)); end if; end Close; diff --git a/gcc/ada/libgnat/g-sercom__mingw.adb b/gcc/ada/libgnat/g-sercom__mingw.adb index 88a23ea..c13e7b3 100644 --- a/gcc/ada/libgnat/g-sercom__mingw.adb +++ b/gcc/ada/libgnat/g-sercom__mingw.adb @@ -31,13 +31,11 @@ -- This is the Windows implementation of this package -with Ada.Streams; use Ada.Streams; -with Ada.Unchecked_Deallocation; use Ada; +with Ada.Streams; use Ada.Streams, Ada; with System; use System; with System.Communication; use System.Communication; with System.CRTL; use System.CRTL; -with System.OS_Constants; with System.Win32; use System.Win32; with System.Win32.Ext; use System.Win32.Ext; @@ -49,8 +47,6 @@ package body GNAT.Serial_Communications is -- Common types - type Port_Data is new HANDLE; - C_Bits : constant array (Data_Bits) of Interfaces.C.unsigned := (8, 7); C_Parity : constant array (Parity_Check) of Interfaces.C.unsigned := (None => NOPARITY, Odd => ODDPARITY, Even => EVENPARITY); @@ -69,15 +65,11 @@ package body GNAT.Serial_Communications is ----------- procedure Close (Port : in out Serial_Port) is - procedure Unchecked_Free is - new Unchecked_Deallocation (Port_Data, Port_Data_Access); - Success : BOOL; begin - if Port.H /= null then - Success := CloseHandle (HANDLE (Port.H.all)); - Unchecked_Free (Port.H); + if Port.H /= -1 then + Success := CloseHandle (HANDLE (Port.H)); if Success = Win32.FALSE then Raise_Error ("error closing the port"); @@ -114,13 +106,11 @@ package body GNAT.Serial_Communications is pragma Unreferenced (Success); begin - if Port.H = null then - Port.H := new Port_Data; - else - Success := CloseHandle (HANDLE (Port.H.all)); + if Port.H /= -1 then + Success := CloseHandle (HANDLE (Port.H)); end if; - Port.H.all := CreateFileA + Port.H := CreateFileA (lpFileName => C_Name (C_Name'First)'Address, dwDesiredAccess => GENERIC_READ or GENERIC_WRITE, dwShareMode => 0, @@ -129,7 +119,9 @@ package body GNAT.Serial_Communications is dwFlagsAndAttributes => 0, hTemplateFile => 0); - if Port.H.all = Port_Data (INVALID_HANDLE_VALUE) then + pragma Assert (INVALID_HANDLE_VALUE = -1); + + if Port.H = Serial_Port_Descriptor (INVALID_HANDLE_VALUE) then Raise_Error ("cannot open com port"); end if; end Open; @@ -159,13 +151,13 @@ package body GNAT.Serial_Communications is Read_Last : aliased DWORD; begin - if Port.H = null then + if Port.H = -1 then Raise_Error ("read: port not opened", 0); end if; Success := ReadFile - (hFile => HANDLE (Port.H.all), + (hFile => HANDLE (Port.H), lpBuffer => Buffer (Buffer'First)'Address, nNumberOfBytesToRead => DWORD (Buffer'Length), lpNumberOfBytesRead => Read_Last'Access, @@ -200,15 +192,14 @@ package body GNAT.Serial_Communications is Com_Settings : aliased DCB; begin - if Port.H = null then + if Port.H = -1 then Raise_Error ("set: port not opened", 0); end if; - Success := GetCommState (HANDLE (Port.H.all), Com_Settings'Access); + Success := GetCommState (HANDLE (Port.H), Com_Settings'Access); if Success = Win32.FALSE then - Success := CloseHandle (HANDLE (Port.H.all)); - Port.H.all := 0; + Success := CloseHandle (HANDLE (Port.H)); Raise_Error ("set: cannot get comm state"); end if; @@ -240,11 +231,10 @@ package body GNAT.Serial_Communications is Com_Settings.Parity := BYTE (C_Parity (Parity)); Com_Settings.StopBits := BYTE (C_Stop_Bits (Stop_Bits)); - Success := SetCommState (HANDLE (Port.H.all), Com_Settings'Access); + Success := SetCommState (HANDLE (Port.H), Com_Settings'Access); if Success = Win32.FALSE then - Success := CloseHandle (HANDLE (Port.H.all)); - Port.H.all := 0; + Success := CloseHandle (HANDLE (Port.H)); Raise_Error ("cannot set comm state"); end if; @@ -274,7 +264,7 @@ package body GNAT.Serial_Communications is Success := SetCommTimeouts - (hFile => HANDLE (Port.H.all), + (hFile => HANDLE (Port.H), lpCommTimeouts => Com_Time_Out'Access); if Success = Win32.FALSE then @@ -282,6 +272,15 @@ package body GNAT.Serial_Communications is end if; end Set; + ------------ + -- To_Ada -- + ------------ + + procedure To_Ada (Port : out Serial_Port; Fd : Serial_Port_Descriptor) is + begin + Port.H := Fd; + end To_Ada; + ----------- -- Write -- ----------- @@ -294,13 +293,13 @@ package body GNAT.Serial_Communications is Temp_Last : aliased DWORD; begin - if Port.H = null then + if Port.H = -1 then Raise_Error ("write: port not opened", 0); end if; Success := WriteFile - (hFile => HANDLE (Port.H.all), + (hFile => HANDLE (Port.H), lpBuffer => Buffer'Address, nNumberOfBytesToWrite => DWORD (Buffer'Length), lpNumberOfBytesWritten => Temp_Last'Access, diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index f63ea52..1e883b9 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -261,6 +261,14 @@ main (void) { TXT("-- This is the version for " TARGET) TXT("") TXT("with Interfaces.C;") +#if defined (__MINGW32__) +# define TARGET_OS "Windows" +# define Serial_Port_Descriptor "System.Win32.HANDLE" +TXT("with System.Win32;") +#else +# define TARGET_OS "Other_OS" +# define Serial_Port_Descriptor "Interfaces.C.int" +#endif /* package System.OS_Constants is @@ -280,11 +288,6 @@ package System.OS_Constants is type OS_Type is (Windows, Other_OS); */ -#if defined (__MINGW32__) -# define TARGET_OS "Windows" -#else -# define TARGET_OS "Other_OS" -#endif C("Target_OS", OS_Type, TARGET_OS, "") /* pragma Warnings (Off, Target_OS); @@ -303,6 +306,8 @@ CST(Target_Name, "") #define SIZEOF_unsigned_int sizeof (unsigned int) CND(SIZEOF_unsigned_int, "Size of unsigned int") +SUB(Serial_Port_Descriptor) + /* ------------------- @@ -405,10 +410,10 @@ CND(FNDELAY, "Nonblocking") #if defined (__FreeBSD__) || defined (__DragonFly__) # define CNI CNU -# define IOCTL_Req_T "unsigned" +# define IOCTL_Req_T "Interfaces.C.unsigned" #else # define CNI CND -# define IOCTL_Req_T "int" +# define IOCTL_Req_T "Interfaces.C.int" #endif SUB(IOCTL_Req_T) @@ -1628,9 +1633,9 @@ CND(IF_NAMESIZE, "Max size of interface name with 0 terminator"); */ #if defined (__sun__) || defined (__hpux__) -# define Msg_Iovlen_T "int" +# define Msg_Iovlen_T "Interfaces.C.int" #else -# define Msg_Iovlen_T "size_t" +# define Msg_Iovlen_T "Interfaces.C.size_t" #endif SUB(Msg_Iovlen_T) diff --git a/gcc/ada/xoscons.adb b/gcc/ada/xoscons.adb index 0d5f635..7c72e4e 100644 --- a/gcc/ada/xoscons.adb +++ b/gcc/ada/xoscons.adb @@ -229,8 +229,7 @@ procedure XOSCons is case Lang is when Lang_Ada => Put (" subtype " & Info.Constant_Name.all - & " is Interfaces.C." - & Info.Text_Value.all & ";"); + & " is " & Info.Text_Value.all & ";"); when Lang_C => Put ("#define " & Info.Constant_Name.all & " " & Info.Text_Value.all); -- cgit v1.1 From 6f65c7ee8635e5559757fd91d4e9267c45e668b7 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 8 Jul 2019 08:15:05 +0000 Subject: [Ada] Small overhaul in Repinfo unit This creates a List_Type_Info procedure to deal with type entities other than arrays and records at top level and a List_Common_Type_Info procedure to handle the common part between them. No functional changes. 2019-07-08 Eric Botcazou gcc/ada/ * repinfo.adb (List_Common_Type_Info): New procedure extracted from... (List_Type_Info): ...here. Call it for the common information, start with a blank line and output the linker section at the end, if any. (List_Mechanisms): Rename to... (List_Subprogram_Info): ...this. (List_Array_Info): Call List_Common_Type_Info. (List_Entities): Adjust to above change and renaming. (List_Record_Info): Call List_Common_Type_Info. From-SVN: r273226 --- gcc/ada/ChangeLog | 13 ++ gcc/ada/repinfo.adb | 509 +++++++++++++++++++++++++++------------------------- 2 files changed, 275 insertions(+), 247 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7df6448..09defe0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2019-07-08 Eric Botcazou + + * repinfo.adb (List_Common_Type_Info): New procedure extracted + from... + (List_Type_Info): ...here. Call it for the common information, + start with a blank line and output the linker section at the + end, if any. + (List_Mechanisms): Rename to... + (List_Subprogram_Info): ...this. + (List_Array_Info): Call List_Common_Type_Info. + (List_Entities): Adjust to above change and renaming. + (List_Record_Info): Call List_Common_Type_Info. + 2019-07-08 Dmitriy Anisimkov * libgnat/g-sercom.ads diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 4bf3351..ff147ac 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -172,6 +172,9 @@ package body Repinfo is procedure List_Array_Info (Ent : Entity_Id; Bytes_Big_Endian : Boolean); -- List representation info for array type Ent + procedure List_Common_Type_Info (Ent : Entity_Id); + -- List common type info (name, size, alignment) for type Ent + procedure List_Linker_Section (Ent : Entity_Id); -- List linker section for Ent (caller has checked that Ent is an entity -- for which the Linker_Section_Pragma field is defined). @@ -179,10 +182,6 @@ package body Repinfo is procedure List_Location (Ent : Entity_Id); -- List location information for Ent - procedure List_Mechanisms (Ent : Entity_Id); - -- List mechanism information for parameters of Ent, which is subprogram, - -- subprogram type, or an entry or entry family. - procedure List_Object_Info (Ent : Entity_Id); -- List representation info for object Ent @@ -195,6 +194,9 @@ package body Repinfo is -- List scalar storage order information for record or array type Ent. -- Also includes bit order information for record types, if necessary. + procedure List_Subprogram_Info (Ent : Entity_Id); + -- List subprogram info for subprogram Ent + procedure List_Type_Info (Ent : Entity_Id); -- List type info for type Ent @@ -346,7 +348,7 @@ package body Repinfo is Write_Line ("{"); end if; - List_Type_Info (Ent); + List_Common_Type_Info (Ent); if List_Representation_Info_To_JSON then Write_Line (","); @@ -370,6 +372,81 @@ package body Repinfo is end if; end List_Array_Info; + --------------------------- + -- List_Common_Type_Info -- + --------------------------- + + procedure List_Common_Type_Info (Ent : Entity_Id) is + begin + if List_Representation_Info_To_JSON then + Write_Str (" ""name"": """); + List_Name (Ent); + Write_Line (""","); + List_Location (Ent); + end if; + + -- Do not list size info for unconstrained arrays, not meaningful + + if Is_Array_Type (Ent) and then not Is_Constrained (Ent) then + null; + + else + -- If Esize and RM_Size are the same, list as Size. This is a common + -- case, which we may as well list in simple form. + + if Esize (Ent) = RM_Size (Ent) then + if List_Representation_Info_To_JSON then + Write_Str (" ""Size"": "); + Write_Val (Esize (Ent)); + Write_Line (","); + else + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Size use "); + Write_Val (Esize (Ent)); + Write_Line (";"); + end if; + + -- Otherwise list size values separately + + else + if List_Representation_Info_To_JSON then + Write_Str (" ""Object_Size"": "); + Write_Val (Esize (Ent)); + Write_Line (","); + + Write_Str (" ""Value_Size"": "); + Write_Val (RM_Size (Ent)); + Write_Line (","); + + else + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Object_Size use "); + Write_Val (Esize (Ent)); + Write_Line (";"); + + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Value_Size use "); + Write_Val (RM_Size (Ent)); + Write_Line (";"); + end if; + end if; + end if; + + if List_Representation_Info_To_JSON then + Write_Str (" ""Alignment"": "); + Write_Val (Alignment (Ent)); + else + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Alignment use "); + Write_Val (Alignment (Ent)); + Write_Line (";"); + end if; + end List_Common_Type_Info; + ------------------- -- List_Entities -- ------------------- @@ -428,7 +505,7 @@ package body Repinfo is and then not In_Subprogram then Need_Blank_Line := True; - List_Mechanisms (Ent); + List_Subprogram_Info (Ent); end if; E := First_Entity (Ent); @@ -457,7 +534,7 @@ package body Repinfo is then if Is_Subprogram (E) then if List_Representation_Info_Mechanisms then - List_Mechanisms (E); + List_Subprogram_Info (E); end if; -- Recurse into entities local to subprogram @@ -472,7 +549,7 @@ package body Repinfo is E_Subprogram_Type) then if List_Representation_Info_Mechanisms then - List_Mechanisms (E); + List_Subprogram_Info (E); end if; elsif Is_Record_Type (E) then @@ -496,16 +573,7 @@ package body Repinfo is elsif Is_Type (E) then if List_Representation_Info >= 2 then - Blank_Line; - if List_Representation_Info_To_JSON then - Write_Line ("{"); - end if; List_Type_Info (E); - List_Linker_Section (E); - if List_Representation_Info_To_JSON then - Write_Eol; - Write_Line ("}"); - end if; end if; elsif Ekind_In (E, E_Variable, E_Constant) then @@ -842,188 +910,6 @@ package body Repinfo is Write_Line (""","); end List_Location; - --------------------- - -- List_Mechanisms -- - --------------------- - - procedure List_Mechanisms (Ent : Entity_Id) is - First : Boolean := True; - Plen : Natural; - Form : Entity_Id; - - begin - Blank_Line; - - if List_Representation_Info_To_JSON then - Write_Line ("{"); - Write_Str (" ""name"": """); - List_Name (Ent); - Write_Line (""","); - List_Location (Ent); - - Write_Str (" ""Convention"": """); - else - case Ekind (Ent) is - when E_Function => - Write_Str ("function "); - - when E_Operator => - Write_Str ("operator "); - - when E_Procedure => - Write_Str ("procedure "); - - when E_Subprogram_Type => - Write_Str ("type "); - - when E_Entry - | E_Entry_Family - => - Write_Str ("entry "); - - when others => - raise Program_Error; - end case; - - List_Name (Ent); - Write_Str (" declared at "); - Write_Location (Sloc (Ent)); - Write_Eol; - - Write_Str ("convention : "); - end if; - - case Convention (Ent) is - when Convention_Ada => - Write_Str ("Ada"); - - when Convention_Ada_Pass_By_Copy => - Write_Str ("Ada_Pass_By_Copy"); - - when Convention_Ada_Pass_By_Reference => - Write_Str ("Ada_Pass_By_Reference"); - - when Convention_Intrinsic => - Write_Str ("Intrinsic"); - - when Convention_Entry => - Write_Str ("Entry"); - - when Convention_Protected => - Write_Str ("Protected"); - - when Convention_Assembler => - Write_Str ("Assembler"); - - when Convention_C => - Write_Str ("C"); - - when Convention_COBOL => - Write_Str ("COBOL"); - - when Convention_CPP => - Write_Str ("C++"); - - when Convention_Fortran => - Write_Str ("Fortran"); - - when Convention_Stdcall => - Write_Str ("Stdcall"); - - when Convention_Stubbed => - Write_Str ("Stubbed"); - end case; - - if List_Representation_Info_To_JSON then - Write_Line (""","); - Write_Str (" ""formal"": ["); - else - Write_Eol; - end if; - - -- Find max length of formal name - - Plen := 0; - Form := First_Formal (Ent); - while Present (Form) loop - Get_Unqualified_Decoded_Name_String (Chars (Form)); - - if Name_Len > Plen then - Plen := Name_Len; - end if; - - Next_Formal (Form); - end loop; - - -- Output formals and mechanisms - - Form := First_Formal (Ent); - while Present (Form) loop - Get_Unqualified_Decoded_Name_String (Chars (Form)); - Set_Casing (Unit_Casing); - - if List_Representation_Info_To_JSON then - if First then - Write_Eol; - First := False; - else - Write_Line (","); - end if; - - Write_Line (" {"); - Write_Str (" ""name"": """); - Write_Str (Name_Buffer (1 .. Name_Len)); - Write_Line (""","); - - Write_Str (" ""mechanism"": """); - Write_Mechanism (Mechanism (Form)); - Write_Line (""""); - Write_Str (" }"); - else - while Name_Len <= Plen loop - Name_Len := Name_Len + 1; - Name_Buffer (Name_Len) := ' '; - end loop; - - Write_Str (" "); - Write_Str (Name_Buffer (1 .. Plen + 1)); - Write_Str (": passed by "); - - Write_Mechanism (Mechanism (Form)); - Write_Eol; - end if; - - Next_Formal (Form); - end loop; - - if List_Representation_Info_To_JSON then - Write_Eol; - Write_Str (" ]"); - end if; - - if Ekind (Ent) = E_Function then - if List_Representation_Info_To_JSON then - Write_Line (","); - Write_Str (" ""mechanism"": """); - Write_Mechanism (Mechanism (Ent)); - Write_Str (""""); - else - Write_Str ("returns by "); - Write_Mechanism (Mechanism (Ent)); - Write_Eol; - end if; - end if; - - if not Is_Entry (Ent) then - List_Linker_Section (Ent); - end if; - - if List_Representation_Info_To_JSON then - Write_Eol; - Write_Line ("}"); - end if; - end List_Mechanisms; - --------------- -- List_Name -- --------------- @@ -1741,7 +1627,7 @@ package body Repinfo is Write_Line ("{"); end if; - List_Type_Info (Ent); + List_Common_Type_Info (Ent); -- First find out max line length and max starting position -- length, for the purpose of lining things up nicely. @@ -1925,79 +1811,201 @@ package body Repinfo is end if; end List_Scalar_Storage_Order; - -------------------- - -- List_Type_Info -- - -------------------- + -------------------------- + -- List_Subprogram_Info -- + -------------------------- + + procedure List_Subprogram_Info (Ent : Entity_Id) is + First : Boolean := True; + Plen : Natural; + Form : Entity_Id; - procedure List_Type_Info (Ent : Entity_Id) is begin + Blank_Line; + if List_Representation_Info_To_JSON then + Write_Line ("{"); Write_Str (" ""name"": """); List_Name (Ent); Write_Line (""","); List_Location (Ent); + + Write_Str (" ""Convention"": """); + else + case Ekind (Ent) is + when E_Function => + Write_Str ("function "); + + when E_Operator => + Write_Str ("operator "); + + when E_Procedure => + Write_Str ("procedure "); + + when E_Subprogram_Type => + Write_Str ("type "); + + when E_Entry + | E_Entry_Family + => + Write_Str ("entry "); + + when others => + raise Program_Error; + end case; + + List_Name (Ent); + Write_Str (" declared at "); + Write_Location (Sloc (Ent)); + Write_Eol; + + Write_Str ("convention : "); end if; - -- Do not list size info for unconstrained arrays, not meaningful + case Convention (Ent) is + when Convention_Ada => + Write_Str ("Ada"); - if Is_Array_Type (Ent) and then not Is_Constrained (Ent) then - null; + when Convention_Ada_Pass_By_Copy => + Write_Str ("Ada_Pass_By_Copy"); + + when Convention_Ada_Pass_By_Reference => + Write_Str ("Ada_Pass_By_Reference"); + + when Convention_Intrinsic => + Write_Str ("Intrinsic"); + + when Convention_Entry => + Write_Str ("Entry"); + + when Convention_Protected => + Write_Str ("Protected"); + when Convention_Assembler => + Write_Str ("Assembler"); + + when Convention_C => + Write_Str ("C"); + + when Convention_COBOL => + Write_Str ("COBOL"); + + when Convention_CPP => + Write_Str ("C++"); + + when Convention_Fortran => + Write_Str ("Fortran"); + + when Convention_Stdcall => + Write_Str ("Stdcall"); + + when Convention_Stubbed => + Write_Str ("Stubbed"); + end case; + + if List_Representation_Info_To_JSON then + Write_Line (""","); + Write_Str (" ""formal"": ["); else - -- If Esize and RM_Size are the same, list as Size. This is a common - -- case, which we may as well list in simple form. + Write_Eol; + end if; - if Esize (Ent) = RM_Size (Ent) then - if List_Representation_Info_To_JSON then - Write_Str (" ""Size"": "); - Write_Val (Esize (Ent)); - Write_Line (","); + -- Find max length of formal name + + Plen := 0; + Form := First_Formal (Ent); + while Present (Form) loop + Get_Unqualified_Decoded_Name_String (Chars (Form)); + + if Name_Len > Plen then + Plen := Name_Len; + end if; + + Next_Formal (Form); + end loop; + + -- Output formals and mechanisms + + Form := First_Formal (Ent); + while Present (Form) loop + Get_Unqualified_Decoded_Name_String (Chars (Form)); + Set_Casing (Unit_Casing); + + if List_Representation_Info_To_JSON then + if First then + Write_Eol; + First := False; else - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Size use "); - Write_Val (Esize (Ent)); - Write_Line (";"); + Write_Line (","); end if; - -- Otherwise list size values separately + Write_Line (" {"); + Write_Str (" ""name"": """); + Write_Str (Name_Buffer (1 .. Name_Len)); + Write_Line (""","); + Write_Str (" ""mechanism"": """); + Write_Mechanism (Mechanism (Form)); + Write_Line (""""); + Write_Str (" }"); else - if List_Representation_Info_To_JSON then - Write_Str (" ""Object_Size"": "); - Write_Val (Esize (Ent)); - Write_Line (","); + while Name_Len <= Plen loop + Name_Len := Name_Len + 1; + Name_Buffer (Name_Len) := ' '; + end loop; - Write_Str (" ""Value_Size"": "); - Write_Val (RM_Size (Ent)); - Write_Line (","); + Write_Str (" "); + Write_Str (Name_Buffer (1 .. Plen + 1)); + Write_Str (": passed by "); - else - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Object_Size use "); - Write_Val (Esize (Ent)); - Write_Line (";"); + Write_Mechanism (Mechanism (Form)); + Write_Eol; + end if; - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Value_Size use "); - Write_Val (RM_Size (Ent)); - Write_Line (";"); - end if; + Next_Formal (Form); + end loop; + + if List_Representation_Info_To_JSON then + Write_Eol; + Write_Str (" ]"); + end if; + + if Ekind (Ent) = E_Function then + if List_Representation_Info_To_JSON then + Write_Line (","); + Write_Str (" ""mechanism"": """); + Write_Mechanism (Mechanism (Ent)); + Write_Str (""""); + else + Write_Str ("returns by "); + Write_Mechanism (Mechanism (Ent)); + Write_Eol; end if; end if; + if not Is_Entry (Ent) then + List_Linker_Section (Ent); + end if; + if List_Representation_Info_To_JSON then - Write_Str (" ""Alignment"": "); - Write_Val (Alignment (Ent)); - else - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Alignment use "); - Write_Val (Alignment (Ent)); - Write_Line (";"); + Write_Eol; + Write_Line ("}"); end if; + end List_Subprogram_Info; + + -------------------- + -- List_Type_Info -- + -------------------- + + procedure List_Type_Info (Ent : Entity_Id) is + begin + Blank_Line; + + if List_Representation_Info_To_JSON then + Write_Line ("{"); + end if; + + List_Common_Type_Info (Ent); -- Special stuff for fixed-point @@ -2046,6 +2054,13 @@ package body Repinfo is end if; end; end if; + + List_Linker_Section (Ent); + + if List_Representation_Info_To_JSON then + Write_Eol; + Write_Line ("}"); + end if; end List_Type_Info; ---------------------- -- cgit v1.1 From 75b41faa236ff0bbedf0cfe7de92d0092fd38757 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Mon, 8 Jul 2019 09:51:07 +0000 Subject: re PR c++/65143 ([C++11] missing devirtualization for virtual base in "final" classes) 2019-07-08 Paolo Carlini PR c++/65143 * g++.dg/tree-ssa/final2.C: New. * g++.dg/tree-ssa/final3.C: Likewise. From-SVN: r273228 --- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/tree-ssa/final2.C | 35 ++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/tree-ssa/final3.C | 23 ++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/final2.C create mode 100644 gcc/testsuite/g++.dg/tree-ssa/final3.C (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ca89951..61150ea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Paolo Carlini + + PR c++/65143 + * g++.dg/tree-ssa/final2.C: New. + * g++.dg/tree-ssa/final3.C: Likewise. + 2019-07-08 Javier Miranda * gnat.dg/interface10.adb: New testcase. diff --git a/gcc/testsuite/g++.dg/tree-ssa/final2.C b/gcc/testsuite/g++.dg/tree-ssa/final2.C new file mode 100644 index 0000000..b0fc860 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/final2.C @@ -0,0 +1,35 @@ +// PR c++/65143 +// { dg-do compile { target c++11 } } +// { dg-additional-options -fdump-tree-gimple } +// { dg-final { scan-tree-dump-times "vptr" 1 gimple } } + +struct A +{ + int i(); +}; + +struct B : public virtual A +{ + int get() + { + return A::i() + 1; + } +}; + +struct C final : public B +{ + int get() + { + return A::i() + 2; + } +}; + +int foo(C& c) +{ + return c.get(); // Need not go via vtable pointer as class C is final +} + +int foo(B& b2) +{ + return b2.get(); // This has to go via vtable as most derived class can change the location of A +} diff --git a/gcc/testsuite/g++.dg/tree-ssa/final3.C b/gcc/testsuite/g++.dg/tree-ssa/final3.C new file mode 100644 index 0000000..9489fc12 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/final3.C @@ -0,0 +1,23 @@ +// PR c++/65143 +// { dg-do compile { target c++11 } } +// { dg-additional-options -fdump-tree-gimple } +// { dg-final { scan-tree-dump-not "vptr" gimple } } + +struct A +{ + int j; +}; + +struct B : public virtual A +{ +}; + +struct C final : public B +{ + int get(); +}; + +int C::get() +{ + return A::j; +} -- cgit v1.1 From ce79110f01f445d97a32f93cc53c346cf98a5425 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 8 Jul 2019 11:53:02 +0200 Subject: Revert r254460 (collect2 LTO for AIX). 2019-07-08 Martin Liska * collect2.c (defined): Revert to before r254460. (scan_prog_file): Revert to before r254460. From-SVN: r273229 --- gcc/ChangeLog | 5 +++++ gcc/collect2.c | 22 +++------------------- 2 files changed, 8 insertions(+), 19 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 74a9890..31ad4e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Martin Liska + + * collect2.c (defined): Revert to before r254460. + (scan_prog_file): Revert to before r254460. + 2019-07-08 Richard Biener PR tree-optimization/83518 diff --git a/gcc/collect2.c b/gcc/collect2.c index d6a7355..e25e339 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -616,7 +616,7 @@ static const char *const target_machine = TARGET_MACHINE; Return 0 if not found, otherwise return its name, allocated with malloc. */ -#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_COFF) +#ifdef OBJECT_FORMAT_NONE /* Add an entry for the object file NAME to object file list LIST. New entries are added at the end of the list. The original pointer @@ -636,7 +636,7 @@ add_lto_object (struct lto_object_list *list, const char *name) list->last = n; } -#endif +#endif /* OBJECT_FORMAT_NONE */ /* Perform a link-time recompilation and relink if any of the object @@ -2799,10 +2799,8 @@ scan_prog_file (const char *prog_name, scanpass which_pass, LDFILE *ldptr = NULL; int sym_index, sym_count; int is_shared = 0; - int found_lto = 0; - if (which_pass != PASS_FIRST && which_pass != PASS_OBJ - && which_pass != PASS_LTOINFO) + if (which_pass != PASS_FIRST && which_pass != PASS_OBJ) return; #ifdef COLLECT_EXPORT_LIST @@ -2815,7 +2813,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass, eliminate scan_libraries() function. */ do { - found_lto = 0; #endif /* Some platforms (e.g. OSF4) declare ldopen as taking a non-const char * filename parameter, even though it will not @@ -2858,19 +2855,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass, ++name; #endif - if (which_pass == PASS_LTOINFO) - { - if (found_lto) - continue; - if (strncmp (name, "__gnu_lto_v1", 12) == 0) - { - add_lto_object (<o_objects, prog_name); - found_lto = 1; - break; - } - continue; - } - switch (is_ctor_dtor (name)) { #if TARGET_AIX_VERSION -- cgit v1.1 From ace4317affd3068cc01c06f0928e119f1559519c Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Mon, 8 Jul 2019 03:47:42 -0700 Subject: RISC-V: Fix splitter for 32-bit AND on 64-bit target. Fixes github.com/riscv/riscv-gcc issue #161. We were accidentally using BITS_PER_WORD to compute shift counts when we should have been using the bitsize of the operand modes. This was wrong when we had an SImode shift and a 64-bit target. Andrew Waterman gcc/ * config/riscv/riscv.md (lshrsi3_zero_extend_3+1): Use operands[1] bitsize instead of BITS_PER_WORD. gcc/testsuite/ * gcc.target/riscv/shift-shift-2.c: Add one more test. From-SVN: r273230 --- gcc/ChangeLog | 7 +++++++ gcc/config/riscv/riscv.md | 5 +++-- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.target/riscv/shift-shift-2.c | 16 ++++++++++++++-- 4 files changed, 28 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 31ad4e5..6429407 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-08 Andrew Waterman + Jim Wilson + + * config/riscv/riscv.md (lshrsi3_zero_extend_3+1): Use operands[1] + bitsize instead of BITS_PER_WORD. + gcc/testsuite/ + 2019-07-08 Martin Liska * collect2.c (defined): Revert to before r254460. diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 0f46266..78260fc 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1776,10 +1776,11 @@ (set (match_dup 0) (lshiftrt:GPR (match_dup 0) (match_dup 2)))] { - operands[2] = GEN_INT (BITS_PER_WORD + /* Op2 is a VOIDmode constant, so get the mode size from op1. */ + operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1])) - exact_log2 (INTVAL (operands[2]) + 1)); }) - + ;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be ;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and. (define_split diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 61150ea..56f2f2c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-08 Jim Wilson + + * gcc.target/riscv/shift-shift-2.c: Add one more test. + 2019-07-08 Paolo Carlini PR c++/65143 diff --git a/gcc/testsuite/gcc.target/riscv/shift-shift-2.c b/gcc/testsuite/gcc.target/riscv/shift-shift-2.c index 3f07e77..10a5bb7 100644 --- a/gcc/testsuite/gcc.target/riscv/shift-shift-2.c +++ b/gcc/testsuite/gcc.target/riscv/shift-shift-2.c @@ -25,5 +25,17 @@ sub4 (unsigned long i) { return (i << 52) >> 52; } -/* { dg-final { scan-assembler-times "slli" 4 } } */ -/* { dg-final { scan-assembler-times "srli" 4 } } */ + +unsigned int +sub5 (unsigned int i) +{ + unsigned int j; + j = i >> 24; + j = j * (1 << 24); + j = i - j; + return j; +} +/* { dg-final { scan-assembler-times "slli" 5 } } */ +/* { dg-final { scan-assembler-times "srli" 5 } } */ +/* { dg-final { scan-assembler-times "slliw" 1 } } */ +/* { dg-final { scan-assembler-times "srliw" 1 } } */ -- cgit v1.1 From b68cae81760cd158ee465466280fc0df58e6a768 Mon Sep 17 00:00:00 2001 From: Joern Rennecke Date: Mon, 8 Jul 2019 11:17:22 +0000 Subject: Avoid clash with system header declaration. * testsuite/gcc.dg/vect/slp-reduc-sad.c (uint32_t): Remove unused declaration. From-SVN: r273231 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/gcc.dg/vect/slp-reduc-sad.c | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6429407..a912a2e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Joern Rennecke + + Avoid clash with system header declaration. + * testsuite/gcc.dg/vect/slp-reduc-sad.c (uint32_t): + Remove unused declaration. + 2019-07-08 Andrew Waterman Jim Wilson diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-sad.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-sad.c index 15b286a..faa1c16 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-sad.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-sad.c @@ -2,7 +2,6 @@ #include "tree-vect.h" -typedef unsigned int uint32_t; typedef unsigned short uint16_t; typedef unsigned char uint8_t; -- cgit v1.1 From 08dfb1d682a707f7319aafec28edda424395dae5 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 8 Jul 2019 11:46:26 +0000 Subject: re PR tree-optimization/91108 (Fails to pun through unions) 2019-07-08 Richard Biener PR tree-optimization/91108 * tree-ssa-sccvn.c: Include builtins.h. (vn_reference_lookup_3): Use only alignment constraints to verify same-valued store disambiguation. * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust back. * gcc.dg/tree-ssa/ssa-fre-78.c: New testcase. From-SVN: r273232 --- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c | 27 +++++++++++++++++++++++++++ gcc/tree-ssa-sccvn.c | 30 ++++++++++++------------------ 4 files changed, 46 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 56f2f2c..dbe70b9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Richard Biener + + PR tree-optimization/91108 + * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust back. + * gcc.dg/tree-ssa/ssa-fre-78.c: New testcase. + 2019-07-08 Jim Wilson * gcc.target/riscv/shift-shift-2.c: Add one more test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c index eae4b15..a4d9a71 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c @@ -1,5 +1,5 @@ /* { dg-do link } */ -/* { dg-options "-O -fstrict-aliasing -fdump-tree-fre1-details" } */ +/* { dg-options "-O -fdump-tree-fre1-details" } */ void link_error (void); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c new file mode 100644 index 0000000..4ad232e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fstrict-aliasing" } */ + +union U { + struct A { int : 2; int x : 8; } a; + struct B { int : 6; int x : 8; } b; +}; + +int __attribute__((noipa)) +foo (union U *p, union U *q) +{ + p->a.x = 1; + q->b.x = 1; + return p->a.x; +} + +int +main() +{ + union U x; + if (foo (&x, &x) != x.a.x) + __builtin_abort (); + return 0; +} + +/* We support arbitrary punning through unions when it happens through + the union type and thus p == q is valid here. */ diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 3c45adc..854222a 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-loop.h" #include "tree-scalar-evolution.h" #include "tree-ssa-loop-niter.h" +#include "builtins.h" #include "tree-ssa-sccvn.h" /* This algorithm is based on the SCC algorithm presented by Keith @@ -2248,24 +2249,10 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, /* If we reach a clobbering statement try to skip it and see if we find a VN result with exactly the same value as the possible clobber. In this case we can ignore the clobber - and return the found value. - Note that we don't need to worry about partial overlapping - accesses as we then can use TBAA to disambiguate against the - clobbering statement when looking up a load (thus the - VN_WALKREWRITE guard). */ - if (data->vn_walk_kind == VN_WALKREWRITE - && is_gimple_reg_type (TREE_TYPE (lhs)) + and return the found value. */ + if (is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) - /* The overlap restriction breaks down when either access - alias-set is zero. Still for accesses of the size of - an addressable unit there can be no overlaps. Overlaps - between different union members are not an issue since - activation of a union member via a store makes the - values of untouched bytes unspecified. */ - && (known_eq (ref->size, BITS_PER_UNIT) - || (flag_strict_aliasing - && get_alias_set (lhs) != 0 - && ao_ref_alias_set (ref) != 0))) + && ref->ref) { tree *saved_last_vuse_ptr = data->last_vuse_ptr; /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ @@ -2284,7 +2271,14 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, if (TREE_CODE (rhs) == SSA_NAME) rhs = SSA_VAL (rhs); if (vnresult->result - && operand_equal_p (vnresult->result, rhs, 0)) + && operand_equal_p (vnresult->result, rhs, 0) + /* We have to honor our promise about union type punning + and also support arbitrary overlaps with + -fno-strict-aliasing. So simply resort to alignment to + rule out overlaps. Do this check last because it is + quite expensive compared to the hash-lookup above. */ + && multiple_p (get_object_alignment (ref->ref), ref->size) + && multiple_p (get_object_alignment (lhs), ref->size)) return res; } } -- cgit v1.1 From e2839e47894f0b4917ddbd59013071e98f525336 Mon Sep 17 00:00:00 2001 From: Robin Dapp Date: Mon, 8 Jul 2019 14:40:48 +0000 Subject: S/390: Rework shift count handling. Add s390_valid_shift_count to determine the validity of a shift-count operand. This is used to replace increasingly complex substitutions that should have allowed address-style shift-count handling, an and mask as well as no-op subregs on the operand. gcc/ChangeLog: 2019-07-08 Robin Dapp * config/s390/constraints.md: Add new jsc constraint. * config/s390/predicates.md: New predicates. * config/s390/s390-protos.h (s390_valid_shift_count): New function. * config/s390/s390.c (s390_valid_shift_count): New function. (print_shift_count_operand): Use s390_valid_shift_count. (print_operand): Likewise. * config/s390/s390.md: Use new predicate. * config/s390/subst.md: Remove addr_style_op and masked_op substs. * config/s390/vector.md: Use new predicate. 2019-07-08 Robin Dapp * gcc.target/s390/combine-rotate-modulo.c: New test. * gcc.target/s390/combine-shift-rotate-add-mod.c: New test. * gcc.target/s390/vector/combine-shift-vec.c: New test. From-SVN: r273236 --- gcc/ChangeLog | 12 +++ gcc/config/s390/constraints.md | 12 +++ gcc/config/s390/predicates.md | 29 ++++++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 66 ++++++++++++- gcc/config/s390/s390.md | 43 +++++---- gcc/config/s390/subst.md | 72 -------------- gcc/config/s390/vector.md | 14 ++- gcc/testsuite/ChangeLog | 6 ++ .../gcc.target/s390/combine-rotate-modulo.c | 36 +++++++ .../gcc.target/s390/combine-shift-rotate-add-mod.c | 29 ++++++ .../gcc.target/s390/vector/combine-shift-vec.c | 107 +++++++++++++++++++++ 12 files changed, 328 insertions(+), 99 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/combine-rotate-modulo.c create mode 100644 gcc/testsuite/gcc.target/s390/combine-shift-rotate-add-mod.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/combine-shift-vec.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a912a2e..c4f0503 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2019-07-08 Robin Dapp + + * config/s390/constraints.md: Add new jsc constraint. + * config/s390/predicates.md: New predicates. + * config/s390/s390-protos.h (s390_valid_shift_count): New function. + * config/s390/s390.c (s390_valid_shift_count): New function. + (print_shift_count_operand): Use s390_valid_shift_count. + (print_operand): Likewise. + * config/s390/s390.md: Use new predicate. + * config/s390/subst.md: Remove addr_style_op and masked_op substs. + * config/s390/vector.md: Use new predicate. + 2019-07-08 Joern Rennecke Avoid clash with system header declaration. diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md index 4055cbc..45d41ae 100644 --- a/gcc/config/s390/constraints.md +++ b/gcc/config/s390/constraints.md @@ -204,6 +204,18 @@ (match_test "s390_decompose_addrstyle_without_index (op, NULL, NULL)" )) +;; Shift count operands are not necessarily legitimate addresses +;; but the predicate shift_count_operand will only allow +;; proper operands. If reload/lra need to change e.g. a spilled register +;; they can still do so via the special handling of address constraints. +;; To avoid further reloading (caused by a non-matching constraint) we +;; always return true here as the predicate's checks are already sufficient. + +(define_address_constraint "jsc" + "Address style operand used as shift count." + (match_test "true" )) + + ;; N -- Multiple letter constraint followed by 4 parameter letters. ;; 0..9,x: number of the part counting from most to least significant ;; S,H,Q: mode of the part diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index 92c602e..4d2f8b2 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -556,3 +556,32 @@ { return memory_operand (op, mode) && !contains_symbol_ref_p (op); }) + +;; Check for a valid shift count operand with an implicit +;; shift truncation mask of 63. + +(define_predicate "shift_count_operand" + (and (match_code "reg, subreg, and, plus, const_int") + (match_test "CONST_INT_P (op) || GET_MODE (op) == E_QImode")) +{ + return s390_valid_shift_count (op, 63); +} +) + +;; This is used as operand predicate. As we do not know +;; the mode of the first operand here and the shift truncation +;; mask depends on the mode, we cannot check the mask. +;; This is supposed to happen in the insn condition which +;; calls s390_valid_shift_count with the proper mode size. +;; We need two separate predicates for non-vector and vector +;; shifts since the (less restrictive) insn condition is checked +;; after the more restrictive operand predicate which will +;; disallow the operand before we can check the condition. + +(define_predicate "shift_count_operand_vec" + (and (match_code "reg, subreg, and, plus, const_int") + (match_test "CONST_INT_P (op) || GET_MODE (op) == E_QImode")) +{ + return s390_valid_shift_count (op, 0); +} +) diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index b162b26..ae70b2f 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -141,6 +141,7 @@ extern void s390_emit_tpf_eh_return (rtx); extern bool s390_legitimate_address_without_index_p (rtx); extern bool s390_decompose_addrstyle_without_index (rtx, rtx *, HOST_WIDE_INT *); +extern bool s390_valid_shift_count (rtx op, HOST_WIDE_INT required_mask = 63); extern int s390_branch_condition_mask (rtx); extern int s390_compare_and_branch_condition_mask (rtx); extern bool s390_extzv_shift_ok (int, int, unsigned HOST_WIDE_INT); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 5ec26a059..324d9d2 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3131,6 +3131,49 @@ s390_decompose_addrstyle_without_index (rtx op, rtx *base, return true; } +/* Check that OP is a valid shift count operand. + It should be of the following structure: + (subreg (and (plus (reg imm_op)) 2^k-1) 7) + where subreg, and and plus are optional. + + If IMPLICIT_MASK is > 0 and OP contains and + (AND ... immediate) + it is checked whether IMPLICIT_MASK and the immediate match. + Otherwise, no checking is performed. + */ +bool +s390_valid_shift_count (rtx op, HOST_WIDE_INT implicit_mask) +{ + /* Strip subreg. */ + while (GET_CODE (op) == SUBREG && subreg_lowpart_p (op)) + op = XEXP (op, 0); + + /* Check for an and with proper constant. */ + if (GET_CODE (op) == AND) + { + rtx op1 = XEXP (op, 0); + rtx imm = XEXP (op, 1); + + if (GET_CODE (op1) == SUBREG && subreg_lowpart_p (op1)) + op1 = XEXP (op1, 0); + + if (!(register_operand (op1, GET_MODE (op1)) || GET_CODE (op1) == PLUS)) + return false; + + if (!immediate_operand (imm, GET_MODE (imm))) + return false; + + HOST_WIDE_INT val = INTVAL (imm); + if (implicit_mask > 0 + && (val & implicit_mask) != implicit_mask) + return false; + + op = op1; + } + + /* Check the rest. */ + return s390_decompose_addrstyle_without_index (op, NULL, NULL); +} /* Return true if CODE is a valid address without index. */ @@ -7448,6 +7491,27 @@ print_addrstyle_operand (FILE *file, rtx op) fprintf (file, "(%s)", reg_names[REGNO (base)]); } +/* Print the shift count operand OP to FILE. + OP is an address-style operand in a form which + s390_valid_shift_count permits. Subregs and no-op + and-masking of the operand are stripped. */ + +static void +print_shift_count_operand (FILE *file, rtx op) +{ + /* No checking of the and mask required here. */ + if (!s390_valid_shift_count (op, 0)) + gcc_unreachable (); + + while (op && GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (GET_CODE (op) == AND) + op = XEXP (op, 0); + + print_addrstyle_operand (file, op); +} + /* Assigns the number of NOP halfwords to be emitted before and after the function label to *HW_BEFORE and *HW_AFTER. Both pointers must not be NULL. If hotpatching is disabled for the function, the values are set to zero. @@ -7912,7 +7976,7 @@ print_operand (FILE *file, rtx x, int code) break; case 'Y': - print_addrstyle_operand (file, x); + print_shift_count_operand (file, x); return; } diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 79451d7..94a7340 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -8937,17 +8937,17 @@ (define_expand "rotl3" [(set (match_operand:GPR 0 "register_operand" "") (rotate:GPR (match_operand:GPR 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] + (match_operand:QI 2 "shift_count_operand" "")))] "" "") ; rll, rllg -(define_insn "*rotl3" +(define_insn "*rotl3" [(set (match_operand:GPR 0 "register_operand" "=d") (rotate:GPR (match_operand:GPR 1 "register_operand" "d") - (match_operand:SI 2 "nonmemory_operand" "an")))] + (match_operand:QI 2 "shift_count_operand" "jsc")))] "" - "rll\t%0,%1," + "rll\t%0,%1,%Y2" [(set_attr "op_type" "RSE") (set_attr "atype" "reg") (set_attr "z10prop" "z10_super_E1")]) @@ -8964,18 +8964,18 @@ (define_expand "3" [(set (match_operand:DSI 0 "register_operand" "") (SHIFT:DSI (match_operand:DSI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] + (match_operand:QI 2 "shift_count_operand" "")))] "" "") ; ESA 64 bit register pair shift with reg or imm shift count ; sldl, srdl -(define_insn "*di3_31" +(define_insn "*di3_31" [(set (match_operand:DI 0 "register_operand" "=d") (SHIFT:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "an")))] + (match_operand:QI 2 "shift_count_operand" "jsc")))] "!TARGET_ZARCH" - "sdl\t%0," + "sdl\t%0,%Y2" [(set_attr "op_type" "RS") (set_attr "atype" "reg") (set_attr "z196prop" "z196_cracked")]) @@ -8983,19 +8983,20 @@ ; 64 bit register shift with reg or imm shift count ; sll, srl, sllg, srlg, sllk, srlk -(define_insn "*3" +(define_insn "*3" [(set (match_operand:GPR 0 "register_operand" "=d, d") (SHIFT:GPR (match_operand:GPR 1 "register_operand" ", d") - (match_operand:SI 2 "nonmemory_operand" "an,an")))] + (match_operand:QI 2 "shift_count_operand" "jsc,jsc")))] "" "@ - sl\t%0,<1> - sl\t%0,%1," + sl\t%0,<1>%Y2 + sl\t%0,%1,%Y2" [(set_attr "op_type" "RS,RSY") (set_attr "atype" "reg,reg") (set_attr "cpu_facility" "*,z196") (set_attr "z10prop" "z10_super_E1,*")]) + ; ; ashr(di|si)3 instruction pattern(s). ; Arithmetic right shifts @@ -9004,7 +9005,7 @@ [(parallel [(set (match_operand:DSI 0 "register_operand" "") (ashiftrt:DSI (match_operand:DSI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" ""))) + (match_operand:QI 2 "shift_count_operand" ""))) (clobber (reg:CC CC_REGNUM))])] "" "") @@ -9013,29 +9014,29 @@ ; number of 2 in the subst pattern for the (clobber (match_scratch... ; The right fix should be to support match_scratch in the output ; pattern of a define_subst. -(define_insn "*ashrdi3_31" +(define_insn "*ashrdi3_31" [(set (match_operand:DI 0 "register_operand" "=d, d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "0, 0") - (match_operand:SI 2 "nonmemory_operand" "an,an"))) + (match_operand:QI 2 "shift_count_operand" "jsc,jsc"))) (clobber (reg:CC CC_REGNUM))] "!TARGET_ZARCH" "@ - srda\t%0, - srda\t%0," + srda\t%0,%Y2 + srda\t%0,%Y2" [(set_attr "op_type" "RS") (set_attr "atype" "reg")]) ; sra, srag -(define_insn "*ashr3" +(define_insn "*ashr3" [(set (match_operand:GPR 0 "register_operand" "=d, d") (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ", d") - (match_operand:SI 2 "nonmemory_operand" "an,an"))) + (match_operand:QI 2 "shift_count_operand" "jsc,jsc"))) (clobber (reg:CC CC_REGNUM))] "" "@ - sra\t%0,<1> - sra\t%0,%1," + sra\t%0,<1>%Y2 + sra\t%0,%1,%Y2" [(set_attr "op_type" "RS,RSY") (set_attr "atype" "reg") (set_attr "cpu_facility" "*,z196") diff --git a/gcc/config/s390/subst.md b/gcc/config/s390/subst.md index 0518ed2..9c0c87a 100644 --- a/gcc/config/s390/subst.md +++ b/gcc/config/s390/subst.md @@ -22,78 +22,6 @@ (define_code_iterator SUBST [rotate ashift lshiftrt ashiftrt]) (define_mode_iterator DSI_VI [SI DI V2QI V4QI V8QI V16QI V2HI V4HI V8HI V2SI V4SI V2DI]) -; This expands an register/immediate operand to a register+immediate -; operand to draw advantage of the address style operand format -; providing a addition for free. -(define_subst "addr_style_op_subst" - [(set (match_operand:DSI_VI 0 "" "") - (SUBST:DSI_VI (match_operand:DSI_VI 1 "" "") - (match_operand:SI 2 "" "")))] - "" - [(set (match_dup 0) - (SUBST:DSI_VI (match_dup 1) - (plus:SI (match_operand:SI 2 "register_operand" "a") - (match_operand 3 "const_int_operand" "n"))))]) - -; Use this in the insn name. -(define_subst_attr "addr_style_op" "addr_style_op_subst" "" "_plus") - -; In the subst pattern the additional const int operand will be used -; as displacement. In the normal version %Y is able to print the -; operand either as displacement or as base register. -(define_subst_attr "addr_style_op_ops" "addr_style_op_subst" "%Y2" "%Y3(%2)") - - -; This substitution adds an explicit AND operation to the second -; operand. This way previous operations on the now masked out bits -; might get optimized away. -(define_subst "masked_op_subst" - [(set (match_operand:DSI 0 "" "") - (SUBST:DSI (match_operand:DSI 1 "" "") - (match_operand:SI 2 "" "")))] - "" - [(set (match_dup 0) - (SUBST:DSI (match_dup 1) - (and:SI (match_dup 2) - (match_operand:SI 3 "const_int_6bitset_operand" "jm6"))))]) - -; Use this in the insn name. -(define_subst_attr "masked_op" "masked_op_subst" "" "_and") - - - -; This is like the addr_style_op substitution above but with a CC clobber. -(define_subst "addr_style_op_cc_subst" - [(set (match_operand:DSI 0 "" "") - (ashiftrt:DSI (match_operand:DSI 1 "" "") - (match_operand:SI 2 "" ""))) - (clobber (reg:CC CC_REGNUM))] - "REG_P (operands[2])" - [(set (match_dup 0) - (ashiftrt:DSI (match_dup 1) - (plus:SI (match_dup 2) - (match_operand 3 "const_int_operand" "n")))) - (clobber (reg:CC CC_REGNUM))]) - -(define_subst_attr "addr_style_op_cc" "addr_style_op_cc_subst" "" "_plus") -(define_subst_attr "addr_style_op_cc_ops" "addr_style_op_cc_subst" "%Y2" "%Y3(%2)") - - -; This is like the masked_op substitution but with a CC clobber. -(define_subst "masked_op_cc_subst" - [(set (match_operand:DSI 0 "" "") - (ashiftrt:DSI (match_operand:DSI 1 "" "") - (match_operand:SI 2 "" ""))) - (clobber (reg:CC CC_REGNUM))] - "" - [(set (match_dup 0) - (ashiftrt:DSI (match_dup 1) - (and:SI (match_dup 2) - (match_operand:SI 3 "const_int_6bitset_operand" "")))) - (clobber (reg:CC CC_REGNUM))]) -(define_subst_attr "masked_op_cc" "masked_op_cc_subst" "" "_and") - - ; This adds an explicit CC reg set to an operation while keeping the ; set for the operation result as well. (define_subst "setcc_subst" diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 140ef47..0702e1d 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -969,21 +969,25 @@ (define_expand "3" [(set (match_operand:VI 0 "register_operand" "") (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] + (match_operand:QI 2 "shift_count_operand" "")))] "TARGET_VX") ; verllb, verllh, verllf, verllg ; veslb, veslh, veslf, veslg ; vesrab, vesrah, vesraf, vesrag ; vesrlb, vesrlh, vesrlf, vesrlg -(define_insn "*3" +(define_insn "*3" [(set (match_operand:VI 0 "register_operand" "=v") (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "nonmemory_operand" "an")))] - "TARGET_VX" - "\t%v0,%v1," + (match_operand:QI 2 "shift_count_operand_vec" "jsc")))] + "TARGET_VX + && s390_valid_shift_count (operands[2], + GET_MODE_BITSIZE (GET_MODE_INNER (mode)) - 1) + " + "\t%v0,%v1,%Y2" [(set_attr "op_type" "VRS")]) + ; Shift each element by corresponding vector element ; veslvb, veslvh, veslvf, veslvg diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dbe70b9..b1c6ea2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Robin Dapp + + * gcc.target/s390/combine-rotate-modulo.c: New test. + * gcc.target/s390/combine-shift-rotate-add-mod.c: New test. + * gcc.target/s390/vector/combine-shift-vec.c: New test. + 2019-07-08 Richard Biener PR tree-optimization/91108 diff --git a/gcc/testsuite/gcc.target/s390/combine-rotate-modulo.c b/gcc/testsuite/gcc.target/s390/combine-rotate-modulo.c new file mode 100644 index 0000000..6cbbb552 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/combine-rotate-modulo.c @@ -0,0 +1,36 @@ +/* Check that we do not emit & 63 via risbg for rotating. */ + +/* { dg-options "-O1 -m64" } */ + +/* { dg-final { scan-assembler-not "risbg" } } */ +/* { dg-final { scan-assembler-not "nilf" } } */ + +long shiftl (long in, unsigned long sh) +{ + sh %= 64; + return (in << sh); +} + +unsigned long shiftll (unsigned long in, unsigned long sh) +{ + sh %= 64; + return (in << sh); +} + +long shiftr (long in, unsigned long sh) +{ + sh %= 64; + return (in >> sh); +} + +unsigned long shiftrl (unsigned long in, unsigned long sh) +{ + sh %= 64; + return (in >> sh); +} + +unsigned long rotlmod (unsigned long in, unsigned long sh) +{ + sh %= 64; + return (in << sh) | (in >> (64 - sh)); +} diff --git a/gcc/testsuite/gcc.target/s390/combine-shift-rotate-add-mod.c b/gcc/testsuite/gcc.target/s390/combine-shift-rotate-add-mod.c new file mode 100644 index 0000000..dc63bfa --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/combine-shift-rotate-add-mod.c @@ -0,0 +1,29 @@ +/* Check shift via address-style displacement. There should not be any + and operations that the instructions perform implicitly anyway.*/ + +/* { dg-options "-O1 -m64" } */ + +/* { dg-final { scan-assembler-not "risbg\t%r.+,.*63" } } */ +/* { dg-final { scan-assembler "rllg\t%r.+,3.%r.+" } } */ +/* { dg-final { scan-assembler "sllg\t%r.+,2.%r.+" } } */ + +unsigned long rotlmodp (unsigned long in, unsigned long sh) +{ + sh = (sh + 3) % 64; + return (in << sh) | (in >> (64 - sh)); +} + +unsigned long shiftmodp (unsigned long in, unsigned long sh) +{ + sh = (sh + 2) % 64; + return (in << sh); +} + +/* We expect a displacement of 1 here since combine simplifies + modulo 255 when substituting into a QImode subreg. */ +/* { dg-final { scan-assembler "sllg\t%r.+,1.%r.+" } } */ +unsigned long shiftp (unsigned long in, unsigned long sh) +{ + sh = sh + 4097; + return (in << sh); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/combine-shift-vec.c b/gcc/testsuite/gcc.target/s390/vector/combine-shift-vec.c new file mode 100644 index 0000000..1ac9496 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/combine-shift-vec.c @@ -0,0 +1,107 @@ +/* Check vector shift patterns. */ + +/* { dg-options "-march=z13 -O1 -m64" } */ + +/* { dg-final { scan-assembler "veslb\t%v.+,%v.+,2.%r2" } } */ +/* { dg-final { scan-assembler "veslh\t%v.+,%v.+,3.%r2" } } */ +/* { dg-final { scan-assembler "veslf\t%v.+,%v.+,4.%r2" } } */ +/* { dg-final { scan-assembler "veslg\t%v.+,%v.+,5.%r2" } } */ +/* { dg-final { scan-assembler "vesrab\t%v.+,%v.+,2.%r2" } } */ +/* { dg-final { scan-assembler "vesrah\t%v.+,%v.+,3.%r2" } } */ +/* { dg-final { scan-assembler "vesraf\t%v.+,%v.+,4.%r2" } } */ +/* { dg-final { scan-assembler "vesrag\t%v.+,%v.+,5.%r2" } } */ +/* { dg-final { scan-assembler "vesrlb\t%v.+,%v.+,2.%r2" } } */ +/* { dg-final { scan-assembler "vesrlh\t%v.+,%v.+,3.%r2" } } */ +/* { dg-final { scan-assembler "vesrlf\t%v.+,%v.+,4.%r2" } } */ +/* { dg-final { scan-assembler "vesrlg\t%v.+,%v.+,5.%r2" } } */ +/* { dg-final { scan-assembler-not "ahi" } } */ +/* { dg-final { scan-assembler-not "nilf" } } */ +/* { dg-final { scan-assembler-not "risbg" } } */ + +typedef __attribute__((vector_size(16))) signed char v16qi; + +v16qi vshiftlqi (v16qi in, unsigned int sh) +{ + sh = (sh + 2) % 8; + return (in << sh); +} + +typedef __attribute__((vector_size(16))) signed short v8hi; + +v8hi vshiftlhi (v8hi in, unsigned int sh) +{ + sh = (sh + 3) % 16; + return (in << sh); +} + +typedef __attribute__((vector_size(16))) signed int v4si; + +v4si vshiftlsi (v4si in, unsigned int sh) +{ + sh = (sh + 4) % 32; + return (in << sh); +} + +typedef __attribute__((vector_size(16))) signed long v2di; + +v2di vshiftldi (v2di in, unsigned int sh) +{ + sh = (sh + 5) % 64; + return (in << sh); +} + +typedef __attribute__((vector_size(16))) unsigned char uv16qi; + +uv16qi vshiftrqiu (uv16qi in, unsigned int sh) +{ + sh = (sh + 2) % 8; + return (in >> sh); +} + +typedef __attribute__((vector_size(16))) unsigned short uv8hi; + +uv8hi vshiftrhiu (uv8hi in, unsigned int sh) +{ + sh = (sh + 3) % 16; + return (in >> sh); +} + +typedef __attribute__((vector_size(16))) unsigned int uv4si; + +uv4si vshiftrsiu (uv4si in, unsigned int sh) +{ + sh = (sh + 4) % 32; + return (in >> sh); +} + +typedef __attribute__((vector_size(16))) unsigned long uv2di; + +uv2di vshiftrdiu (uv2di in, unsigned int sh) +{ + sh = (sh + 5) % 64; + return (in >> sh); +} + +v16qi vshiftrqi (v16qi in, unsigned int sh) +{ + sh = (sh + 2) % 8; + return (in >> sh); +} + +v8hi vshiftrhi (v8hi in, unsigned int sh) +{ + sh = (sh + 3) % 16; + return (in >> sh); +} + +v4si vshiftrsi (v4si in, unsigned int sh) +{ + sh = (sh + 4) % 32; + return (in >> sh); +} + +v2di vshiftrdi (v2di in, unsigned int sh) +{ + sh = (sh + 5) % 64; + return (in >> sh); +} -- cgit v1.1 From 5fad9d33e1dacbd754473e441f5e305ba7d3ef6c Mon Sep 17 00:00:00 2001 From: Robin Dapp Date: Mon, 8 Jul 2019 14:42:49 +0000 Subject: S/390: Define shift_truncation_mask. Define s390_shift_truncation_mask to allow the optabs optimization sh = (64 - sh) -> sh = -sh for a rotation operation. gcc/ChangeLog: 2019-07-08 Robin Dapp * config/s390/s390.c (s390_shift_truncation_mask): Define. (TARGET_SHIFT_TRUNCATION_MASK): Define. gcc/testsuite/ChangeLog: 2019-07-08 Robin Dapp * gcc.target/s390/rotate-truncation-mask.c: New test. From-SVN: r273237 --- gcc/ChangeLog | 5 +++++ gcc/config/s390/s390.c | 8 ++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.target/s390/rotate-truncation-mask.c | 11 +++++++++++ 4 files changed, 28 insertions(+) create mode 100644 gcc/testsuite/gcc.target/s390/rotate-truncation-mask.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c4f0503..b47aead 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2019-07-08 Robin Dapp + * config/s390/s390.c (s390_shift_truncation_mask): Define. + (TARGET_SHIFT_TRUNCATION_MASK): Define. + +2019-07-08 Robin Dapp + * config/s390/constraints.md: Add new jsc constraint. * config/s390/predicates.md: New predicates. * config/s390/s390-protos.h (s390_valid_shift_count): New function. diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 324d9d2..75b0b5b 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -16412,7 +16412,13 @@ s390_sched_dependencies_evaluation (rtx_insn *head, rtx_insn *tail) add_dependence (r11_restore, r15_restore, REG_DEP_ANTI); } +/* Implement TARGET_SHIFT_TRUNCATION_MASK for integer shifts. */ +static unsigned HOST_WIDE_INT +s390_shift_truncation_mask (machine_mode mode) +{ + return mode == DImode || mode == SImode ? 63 : 0; +} /* Initialize GCC target structure. */ @@ -16709,6 +16715,8 @@ s390_sched_dependencies_evaluation (rtx_insn *head, rtx_insn *tail) #define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK \ s390_sched_dependencies_evaluation +#undef TARGET_SHIFT_TRUNCATION_MASK +#define TARGET_SHIFT_TRUNCATION_MASK s390_shift_truncation_mask /* Use only short displacement, since long displacement is not available for the floating point instructions. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b1c6ea2..a7a67fb9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-08 Robin Dapp + * gcc.target/s390/rotate-truncation-mask.c: New test. + +2019-07-08 Robin Dapp + * gcc.target/s390/combine-rotate-modulo.c: New test. * gcc.target/s390/combine-shift-rotate-add-mod.c: New test. * gcc.target/s390/vector/combine-shift-vec.c: New test. diff --git a/gcc/testsuite/gcc.target/s390/rotate-truncation-mask.c b/gcc/testsuite/gcc.target/s390/rotate-truncation-mask.c new file mode 100644 index 0000000..1cdd209 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/rotate-truncation-mask.c @@ -0,0 +1,11 @@ +/* Check that we do not use (64 - sh) for rotating. */ + +/* { dg-options "-O1 -m64" } */ + +/* { dg-final { scan-assembler "lcr\t%r.+,%r.+" } } */ +/* { dg-final { scan-assembler-not "lhi\t%r.+,64" } } */ +/* { dg-final { scan-assembler-not "sr\t%r.+,%r.+" } } */ +unsigned long rotr (unsigned long in, unsigned long sh) +{ + return (in >> sh) | (in << (64 - sh)); +} -- cgit v1.1 From 8f783191775bc266a74175e92c7eb64098bd4283 Mon Sep 17 00:00:00 2001 From: Wilco Dijkstra Date: Mon, 8 Jul 2019 17:02:35 +0000 Subject: Turn of ipa-ra in builtins test (PR91059) The gcc.c-torture/execute/builtins/lib directory contains a reimplementation of many C library string functions, which causes non-trivial register allocation bugs with LTO and static linked libraries. To fix this long-standing test issue, turn off ipa-ra which avoids the register corruption across calls. All builtin torture tests now pass on aarch64-none-elf. Committed as obvious. testsuite/ PR testsuite/91059 PR testsuite/78529 * gcc.c-torture/execute/builtins/builtins.exp: Add -fno-ipa-ra. From-SVN: r273238 --- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a7a67fb9..31c3314 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Wilco Dijkstra + + PR testsuite/91059 + PR testsuite/78529 + * gcc.c-torture/execute/builtins/builtins.exp: Add -fno-ipa-ra. + 2019-07-08 Robin Dapp * gcc.target/s390/rotate-truncation-mask.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp index fb9d3ec..d62f78c 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp @@ -37,7 +37,7 @@ load_lib c-torture.exp torture-init set-torture-options $C_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS -set additional_flags "-fno-tree-dse -fno-tree-loop-distribute-patterns -fno-tracer" +set additional_flags "-fno-tree-dse -fno-tree-loop-distribute-patterns -fno-tracer -fno-ipa-ra" if [istarget "powerpc-*-darwin*"] { lappend additional_flags "-Wl,-multiply_defined,suppress" } -- cgit v1.1 From b18081df8cca5f2306e99709fa2c06b9cbeea8d0 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Mon, 8 Jul 2019 19:35:12 +0200 Subject: subreg: Add -fsplit-wide-types-early (PR88233) Currently the second lower-subreg pass is run right before RA. This is much too late to be very useful. At least for targets that do not have RTL patterns for operations on multi-register modes it is a lot better to split patterns earlier, before combine and all related passes. This adds an option -fsplit-wide-types-early that does that, and enables it by default for rs6000. PR rtl-optimization/88233 * common.opt (fsplit-wide-types-early): New option. * common/config/rs6000/rs6000-common.c (rs6000_option_optimization_table): Add OPT_fsplit_wide_types_early for OPT_LEVELS_ALL. * doc/invoke.texi (Optimization Options): Add -fsplit-wide-types-early. * lower-subreg.c (pass_lower_subreg2::gate): Add test for flag_split_wide_types_early. (pass_data_lower_subreg3): New. (pass_lower_subreg3): New. (make_pass_lower_subreg3): New. * passes.def (pass_lower_subreg2): Move after the loop passes. (pass_lower_subreg3): New, inserted where pass_lower_subreg2 was. * tree-pass.h (make_pass_lower_subreg2): Move up, to its new place in the pass pipeline; its previous place is taken by ... (make_pass_lower_subreg3): ... this. From-SVN: r273240 --- gcc/ChangeLog | 19 +++++++++++++ gcc/common.opt | 4 +++ gcc/common/config/rs6000/rs6000-common.c | 2 ++ gcc/doc/invoke.texi | 9 ++++++- gcc/lower-subreg.c | 46 +++++++++++++++++++++++++++++++- gcc/passes.def | 3 ++- gcc/tree-pass.h | 3 ++- 7 files changed, 82 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b47aead..d86ec3f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2019-07-08 Segher Boessenkool + + PR rtl-optimization/88233 + * common.opt (fsplit-wide-types-early): New option. + * common/config/rs6000/rs6000-common.c + (rs6000_option_optimization_table): Add OPT_fsplit_wide_types_early for + OPT_LEVELS_ALL. + * doc/invoke.texi (Optimization Options): Add -fsplit-wide-types-early. + * lower-subreg.c (pass_lower_subreg2::gate): Add test for + flag_split_wide_types_early. + (pass_data_lower_subreg3): New. + (pass_lower_subreg3): New. + (make_pass_lower_subreg3): New. + * passes.def (pass_lower_subreg2): Move after the loop passes. + (pass_lower_subreg3): New, inserted where pass_lower_subreg2 was. + * tree-pass.h (make_pass_lower_subreg2): Move up, to its new place in + the pass pipeline; its previous place is taken by ... + (make_pass_lower_subreg3): ... this. + 2019-07-08 Robin Dapp * config/s390/s390.c (s390_shift_truncation_mask): Define. diff --git a/gcc/common.opt b/gcc/common.opt index 41514df..b998b25 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2430,6 +2430,10 @@ fsplit-wide-types Common Report Var(flag_split_wide_types) Optimization Split wide types into independent registers. +fsplit-wide-types-early +Common Report Var(flag_split_wide_types_early) Optimization +Split wide types into independent registers earlier. + fssa-backprop Common Report Var(flag_ssa_backprop) Init(1) Optimization Enable backward propagation of use properties at the SSA level. diff --git a/gcc/common/config/rs6000/rs6000-common.c b/gcc/common/config/rs6000/rs6000-common.c index 9857b54..4b0c205 100644 --- a/gcc/common/config/rs6000/rs6000-common.c +++ b/gcc/common/config/rs6000/rs6000-common.c @@ -31,6 +31,8 @@ /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ static const struct default_options rs6000_option_optimization_table[] = { + /* Split multi-word types early. */ + { OPT_LEVELS_ALL, OPT_fsplit_wide_types_early, NULL, 1 }, /* Enable -fsched-pressure for first pass instruction scheduling. */ { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, { OPT_LEVELS_NONE, 0, NULL, 0 } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 73d16b5..7654c9b 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -467,7 +467,7 @@ Objective-C and Objective-C++ Dialects}. -fsignaling-nans @gol -fsingle-precision-constant -fsplit-ivs-in-unroller -fsplit-loops@gol -fsplit-paths @gol --fsplit-wide-types -fssa-backprop -fssa-phiopt @gol +-fsplit-wide-types -fsplit-wide-types-early -fssa-backprop -fssa-phiopt @gol -fstdarg-opt -fstore-merging -fstrict-aliasing @gol -fthread-jumps -ftracer -ftree-bit-ccp @gol -ftree-builtin-call-dce -ftree-ccp -ftree-ch @gol @@ -8731,6 +8731,13 @@ but may make debugging more difficult. Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}. +@item -fsplit-wide-types-early +@opindex fsplit-wide-types-early +Fully split wide types early, instead of very late. +This option has no effect unless @option{-fsplit-wide-types} is turned on. + +This is the default on some targets. + @item -fcse-follow-jumps @opindex fcse-follow-jumps In common subexpression elimination (CSE), scan through jump instructions diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index 4f68a73..e1418e5 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -1801,7 +1801,8 @@ public: {} /* opt_pass methods: */ - virtual bool gate (function *) { return flag_split_wide_types != 0; } + virtual bool gate (function *) { return flag_split_wide_types + && flag_split_wide_types_early; } virtual unsigned int execute (function *) { decompose_multiword_subregs (true); @@ -1817,3 +1818,46 @@ make_pass_lower_subreg2 (gcc::context *ctxt) { return new pass_lower_subreg2 (ctxt); } + +/* Implement third lower subreg pass. */ + +namespace { + +const pass_data pass_data_lower_subreg3 = +{ + RTL_PASS, /* type */ + "subreg3", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_LOWER_SUBREG, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_df_finish, /* todo_flags_finish */ +}; + +class pass_lower_subreg3 : public rtl_opt_pass +{ +public: + pass_lower_subreg3 (gcc::context *ctxt) + : rtl_opt_pass (pass_data_lower_subreg3, ctxt) + {} + + /* opt_pass methods: */ + virtual bool gate (function *) { return flag_split_wide_types + && !flag_split_wide_types_early; } + virtual unsigned int execute (function *) + { + decompose_multiword_subregs (true); + return 0; + } + +}; // class pass_lower_subreg3 + +} // anon namespace + +rtl_opt_pass * +make_pass_lower_subreg3 (gcc::context *ctxt) +{ + return new pass_lower_subreg3 (ctxt); +} diff --git a/gcc/passes.def b/gcc/passes.def index 9a5b0cd..1a7fd14 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -427,6 +427,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_rtl_doloop); NEXT_PASS (pass_rtl_loop_done); POP_INSERT_PASSES () + NEXT_PASS (pass_lower_subreg2); NEXT_PASS (pass_web); NEXT_PASS (pass_rtl_cprop); NEXT_PASS (pass_cse2); @@ -440,7 +441,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_partition_blocks); NEXT_PASS (pass_outof_cfg_layout_mode); NEXT_PASS (pass_split_all_insns); - NEXT_PASS (pass_lower_subreg2); + NEXT_PASS (pass_lower_subreg3); NEXT_PASS (pass_df_initialize_no_opt); NEXT_PASS (pass_stack_ptr_mod); NEXT_PASS (pass_mode_switching); diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index b27dbdd..7b83293 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -552,6 +552,7 @@ extern rtl_opt_pass *make_pass_rtl_unroll_loops (gcc::context *ctxt); extern rtl_opt_pass *make_pass_rtl_doloop (gcc::context *ctxt); extern rtl_opt_pass *make_pass_rtl_loop_done (gcc::context *ctxt); +extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_web (gcc::context *ctxt); extern rtl_opt_pass *make_pass_cse2 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_df_initialize_opt (gcc::context *ctxt); @@ -567,7 +568,7 @@ extern rtl_opt_pass *make_pass_partition_blocks (gcc::context *ctxt); extern rtl_opt_pass *make_pass_match_asm_constraints (gcc::context *ctxt); extern rtl_opt_pass *make_pass_split_all_insns (gcc::context *ctxt); extern rtl_opt_pass *make_pass_fast_rtl_byte_dce (gcc::context *ctxt); -extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt); +extern rtl_opt_pass *make_pass_lower_subreg3 (gcc::context *ctxt); extern rtl_opt_pass *make_pass_mode_switching (gcc::context *ctxt); extern rtl_opt_pass *make_pass_sms (gcc::context *ctxt); extern rtl_opt_pass *make_pass_sched (gcc::context *ctxt); -- cgit v1.1 From 9d9171550a399cac1d1717cf1bd31ec3750b0dfd Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Mon, 8 Jul 2019 22:38:46 +0200 Subject: rs6000: Add testcase for PR88233 This testcase tests that with -mcpu=power8 we do not generate any mtvsr* instructions, and we do the copy with {l,st}xvd2x. gcc/testsuite/ PR rtl-optimization/88233 * gcc.target/powerpc/pr88233.c: New testcase. From-SVN: r273245 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/powerpc/pr88233.c | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr88233.c (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31c3314..a78c745 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Segher Boessenkool + + PR rtl-optimization/88233 + * gcc.target/powerpc/pr88233.c: New testcase. + 2019-07-08 Wilco Dijkstra PR testsuite/91059 diff --git a/gcc/testsuite/gcc.target/powerpc/pr88233.c b/gcc/testsuite/gcc.target/powerpc/pr88233.c new file mode 100644 index 0000000..fa47b57 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr88233.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=power8" } */ + +typedef struct { double a[2]; } A; +A +foo (const A *a) +{ + return *a; +} + +/* { dg-final { scan-assembler-not {\mmtvsr} } } */ +/* { dg-final { scan-assembler-times {\mlxvd2x\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mstxvd2x\M} 1 } } */ -- cgit v1.1 From c83faba13da6d67e6784b3781419cd0605700daf Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Mon, 8 Jul 2019 23:14:33 +0200 Subject: rs6000: Ignore GFXOPT (and GPOPT) for choosing machine The function rs6000_machine_from_flags chooses what .machine string to used based on the rs6000_isa_flags flags. For that it checks for each ISA level if something for its ISA_*_MASKS is selected. This does not work for GFXOPT and GPOPT: these are set as flags in ISA_2_5_MASKS_SERVER, but they aren't actually new there, they just are not selected by default for older ISAs (they were optional). This patch makes OPTION_MASK_PPC_GFXOPT and OPTION_MASK_PPC_GPOPT not influence the .machine selection. * config/rs6000/rs6000.c (rs6000_machine_from_flags): Ignore OPTION_MASK_PPC_GFXOPT and OPTION_MASK_PPC_GPOPT for selecting the .machine string. From-SVN: r273246 --- gcc/ChangeLog | 6 ++++++ gcc/config/rs6000/rs6000.c | 22 +++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d86ec3f..db0cf7e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-07-08 Segher Boessenkool + * config/rs6000/rs6000.c (rs6000_machine_from_flags): Ignore + OPTION_MASK_PPC_GFXOPT and OPTION_MASK_PPC_GPOPT for selecting the + .machine string. + +2019-07-08 Segher Boessenkool + PR rtl-optimization/88233 * common.opt (fsplit-wide-types-early): New option. * common/config/rs6000/rs6000-common.c diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index f59f3a9..bec3436 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -5547,22 +5547,26 @@ const char *rs6000_machine; const char * rs6000_machine_from_flags (void) { - if ((rs6000_isa_flags & (ISA_FUTURE_MASKS_SERVER & ~ISA_3_0_MASKS_SERVER)) - != 0) + HOST_WIDE_INT flags = rs6000_isa_flags; + + /* Disable the flags that should never influence the .machine selection. */ + flags &= ~(OPTION_MASK_PPC_GFXOPT | OPTION_MASK_PPC_GPOPT); + + if ((flags & (ISA_FUTURE_MASKS_SERVER & ~ISA_3_0_MASKS_SERVER)) != 0) return "future"; - if ((rs6000_isa_flags & (ISA_3_0_MASKS_SERVER & ~ISA_2_7_MASKS_SERVER)) != 0) + if ((flags & (ISA_3_0_MASKS_SERVER & ~ISA_2_7_MASKS_SERVER)) != 0) return "power9"; - if ((rs6000_isa_flags & (ISA_2_7_MASKS_SERVER & ~ISA_2_6_MASKS_SERVER)) != 0) + if ((flags & (ISA_2_7_MASKS_SERVER & ~ISA_2_6_MASKS_SERVER)) != 0) return "power8"; - if ((rs6000_isa_flags & (ISA_2_6_MASKS_SERVER & ~ISA_2_5_MASKS_SERVER)) != 0) + if ((flags & (ISA_2_6_MASKS_SERVER & ~ISA_2_5_MASKS_SERVER)) != 0) return "power7"; - if ((rs6000_isa_flags & (ISA_2_5_MASKS_SERVER & ~ISA_2_4_MASKS)) != 0) + if ((flags & (ISA_2_5_MASKS_SERVER & ~ISA_2_4_MASKS)) != 0) return "power6"; - if ((rs6000_isa_flags & (ISA_2_4_MASKS & ~ISA_2_1_MASKS)) != 0) + if ((flags & (ISA_2_4_MASKS & ~ISA_2_1_MASKS)) != 0) return "power5"; - if ((rs6000_isa_flags & ISA_2_1_MASKS) != 0) + if ((flags & ISA_2_1_MASKS) != 0) return "power4"; - if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) != 0) + if ((flags & OPTION_MASK_POWERPC64) != 0) return "ppc64"; return "ppc"; } -- cgit v1.1 From 079e0f619684ff63b32e0fa02f460f57e271e3b4 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 8 Jul 2019 21:37:33 +0000 Subject: emit-rtl.c (set_insn_locations): New function moved from... * emit-rtl.c (set_insn_locations): New function moved from... * function.c (set_insn_locations): ...here. * ira-emit.c (emit_moves): Propagate location of the first instruction to the inserted move instructions. * reg-stack.c (compensate_edge): Set the location if the sequence is inserted on the edge. * rtl.h (set_insn_locations): Declare. From-SVN: r273247 --- gcc/ChangeLog | 10 ++++++++++ gcc/emit-rtl.c | 12 ++++++++++++ gcc/function.c | 13 ------------- gcc/ira-emit.c | 4 ++++ gcc/reg-stack.c | 1 + gcc/rtl.h | 1 + 6 files changed, 28 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index db0cf7e..d0d3494 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-07-08 Eric Botcazou + + * emit-rtl.c (set_insn_locations): New function moved from... + * function.c (set_insn_locations): ...here. + * ira-emit.c (emit_moves): Propagate location of the first instruction + to the inserted move instructions. + * reg-stack.c (compensate_edge): Set the location if the sequence is + inserted on the edge. + * rtl.h (set_insn_locations): Declare. + 2019-07-08 Segher Boessenkool * config/rs6000/rs6000.c (rs6000_machine_from_flags): Ignore diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index e265fa6..f60f2e2 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -6582,6 +6582,18 @@ curr_insn_location (void) return curr_location; } +/* Set the location of the insn chain starting at INSN to LOC. */ +void +set_insn_locations (rtx_insn *insn, location_t loc) +{ + while (insn) + { + if (INSN_P (insn)) + INSN_LOCATION (insn) = loc; + insn = NEXT_INSN (insn); + } +} + /* Return lexical scope block insn belongs to. */ tree insn_scope (const rtx_insn *insn) diff --git a/gcc/function.c b/gcc/function.c index a957679..0bce4ec 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -5244,19 +5244,6 @@ use_return_register (void) diddle_return_value (do_use_return_reg, NULL); } -/* Set the location of the insn chain starting at INSN to LOC. */ - -static void -set_insn_locations (rtx_insn *insn, int loc) -{ - while (insn != NULL) - { - if (INSN_P (insn)) - INSN_LOCATION (insn) = loc; - insn = NEXT_INSN (insn); - } -} - /* Generate RTL for the end of the current function. */ void diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c index 51bf9c8..c42acad 100644 --- a/gcc/ira-emit.c +++ b/gcc/ira-emit.c @@ -1011,6 +1011,10 @@ emit_moves (void) tmp = NEXT_INSN (tmp); if (NOTE_INSN_BASIC_BLOCK_P (tmp)) tmp = NEXT_INSN (tmp); + /* Propagate the location of the current first instruction to the + moves so that they don't inherit a random location. */ + if (tmp != NULL_RTX && INSN_P (tmp)) + set_insn_locations (insns, INSN_LOCATION (tmp)); if (tmp == BB_HEAD (bb)) emit_insn_before (insns, tmp); else if (tmp != NULL_RTX) diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 5576630..710f14a 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -2929,6 +2929,7 @@ compensate_edge (edge e) seq = get_insns (); end_sequence (); + set_insn_locations (seq, e->goto_locus); insert_insn_on_edge (seq, e); return true; } diff --git a/gcc/rtl.h b/gcc/rtl.h index 31fba82..a4fde4e 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -4338,6 +4338,7 @@ extern void insn_locations_init (void); extern void insn_locations_finalize (void); extern void set_curr_insn_location (location_t); extern location_t curr_insn_location (void); +extern void set_insn_locations (rtx_insn *, location_t); /* rtl-error.c */ extern void _fatal_insn_not_found (const_rtx, const char *, int, const char *) -- cgit v1.1 From 9c6e2f8274d1e6a621e410dc945488aa9ff6f779 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 9 Jul 2019 00:08:27 +0200 Subject: re PR c++/91110 (ICE: tree check: expected class 'type', have 'exceptional' (error_mark) in cp_omp_mappable_type_1, at cp/decl2.c:1421) PR c++/91110 * decl2.c (cp_omp_mappable_type_1): Don't emit any note for error_mark_node type. * g++.dg/gomp/pr91110.C: New test. From-SVN: r273248 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/decl2.c | 2 +- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/gomp/pr91110.C | 11 +++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/gomp/pr91110.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1967c9b..0fcbfe5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2019-07-08 Jakub Jelinek + + PR c++/91110 + * decl2.c (cp_omp_mappable_type_1): Don't emit any note for + error_mark_node type. + 2019-07-05 Jakub Jelinek PR c++/67184 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index b415716..3aba194 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1416,7 +1416,7 @@ cp_omp_mappable_type_1 (tree type, bool notes) /* Mappable type has to be complete. */ if (type == error_mark_node || !COMPLETE_TYPE_P (type)) { - if (notes) + if (notes && type != error_mark_node) { tree decl = TYPE_MAIN_DECL (type); inform ((decl ? DECL_SOURCE_LOCATION (decl) : input_location), diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a78c745..3e24415 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-08 Jakub Jelinek + + PR c++/91110 + * g++.dg/gomp/pr91110.C: New test. + 2019-07-08 Segher Boessenkool PR rtl-optimization/88233 diff --git a/gcc/testsuite/g++.dg/gomp/pr91110.C b/gcc/testsuite/g++.dg/gomp/pr91110.C new file mode 100644 index 0000000..332c99a --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/pr91110.C @@ -0,0 +1,11 @@ +// PR c++/91110 +// { dg-do compile } + +void +foo () +{ + X b[2]; // { dg-error "'X' was not declared in this scope" } + b[0] = 1; // { dg-error "'b' was not declared in this scope" } + #pragma omp target map(to: b) // { dg-error "'b' does not have a mappable type in 'map' clause" } + ; +} -- cgit v1.1 From 6cda84b509af152b2ea2cfc48f896cb7b776548d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 9 Jul 2019 00:11:59 +0200 Subject: tree-vect-stmts.c (scan_operand_equal_p): Look through MEM_REF with SSA_NAME address of POINTER_PLUS_EXPR. * tree-vect-stmts.c (scan_operand_equal_p): Look through MEM_REF with SSA_NAME address of POINTER_PLUS_EXPR. Handle MULT_EXPR and casts in offset when different, both through gimple stmts and through trees. Rewritten using loops to minimize code duplication for each operand. * g++.dg/vect/simd-6.cc: Replace xfail with target x86. * g++.dg/vect/simd-9.cc: Likewise. * testsuite/libgomp.c++/scan-13.C: Replace xfail with target x86. * testsuite/libgomp.c++/scan-16.C: Likewise. From-SVN: r273249 --- gcc/ChangeLog | 8 +++ gcc/testsuite/ChangeLog | 3 ++ gcc/testsuite/g++.dg/vect/simd-6.cc | 2 +- gcc/testsuite/g++.dg/vect/simd-9.cc | 2 +- gcc/tree-vect-stmts.c | 102 ++++++++++++++++++++++++++++-------- 5 files changed, 93 insertions(+), 24 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d0d3494..5433376 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-08 Jakub Jelinek + + * tree-vect-stmts.c (scan_operand_equal_p): Look through MEM_REF + with SSA_NAME address of POINTER_PLUS_EXPR. Handle MULT_EXPR + and casts in offset when different, both through gimple stmts + and through trees. Rewritten using loops to minimize code duplication + for each operand. + 2019-07-08 Eric Botcazou * emit-rtl.c (set_insn_locations): New function moved from... diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3e24415..31ba420 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2019-07-08 Jakub Jelinek + * g++.dg/vect/simd-6.cc: Replace xfail with target x86. + * g++.dg/vect/simd-9.cc: Likewise. + PR c++/91110 * g++.dg/gomp/pr91110.C: New test. diff --git a/gcc/testsuite/g++.dg/vect/simd-6.cc b/gcc/testsuite/g++.dg/vect/simd-6.cc index 997f7b1..883b769 100644 --- a/gcc/testsuite/g++.dg/vect/simd-6.cc +++ b/gcc/testsuite/g++.dg/vect/simd-6.cc @@ -1,7 +1,7 @@ // { dg-require-effective-target size32plus } // { dg-additional-options "-fopenmp-simd" } // { dg-additional-options "-mavx" { target avx_runtime } } -// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { xfail *-*-* } } } +// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } #include "../../gcc.dg/vect/tree-vect.h" diff --git a/gcc/testsuite/g++.dg/vect/simd-9.cc b/gcc/testsuite/g++.dg/vect/simd-9.cc index bfef445..4c5b050 100644 --- a/gcc/testsuite/g++.dg/vect/simd-9.cc +++ b/gcc/testsuite/g++.dg/vect/simd-9.cc @@ -1,7 +1,7 @@ // { dg-require-effective-target size32plus } // { dg-additional-options "-fopenmp-simd" } // { dg-additional-options "-mavx" { target avx_runtime } } -// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { xfail *-*-* } } } +// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } #include "../../gcc.dg/vect/tree-vect.h" diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index ead079d..10ce2a2 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -6334,30 +6334,88 @@ get_group_alias_ptr_type (stmt_vec_info first_stmt_info) static bool scan_operand_equal_p (tree ref1, tree ref2) { - machine_mode mode1, mode2; - poly_int64 bitsize1, bitsize2, bitpos1, bitpos2; - tree offset1, offset2; - int unsignedp1, unsignedp2, reversep1, reversep2; - int volatilep1 = 0, volatilep2 = 0; - tree base1 = get_inner_reference (ref1, &bitsize1, &bitpos1, &offset1, - &mode1, &unsignedp1, &reversep1, - &volatilep1); - tree base2 = get_inner_reference (ref2, &bitsize2, &bitpos2, &offset2, - &mode2, &unsignedp2, &reversep2, - &volatilep2); - if (reversep1 || reversep2 || volatilep1 || volatilep2) - return false; - if (!operand_equal_p (base1, base2, 0)) - return false; - if (maybe_ne (bitpos1, 0) || maybe_ne (bitpos2, 0)) - return false; - if (maybe_ne (bitsize1, bitsize2)) + tree ref[2] = { ref1, ref2 }; + poly_int64 bitsize[2], bitpos[2]; + tree offset[2], base[2]; + for (int i = 0; i < 2; ++i) + { + machine_mode mode; + int unsignedp, reversep, volatilep = 0; + base[i] = get_inner_reference (ref[i], &bitsize[i], &bitpos[i], + &offset[i], &mode, &unsignedp, + &reversep, &volatilep); + if (reversep || volatilep || maybe_ne (bitpos[i], 0)) + return false; + if (TREE_CODE (base[i]) == MEM_REF + && offset[i] == NULL_TREE + && TREE_CODE (TREE_OPERAND (base[i], 0)) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (base[i], 0)); + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR + && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == ADDR_EXPR + && TREE_CODE (gimple_assign_rhs2 (def_stmt)) == SSA_NAME) + { + if (maybe_ne (mem_ref_offset (base[i]), 0)) + return false; + base[i] = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0); + offset[i] = gimple_assign_rhs2 (def_stmt); + } + } + } + + if (!operand_equal_p (base[0], base[1], 0)) return false; - if (offset1 != offset2 - && (!offset1 - || !offset2 - || !operand_equal_p (offset1, offset2, 0))) + if (maybe_ne (bitsize[0], bitsize[1])) return false; + if (offset[0] != offset[1]) + { + if (!offset[0] || !offset[1]) + return false; + if (!operand_equal_p (offset[0], offset[1], 0)) + { + tree step[2]; + for (int i = 0; i < 2; ++i) + { + step[i] = integer_one_node; + if (TREE_CODE (offset[i]) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (offset[i]); + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == MULT_EXPR + && (TREE_CODE (gimple_assign_rhs2 (def_stmt)) + == INTEGER_CST)) + { + step[i] = gimple_assign_rhs2 (def_stmt); + offset[i] = gimple_assign_rhs1 (def_stmt); + } + } + else if (TREE_CODE (offset[i]) == MULT_EXPR) + { + step[i] = TREE_OPERAND (offset[i], 1); + offset[i] = TREE_OPERAND (offset[i], 0); + } + tree rhs1 = NULL_TREE; + if (TREE_CODE (offset[i]) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (offset[i]); + if (gimple_assign_cast_p (def_stmt)) + rhs1 = gimple_assign_rhs1 (def_stmt); + } + else if (CONVERT_EXPR_P (offset[i])) + rhs1 = TREE_OPERAND (offset[i], 0); + if (rhs1 + && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) + && INTEGRAL_TYPE_P (TREE_TYPE (offset[i])) + && (TYPE_PRECISION (TREE_TYPE (offset[i])) + >= TYPE_PRECISION (TREE_TYPE (rhs1)))) + offset[i] = rhs1; + } + if (!operand_equal_p (offset[0], offset[1], 0) + || !operand_equal_p (step[0], step[1], 0)) + return false; + } + } return true; } -- cgit v1.1 From 7d64aec499687f593a1bab4ae7cac843bc1d47af Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 9 Jul 2019 00:16:23 +0000 Subject: Daily bump. From-SVN: r273260 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index fd804b8..02c3d86 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190708 +20190709 -- cgit v1.1 From aac9480da1ffd037ceb21790fe341b3ec23283d9 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 9 Jul 2019 04:15:42 +0000 Subject: PR middle-end/71924 - missing -Wreturn-local-addr returning alloca result PR middle-end/71924 - missing -Wreturn-local-addr returning alloca result PR middle-end/90549 - missing -Wreturn-local-addr maybe returning an address of a local array plus offset gcc/ChangeLog: PR middle-end/71924 PR middle-end/90549 * gimple-ssa-isolate-paths.c (isolate_path): Add attribute. Update comment. (args_loc_t): New type. (args_loc_t, locmap_t): same. (diag_returned_locals): New function. (is_addr_local): Same. (handle_return_addr_local_phi_arg, warn_return_addr_local): Same. (find_implicit_erroneous_behavior): Call warn_return_addr_local_phi_arg. (find_explicit_erroneous_behavior): Call warn_return_addr_local. gcc/testsuite/ChangeLog: PR middle-end/71924 PR middle-end/90549 * gcc.c-torture/execute/return-addr.c: New test. * gcc.dg/Wreturn-local-addr-2.c: New test. * gcc.dg/Wreturn-local-addr-4.c: New test. * gcc.dg/Wreturn-local-addr-5.c: New test. * gcc.dg/Wreturn-local-addr-6.c: New test. * gcc.dg/Wreturn-local-addr-7.c: New test. * gcc.dg/Wreturn-local-addr-8.c: New test. * gcc.dg/Wreturn-local-addr-9.c: New test. * gcc.dg/Wreturn-local-addr-10.c: New test. * gcc.dg/Walloca-4.c: Handle expected warnings. * gcc.dg/pr41551.c: Same. * gcc.dg/pr59523.c: Same. * gcc.dg/tree-ssa/pr88775-2.c: Same. * gcc.dg/tree-ssa/alias-37.c: Same. * gcc.dg/winline-7.c: Same. From-SVN: r273261 --- gcc/ChangeLog | 14 + gcc/gimple-ssa-isolate-paths.c | 488 ++++++++++++++++++---- gcc/testsuite/ChangeLog | 20 + gcc/testsuite/gcc.c-torture/execute/return-addr.c | 122 ++++++ gcc/testsuite/gcc.dg/Walloca-4.c | 7 +- gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c | 56 +++ gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c | 293 +++++++++++++ gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c | 248 +++++++++++ gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c | 370 ++++++++++++++++ gcc/testsuite/gcc.dg/Wreturn-local-addr-5.c | 40 ++ gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c | 203 +++++++++ gcc/testsuite/gcc.dg/Wreturn-local-addr-7.c | 50 +++ gcc/testsuite/gcc.dg/Wreturn-local-addr-8.c | 88 ++++ gcc/testsuite/gcc.dg/Wreturn-local-addr-9.c | 73 ++++ gcc/testsuite/gcc.dg/pr41551.c | 2 + gcc/testsuite/gcc.dg/pr59523.c | 2 + gcc/testsuite/gcc.dg/tree-ssa/alias-37.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c | 2 + gcc/testsuite/gcc.dg/winline-7.c | 2 + 19 files changed, 1987 insertions(+), 95 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/return-addr.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-5.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-7.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-8.c create mode 100644 gcc/testsuite/gcc.dg/Wreturn-local-addr-9.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5433376..a6c99ac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-07-08 Martin Sebor + + PR middle-end/71924 + PR middle-end/90549 + * gimple-ssa-isolate-paths.c (isolate_path): Add attribute. Update + comment. + (args_loc_t): New type. + (args_loc_t, locmap_t): same. + (diag_returned_locals): New function. + (is_addr_local): Same. + (handle_return_addr_local_phi_arg, warn_return_addr_local): Same. + (find_implicit_erroneous_behavior): Call warn_return_addr_local_phi_arg. + (find_explicit_erroneous_behavior): Call warn_return_addr_local. + 2019-07-08 Jakub Jelinek * tree-vect-stmts.c (scan_operand_equal_p): Look through MEM_REF diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c index 33fe352..72e6c77 100644 --- a/gcc/gimple-ssa-isolate-paths.c +++ b/gcc/gimple-ssa-isolate-paths.c @@ -128,9 +128,9 @@ insert_trap (gimple_stmt_iterator *si_p, tree op) DUPLICATE is a pre-existing duplicate, use it as BB' if it exists. - Return BB'. */ + Return BB' (which may be equal to DUPLICATE). */ -basic_block +ATTRIBUTE_RETURNS_NONNULL basic_block isolate_path (basic_block bb, basic_block duplicate, edge e, gimple *stmt, tree op, bool ret_zero) { @@ -341,6 +341,322 @@ stmt_uses_0_or_null_in_undefined_way (gimple *stmt) return false; } +/* Describes the property of a return statement that may return + the address of one or more local variables. The type must + be safely assignable and copyable so that it can be stored in + a hash_map. */ +class args_loc_t +{ + public: + + args_loc_t (): nargs (), locvec (), ptr (&ptr) + { + locvec.create (4); + } + + args_loc_t (const args_loc_t &rhs) + : nargs (rhs.nargs), locvec (rhs.locvec.copy ()), ptr (&ptr) { } + + args_loc_t& operator= (const args_loc_t &rhs) + { + nargs = rhs.nargs; + locvec.release (); + locvec = rhs.locvec.copy (); + return *this; + } + + ~args_loc_t () + { + locvec.release (); + gcc_assert (ptr == &ptr); + } + + /* For a PHI in a return statement its number of arguments. When greater + than LOCVEC.LENGTH () implies that an address of one of the locals in + LOCVEC may but need not be returned by the statement. Otherwise, + unless both are zero, it implies it definitely is returned. */ + unsigned nargs; + /* The locations of local variables/alloca calls returned by the return + statement. Avoid using auto_vec here since it's not safe to copy due + to pr90904. */ + vec locvec; + void *ptr; +}; + +/* A mapping from a return statement to the locations of local variables + whose addresses it may return. */ +typedef hash_map locmap_t; + +/* Given the LOCMAP mapping, issue diagnostics about returning addresses + of local variables. When MAYBE is set, all diagnostics will be of + the "may return" kind. Otherwise each will be determined based on + the equality of the corresponding NARGS and LOCVEC.LENGTH () values. */ + +static void +diag_returned_locals (bool maybe, const locmap_t &locmap) +{ + for (locmap_t::iterator it = locmap.begin (); it != locmap.end (); ++it) + { + gimple *stmt = (*it).first; + const args_loc_t &argsloc = (*it).second; + location_t stmtloc = gimple_location (stmt); + + auto_diagnostic_group d; + unsigned nargs = argsloc.locvec.length (); + if (warning_at (stmtloc, OPT_Wreturn_local_addr, + (maybe || argsloc.nargs > nargs + ? G_("function may return address of local variable") + : G_("function returns address of local variable")))) + { + for (unsigned i = 0; i != nargs; ++i) + inform (argsloc.locvec[i], "declared here"); + } + } +} + +/* Return true if EXPR is an expression of pointer type that refers + to the address of one or more variables with automatic storage + duration. If so, add an entry to *PLOCMAP and insert into + PLOCMAP->LOCVEC the locations of the corresponding local variables + whose address is returned by the RETURN_STMT (which may be set to + (gimple*)-1 as a placeholder for such a statement). VISITED is + a bitmap of PHI nodes already visited by recursive calls. When + null, PHI expressions are not considered. */ + +static bool +is_addr_local (gimple *return_stmt, tree exp, locmap_t *plocmap, + hash_set *visited) +{ + if (TREE_CODE (exp) == ADDR_EXPR) + { + tree baseaddr = get_base_address (TREE_OPERAND (exp, 0)); + if (TREE_CODE (baseaddr) == MEM_REF) + return is_addr_local (return_stmt, TREE_OPERAND (baseaddr, 0), + plocmap, visited); + + if ((!VAR_P (baseaddr) + || is_global_var (baseaddr)) + && TREE_CODE (baseaddr) != PARM_DECL) + return false; + + args_loc_t &argsloc = plocmap->get_or_insert (return_stmt); + argsloc.locvec.safe_push (DECL_SOURCE_LOCATION (baseaddr)); + return true; + } + + if (!POINTER_TYPE_P (TREE_TYPE (exp))) + return false; + + if (TREE_CODE (exp) == SSA_NAME) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (exp); + enum gimple_code code = gimple_code (def_stmt); + + if (is_gimple_assign (def_stmt)) + { + tree type = TREE_TYPE (gimple_assign_lhs (def_stmt)); + if (POINTER_TYPE_P (type)) + { + tree_code code = gimple_assign_rhs_code (def_stmt); + tree ptr1 = NULL_TREE, ptr2 = NULL_TREE; + + /* Set to the number of arguments examined that should + be added to ARGSLOC->NARGS to identify expressions + only some but not all of whose operands refer to local + addresses. */ + unsigned nargs = 0; + if (code == COND_EXPR) + { + ptr1 = gimple_assign_rhs2 (def_stmt); + ptr2 = gimple_assign_rhs3 (def_stmt); + nargs = 2; + } + else if (code == MAX_EXPR || code == MIN_EXPR) + { + ptr1 = gimple_assign_rhs1 (def_stmt); + ptr2 = gimple_assign_rhs2 (def_stmt); + nargs = 2; + } + else if (code == ADDR_EXPR + || code == NOP_EXPR + || code == POINTER_PLUS_EXPR) + /* Leave NARGS at zero and let the recursive call set it. */ + ptr1 = gimple_assign_rhs1 (def_stmt); + + /* Avoid short-circuiting the logical OR result in case + both operands refer to local variables, in which case + both should be considered and identified in the warning. */ + bool res1 = false, res2 = false; + if (ptr1) + res1 = is_addr_local (return_stmt, ptr1, plocmap, visited); + if (ptr2) + res2 = is_addr_local (return_stmt, ptr2, plocmap, visited); + + if (nargs) + if (args_loc_t *argsloc = plocmap->get (return_stmt)) + argsloc->nargs += nargs; + + return res1 || res2; + } + return false; + } + + if (code == GIMPLE_CALL + && gimple_call_builtin_p (def_stmt)) + { + /* Handle alloca and friends that return pointers to automatic + storage. */ + tree fn = gimple_call_fndecl (def_stmt); + int code = DECL_FUNCTION_CODE (fn); + if (code == BUILT_IN_ALLOCA + || code == BUILT_IN_ALLOCA_WITH_ALIGN + || code == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX) + { + args_loc_t &argsloc = plocmap->get_or_insert (return_stmt); + argsloc.locvec.safe_push (gimple_location (def_stmt)); + return true; + } + + if (gimple_call_num_args (def_stmt) < 1) + return false; + + /* Recursively examine the first argument of calls to built-ins + that return it. */ + switch (code) + { + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMPCPY: + case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_STPCPY: + case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STPNCPY: + case BUILT_IN_STPNCPY_CHK: + case BUILT_IN_STRCAT: + case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCHR: + case BUILT_IN_STRCPY: + case BUILT_IN_STRCPY_CHK: + case BUILT_IN_STRNCAT: + case BUILT_IN_STRNCAT_CHK: + case BUILT_IN_STRNCPY: + case BUILT_IN_STRNCPY_CHK: + case BUILT_IN_STRRCHR: + case BUILT_IN_STRSTR: + return is_addr_local (return_stmt, + gimple_call_arg (def_stmt, 0), + plocmap, visited); + default: + return false; + } + } + + if (code == GIMPLE_PHI && visited) + { + gphi *phi_stmt = as_a (def_stmt); + if (visited->add (phi_stmt)) + return false; + + unsigned count = 0; + unsigned nargs = gimple_phi_num_args (phi_stmt); + args_loc_t &argsloc = plocmap->get_or_insert (return_stmt); + /* Bump up the number of operands examined by the number of + operands of this PHI. */ + argsloc.nargs += nargs; + for (unsigned i = 0; i < gimple_phi_num_args (phi_stmt); ++i) + { + tree arg = gimple_phi_arg_def (phi_stmt, i); + if (is_addr_local (return_stmt, arg, plocmap, visited)) + ++count; + } + return count != 0; + } + } + + return false; +} + +/* Detect returning the address of a local variable in a PHI result LHS + and argument ARG and PHI edge E in basic block BB. Add an entry for + each use to LOCMAP, setting its NARGS member to the NARGS argument + (the number of PHI operands) plus the number of arguments in binary + expressions refereced by ARG. Call isolate_path for each returned + address and set *ISOLATED to true if called. + Return either DUPLICATE or the most recent result of isolate_path. */ + +static basic_block +handle_return_addr_local_phi_arg (basic_block bb, basic_block duplicate, + tree lhs, tree arg, edge e, locmap_t &locmap, + unsigned nargs, bool *isolated) +{ + /* Use (gimple*)-1 as a temporary placeholder and replace it with + the return statement below once it is known. Using a null doesn't + work because it's used by the hash_map to mean "no-entry." Pass + null instead of a visited_phis bitmap to avoid descending into + PHIs since they are being processed by the caller. Those that + remain will be checked again later. */ + if (!is_addr_local ((gimple*)-1, arg, &locmap, NULL)) + { + /* Remove the placeholder regardless of success or failure. */ + locmap.remove ((gimple*)-1); + return duplicate; + } + + const args_loc_t* const placeargsloc = locmap.get ((gimple*)-1); + const unsigned nlocs = placeargsloc->locvec.length (); + gcc_assert (nlocs); + + /* Add to the number of PHI arguments determined by the caller + the number of operands of the expressions referenced by ARG. + This lets the caller determine whether it's dealing with + a "may return" or "definitely returns." */ + nargs += placeargsloc->nargs; + + /* Set to true if any expressions referenced by ARG involve + multiple addresses only some of which are those of locals. */ + bool maybe = placeargsloc->nargs > placeargsloc->locvec.length (); + + gimple *use_stmt; + imm_use_iterator iter; + + /* Look for uses of the PHI result LHS in return statements. */ + FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) + { + greturn *return_stmt = dyn_cast (use_stmt); + if (!return_stmt) + continue; + + if (gimple_return_retval (return_stmt) != lhs) + continue; + + /* Add an entry for the return statement and the locations + oof the PHI arguments obtained above to the map. */ + args_loc_t &argsloc = locmap.get_or_insert (use_stmt); + argsloc.nargs = nargs; + unsigned nelts = argsloc.locvec.length () + nlocs; + argsloc.locvec.reserve (nelts); + argsloc.locvec.splice (placeargsloc->locvec); + + if (!maybe + && (flag_isolate_erroneous_paths_dereference + || flag_isolate_erroneous_paths_attribute) + && gimple_bb (use_stmt) == bb) + { + duplicate = isolate_path (bb, duplicate, e, + use_stmt, lhs, true); + + /* Let caller know the path has been isolated. */ + *isolated = true; + } + } + + locmap.remove ((gimple*)-1); + + return duplicate; +} + /* Look for PHI nodes which feed statements in the same block where the value of the PHI node implies the statement is erroneous. @@ -352,6 +668,8 @@ stmt_uses_0_or_null_in_undefined_way (gimple *stmt) static void find_implicit_erroneous_behavior (void) { + locmap_t locmap; + basic_block bb; FOR_EACH_BB_FN (bb, cfun) @@ -388,70 +706,46 @@ find_implicit_erroneous_behavior (void) gphi *phi = si.phi (); tree lhs = gimple_phi_result (phi); + /* Initial number of PHI arguments. The result may change + from one iteration of the loop below to the next in + response to changes to the CFG but only the initial + value is stored below for use by diagnostics. */ + unsigned nargs = gimple_phi_num_args (phi); + /* PHI produces a pointer result. See if any of the PHI's arguments are NULL. When we remove an edge, we want to reprocess the current - index, hence the ugly way we update I for each iteration. */ + index since the argument at that index will have been + removed, hence the ugly way we update I for each iteration. */ basic_block duplicate = NULL; for (unsigned i = 0, next_i = 0; - i < gimple_phi_num_args (phi); - i = next_i) + i < gimple_phi_num_args (phi); i = next_i) { - tree op = gimple_phi_arg_def (phi, i); + tree arg = gimple_phi_arg_def (phi, i); edge e = gimple_phi_arg_edge (phi, i); - imm_use_iterator iter; - gimple *use_stmt; + /* Advance the argument index unless a path involving + the current argument has been isolated. */ next_i = i + 1; - - if (TREE_CODE (op) == ADDR_EXPR) + bool isolated = false; + duplicate = handle_return_addr_local_phi_arg (bb, duplicate, lhs, + arg, e, locmap, + nargs, &isolated); + if (isolated) { - tree valbase = get_base_address (TREE_OPERAND (op, 0)); - if ((VAR_P (valbase) && !is_global_var (valbase)) - || TREE_CODE (valbase) == PARM_DECL) - { - FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) - { - greturn *return_stmt - = dyn_cast (use_stmt); - if (!return_stmt) - continue; - - if (gimple_return_retval (return_stmt) != lhs) - continue; - - { - auto_diagnostic_group d; - if (warning_at (gimple_location (use_stmt), - OPT_Wreturn_local_addr, - "function may return address " - "of local variable")) - inform (DECL_SOURCE_LOCATION(valbase), - "declared here"); - } - - if ((flag_isolate_erroneous_paths_dereference - || flag_isolate_erroneous_paths_attribute) - && gimple_bb (use_stmt) == bb) - { - duplicate = isolate_path (bb, duplicate, e, - use_stmt, lhs, true); - - /* When we remove an incoming edge, we need to - reprocess the Ith element. */ - next_i = i; - cfg_altered = true; - } - } - } + cfg_altered = true; + next_i = i; } - if (!integer_zerop (op)) + if (!integer_zerop (arg)) continue; location_t phi_arg_loc = gimple_phi_arg_location (phi, i); + imm_use_iterator iter; + gimple *use_stmt; + /* We've got a NULL PHI argument. Now see if the PHI's result is dereferenced within BB. */ FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) @@ -480,6 +774,57 @@ find_implicit_erroneous_behavior (void) } } } + + diag_returned_locals (false, locmap); +} + +/* Detect and diagnose returning the address of a local variable + in RETURN_STMT in basic block BB. This only becomes undefined + behavior if the result is used, so we do not insert a trap and + only return NULL instead. */ + +static void +warn_return_addr_local (basic_block bb, greturn *return_stmt) +{ + tree val = gimple_return_retval (return_stmt); + if (!val) + return; + + locmap_t locmap; + hash_set visited_phis; + if (!is_addr_local (return_stmt, val, &locmap, &visited_phis)) + return; + + /* We only need it for this particular case. */ + calculate_dominance_info (CDI_POST_DOMINATORS); + + const args_loc_t *argsloc = locmap.get (return_stmt); + gcc_assert (argsloc); + + bool maybe = argsloc->nargs > argsloc->locvec.length (); + if (!maybe) + maybe = !dominated_by_p (CDI_POST_DOMINATORS, + single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)), bb); + + diag_returned_locals (maybe, locmap); + + /* Bail if the statement isn't certain to return the address + of a local (e.g., if it involves a conditional expression + that wasn't trasnformed into a PHI or if it involves + a MAX_EXPR or MIN_EXPR only one of whose operands is a local + (even though such an expression isn't valid in C or has + defined semantics in C++). */ + if (maybe) + return; + + /* Do not modify code if the user only asked for warnings. */ + if (flag_isolate_erroneous_paths_dereference + || flag_isolate_erroneous_paths_attribute) + { + tree zero = build_zero_cst (TREE_TYPE (val)); + gimple_return_set_retval (return_stmt, zero); + update_stmt (return_stmt); + } } /* Look for statements which exhibit erroneous behavior. For example @@ -525,49 +870,10 @@ find_explicit_erroneous_behavior (void) break; } - /* Detect returning the address of a local variable. This only - becomes undefined behavior if the result is used, so we do not - insert a trap and only return NULL instead. */ + /* Look for a return statement that returns the address + of a local variable or the result of alloca. */ if (greturn *return_stmt = dyn_cast (stmt)) - { - tree val = gimple_return_retval (return_stmt); - if (val && TREE_CODE (val) == ADDR_EXPR) - { - tree valbase = get_base_address (TREE_OPERAND (val, 0)); - if ((VAR_P (valbase) && !is_global_var (valbase)) - || TREE_CODE (valbase) == PARM_DECL) - { - /* We only need it for this particular case. */ - calculate_dominance_info (CDI_POST_DOMINATORS); - const char* msg; - bool always_executed = dominated_by_p - (CDI_POST_DOMINATORS, - single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)), bb); - if (always_executed) - msg = N_("function returns address of local variable"); - else - msg = N_("function may return address of " - "local variable"); - { - auto_diagnostic_group d; - if (warning_at (gimple_location (stmt), - OPT_Wreturn_local_addr, msg)) - inform (DECL_SOURCE_LOCATION(valbase), - "declared here"); - } - - /* Do not modify code if the user only asked for - warnings. */ - if (flag_isolate_erroneous_paths_dereference - || flag_isolate_erroneous_paths_attribute) - { - tree zero = build_zero_cst (TREE_TYPE (val)); - gimple_return_set_retval (return_stmt, zero); - update_stmt (stmt); - } - } - } - } + warn_return_addr_local (bb, return_stmt); } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31ba420..2941e43 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,23 @@ +2019-07-08 Martin Sebor + + PR middle-end/71924 + PR middle-end/90549 + * gcc.c-torture/execute/return-addr.c: New test. + * gcc.dg/Wreturn-local-addr-2.c: New test. + * gcc.dg/Wreturn-local-addr-4.c: New test. + * gcc.dg/Wreturn-local-addr-5.c: New test. + * gcc.dg/Wreturn-local-addr-6.c: New test. + * gcc.dg/Wreturn-local-addr-7.c: New test. + * gcc.dg/Wreturn-local-addr-8.c: New test. + * gcc.dg/Wreturn-local-addr-9.c: New test. + * gcc.dg/Wreturn-local-addr-10.c: New test. + * gcc.dg/Walloca-4.c: Handle expected warnings. + * gcc.dg/pr41551.c: Same. + * gcc.dg/pr59523.c: Same. + * gcc.dg/tree-ssa/pr88775-2.c: Same. + * gcc.dg/tree-ssa/alias-37.c: Same. + * gcc.dg/winline-7.c: Same. + 2019-07-08 Jakub Jelinek * g++.dg/vect/simd-6.cc: Replace xfail with target x86. diff --git a/gcc/testsuite/gcc.c-torture/execute/return-addr.c b/gcc/testsuite/gcc.c-torture/execute/return-addr.c new file mode 100644 index 0000000..7981818 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/return-addr.c @@ -0,0 +1,122 @@ +/* Test to verify that a function that returns either the address + of a local variable or a non-local via a MAX_EXPR or MIN_EXPR + doesn't return null when the result of the expression is + the latter. */ + +#define NOIPA __attribute__ ((noclone, noinline, noipa)) + +#define A(expr) \ + ((expr) \ + ? (void)0 \ + : (__builtin_printf ("assertion failed on line %i: %s\n", \ + __LINE__, #expr), \ + __builtin_abort ())) + + +typedef __UINTPTR_TYPE__ uintptr_t; + +/* Return a bigger value than P. The address still points (just + past) the local variable pointed to by P so the caller does + return the address of a local variable but that's hidden from + GCC by the attribute and the point of the test is to verify + that the address in the return statement in the caller isn't + replaced by null when GCC cannot prove the address doesn't + reference a non-local variable. */ + +NOIPA char* get_max_2 (char *p) +{ + return p + 1; +} + +NOIPA char* get_max_3 (char *p, char *q) +{ + return p < q ? q + 1 : p + 1; +} + +/* Analogous to the above. The expressions are undefined because + they form an address prior to the beginning of the object but + it's hidden from GCC by the attributes. */ + +NOIPA char* get_min_2 (char *p) +{ + return p - 1; +} + +NOIPA char* get_min_3 (char *p, char *q) +{ + return p < q ? p - 1 : q - 1; +} + + +NOIPA void* test_max_2 (void) +{ + char c; + + char *p = get_max_2 (&c); + + void *q = p > &c ? p : &c; /* MAX_EXPR */ + return q; +} + +NOIPA void* test_max_3 (void) +{ + char c; + char d; + + char *p = get_max_3 (&c, &d); + + void *q = p < &c ? &c < &d ? &d : &c : p; + return q; +} + +NOIPA void* test_min_2 (void) +{ + char c; + + char *p = get_min_2 (&c); + + void *q = p < &c ? p : &c; /* MIN_EXPR" */ + return q; +} + +NOIPA void* test_min_3 (void) +{ + char c; + char d; + + char *p = get_min_3 (&c, &d); + + void *q = p > &c ? &c > &d ? &d : &c : p; + return q; +} + +NOIPA void* test_min_3_phi (int i) +{ + char a, b; + + char *p0 = &a; + char *p1 = &b; + char *p2 = get_min_3 (&a, &b); + char *p3 = get_min_3 (&a, &b); + + char *p4 = p2 < p0 ? p2 : p0; + char *p5 = p3 < p1 ? p3 : p1; + + __builtin_printf ("%p %p %p %p\n", p2, p3, p4, p5); + + if (i == 1) + return p4; + else + return p5; +} + +int main () +{ + A (0 != test_max_2 ()); + A (0 != test_max_3 ()); + + A (0 != test_min_2 ()); + A (0 != test_min_3 ()); + + A (0 != test_min_3_phi (0)); +} diff --git a/gcc/testsuite/gcc.dg/Walloca-4.c b/gcc/testsuite/gcc.dg/Walloca-4.c index 85dcb7b..1fbed59 100644 --- a/gcc/testsuite/gcc.dg/Walloca-4.c +++ b/gcc/testsuite/gcc.dg/Walloca-4.c @@ -7,11 +7,12 @@ { char *src; - _Bool - use_alloca = (((rear_ptr - w) * sizeof (char)) < 4096U); - if (use_alloca) + _Bool use_alloca = (((rear_ptr - w) * sizeof (char)) < 4096U); + if (use_alloca) src = (char *) __builtin_alloca ((rear_ptr - w) * sizeof (char)); else src = (char *) __builtin_malloc ((rear_ptr - w) * sizeof (char)); return src; } + +/* { dg-prune-output "-Wreturn-local-addr" } */ diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c new file mode 100644 index 0000000..ddd2c36 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-10.c @@ -0,0 +1,56 @@ +/* PR c/71924 - missing -Wreturn-local-addr returning alloca result + Test reduced from libstdc++-v3/testsuite/ext/ext_pointer/1.cc. + It verifies that iteration in find_implicit_erroneous_behavior + in gimple-ssa-isolate-path.c terminates under specific conditions. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __UINTPTR_TYPE__ uintptr_t; + +struct A { int i; }; +struct P { uintptr_t d; }; + +static inline struct A* get (const struct P *p) +{ + if (p->d == 1) + return 0; + + return (struct A*)((uintptr_t)p + p->d); +} + +static inline void set (struct P *p, struct A* q) +{ + /* The basic block below would cause an infinite loop in + find_implicit_erroneous_behavior due to assuming the DUPLICATE + pointer returned from isolate_path would distinct from the one + passed to it. (Replacing the if statement with the ternary ?: + expression did not have this effect (it gets optimized early + on). + [local count: 1073741823]: + # _14 = PHI <0B(2), &MEM [(void *)&a + 4B](3)> + _2 = _14->i; + if (_2 != 2) + goto ; [0.00%] + else + goto ; [100.00%] + */ + if (!q) + p->d = 1; + else + p->d = (uintptr_t)(q) - (uintptr_t)(p); +} + +void f (void) +{ + struct A a[2] = { { 1 }, { 2 } }; + + struct P p, q; + set (&p, a); + set (&q, get (&p)); + + set (&q, get (&q) + 0); + set (&q, get (&q) + 1); + + if (get (&q)[0].i != get (&p)[1].i) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c new file mode 100644 index 0000000..0e3435c --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-2.c @@ -0,0 +1,293 @@ +/* PR c/71924 - missing -Wreturn-local-addr returning alloca result + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define ATTR(...) __attribute__ ((__VA_ARGS__)) + +struct A { int a, b, c; }; +struct B { int a, b, c[]; }; + +void sink (void*, ...); + +ATTR (noipa) void* +return_alloca (int n) +{ + void *p = __builtin_alloca (n); + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_index_cst (int n) +{ + int *p = (int*)__builtin_alloca (n); + p = &p[1]; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_plus_cst (int n) +{ + int *p = (int*)__builtin_alloca (n); + p += 1; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_plus_var (int n, int i) +{ + char *p = (char*)__builtin_alloca (n); + p += i; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_member_1 (int n) +{ + struct A *p = (struct A*)__builtin_alloca (n); + sink (&p->a); + return &p->a; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_member_2 (int n) +{ + struct A *p = (struct A*)__builtin_alloca (n); + sink (&p->b); + return &p->b; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_flexarray (int n) +{ + struct B *p = (struct B*)__builtin_alloca (n); + sink (p->c); + return p->c; /* { dg-warning "function returns address of local" } */ +} + + +ATTR (noipa) void* +return_array (void) +{ + int a[32]; + void *p = a; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_array_index_cst (void) +{ + int a[32]; + void *p = &a[2]; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_array_plus_cst (void) +{ + int a[32]; + void *p = a + 2; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_array_plus_var (int i) +{ + int a[32]; + void *p = a + i; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_array_member_1 (void) +{ + struct A a[2]; + int *p = &a[1].a; + sink (a, p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_array_member_2 (void) +{ + struct A a[32]; + int *p = &a[1].b; + sink (a, p); + return p; /* { dg-warning "function returns address of local" } */ +} + + +ATTR (noipa) void* +return_vla (int n) +{ + char a[n]; + void *p = a; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_vla_index_cst (int n) +{ + char a[n]; + char *p = &a[3]; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_vla_plus_cst (int n) +{ + char a[n]; + char *p = a + 3; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_vla_index_var (int n, int i) +{ + char a[n]; + char *p = &a[i]; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_vla_plus_var (int n, int i) +{ + char a[n]; + char *p = a + i; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_vla_member_1 (int n, int i) +{ + struct A a[n]; + void *p = &a[i].a; + sink (a, p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_vla_member_2 (int n, int i) +{ + struct A a[n]; + void *p = &a[i].b; + sink (a, p); + return p; /* { dg-warning "function returns address of local" } */ +} + + +ATTR (noipa) void* +return_alloca_or_alloca (int n, int i) +{ + void *p = i ? __builtin_alloca (n * i) : __builtin_alloca (n); + sink (p); + /* The warning here should really be "function returns". */ + return p; /* { dg-warning "function (returns|may return) address of local" } */ +} + +ATTR (noipa) void* +return_alloca_or_alloca_2 (int n, int i) +{ + void *p0 = __builtin_alloca (n); + void *p1 = __builtin_alloca (n * 2); + void *p = i ? p0 : p1; + sink (p0, p1, p); + /* Same as above. */ + return p; /* { dg-warning "function (returns|may return) address of local" } */ +} + +ATTR (noipa) void* +return_array_or_array (int i) +{ + int a[5]; + int b[7]; + void *p = i ? a : b; + sink (a, b, p); + /* The warning here should really be "function returns". */ + return p; /* { dg-warning "function (returns|may return) address of local" } */ +} + +ATTR (noipa) void* +return_array_or_array_plus_var (int i, int j) +{ + int a[5]; + int b[7]; + + void *p0 = a + i; + void *p1 = b + j; + + void *p = i < j ? p0 : p1; + sink (a, b, p0, p1, p); + /* The warning here should really be "function returns". */ + return p; /* { dg-warning "function (returns|may return) address of local" } */ +} + +extern int global[32]; + +ATTR (noipa) void* +may_return_global_or_alloca (int n, int i) +{ + void *p = i ? global : __builtin_alloca (n); + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + + +ATTR (noipa) void* +may_return_global_or_alloca_plus_cst (int n, int i) +{ + int *p = i ? global : (int*)__builtin_alloca (n); + p += 7; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +may_return_global_or_array (int n, int i) +{ + int a[32]; + void *p = i ? global : a; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +may_return_global_or_array_plus_cst (int n, int i) +{ + int a[32]; + int *p = i ? global : a; + p += 4; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +may_return_global_or_vla (int n, int i) +{ + int a[n]; + void *p = i ? global : a; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +may_return_global_or_vla_plus_cst (int n, int i) +{ + int a[n]; + int *p = i ? global : a; + p += 4; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c new file mode 100644 index 0000000..6dad7af --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-3.c @@ -0,0 +1,248 @@ +/* PR c/71924 - missing -Wreturn-local-addr returning alloca result + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define ATTR(...) __attribute__ ((__VA_ARGS__)) + +typedef __INTPTR_TYPE__ intptr_t; + +struct A { int a, b, c; }; +struct B { int a, b, c[]; }; + +extern int g1[5], g2[5], g3[5], g4[5], g5[5]; + +void sink (void*, ...); + +/* Verify that a pointer difference expression is handled correctly + even when converted to a pointer. */ + +ATTR (noipa) void* +return_local_diff_cst (void) +{ + int a[5]; + void *p = (void*)(&a[4] - &a[1]); + return p; +} + +ATTR (noipa) void* +return_local_diff_var (int i, int j) +{ + int a[5]; + void *p = (void*)(&a[j] - &a[i]); + return p; +} + +ATTR (noipa) void* +return_2_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + void *p = i < 0 ? a : b; + return p; /* { dg-warning "function returns address of local" } */ +} + +/* Verify that returning the address of a local converted to intptr_t + is not diagnosed (see bug 90737 for a case the front-end gets wrong). */ + +ATTR (noipa) intptr_t +return_int_2_locals (int i) +{ + int a[1]; + int b[2]; + void *p = i < 0 ? a : b; + return (intptr_t)p; +} + +/* Verify that a conditional expression with a pointer first operand + is handled correctly. */ + +ATTR (noipa) void* +return_2_locals_ptrcond (void *q) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + void *p = q ? a : b; + return p; /* { dg-warning "function returns address of local" } */ +} + +/* Verify that a preincrement expression with a pointer operand is + handled correctly. */ + +ATTR (noipa) void* +return_2_locals_ptrinc (void *q) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int *p = q ? a : b; + return ++p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_3_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + + void *p = i < 0 ? a : 0 < i ? c : b; + return p; /* { dg-warning "function returns address of local" } */ +} + +/* Verify that a conditional expression with a pointer first operand + is handled correctly. */ + +ATTR (noipa) void* +return_3_locals_ptrcond (void *p, void *q) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + + void *r = q ? r ? a : b : c; + return r; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_5_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + int d[4]; /* { dg-message "declared here" } */ + int e[5]; /* { dg-message "declared here" } */ + + void *p = i < -1 ? a : i < 0 ? b : 1 < i ? e : 0 < i ? d : c; + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_1_global_4_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + int d[4]; /* { dg-message "declared here" } */ + + void *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? d : c; + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_2_globals_3_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + + void *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : c; + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_3_globals_2_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + void *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : g3; + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_4_globals_1_local (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + + void *p = i < -1 ? a : i < 0 ? g1 : 1 < i ? g2 : 0 < i ? g4 : g3; + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_all_globals (int i) +{ + void *p = i < -1 ? g1 : i < 0 ? g2 : 1 < i ? g3 : 0 < i ? g5 : g4; + return p; +} + + +ATTR (noipa) void* +return_2_alloca_local_cstoff (int n, int i) +{ + int *a = __builtin_alloca (n); /* { dg-message "declared here" } */ + int *b = __builtin_alloca (n); /* { dg-message "declared here" } */ + int *p = i < 0 ? a : b; + p += 1; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_local_cstoff (int n, int i) +{ + int *a = __builtin_alloca (n); /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int *p = i < 0 ? a : b; + p += 1; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_local_alloca_cstoff (int n, int i) +{ + int a[2]; /* { dg-message "declared here" } */ + int *b = __builtin_alloca (n); /* { dg-message "declared here" } */ + int *p = i < 0 ? a : b; + p += 1; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_2_locals_cstoff (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int *p = i < 0 ? a : b; + p += 1; + sink (p); + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_2_globals_3_locals_cstoff (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + + int *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : c; + p += 1; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_3_globals_alloca_local_varoff (int n, int i, int j) +{ + int *a = __builtin_alloca (n); /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + int *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : g3; + p += j; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_3_globals_2_locals_varoff (int i, int j) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + int *p = i < -1 ? a : i < 0 ? b : 1 < i ? g1 : 0 < i ? g2 : g3; + p += j; + sink (p); + return p; /* { dg-warning "function may return address of local" } */ +} + diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c new file mode 100644 index 0000000..0a451ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-4.c @@ -0,0 +1,370 @@ +/* PR c/71924 - missing -Wreturn-local-addr returning alloca result + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +#define ATTR(...) __attribute__ ((__VA_ARGS__)) + +struct A { int a, b, c; }; +struct B { int a, b, c[]; }; + +extern int g1[5], g2[5], g3[5], g4[5], g5[5]; + +void sink (void*, ...); + +ATTR (noipa) void* +return_2_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + void *p = b; + if (i < 0) + p = a; + + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_2_locals_after_2_globals (int i, int j) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + int *p; + if (i < 0) + p = g1; + else + p = g2; + + sink (p); + + if (j < 0) + p = a; + else + p = b; + + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_3_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + + void *p = b + 1; + if (i < 0) + p = a; + else if (0 < i) + p = c + 2; + + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_5_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + int d[4]; /* { dg-message "declared here" } */ + int e[5]; /* { dg-message "declared here" } */ + + void *p = &c[2]; + if (i < -1) + p = a; + else if (i < 0) + p = &b[1]; + else if (1 < i) + p = &e[4]; + else if (0 < i) + p = &d[3]; + + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_5_locals_switch (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + int d[4]; /* { dg-message "declared here" } */ + int e[5]; /* { dg-message "declared here" } */ + + void *p = 0; + + switch (i) + { + case 0: p = &a[1]; break; + case 1: p = &b[2]; break; + case 2: p = &c[3]; break; + case 3: p = &d[4]; break; + default: p = &e[5]; break; + } + + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_1_global_4_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + int d[4]; /* { dg-message "declared here" } */ + + void *p = c; + if (i < -1) + sink (p = a); + else if (i < 0) + sink (p = b); + else if (1 < i) + sink (p = g1); + else if (0 < i) + sink (p = d); + + sink (p, a, b, c, d); + + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_1_global_4_locals_switch (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + int d[4]; /* { dg-message "declared here" } */ + + void *p = 0; + + switch (i) + { + case 0: p = &a[0]; break; + case 1: p = &b[1]; break; + case 2: p = &c[2]; break; + case 3: p = &d[3]; break; + } + + sink (p); + + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_2_globals_3_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + + void *p = c; + if (i < -1) + p = a; + else if (i < 0) + p = b; + else if (1 < i) + p = g1; + else if (0 < i) + p = g2; + + sink (p); + + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_3_globals_2_locals (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + void *p = g3; + if (i < -1) + p = a; + else if (i < 0) + p = b; + else if (1 < i) + p = g1; + else if (0 < i) + p = g2; + + sink (p); + + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_4_globals_1_local (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + + void *p = g3; + if (i < -1) + p = a; + else if (i < 0) + p = g1; + else if (1 < i) + p = g2; + else if (0 < i) + p = g4; + + sink (p); + + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_all_globals (int i) +{ + void *p = g4; + if (i < -1) + p = g1; + else if (i < 0) + p = g2; + else if (1 < i) + p = g3; + else if (0 < i) + p = g5; + return p; +} + + +ATTR (noipa) void* +return_2_alloca_local_cstoff (int n, int i) +{ + int *a = __builtin_alloca (n); /* { dg-message "declared here" } */ + int *b = __builtin_alloca (n); /* { dg-message "declared here" } */ + int *p = i < 0 ? a : b; + + p += 1; + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_alloca_local_cstoff (int n, int i) +{ + int *a = __builtin_alloca (n); /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + int *p = b; + if (i < 0) + p = a; + + p += 1; + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_local_alloca_cstoff (int n, int i) +{ + int a[2]; /* { dg-message "declared here" } */ + int *b = __builtin_alloca (n); /* { dg-message "declared here" } */ + int *p = b; + if (i < 0) + p = a; + + p += 1; + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_2_locals_cstoff (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + int *p = b; + if (i < 0) + p = a; + + p += 1; + sink (p); + + return p; /* { dg-warning "function returns address of local" } */ +} + +ATTR (noipa) void* +return_2_globals_3_locals_cstoff (int i) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + int c[3]; /* { dg-message "declared here" } */ + + int *p = c; + if (i < -1) + p = a; + else if (i < 0) + p = b; + else if (1 < i) + p = g1; + else if (0 < i) + p = g2; + + p += 1; + sink (p); + + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_3_globals_alloca_local_varoff (int n, int i, int j) +{ + int *a = __builtin_alloca (n); /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + int *p = g3; + if (i < -1) + p = a; + else if (i < 0) + p = b; + else if (1 < i) + p = g1; + else if (0 < i) + p = g2; + + p += j; + sink (p); + + return p; /* { dg-warning "function may return address of local" } */ +} + +ATTR (noipa) void* +return_3_globals_2_locals_varoff (int i, int j) +{ + int a[1]; /* { dg-message "declared here" } */ + int b[2]; /* { dg-message "declared here" } */ + + int *p = g3; + if (i < -1) + p = a; + else if (i < 0) + p = b; + else if (1 < i) + p = g1; + else if (0 < i) + p = g2; + + p += j; + sink (p); + + return p; /* { dg-warning "function may return address of local" } */ +} + diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-5.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-5.c new file mode 100644 index 0000000..bdf1cd4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-5.c @@ -0,0 +1,40 @@ +/* PR c/71924 - missing -Wreturn-local-addr returning alloca result + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +void sink (void*); + +void* loop_idx (int x) +{ + char a[32]; /* { dg-message "declared here" } */ + char *p = a; + + sink (a); + + int i; + for (i = 0; i != 32; ++i) + if (p[i] == x) + break; + + p = i < 32 ? &p[i] : 0; + return p; /* { dg-warning "may return address of local variable" } */ +} + + +void* loop_ptr (int i, int x) +{ + char a[32]; /* { dg-message "declared here" } */ + char *p; + + sink (a); + + /* The warning for the statement below would ideally be a "returns" + because it definitely returns the address of a, but when both + returns get merged into one we end up with a "may return". */ + for (p = a; *p; ++p) + if (*p == x) + return p; /* { dg-warning "(returns|may return) address of local variable" "missing location" { xfail *-*-* } } */ + /* { dg-warning "(returns|may return) address of local variable" "pr90735" { target *-*-* } 0 } */ + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c new file mode 100644 index 0000000..70138b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-6.c @@ -0,0 +1,203 @@ +/* PR c/71924 - missing -Wreturn-local-addr returning alloca result + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +void* memcpy (void*, const void*, size_t); +void* mempcpy (void*, const void*, size_t); +void* memmove (void*, const void*, size_t); + +char* stpcpy (char*, const char*); +char* stpncpy (char*, const char*, size_t); + +size_t strlen (const char*); +size_t strnlen (const char*, size_t); + +char* strcat (char*, const char*); +char* strncat (char*, const char*, size_t); + +char* strcpy (char*, const char*); +char* strncpy (char*, const char*, size_t); + +char* strdup (const char*); + +char* strchr (const char*, int); +char* strrchr (const char*, int); +char* strstr (const char*, const char*); + +void sink (void*, ...); + + +void* return_memcpy (const void *s, unsigned n) +{ + char a[n]; /* { dg-message "declared here" } */ + void *p = memcpy (a, s, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +void* return_memcpy_cst (const void *s, unsigned n) +{ + char a[n]; /* { dg-message "declared here" } */ + void *p = memcpy (a + 1, s, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +void* return_memcpy_var (const void *s, unsigned n, int i) +{ + char a[n]; /* { dg-message "declared here" } */ + void *p = memcpy (a + i, s, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +void* return_mempcpy (const void *s, unsigned n) +{ + char a[n]; /* { dg-message "declared here" } */ + void *p = mempcpy (a, s, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +void* return_memmove_cst (unsigned n) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + void *p = memmove (a + 1, a, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +void* return_memmove_var (unsigned n, int i) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + void *p = memmove (a + i, a, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_stpcpy (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + char *p = stpcpy (a, s); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_stpncpy (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + char *p = stpncpy (a, s, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strcat (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + char *p = strcat (a, s); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strncat (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + char *p = strncat (a, s, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ + +} +char* return_strcpy (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + char *p = strcpy (a, s); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strcpy_plus_strlen (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + char *p = strcpy (a, s); + sink (p); + p += strlen (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strcpy_cst_plus_strlen (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + char *p = strcpy (a + 1, s); + sink (p); + p += strlen (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strcpy_var_plus_strlen (unsigned n, const char *s, int i) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + char *p = strcpy (a + i, s); + sink (p); + p += strlen (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strncpy (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + char *p = strncpy (a, s, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strncpy_plus_strnlen (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + char *p = strncpy (a, s, n); + p += strnlen (p, n); + sink (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strdup (unsigned n) +{ + char a[n]; + sink (a); + char *p = strdup (a); + return p; +} + +char* return_strchr (unsigned n, int c) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + char *p = strchr (a, c); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strstr (unsigned n, const char *s) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + char *p = strstr (a, s); + if (p) + p += strlen (p); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ +} + +char* return_strrchr (unsigned n, int c) +{ + char a[n]; /* { dg-message "declared here" } */ + sink (a); + char *p = strrchr (a, c); + return p; /* { dg-warning "\\\[-Wreturn-local-addr]" } */ + +} diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-7.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-7.c new file mode 100644 index 0000000..ac1fb76 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-7.c @@ -0,0 +1,50 @@ +/* Test to verify that a PHI with a COND_EXPR argument in a return + statement is handled correctly. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +extern struct S s; + +void* f (int n) +{ + void *p; + int x = 0; + + for (int i = n; i >= 0; i--) + { + p = &s; + if (p == (void*)-1) + x = 1; + else if (p) + return p; + } + + /* The return statement below ends up with the following IL: + [local count: 59055800]: + # x_10 = PHI <1(5), 0(2)> + _5 = x_10 != 0 ? -1B : 0B; + + [local count: 114863532]: + # _3 = PHI <&s(4), _5(6), &s(3)> + return _3; */ + return x ? (void*)-1 : 0; +} + +void* g (int n) +{ + void *p; + int x = 0; /* { dg-message "declared here" } */ + + for (int i = n; i >= 0; i--) + { + p = &s; + if (p == (void*)-1) + x = 1; + else if (p) + return p; + } + + /* The return statement below does not reference a COND_EXPR argument. */ + return x ? &x : 0; /* { dg-warning "may return address of local variable" "missing location" { xfail *-*-* } } */ + /* { dg-warning "may return address of local variable" "pr90735" { target *-*-* } 0 } */ +} diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-8.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-8.c new file mode 100644 index 0000000..98a3805 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-8.c @@ -0,0 +1,88 @@ +/* Test to verify that a MAX_EXPR and MIN_EXPR in a return statement + is handled correctly and that all local variables whose address + is or may be returned are identified. + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +char* sink (char*, ...); + +void* test_max_2 (void) +{ + char c; /* { dg-message "declared here" } */ + + char *p = sink (&c); + + void *q = p > &c ? p : &c; /* MAX_EXPR */ + return q; /* { dg-warning "\\\[-Wreturn-local-addr" } */ +} + +void* test_max_3 (void) +{ + char c; /* { dg-message "declared here" } */ + char d; /* { dg-message "declared here" } */ + + char *p = sink (&c, &d); + + void *q = p < &c ? &c < &d ? &d : &c : p; + return q; /* { dg-warning "\\\[-Wreturn-local-addr" } */ +} + +void* test_min_2 (void) +{ + char c; /* { dg-message "declared here" } */ + + char *p = sink (&c); + + void *q = p < &c ? p : &c; /* MIN_EXPR" */ + return q; /* { dg-warning "\\\[-Wreturn-local-addr" } */ +} + +void* test_min_3 (void) +{ + char c; /* { dg-message "declared here" } */ + char d; /* { dg-message "declared here" } */ + + char *p = sink (&c, &d); + + void *q = p > &c ? &c > &d ? &d : &c : p; + return q; /* { dg-warning "\\\[-Wreturn-local-addr" } */ +} + +void* test_min_2_phi (int i) +{ + char a; /* { dg-message "declared here" } */ + + char *p = &a; + char *q = sink (&a); + p = p < q ? p : q; + if (i == 1) + return p; + /* { dg-warning "may return address of local variable" "missing location" { xfail *-*-* } } */ + else + return q; +} + +void* test_min_3_phi (int i) +{ + char a; /* { dg-message "declared here" } */ + char b; /* { dg-message "declared here" } */ + + char *p0 = &a; + char *p1 = &b; + char *p2 = sink (&a, &b); + char *p3 = sink (&a, &b); + + char *p4 = p2 < p0 ? p2 : p0; + char *p5 = p3 < p1 ? p3 : p1; + + if (i == 1) + /* { dg-warning "may return address of local variable" "missing location" { xfail *-*-* } } */ + return p4; + else + /* { dg-warning "may return address of local variable" "missing location" { xfail *-*-* } } */ + return p5; +} + +/* The directive below "swallows" warnings for both test_min_2_phi + and test_min_3_phi. + { dg-warning "may return address of local variable" "pr90735" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr-9.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr-9.c new file mode 100644 index 0000000..d24f911 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr-9.c @@ -0,0 +1,73 @@ +/* PR c/71924 - missing -Wreturn-local-addr returning alloca result + Test derived from gcc.c-torture/execute/20071108-1.c. It shows + a false positive at -Os caused by the jump threading/vrp1 pass. + { dg-do compile } + { dg-options "-Os -fdump-tree-optimized" } */ + +struct S +{ + int i; +}; + +void* f (void); + +__attribute__ ((noinline)) +struct S* g (int i) +{ + struct S *p = f (), q; + + if (p == 0) + p = &q; + + p->i = i; + + if (p == &q) + p = 0; + + /* With -Os the warning pass sees: + + ... + + # p_1 = PHI <&q(2), p_5(3)> + p_1->i = i_6(D); + if (&q == p_1) + goto ; [14.90%] + else + goto ; [85.10%] + + + + + # p_2 = PHI <0B(4), p_1(5)> + q ={v} {CLOBBER}; + return p_2; + } + + which leads to: */ + return p; /* { dg-bogus "may return address of local variable" "" { xfail *-*-* } } */ + + /* Whereas as -O2 the pass sees: + + + p_5 = f (); + if (p_5 == 0B) + goto ; [30.00%] + else + goto ; [70.00%] + + + # p_2 = PHI <0B(5), p_5(4)> + q ={v} {CLOBBER}; + return p_2; + + + p_5->i = i_6(D); + goto ; [100.00%] + + + q.i = i_6(D); + goto ; [100.00%] + } + + and no warning. */ +} diff --git a/gcc/testsuite/gcc.dg/pr41551.c b/gcc/testsuite/gcc.dg/pr41551.c index 2f2ad2b..e112320 100644 --- a/gcc/testsuite/gcc.dg/pr41551.c +++ b/gcc/testsuite/gcc.dg/pr41551.c @@ -10,3 +10,5 @@ int main(void) int var, *p = &var; return (double)(uintptr_t)(p); } + +/* { dg-prune-output "-Wreturn-local-addr" } */ diff --git a/gcc/testsuite/gcc.dg/pr59523.c b/gcc/testsuite/gcc.dg/pr59523.c index a6c3302..49cbe5d 100644 --- a/gcc/testsuite/gcc.dg/pr59523.c +++ b/gcc/testsuite/gcc.dg/pr59523.c @@ -16,3 +16,5 @@ foo (int a, int *b, int *c, int *d) r[i] = 1; return r; } + +/* { dg-prune-output "-Wreturn-local-addr" } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c index 2fb0e0c..c913d26 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c @@ -12,7 +12,7 @@ int *foo (int bogus, int n) p = &a[2]; else p = &i; - return p; + return p; /* { dg-warning "\\\[-Wreturn-local-addr" } */ } /* { dg-final { scan-tree-dump "Deleted dead store" "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c index 292ce6e..ed5df82 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c @@ -41,3 +41,5 @@ f5 (void) int c[64] = {}, d[64] = {}; return (__UINTPTR_TYPE__) &c[64] != (__UINTPTR_TYPE__) &d[0]; } + +/* { dg-prune-output "-Wreturn-local-addr" } */ diff --git a/gcc/testsuite/gcc.dg/winline-7.c b/gcc/testsuite/gcc.dg/winline-7.c index 34deca4..239d748 100644 --- a/gcc/testsuite/gcc.dg/winline-7.c +++ b/gcc/testsuite/gcc.dg/winline-7.c @@ -13,3 +13,5 @@ inline void *t (void) { return q (); /* { dg-message "called from here" } */ } + +/* { dg-prune-output "-Wreturn-local-addr" } */ -- cgit v1.1 From 64865fe0f97de642327c673090e2e0d051bb3ec3 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Tue, 9 Jul 2019 09:41:19 +0200 Subject: Enhance documentation of -fprofile-note option. 2019-07-09 Martin Liska * doc/invoke.texi: Add link from -fprofile-dir option. Use better wording for 'gcno filename'. From-SVN: r273262 --- gcc/ChangeLog | 5 +++++ gcc/doc/invoke.texi | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a6c99ac..1b7bfb6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Martin Liska + + * doc/invoke.texi: Add link from -fprofile-dir option. + Use better wording for 'gcno filename'. + 2019-07-08 Martin Sebor PR middle-end/71924 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7654c9b..0c20cb6 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -12376,7 +12376,7 @@ profile data file appears in the same directory as the object file. In order to prevent the file name clashing, if the object file name is not an absolute path, we mangle the absolute path of the @file{@var{sourcename}.gcda} file and use it as the file name of a -@file{.gcda} file. +@file{.gcda} file. See similar option @option{-fprofile-note}. When an executable is run in a massive parallel environment, it is recommended to save profile to different folders. That can be done with variables @@ -12414,7 +12414,9 @@ To optimize the program based on the collected profile information, use @item -fprofile-note=@var{path} @opindex fprofile-note -If @var{path} is specified, GCC saves gcno filename into @var{path} location. +If @var{path} is specified, GCC saves @file{.gcno} file into @var{path} +location. If you combine the option with multiple source files, +the @file{.gcno} file will be overwritten. @item -fprofile-update=@var{method} @opindex fprofile-update -- cgit v1.1 From 7a26ff040e7b1d93e364010ac44f4b4797de778c Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Tue, 9 Jul 2019 09:41:39 +0200 Subject: Remove usage of ZSTD_CLEVEL_DEFAULT define. 2019-07-09 Martin Liska * lto-compress.c (lto_normalized_zstd_level): Do not use ZSTD_CLEVEL_DEFAULT as it is not default in old releases of libzstd. One can use 0 as a default compression level. From-SVN: r273263 --- gcc/ChangeLog | 6 ++++++ gcc/lto-compress.c | 11 ++++------- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b7bfb6..a3c7971 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-07-09 Martin Liska + * lto-compress.c (lto_normalized_zstd_level): Do not use + ZSTD_CLEVEL_DEFAULT as it is not default in old releases + of libzstd. One can use 0 as a default compression level. + +2019-07-09 Martin Liska + * doc/invoke.texi: Add link from -fprofile-dir option. Use better wording for 'gcno filename'. diff --git a/gcc/lto-compress.c b/gcc/lto-compress.c index b925363..c5c37db 100644 --- a/gcc/lto-compress.c +++ b/gcc/lto-compress.c @@ -115,13 +115,10 @@ lto_normalized_zstd_level (void) { int level = flag_lto_compression_level; - if (level != ZSTD_CLEVEL_DEFAULT) - { - if (level < 1) - level = 1; - else if (level > ZSTD_maxCLevel ()) - level = ZSTD_maxCLevel (); - } + if (level < 0) + level = 0; + else if (level > ZSTD_maxCLevel ()) + level = ZSTD_maxCLevel (); return level; } -- cgit v1.1 From 0cb51ac7fb5f28e069cc2a6094a6c0188b1aa02e Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Tue, 9 Jul 2019 07:53:11 +0000 Subject: [Ada] Update -fdump-ada-spec documentation 2019-07-09 Arnaud Charlet gcc/ada/ * doc/gnat_ugn/the_gnat_compilation_model.rst: Update doc on -fdump-ada-spec now that we generate Ada 2012. * gnat_ugn.texi: Regenerate. From-SVN: r273264 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst | 7 ++++--- gcc/ada/gnat_ugn.texi | 7 ++++--- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 09defe0..a7796cb 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Arnaud Charlet + + * doc/gnat_ugn/the_gnat_compilation_model.rst: Update doc on + -fdump-ada-spec now that we generate Ada 2012. + * gnat_ugn.texi: Regenerate. + 2019-07-08 Eric Botcazou * repinfo.adb (List_Common_Type_Info): New procedure extracted diff --git a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst index 48fedfe..d7388bb 100644 --- a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst +++ b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst @@ -4531,8 +4531,9 @@ Some of the known limitations include: * identifiers with identical name (except casing) will generate compilation errors (e.g. ``shm_get`` vs ``SHM_GET``). -The code generated is using the Ada 2005 syntax, which makes it -easier to interface with other languages than previous versions of Ada. +The code is generated using Ada 2012 syntax, which makes it easier to interface +with other languages. In most cases you can still use the generated binding +even if your code is compiled using earlier versions of Ada (e.g. ``-gnat95``). .. _Running_the_binding_generator: @@ -4547,7 +4548,7 @@ header files needed by these files transitively. For example: .. code-block:: sh $ g++ -c -fdump-ada-spec -C /usr/include/time.h - $ gcc -c -gnat05 *.ads + $ gcc -c *.ads will generate, under GNU/Linux, the following files: :file:`time_h.ads`, :file:`bits_time_h.ads`, :file:`stddef_h.ads`, :file:`bits_types_h.ads` which diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 5ace5cf..3f99340 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -6646,8 +6646,9 @@ identifiers with identical name (except casing) will generate compilation errors (e.g. @code{shm_get} vs @code{SHM_GET}). @end itemize -The code generated is using the Ada 2005 syntax, which makes it -easier to interface with other languages than previous versions of Ada. +The code is generated using Ada 2012 syntax, which makes it easier to interface +with other languages. In most cases you can still use the generated binding +even if your code is compiled using earlier versions of Ada (e.g. @code{-gnat95}). @menu * Running the Binding Generator:: @@ -6668,7 +6669,7 @@ header files needed by these files transitively. For example: @example $ g++ -c -fdump-ada-spec -C /usr/include/time.h -$ gcc -c -gnat05 *.ads +$ gcc -c *.ads @end example will generate, under GNU/Linux, the following files: @code{time_h.ads}, -- cgit v1.1 From b5d3d113ca9c67320ed06b65c50e8e46e22b6198 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 9 Jul 2019 07:53:16 +0000 Subject: [Ada] Make -gnatRj output strictly conforming JSON This changes the -gnatRj output from a concatenation of entities to an array of entities, thus making it strictly conforming JSON and easier to be parsed by means of GNATColl or Python. 2019-07-09 Eric Botcazou gcc/ada/ * repinfo.ads (JSON format): Adjust. * repinfo.adb (Need_Blank_Line): Rename to... (Need_Separator): ...this. (Blank_Line): Rename to... (Write_Separator): ...this and add JSON specific handling. (List_Array_Info): Adjust to above renaming. (List_Object_Info): Likewise. (List_Record_Info): Likewise. (List_Subprogram_Info): Likewise. (List_Type_Info): Likewise. (List_Entities): Do not set Need_Blank_Line. (List_Rep_Info): Set Need_Separator and add JSON specific handling. Output a single JSON stream in the normal case. From-SVN: r273265 --- gcc/ada/ChangeLog | 16 +++++++++++ gcc/ada/repinfo.adb | 80 ++++++++++++++++++++++++++++++++++------------------- gcc/ada/repinfo.ads | 2 +- 3 files changed, 69 insertions(+), 29 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a7796cb..02dc4ad 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,19 @@ +2019-07-09 Eric Botcazou + + * repinfo.ads (JSON format): Adjust. + * repinfo.adb (Need_Blank_Line): Rename to... + (Need_Separator): ...this. + (Blank_Line): Rename to... + (Write_Separator): ...this and add JSON specific handling. + (List_Array_Info): Adjust to above renaming. + (List_Object_Info): Likewise. + (List_Record_Info): Likewise. + (List_Subprogram_Info): Likewise. + (List_Type_Info): Likewise. + (List_Entities): Do not set Need_Blank_Line. + (List_Rep_Info): Set Need_Separator and add JSON specific + handling. Output a single JSON stream in the normal case. + 2019-07-09 Arnaud Charlet * doc/gnat_ugn/the_gnat_compilation_model.rst: Update doc on diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index ff147ac..75da2b6 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -115,10 +115,9 @@ package body Repinfo is -- Identifier casing for current unit. This is set by List_Rep_Info for -- each unit, before calling subprograms which may read it. - Need_Blank_Line : Boolean; - -- Set True if a blank line is needed before outputting any information for - -- the current entity. Set True when a new entity is processed, and false - -- when the blank line is output. + Need_Separator : Boolean; + -- Set True if a separator is needed before outputting any information for + -- the current entity. ------------------------------ -- Set of Relevant Entities -- @@ -151,10 +150,6 @@ package body Repinfo is -- is used rather than checking the configuration parameter because we do -- not want Repinfo to depend on Targparm (for ASIS) - procedure Blank_Line; - -- Called before outputting anything for an entity. Ensures that - -- a blank line precedes the output for a particular entity. - procedure List_Entities (Ent : Entity_Id; Bytes_Big_Endian : Boolean; @@ -217,6 +212,10 @@ package body Repinfo is procedure Write_Mechanism (M : Mechanism_Type); -- Writes symbolic string for mechanism represented by M + procedure Write_Separator; + -- Called before outputting anything for an entity. Ensures that + -- a separator precedes the output for a particular entity. + procedure Write_Unknown_Val; -- Writes symbolic string for an unknown or non-representable value @@ -238,18 +237,6 @@ package body Repinfo is return Rep_Table.Last > 0; end Back_End_Layout; - ---------------- - -- Blank_Line -- - ---------------- - - procedure Blank_Line is - begin - if Need_Blank_Line then - Write_Eol; - Need_Blank_Line := False; - end if; - end Blank_Line; - ------------------------ -- Create_Discrim_Ref -- ------------------------ @@ -342,7 +329,7 @@ package body Repinfo is procedure List_Array_Info (Ent : Entity_Id; Bytes_Big_Endian : Boolean) is begin - Blank_Line; + Write_Separator; if List_Representation_Info_To_JSON then Write_Line ("{"); @@ -504,14 +491,11 @@ package body Repinfo is or else Ekind (Ent) = E_Entry_Family) and then not In_Subprogram then - Need_Blank_Line := True; List_Subprogram_Info (Ent); end if; E := First_Entity (Ent); while Present (E) loop - Need_Blank_Line := True; - -- We list entities that come from source (excluding private or -- incomplete types or deferred constants, for which we will list -- the information for the full view). If requested, we also list @@ -939,7 +923,7 @@ package body Repinfo is procedure List_Object_Info (Ent : Entity_Id) is begin - Blank_Line; + Write_Separator; if List_Representation_Info_To_JSON then Write_Line ("{"); @@ -1621,7 +1605,7 @@ package body Repinfo is -- Start of processing for List_Record_Info begin - Blank_Line; + Write_Separator; if List_Representation_Info_To_JSON then Write_Line ("{"); @@ -1694,6 +1678,15 @@ package body Repinfo is if List_Representation_Info /= 0 or else List_Representation_Info_Mechanisms then + -- For the normal case, we output a single JSON stream + + if not List_Representation_Info_To_File + and then List_Representation_Info_To_JSON + then + Write_Line ("["); + Need_Separator := False; + end if; + for U in Main_Unit .. Last_Unit loop if In_Extended_Main_Source_Unit (Cunit_Entity (U)) then Unit_Casing := Identifier_Casing (Source_Index (U)); @@ -1717,6 +1710,7 @@ package body Repinfo is end loop; Write_Eol; + Need_Separator := True; end if; List_Entities (Cunit_Entity (U), Bytes_Big_Endian); @@ -1727,12 +1721,25 @@ package body Repinfo is Create_Repinfo_File_Access.all (Get_Name_String (File_Name (Source_Index (U)))); Set_Special_Output (Write_Info_Line'Access); + if List_Representation_Info_To_JSON then + Write_Line ("["); + end if; + Need_Separator := False; List_Entities (Cunit_Entity (U), Bytes_Big_Endian); + if List_Representation_Info_To_JSON then + Write_Line ("]"); + end if; Cancel_Special_Output; Close_Repinfo_File_Access.all; end if; end if; end loop; + + if not List_Representation_Info_To_File + and then List_Representation_Info_To_JSON + then + Write_Line ("]"); + end if; end if; end List_Rep_Info; @@ -1821,7 +1828,7 @@ package body Repinfo is Form : Entity_Id; begin - Blank_Line; + Write_Separator; if List_Representation_Info_To_JSON then Write_Line ("{"); @@ -1999,7 +2006,7 @@ package body Repinfo is procedure List_Type_Info (Ent : Entity_Id) is begin - Blank_Line; + Write_Separator; if List_Representation_Info_To_JSON then Write_Line ("{"); @@ -2335,6 +2342,23 @@ package body Repinfo is end case; end Write_Mechanism; + --------------------- + -- Write_Separator -- + --------------------- + + procedure Write_Separator is + begin + if Need_Separator then + if List_Representation_Info_To_JSON then + Write_Line (","); + else + Write_Eol; + end if; + else + Need_Separator := True; + end if; + end Write_Separator; + ----------------------- -- Write_Unknown_Val -- ----------------------- diff --git a/gcc/ada/repinfo.ads b/gcc/ada/repinfo.ads index c013721..c51948e 100644 --- a/gcc/ada/repinfo.ads +++ b/gcc/ada/repinfo.ads @@ -193,7 +193,7 @@ package Repinfo is -- following description, the terminology is that of the JSON syntax -- from the ECMA document and of the JSON grammar from www.json.org. - -- The output is a concatenation of entities + -- The output is an array of entities -- An entity is an object whose members are pairs taken from: -- cgit v1.1 From e0201d823abfcbc3acadc1f78a0c94fdc8474dfe Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 9 Jul 2019 07:53:21 +0000 Subject: [Ada] Fix ownership checking for pointers in SPARK Checking of the readable status of sub-expressions occurring in the target path of an assignment should occur before the right-hand-side is moved or borrowed or observed. There is no impact on compilation. 2019-07-09 Yannick Moy gcc/ada/ * sem_spark.adb (Check_Expression): Change signature to take an Extended_Checking_Mode, for handling read permission checking of sub-expressions in an assignment. (Check_Parameter_Or_Global): Adapt to new behavior of Check_Expression for mode Assign. (Check_Safe_Pointers): Do not analyze generic bodies. (Check_Assignment): Separate checking of the target of an assignment. From-SVN: r273266 --- gcc/ada/ChangeLog | 11 ++++++++ gcc/ada/sem_spark.adb | 74 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 62 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 02dc4ad..9f6b789 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2019-07-09 Yannick Moy + + * sem_spark.adb (Check_Expression): Change signature to take an + Extended_Checking_Mode, for handling read permission checking of + sub-expressions in an assignment. + (Check_Parameter_Or_Global): Adapt to new behavior of + Check_Expression for mode Assign. + (Check_Safe_Pointers): Do not analyze generic bodies. + (Check_Assignment): Separate checking of the target of an + assignment. + 2019-07-09 Eric Botcazou * repinfo.ads (JSON format): Adjust. diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index fb46e62..2b19919 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -560,9 +560,13 @@ package body Sem_SPARK is -- has the right permission, and also updating permissions when a path is -- moved, borrowed, or observed. - type Checking_Mode is + type Extended_Checking_Mode is - (Read, + (Read_Subexpr, + -- Special value used for assignment, to check that subexpressions of + -- the assigned path are readable. + + Read, -- Default mode Move, @@ -591,6 +595,8 @@ package body Sem_SPARK is -- and extensions are set to Read_Only. ); + subtype Checking_Mode is Extended_Checking_Mode range Read .. Observe; + type Result_Kind is (Folded, Unfolded); -- The type declaration to discriminate in the Perm_Or_Tree type @@ -631,7 +637,7 @@ package body Sem_SPARK is procedure Check_Declaration (Decl : Node_Id); - procedure Check_Expression (Expr : Node_Id; Mode : Checking_Mode); + procedure Check_Expression (Expr : Node_Id; Mode : Extended_Checking_Mode); pragma Precondition (Nkind_In (Expr, N_Index_Or_Discriminant_Constraint, N_Range_Constraint, N_Subtype_Indication) @@ -1421,8 +1427,10 @@ package body Sem_SPARK is -- Check_Expression -- ---------------------- - procedure Check_Expression (Expr : Node_Id; Mode : Checking_Mode) is - + procedure Check_Expression + (Expr : Node_Id; + Mode : Extended_Checking_Mode) + is -- Local subprograms function Is_Type_Name (Expr : Node_Id) return Boolean; @@ -1543,8 +1551,14 @@ package body Sem_SPARK is return; elsif Is_Path_Expression (Expr) then - Read_Indexes (Expr); - Process_Path (Expr, Mode); + if Mode /= Assign then + Read_Indexes (Expr); + end if; + + if Mode /= Read_Subexpr then + Process_Path (Expr, Mode); + end if; + return; end if; @@ -2511,6 +2525,10 @@ package body Sem_SPARK is Mode := Move; end case; + if Mode = Assign then + Check_Expression (Expr, Read_Subexpr); + end if; + Check_Expression (Expr, Mode); end Check_Parameter_Or_Global; @@ -2618,11 +2636,6 @@ package body Sem_SPARK is Reset (Current_Perm_Env); end Initialize; - -- Local variables - - Prag : Node_Id; - -- SPARK_Mode pragma in application - -- Start of processing for Check_Safe_Pointers begin @@ -2636,20 +2649,28 @@ package body Sem_SPARK is | N_Package_Declaration | N_Subprogram_Body => - Prag := SPARK_Pragma (Defining_Entity (N)); + declare + E : constant Entity_Id := Defining_Entity (N); + Prag : constant Node_Id := SPARK_Pragma (E); + -- SPARK_Mode pragma in application - if Present (Prag) then - if Get_SPARK_Mode_From_Annotation (Prag) = Opt.On then - Check_Node (N); - end if; + begin + if Ekind (Unique_Entity (E)) in Generic_Unit_Kind then + null; - elsif Nkind (N) = N_Package_Body then - Check_List (Declarations (N)); + elsif Present (Prag) then + if Get_SPARK_Mode_From_Annotation (Prag) = Opt.On then + Check_Node (N); + end if; - elsif Nkind (N) = N_Package_Declaration then - Check_List (Private_Declarations (Specification (N))); - Check_List (Visible_Declarations (Specification (N))); - end if; + elsif Nkind (N) = N_Package_Body then + Check_List (Declarations (N)); + + elsif Nkind (N) = N_Package_Declaration then + Check_List (Private_Declarations (Specification (N))); + Check_List (Visible_Declarations (Specification (N))); + end if; + end; when others => null; @@ -2717,7 +2738,14 @@ package body Sem_SPARK is when N_Assignment_Statement => declare Target : constant Node_Id := Name (Stmt); + begin + -- Start with checking that the subexpressions of the target + -- path are readable, before possibly updating the permission + -- of these subexpressions in Check_Assignment. + + Check_Expression (Target, Read_Subexpr); + Check_Assignment (Target => Target, Expr => Expression (Stmt)); -- cgit v1.1 From e5ce97d294608b4918b3809bc461052b58de8993 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 9 Jul 2019 07:53:26 +0000 Subject: [Ada] Issue error on illegal ownership in SPARK Check for declaration of global variables prior to use in the ownership checking for SPARK. There is no impact on compilation. 2019-07-09 Yannick Moy gcc/ada/ * sem_spark.adb (Get_Perm_Or_Tree): Issue an error when encountering unknown global variable. From-SVN: r273267 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_spark.adb | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9f6b789..0fd03b72 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-09 Yannick Moy + * sem_spark.adb (Get_Perm_Or_Tree): Issue an error when + encountering unknown global variable. + +2019-07-09 Yannick Moy + * sem_spark.adb (Check_Expression): Change signature to take an Extended_Checking_Mode, for handling read permission checking of sub-expressions in an assignment. diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 2b19919..6f27d20 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -3270,7 +3270,16 @@ package body Sem_SPARK is C : constant Perm_Tree_Access := Get (Current_Perm_Env, Unique_Entity (Entity (N))); begin - pragma Assert (C /= null); + -- Except during elaboration, the root object should have been + -- declared and entered into the current permission + -- environment. + + if not Inside_Elaboration + and then C = null + then + Illegal_Global_Usage (N); + end if; + return (R => Unfolded, Tree_Access => C); end; -- cgit v1.1 From 9ae497cb69e5a944e29225a402883ad359d5c031 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Tue, 9 Jul 2019 07:53:30 +0000 Subject: [Ada] Set Dynamic_Elaboration_Checks to True in CodePeer mode 2019-07-09 Arnaud Charlet gcc/ada/ * gnat1drv.adb (Adjust_Global_Switches): Set Dynamic_Elaboration_Checks to True in CodePeer mode. From-SVN: r273268 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/gnat1drv.adb | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0fd03b72..1e109c2 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Arnaud Charlet + + * gnat1drv.adb (Adjust_Global_Switches): Set + Dynamic_Elaboration_Checks to True in CodePeer mode. + 2019-07-09 Yannick Moy * sem_spark.adb (Get_Perm_Or_Tree): Issue an error when diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 86d6be2..f0f8de7 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -320,7 +320,12 @@ procedure Gnat1drv is Elaboration_Check => True, others => False); - Dynamic_Elaboration_Checks := False; + -- Need to enable dynamic elaboration checks to disable strict + -- static checking performed by gnatbind. We are at the same time + -- suppressing actual compile time elaboration checks to simplify + -- the generated code. + + Dynamic_Elaboration_Checks := True; -- Set STRICT mode for overflow checks if not set explicitly. This -- prevents suppressing of overflow checks by default, in code down -- cgit v1.1 From 93ba65d54c7d4e5f3dc4612c642a585dc274344e Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Tue, 9 Jul 2019 07:53:35 +0000 Subject: [Ada] Fix scopes for local variables in task/protected bodies No impact on compilation with GCC. 2019-07-09 Ed Schonberg gcc/ada/ * sem_util.adb (Scope_Within_Or_Same): Handle properly task bodies and protected bodies, so that local variables within have their proper scopes after these constructs have been rewritten during expansion. This patch resembles but is not identical to the code in Scope_Within. From-SVN: r273269 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/sem_util.adb | 25 ++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1e109c2..c5fa67f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-09 Ed Schonberg + + * sem_util.adb (Scope_Within_Or_Same): Handle properly task + bodies and protected bodies, so that local variables within have + their proper scopes after these constructs have been rewritten + during expansion. This patch resembles but is not identical to + the code in Scope_Within. + 2019-07-09 Arnaud Charlet * gnat1drv.adb (Adjust_Global_Switches): Set diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 0d4ec9c..7b7d044 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -24268,13 +24268,32 @@ package body Sem_Util is (Inner : Entity_Id; Outer : Entity_Id) return Boolean is - Curr : Entity_Id; - + Curr : Entity_Id := Inner; begin - Curr := Inner; + -- Similar to the above, but check for scope identity first. + while Present (Curr) and then Curr /= Standard_Standard loop if Curr = Outer then return True; + + elsif Ekind (Curr) = E_Task_Type + and then Outer = Task_Body_Procedure (Curr) + then + return True; + + elsif Is_Subprogram (Curr) + and then Outer = Protected_Body_Subprogram (Curr) + then + return True; + + elsif Is_Private_Type (Curr) + and then Present (Full_View (Curr)) + then + if Full_View (Curr) = Outer then + return True; + else + return Scope_Within (Full_View (Curr), Outer); + end if; end if; Curr := Scope (Curr); -- cgit v1.1 From 578d5941ee23743c28959d84fd5f6eec09c7734d Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 9 Jul 2019 07:53:40 +0000 Subject: [Ada] Einfo: fix a typo 2019-07-09 Piotr Trojanek gcc/ada/ * einfo.ads: Fix a typo. From-SVN: r273270 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/einfo.ads | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c5fa67f..c0ba4af 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-09 Piotr Trojanek + + * einfo.ads: Fix a typo. + 2019-07-09 Ed Schonberg * sem_util.adb (Scope_Within_Or_Same): Handle properly task diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index a248568..d948151 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -4133,7 +4133,7 @@ package Einfo is -- Defined in generic subprograms, generic packages, and their -- instances. Also defined in the instances of the corresponding -- bodies. Denotes the renaming map (generic entities => instance --- entities) used to construct the instance by givin an index into +-- entities) used to construct the instance by giving an index into -- the tables used to represent these maps. See Sem_Ch12 for further -- details. The maps for package instances are also used when the -- instance is the actual corresponding to a formal package. -- cgit v1.1 From 995d28c7551ce6a65bd34355169106aab9ee65b6 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 9 Jul 2019 07:53:45 +0000 Subject: [Ada] Handle implicit moves in SPARK ownership pointer support Allocator expressions and sub-expressions of (extension) aggregates are implicitly the source of assignments in Ada. Thus, they should be moved when of a deep type when checking ownership rules in SPARK. There is no impact on compilation. 2019-07-09 Yannick Moy gcc/ada/ * sem_spark.adb (Check_Expression): Handle correctly implicit assignments as part of allocators and (extension) aggregates. (Get_Root_Object): Adapt for new path expressions. (Is_Path_Expression): Return True for (extension) aggregate. From-SVN: r273271 --- gcc/ada/ChangeLog | 7 ++ gcc/ada/sem_spark.adb | 208 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 167 insertions(+), 48 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c0ba4af..86b02b3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-09 Yannick Moy + + * sem_spark.adb (Check_Expression): Handle correctly implicit + assignments as part of allocators and (extension) aggregates. + (Get_Root_Object): Adapt for new path expressions. + (Is_Path_Expression): Return True for (extension) aggregate. + 2019-07-09 Piotr Trojanek * einfo.ads: Fix a typo. diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 6f27d20..bbd7279 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -1436,6 +1436,13 @@ package body Sem_SPARK is function Is_Type_Name (Expr : Node_Id) return Boolean; -- Detect when a path expression is in fact a type name + procedure Move_Expression (Expr : Node_Id); + -- Some subexpressions are only analyzed in Move mode. This is a + -- specialized version of Check_Expression for that case. + + procedure Move_Expression_List (L : List_Id); + -- Call Move_Expression on every expression in the list L + procedure Read_Expression (Expr : Node_Id); -- Most subexpressions are only analyzed in Read mode. This is a -- specialized version of Check_Expression for that case. @@ -1459,6 +1466,36 @@ package body Sem_SPARK is end Is_Type_Name; --------------------- + -- Move_Expression -- + --------------------- + + -- Distinguish the case where the argument is a path expression that + -- needs explicit moving. + + procedure Move_Expression (Expr : Node_Id) is + begin + if Is_Path_Expression (Expr) then + Check_Expression (Expr, Move); + else + Read_Expression (Expr); + end if; + end Move_Expression; + + -------------------------- + -- Move_Expression_List -- + -------------------------- + + procedure Move_Expression_List (L : List_Id) is + N : Node_Id; + begin + N := First (L); + while Present (N) loop + Move_Expression (N); + Next (N); + end loop; + end Move_Expression_List; + + --------------------- -- Read_Expression -- --------------------- @@ -1489,7 +1526,26 @@ package body Sem_SPARK is -- Local subprograms + function Is_Singleton_Choice (Choices : List_Id) return Boolean; + -- Return whether Choices is a singleton choice + procedure Read_Param (Formal : Entity_Id; Actual : Node_Id); + -- Call Read_Expression on the actual + + ------------------------- + -- Is_Singleton_Choice -- + ------------------------- + + function Is_Singleton_Choice (Choices : List_Id) return Boolean is + Choice : constant Node_Id := First (Choices); + begin + return List_Length (Choices) = 1 + and then Nkind (Choice) /= N_Others_Choice + and then not Nkind_In (Choice, N_Subtype_Indication, N_Range) + and then not + (Nkind_In (Choice, N_Identifier, N_Expanded_Name) + and then Is_Type (Entity (Choice))); + end Is_Singleton_Choice; ---------------- -- Read_Param -- @@ -1526,8 +1582,11 @@ package body Sem_SPARK is Read_Indexes (Prefix (Expr)); Read_Expression (Discrete_Range (Expr)); + -- The argument of an allocator is moved as part of the implicit + -- assignment. + when N_Allocator => - Read_Expression (Expression (Expr)); + Move_Expression (Expression (Expr)); when N_Function_Call => Read_Params (Expr); @@ -1539,6 +1598,91 @@ package body Sem_SPARK is => Read_Indexes (Expression (Expr)); + when N_Aggregate => + declare + Assocs : constant List_Id := Component_Associations (Expr); + CL : List_Id; + Assoc : Node_Id := Nlists.First (Assocs); + Choice : Node_Id; + + begin + -- The subexpressions of an aggregate are moved as part + -- of the implicit assignments. Handle the positional + -- components first. + + Move_Expression_List (Expressions (Expr)); + + -- Handle the named components next. + + while Present (Assoc) loop + CL := Choices (Assoc); + + -- For an array aggregate, we should also check that the + -- expressions used in choices are readable. + + if Is_Array_Type (Etype (Expr)) then + Choice := Nlists.First (CL); + while Present (Choice) loop + if Nkind (Choice) /= N_Others_Choice then + Read_Expression (Choice); + end if; + Next (Choice); + end loop; + end if; + + -- There can be only one element for a value of deep type + -- in order to avoid aliasing. + + if Is_Deep (Etype (Expression (Assoc))) + and then not Is_Singleton_Choice (CL) + then + Error_Msg_F ("singleton choice required" + & " to prevent aliasing", First (CL)); + end if; + + -- The subexpressions of an aggregate are moved as part + -- of the implicit assignments. + + Move_Expression (Expression (Assoc)); + + Next (Assoc); + end loop; + end; + + when N_Extension_Aggregate => + declare + Exprs : constant List_Id := Expressions (Expr); + Assocs : constant List_Id := Component_Associations (Expr); + CL : List_Id; + Assoc : Node_Id := Nlists.First (Assocs); + + begin + Move_Expression (Ancestor_Part (Expr)); + + -- No positional components allowed at this stage + + if Present (Exprs) then + raise Program_Error; + end if; + + while Present (Assoc) loop + CL := Choices (Assoc); + + -- Only singleton components allowed at this stage + + if not Is_Singleton_Choice (CL) then + raise Program_Error; + end if; + + -- The subexpressions of an aggregate are moved as part + -- of the implicit assignments. + + Move_Expression (Expression (Assoc)); + + Next (Assoc); + end loop; + end; + when others => raise Program_Error; end case; @@ -1759,45 +1903,6 @@ package body Sem_SPARK is Read_Expression (Condition (Expr)); end; - when N_Aggregate => - declare - Assocs : constant List_Id := Component_Associations (Expr); - Assoc : Node_Id := First (Assocs); - CL : List_Id; - Choice : Node_Id; - - begin - while Present (Assoc) loop - - -- An array aggregate with a single component association - -- may have a nonstatic choice expression that needs to be - -- analyzed. This can only occur for a single choice that - -- is not the OTHERS one. - - if Is_Array_Type (Etype (Expr)) then - CL := Choices (Assoc); - if List_Length (CL) = 1 then - Choice := First (CL); - if Nkind (Choice) /= N_Others_Choice then - Read_Expression (Choice); - end if; - end if; - end if; - - -- The expression in the component association also needs to - -- be analyzed. - - Read_Expression (Expression (Assoc)); - Next (Assoc); - end loop; - - Read_Expression_List (Expressions (Expr)); - end; - - when N_Extension_Aggregate => - Read_Expression (Ancestor_Part (Expr)); - Read_Expression_List (Expressions (Expr)); - when N_Character_Literal | N_Numeric_Or_String_Literal | N_Operator_Symbol @@ -1818,9 +1923,11 @@ package body Sem_SPARK is -- Path expressions are handled before this point - when N_Allocator + when N_Aggregate + | N_Allocator | N_Expanded_Name | N_Explicit_Dereference + | N_Extension_Aggregate | N_Function_Call | N_Identifier | N_Indexed_Component @@ -3283,7 +3390,7 @@ package body Sem_SPARK is return (R => Unfolded, Tree_Access => C); end; - -- For a non-terminal path, we get the permission tree of its + -- For a nonterminal path, we get the permission tree of its -- prefix, and then get the subtree associated with the extension, -- if unfolded. If folded, we return the permission associated with -- children. @@ -3389,9 +3496,12 @@ package body Sem_SPARK is => return Get_Root_Object (Prefix (Expr), Through_Traversal); - -- There is no root object for an allocator or NULL + -- There is no root object for an (extension) aggregate, allocator, + -- or NULL. - when N_Allocator + when N_Aggregate + | N_Allocator + | N_Extension_Aggregate | N_Null => return Empty; @@ -3596,10 +3706,12 @@ package body Sem_SPARK is when N_Null => return True; - -- Object returned by a allocator or function call corresponds to - -- a path. + -- Object returned by an (extension) aggregate, an allocator, or + -- a function call corresponds to a path. - when N_Allocator + when N_Aggregate + | N_Allocator + | N_Extension_Aggregate | N_Function_Call => return True; @@ -4763,7 +4875,7 @@ package body Sem_SPARK is return C; end; - -- For a non-terminal path, we set the permission tree of its prefix, + -- For a nonterminal path, we set the permission tree of its prefix, -- and then we extract from the returned pointer the subtree and -- assign an adequate permission to it, if unfolded. If folded, -- we unroll the tree one level. -- cgit v1.1 From a569f21920e9f53489a59be84c44d6345bbbfa6d Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 9 Jul 2019 07:53:50 +0000 Subject: [Ada] Reword "wild card" to "wildcard" 2019-07-09 Piotr Trojanek gcc/ada/ * doc/gnat_rm/the_gnat_library.rst, doc/gnat_ugn/building_executable_programs_with_gnat.rst, erroutc.adb, libgnat/g-comlin.adb, libgnat/g-comlin.ads, libgnat/g-regexp.ads, libgnat/g-regpat.ads, libgnat/g-spipat.ads, libgnat/s-os_lib.ads, libgnat/s-regexp.ads: Reword "wild card" to "wildcard". * gnat_rm.texi, gnat_ugn.texi: Regenerate. From-SVN: r273272 --- gcc/ada/ChangeLog | 10 ++++++++++ gcc/ada/doc/gnat_rm/the_gnat_library.rst | 2 +- .../doc/gnat_ugn/building_executable_programs_with_gnat.rst | 2 +- gcc/ada/erroutc.adb | 2 +- gcc/ada/gnat_rm.texi | 2 +- gcc/ada/gnat_ugn.texi | 2 +- gcc/ada/libgnat/g-comlin.adb | 2 +- gcc/ada/libgnat/g-comlin.ads | 6 +++--- gcc/ada/libgnat/g-regexp.ads | 2 +- gcc/ada/libgnat/g-regpat.ads | 2 +- gcc/ada/libgnat/g-spipat.ads | 2 +- gcc/ada/libgnat/s-os_lib.ads | 2 +- gcc/ada/libgnat/s-regexp.ads | 2 +- 13 files changed, 24 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 86b02b3..ed8dfda 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-07-09 Piotr Trojanek + + * doc/gnat_rm/the_gnat_library.rst, + doc/gnat_ugn/building_executable_programs_with_gnat.rst, + erroutc.adb, libgnat/g-comlin.adb, libgnat/g-comlin.ads, + libgnat/g-regexp.ads, libgnat/g-regpat.ads, + libgnat/g-spipat.ads, libgnat/s-os_lib.ads, + libgnat/s-regexp.ads: Reword "wild card" to "wildcard". + * gnat_rm.texi, gnat_ugn.texi: Regenerate. + 2019-07-09 Yannick Moy * sem_spark.adb (Check_Expression): Handle correctly implicit diff --git a/gcc/ada/doc/gnat_rm/the_gnat_library.rst b/gcc/ada/doc/gnat_rm/the_gnat_library.rst index e15e239..08497f3 100644 --- a/gcc/ada/doc/gnat_rm/the_gnat_library.rst +++ b/gcc/ada/doc/gnat_rm/the_gnat_library.rst @@ -937,7 +937,7 @@ programs written in Ada. Provides a high level interface to ``Ada.Command_Line`` facilities, including the ability to scan for named switches with optional parameters -and expand file names using wild card notations. +and expand file names using wildcard notations. .. _`GNAT.Compiler_Version_(g-comver.ads)`: diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index 57c3fe1..93956be 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -5290,7 +5290,7 @@ Using ``gcc`` for Syntax Checking compiles file :file:`x.adb` in syntax-check-only mode. You can check a series of files in a single command - , and can use wild cards to specify such a group of files. + , and can use wildcards to specify such a group of files. Note that you must specify the :switch:`-c` (compile only) flag in addition to the :switch:`-gnats` flag. diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb index 2ea0c2d..81e2910 100644 --- a/gcc/ada/erroutc.adb +++ b/gcc/ada/erroutc.adb @@ -53,7 +53,7 @@ package body Erroutc is function Matches (S : String; P : String) return Boolean; -- Returns true if the String S patches the pattern P, which can contain - -- wild card chars (*). The entire pattern must match the entire string. + -- wildcard chars (*). The entire pattern must match the entire string. -- Case is ignored in the comparison (so X matches x). function Sloc_In_Range (Loc, Start, Stop : Source_Ptr) return Boolean; diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 91ac523..2de8802 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -24044,7 +24044,7 @@ programs written in Ada. Provides a high level interface to @code{Ada.Command_Line} facilities, including the ability to scan for named switches with optional parameters -and expand file names using wild card notations. +and expand file names using wildcard notations. @node GNAT Compiler_Version g-comver ads,GNAT Ctrl_C g-ctrl_c ads,GNAT Command_Line g-comlin ads,The GNAT Library @anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{346}@anchor{gnat_rm/the_gnat_library id61}@anchor{347} diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 3f99340..2867018 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -14285,7 +14285,7 @@ $ gcc -c -gnats x.adb compiles file @code{x.adb} in syntax-check-only mode. You can check a series of files in a single command -, and can use wild cards to specify such a group of files. +, and can use wildcards to specify such a group of files. Note that you must specify the @code{-c} (compile only) flag in addition to the @code{-gnats} flag. diff --git a/gcc/ada/libgnat/g-comlin.adb b/gcc/ada/libgnat/g-comlin.adb index 0f527c6..29100af 100644 --- a/gcc/ada/libgnat/g-comlin.adb +++ b/gcc/ada/libgnat/g-comlin.adb @@ -443,7 +443,7 @@ package body GNAT.Command_Line is Parser.Current_Argument := Parser.Current_Argument + 1; - -- Could it be a file name with wild cards to expand? + -- Could it be a file name with wildcards to expand? if Do_Expansion then declare diff --git a/gcc/ada/libgnat/g-comlin.ads b/gcc/ada/libgnat/g-comlin.ads index 8306f9a..f1251b6 100644 --- a/gcc/ada/libgnat/g-comlin.ads +++ b/gcc/ada/libgnat/g-comlin.ads @@ -466,9 +466,9 @@ package GNAT.Command_Line is -- function should not be called before Getopt has returned ASCII.NUL. -- -- If Do_Expansion is True, then the parameter on the command line will - -- be considered as a filename with wild cards, and will be expanded. The + -- be considered as a filename with wildcards, and will be expanded. The -- matching file names will be returned one at a time. This is useful in - -- non-Unix systems for obtaining normal expansion of wild card references. + -- non-Unix systems for obtaining normal expansion of wildcard references. -- When there are no more arguments on the command line, this function -- returns an empty string. @@ -515,7 +515,7 @@ package GNAT.Command_Line is Pattern : String; Directory : String := ""; Basic_Regexp : Boolean := True); - -- Initialize a wild card expansion. The next calls to Expansion will + -- Initialize a wildcard expansion. The next calls to Expansion will -- return the next file name in Directory which match Pattern (Pattern -- is a regular expression, using only the Unix shell and DOS syntax if -- Basic_Regexp is True). When Directory is an empty string, the current diff --git a/gcc/ada/libgnat/g-regexp.ads b/gcc/ada/libgnat/g-regexp.ads index 50c992d..162738b 100644 --- a/gcc/ada/libgnat/g-regexp.ads +++ b/gcc/ada/libgnat/g-regexp.ads @@ -50,7 +50,7 @@ -- matching with the restriction that it matches entire strings. It -- is particularly useful for file name matching, and in particular -- it provides "globbing patterns" that are useful in implementing --- unix or DOS style wild card matching for file names. +-- unix or DOS style wildcard matching for file names. -- GNAT.Regpat (files g-regpat.ads/s-regpat.ads/g-regpat.adb) -- This is a more complete implementation of Unix-style regular diff --git a/gcc/ada/libgnat/g-regpat.ads b/gcc/ada/libgnat/g-regpat.ads index bac4d74..62fc2e8 100644 --- a/gcc/ada/libgnat/g-regpat.ads +++ b/gcc/ada/libgnat/g-regpat.ads @@ -53,7 +53,7 @@ -- matching with the restriction that it matches entire strings. It -- is particularly useful for file name matching, and in particular -- it provides "globbing patterns" that are useful in implementing --- unix or DOS style wild card matching for file names. +-- unix or DOS style wildcard matching for file names. -- GNAT.Regpat (files g-regpat.ads/s-regpat.ads/s-regpat.adb) -- This is a more complete implementation of Unix-style regular diff --git a/gcc/ada/libgnat/g-spipat.ads b/gcc/ada/libgnat/g-spipat.ads index 4d6a7f8..4dfc25a 100644 --- a/gcc/ada/libgnat/g-spipat.ads +++ b/gcc/ada/libgnat/g-spipat.ads @@ -48,7 +48,7 @@ -- matching with the restriction that it matches entire strings. It -- is particularly useful for file name matching, and in particular -- it provides "globbing patterns" that are useful in implementing --- unix or DOS style wild card matching for file names. +-- unix or DOS style wildcard matching for file names. -- GNAT.Regpat (files g-regpat.ads/g-regpat.adb) -- This is a more complete implementation of Unix-style regular diff --git a/gcc/ada/libgnat/s-os_lib.ads b/gcc/ada/libgnat/s-os_lib.ads index 8b21aa7..3e8c21d 100644 --- a/gcc/ada/libgnat/s-os_lib.ads +++ b/gcc/ada/libgnat/s-os_lib.ads @@ -246,7 +246,7 @@ package System.OS_Lib is Success : out Boolean; Mode : Copy_Mode := Copy; Preserve : Attribute := Time_Stamps); - -- Copy a file. Name must designate a single file (no wild cards allowed). + -- Copy a file. Name must designate a single file (no wildcards allowed). -- Pathname can be a filename or directory name. In the latter case Name -- is copied into the directory preserving the same file name. Mode -- defines the kind of copy, see above with the default being a normal diff --git a/gcc/ada/libgnat/s-regexp.ads b/gcc/ada/libgnat/s-regexp.ads index f521f91..4d9fb5b 100644 --- a/gcc/ada/libgnat/s-regexp.ads +++ b/gcc/ada/libgnat/s-regexp.ads @@ -77,7 +77,7 @@ package System.Regexp is -- See also regexp(1) man page on Unix systems for further details -- A second kind of regular expressions is provided. This one is more - -- like the wild card patterns used in file names by the Unix shell (or + -- like the wildcard patterns used in file names by the Unix shell (or -- DOS prompt) command lines. The grammar is the following: -- regexp ::= term -- cgit v1.1 From 5dd6327237996b7f4103e11c76aac01bf2420e19 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 9 Jul 2019 07:53:55 +0000 Subject: [Ada] Expand type of static expressions in GNATprove mode In the special mode for GNATprove, expand the type of static expressions like done during compilation, to both get suitable legality checks and increase the precision of the formal analysis. There is no impact on compilation. 2019-07-09 Yannick Moy gcc/ada/ * exp_util.adb (Expand_Subtype_From_Expr): Still expand the type of static expressions in GNATprove_Mode. * sem_ch3.adb (Analyze_Object_Declaration): Remove obsolete special case for GNATprove_Mode. From-SVN: r273273 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/exp_util.adb | 12 +++++++++--- gcc/ada/sem_ch3.adb | 8 -------- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ed8dfda..8c07082 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-09 Yannick Moy + + * exp_util.adb (Expand_Subtype_From_Expr): Still expand the type + of static expressions in GNATprove_Mode. + * sem_ch3.adb (Analyze_Object_Declaration): Remove obsolete + special case for GNATprove_Mode. + 2019-07-09 Piotr Trojanek * doc/gnat_rm/the_gnat_library.rst, diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 4206090..6f73ec3 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -5067,9 +5067,15 @@ package body Exp_Util is -- may be constants that depend on the bounds of a string literal, both -- standard string types and more generally arrays of characters. - -- In GNATprove mode, these extra subtypes are not needed - - if GNATprove_Mode then + -- In GNATprove mode, these extra subtypes are not needed, unless Exp is + -- a static expression. In that case, the subtype will be constrained + -- while the original type might be unconstrained, so expanding the type + -- is necessary both for passing legality checks in GNAT and for precise + -- analysis in GNATprove. + + if GNATprove_Mode + and then not Is_Static_Expression (Exp) + then return; end if; diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index ec86266..38fab90 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -4592,14 +4592,6 @@ package body Sem_Ch3 is elsif Is_Interface (T) then null; - -- In GNATprove mode, Expand_Subtype_From_Expr does nothing. Thus, - -- we should prevent the generation of another Itype with the - -- same name as the one already generated, or we end up with - -- two identical types in GNATprove. - - elsif GNATprove_Mode then - null; - -- If the type is an unchecked union, no subtype can be built from -- the expression. Rewrite declaration as a renaming, which the -- back-end can handle properly. This is a rather unusual case, -- cgit v1.1 From 554a9844f74932d2c6e9a690d04bfd96b361055b Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 9 Jul 2019 07:54:00 +0000 Subject: [Ada] Prevent inconsistent state for inlining in GNATprove In GNATprove mode, subprograms with a body to inline should have been filtered in Analyze_Subprogram_Body_Helper to match the conditions for inlining subprograms in GNATprove. Prevent a call to Set_Body_To_Inline in GNATprove mode that did not go through this filtering. There is no impact on compilation. 2019-07-09 Yannick Moy gcc/ada/ * freeze.adb (Build_Renamed_Body): Do not set body to inline in GNATprove mode. From-SVN: r273274 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/freeze.adb | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8c07082..b74910d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-09 Yannick Moy + * freeze.adb (Build_Renamed_Body): Do not set body to inline in + GNATprove mode. + +2019-07-09 Yannick Moy + * exp_util.adb (Expand_Subtype_From_Expr): Still expand the type of static expressions in GNATprove_Mode. * sem_ch3.adb (Analyze_Object_Declaration): Remove obsolete diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 5b843f2..b29ff67 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -407,11 +407,14 @@ package body Freeze is -- calls to the renamed entity. The body must be generated in any case -- for calls that may appear elsewhere. This is not done in the case -- where the subprogram is an instantiation because the actual proper - -- body has not been built yet. + -- body has not been built yet. This is also not done in GNATprove mode + -- as we need to check other conditions for creating a body to inline + -- in that case, which are controlled in Analyze_Subprogram_Body_Helper. if Ekind_In (Old_S, E_Function, E_Procedure) and then Nkind (Decl) = N_Subprogram_Declaration and then not Is_Generic_Instance (Old_S) + and then not GNATprove_Mode then Set_Body_To_Inline (Decl, Old_S); end if; -- cgit v1.1 From a74d1bf6af0aaeb693cdbddf924c9af53f92b549 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Tue, 9 Jul 2019 07:54:05 +0000 Subject: [Ada] Spurious error when instance of generic is used as formal package This patch removes a spurious bug on the use of the current instance of a generic package G as the actual in a nested instantiation of a generic unit GU that has a formal package whose generic_package name is G. This is only legal if G has no generic formal part, and the formal package declaration is declared with a box or without a formal_paxkage_actual part. 2019-07-09 Ed Schonberg gcc/ada/ * sem_ch12.adb (Instantiate_Formal_Package): Handle properly the case where the actual for a formal package in an instance is the current instance of an enclosing generic package. (Check_Formal_Packages): If the formal package declaration is box-initialized or lacks associations altogether, no internal instance was created to verify conformance, and there is no validating package to remove from tree. gcc/testsuite/ * gnat.dg/generic_inst5.adb, gnat.dg/generic_inst6.adb, gnat.dg/generic_inst6_g1-c.adb, gnat.dg/generic_inst6_g1-c.ads, gnat.dg/generic_inst6_g1.ads, gnat.dg/generic_inst6_i1.ads, gnat.dg/generic_inst6_i2.ads, gnat.dg/generic_inst6_x.ads: New testcases. From-SVN: r273275 --- gcc/ada/ChangeLog | 10 ++++++++++ gcc/ada/sem_ch12.adb | 30 +++++++++++++++++++++++++--- gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/gnat.dg/generic_inst5.adb | 20 +++++++++++++++++++ gcc/testsuite/gnat.dg/generic_inst6.adb | 9 +++++++++ gcc/testsuite/gnat.dg/generic_inst6_g1-c.adb | 6 ++++++ gcc/testsuite/gnat.dg/generic_inst6_g1-c.ads | 3 +++ gcc/testsuite/gnat.dg/generic_inst6_g1.ads | 3 +++ gcc/testsuite/gnat.dg/generic_inst6_i1.ads | 2 ++ gcc/testsuite/gnat.dg/generic_inst6_i2.ads | 2 ++ gcc/testsuite/gnat.dg/generic_inst6_x.ads | 7 +++++++ 11 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/generic_inst5.adb create mode 100644 gcc/testsuite/gnat.dg/generic_inst6.adb create mode 100644 gcc/testsuite/gnat.dg/generic_inst6_g1-c.adb create mode 100644 gcc/testsuite/gnat.dg/generic_inst6_g1-c.ads create mode 100644 gcc/testsuite/gnat.dg/generic_inst6_g1.ads create mode 100644 gcc/testsuite/gnat.dg/generic_inst6_i1.ads create mode 100644 gcc/testsuite/gnat.dg/generic_inst6_i2.ads create mode 100644 gcc/testsuite/gnat.dg/generic_inst6_x.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b74910d..c80c9e4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-07-09 Ed Schonberg + + * sem_ch12.adb (Instantiate_Formal_Package): Handle properly the + case where the actual for a formal package in an instance is the + current instance of an enclosing generic package. + (Check_Formal_Packages): If the formal package declaration is + box-initialized or lacks associations altogether, no internal + instance was created to verify conformance, and there is no + validating package to remove from tree. + 2019-07-09 Yannick Moy * freeze.adb (Build_Renamed_Body): Do not set body to inline in diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 0df4d96..9afa095 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -6657,9 +6657,11 @@ package body Sem_Ch12 is Formal_Decl := Parent (Associated_Formal_Package (E)); -- Nothing to check if the formal has a box or an others_clause - -- (necessarily with a box). + -- (necessarily with a box), or no associations altogether - if Box_Present (Formal_Decl) then + if Box_Present (Formal_Decl) + or else No (Generic_Associations (Formal_Decl)) + then null; elsif Nkind (First (Generic_Associations (Formal_Decl))) = @@ -10309,8 +10311,11 @@ package body Sem_Ch12 is begin Analyze (Actual); + -- The actual must be a package instance, or else a current instance + -- such as a parent generic within the body of a generic child. + if not Is_Entity_Name (Actual) - or else Ekind (Entity (Actual)) /= E_Package + or else not Ekind_In (Entity (Actual), E_Package, E_Generic_Package) then Error_Msg_N ("expect package instance to instantiate formal", Actual); @@ -10354,6 +10359,14 @@ package body Sem_Ch12 is then null; + -- If this is the current instance of an enclosing generic, that + -- unit is the generic package we need. + + elsif In_Open_Scopes (Actual_Pack) + and then Ekind (Actual_Pack) = E_Generic_Package + then + null; + else Error_Msg_NE ("actual parameter must be instance of&", Actual, Gen_Parent); @@ -10487,6 +10500,17 @@ package body Sem_Ch12 is Next_Entity (Actual_Ent); end loop; + + -- No conformance to check if the generic has no formal parameters + -- and the formal package has no generic associations. + + if Is_Empty_List (Formals) + and then + (Box_Present (Formal) + or else No (Generic_Associations (Formal))) + then + return Decls; + end if; end; -- If the formal is not declared with a box, reanalyze it as an diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2941e43..af4a009 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-07-09 Ed Schonberg + + * gnat.dg/generic_inst5.adb, gnat.dg/generic_inst6.adb, + gnat.dg/generic_inst6_g1-c.adb, gnat.dg/generic_inst6_g1-c.ads, + gnat.dg/generic_inst6_g1.ads, gnat.dg/generic_inst6_i1.ads, + gnat.dg/generic_inst6_i2.ads, gnat.dg/generic_inst6_x.ads: New + testcases. + 2019-07-08 Martin Sebor PR middle-end/71924 diff --git a/gcc/testsuite/gnat.dg/generic_inst5.adb b/gcc/testsuite/gnat.dg/generic_inst5.adb new file mode 100644 index 0000000..25e92f0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst5.adb @@ -0,0 +1,20 @@ +-- { dg-do compile } + +procedure Generic_Inst5 is + generic + package G1 is + end G1; + + generic + with package I1 is new G1; + package G2 is + end G2; + + package body G1 is + package I2 is new G2 (I1 => G1); + end G1; + + package I1 is new G1; +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/generic_inst6.adb b/gcc/testsuite/gnat.dg/generic_inst6.adb new file mode 100644 index 0000000..780fae9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst6.adb @@ -0,0 +1,9 @@ +-- { dg-do run } +with Text_IO; use Text_IO; +with Generic_Inst6_I2; +procedure Generic_Inst6 is +begin + if Generic_Inst6_I2.Check /= 49 then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/generic_inst6_g1-c.adb b/gcc/testsuite/gnat.dg/generic_inst6_g1-c.adb new file mode 100644 index 0000000..ed671f1 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst6_g1-c.adb @@ -0,0 +1,6 @@ +with Generic_Inst6_X; +package body Generic_Inst6_G1.C is + package N is new Generic_Inst6_X + (Generic_Inst6_G1, Generic_Inst6_G1); + function Check return Integer is (N.Result); +end; diff --git a/gcc/testsuite/gnat.dg/generic_inst6_g1-c.ads b/gcc/testsuite/gnat.dg/generic_inst6_g1-c.ads new file mode 100644 index 0000000..c00d19d --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst6_g1-c.ads @@ -0,0 +1,3 @@ +generic package Generic_Inst6_G1.C is + function Check return Integer; +end; diff --git a/gcc/testsuite/gnat.dg/generic_inst6_g1.ads b/gcc/testsuite/gnat.dg/generic_inst6_g1.ads new file mode 100644 index 0000000..9beeb21 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst6_g1.ads @@ -0,0 +1,3 @@ +generic package Generic_Inst6_G1 is + Val : Integer := 7; + end; diff --git a/gcc/testsuite/gnat.dg/generic_inst6_i1.ads b/gcc/testsuite/gnat.dg/generic_inst6_i1.ads new file mode 100644 index 0000000..016dfb7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst6_i1.ads @@ -0,0 +1,2 @@ +with Generic_Inst6_G1; +package Generic_Inst6_I1 is new Generic_Inst6_G1; diff --git a/gcc/testsuite/gnat.dg/generic_inst6_i2.ads b/gcc/testsuite/gnat.dg/generic_inst6_i2.ads new file mode 100644 index 0000000..03abe22 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst6_i2.ads @@ -0,0 +1,2 @@ +with Generic_Inst6_I1, Generic_Inst6_G1.C; +package Generic_Inst6_I2 is new Generic_Inst6_I1.C; diff --git a/gcc/testsuite/gnat.dg/generic_inst6_x.ads b/gcc/testsuite/gnat.dg/generic_inst6_x.ads new file mode 100644 index 0000000..657dc41 --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_inst6_x.ads @@ -0,0 +1,7 @@ +with Generic_Inst6_G1; +generic + with package G2 is new Generic_Inst6_G1 (<>); + with package G3 is new Generic_Inst6_G1 (<>); +package Generic_Inst6_X is + Result : Integer := G2.Val * G3.Val; +end; -- cgit v1.1 From dd9290ec5334de4426f4a510f4a32fd02e012f04 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 9 Jul 2019 07:54:10 +0000 Subject: [Ada] Expand Enum_Rep attribute reference in GNATprove mode In the special GNATprove mode for proof of programs, expand the Enum_Rep attribute reference so that a suitable static integer is in the AST where required by the rest of analysis. There is no impact on compilation. 2019-07-09 Yannick Moy gcc/ada/ * exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Expand attribute reference on Enum_Rep. From-SVN: r273276 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_spark.adb | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c80c9e4..948d0fa 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Yannick Moy + + * exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Expand + attribute reference on Enum_Rep. + 2019-07-09 Ed Schonberg * sem_ch12.adb (Instantiate_Formal_Package): Handle properly the diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb index b008c79..58f9243 100644 --- a/gcc/ada/exp_spark.adb +++ b/gcc/ada/exp_spark.adb @@ -26,6 +26,7 @@ with Atree; use Atree; with Checks; use Checks; with Einfo; use Einfo; +with Exp_Attr; with Exp_Ch4; with Exp_Ch5; use Exp_Ch5; with Exp_Dbug; use Exp_Dbug; @@ -196,6 +197,12 @@ package body Exp_SPARK is Parameter_Associations => New_List (Expr))); Analyze_And_Resolve (N, Typ); + -- Whenever possible, replace a prefix which is an enumeration literal + -- by the corresponding literal value. + + elsif Attr_Id = Attribute_Enum_Rep then + Exp_Attr.Expand_N_Attribute_Reference (N); + -- For attributes which return Universal_Integer, introduce a conversion -- to the expected type with the appropriate check flags set. -- cgit v1.1 From ff606db0166573fee17f6d81895f7d882fd15169 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 9 Jul 2019 07:54:14 +0000 Subject: [Ada] Sinfo: refine comment for Do_Range_Check 2019-07-09 Yannick Moy gcc/ada/ * sinfo.ads: Refine comment for Do_Range_Check. From-SVN: r273277 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/sinfo.ads | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 948d0fa..17c27abc 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,9 @@ 2019-07-09 Yannick Moy + * sinfo.ads: Refine comment for Do_Range_Check. + +2019-07-09 Yannick Moy + * exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Expand attribute reference on Enum_Rep. diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index b1e57bf..7be56cb 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -754,7 +754,11 @@ package Sinfo is -- GNATprove mode. As a special case, the front end does not insert a -- Do_Division_Check flag on float exponentiation expressions, for the case -- where the value is 0.0 and the exponent is negative, although this case - -- does lead to a division check failure. + -- does lead to a division check failure. As another special case, + -- the frontend does not insert a Do_Range_Check on an allocator where + -- the designated type is scalar, and the designated type is more + -- constrained than the type of the initialized allocator value or the type + -- of the default value for an uninitialized allocator. -- Note: the expander always takes care of the Do_Range check case, -- so this flag will never be set in the expanded tree passed to the -- cgit v1.1 From 5da544339b2b3b3d00d3dd5b91c06d2d09a386b2 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Tue, 9 Jul 2019 07:54:19 +0000 Subject: [Ada] Missing runtime range checks with -gnatVa Under validity checking mode the compiler may silently skip generating code to perform runtime range checks. 2019-07-09 Javier Miranda gcc/ada/ * exp_util.adb (Remove_Side_Effects): Preserve the Do_Range_Check flag. gcc/testsuite/ * gnat.dg/range_check3.adb, gnat.dg/range_check3_pkg.adb, gnat.dg/range_check3_pkg.ads: New testcase. From-SVN: r273278 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_util.adb | 4 ++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/range_check3.adb | 13 +++++++++++++ gcc/testsuite/gnat.dg/range_check3_pkg.adb | 18 ++++++++++++++++++ gcc/testsuite/gnat.dg/range_check3_pkg.ads | 9 +++++++++ 6 files changed, 54 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/range_check3.adb create mode 100644 gcc/testsuite/gnat.dg/range_check3_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/range_check3_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 17c27abc..e5aba8b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Javier Miranda + + * exp_util.adb (Remove_Side_Effects): Preserve the + Do_Range_Check flag. + 2019-07-09 Yannick Moy * sinfo.ads: Refine comment for Do_Range_Check. diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 6f73ec3..77809bc 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -11693,6 +11693,10 @@ package body Exp_Util is Set_Assignment_OK (Res, Assignment_OK (Exp)); + -- Preserve the Do_Range_Check flag in all copies. + + Set_Do_Range_Check (Res, Do_Range_Check (Exp)); + -- Finally rewrite the original expression and we are done Rewrite (Exp, Res); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index af4a009..e1f1678 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Javier Miranda + + * gnat.dg/range_check3.adb, gnat.dg/range_check3_pkg.adb, + gnat.dg/range_check3_pkg.ads: New testcase. + 2019-07-09 Ed Schonberg * gnat.dg/generic_inst5.adb, gnat.dg/generic_inst6.adb, diff --git a/gcc/testsuite/gnat.dg/range_check3.adb b/gcc/testsuite/gnat.dg/range_check3.adb new file mode 100644 index 0000000..d134a79 --- /dev/null +++ b/gcc/testsuite/gnat.dg/range_check3.adb @@ -0,0 +1,13 @@ +-- { dg-do run } +-- { dg-options "-gnatVa" } + +with Range_Check3_Pkg; use Range_Check3_Pkg; +procedure Range_Check3 is + Ptr : Array_Access; +begin + Ptr := Allocate; + raise Program_Error; +exception + when Constraint_Error => null; +end Range_Check3; + diff --git a/gcc/testsuite/gnat.dg/range_check3_pkg.adb b/gcc/testsuite/gnat.dg/range_check3_pkg.adb new file mode 100644 index 0000000..50c1b1d --- /dev/null +++ b/gcc/testsuite/gnat.dg/range_check3_pkg.adb @@ -0,0 +1,18 @@ +package body Range_Check3_Pkg is + function One return Positive is + begin + return 1; + end One; + + function Zero return Natural is + begin + return 0; + end Zero; + + function Allocate return Array_Access is + begin + return + new Array_Type + (Positive (One) .. Positive (Zero)); -- Failed range check + end Allocate; +end Range_Check3_Pkg; diff --git a/gcc/testsuite/gnat.dg/range_check3_pkg.ads b/gcc/testsuite/gnat.dg/range_check3_pkg.ads new file mode 100644 index 0000000..d5864c6 --- /dev/null +++ b/gcc/testsuite/gnat.dg/range_check3_pkg.ads @@ -0,0 +1,9 @@ +package Range_Check3_Pkg is + type Array_Type is array (Positive range <>) of Integer; + type Array_Access is access Array_Type; + + function One return Positive; + function Zero return Natural; + + function Allocate return Array_Access; +end Range_Check3_Pkg; -- cgit v1.1 From fb95bfcc8138378d4e5786c67f5eb49b84a54683 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 9 Jul 2019 07:54:24 +0000 Subject: [Ada] Missing escape of the double quote in JSON output In Ada, the name of operators contains a pair of double quotes, which need to be properly escaped when the name appears in the JSON output of -gnatR. The change also ensures that formal parameters are not listed in the layout information, since this information is not back-annotated for them. 2019-07-09 Eric Botcazou gcc/ada/ * repinfo.adb (List_Entities): Disregard formals altogether. (List_Name): Properly escape the double quote in the JSON output. From-SVN: r273279 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/repinfo.adb | 24 +++++++++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e5aba8b..1dd1d70 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Eric Botcazou + + * repinfo.adb (List_Entities): Disregard formals altogether. + (List_Name): Properly escape the double quote in the JSON + output. + 2019-07-09 Javier Miranda * exp_util.adb (Remove_Side_Effects): Preserve the diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 75da2b6..1ba7e11 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -525,9 +525,6 @@ package body Repinfo is List_Entities (E, Bytes_Big_Endian, True); - elsif Is_Formal (E) and then In_Subprogram then - null; - elsif Ekind_In (E, E_Entry, E_Entry_Family, E_Subprogram_Type) @@ -560,12 +557,10 @@ package body Repinfo is List_Type_Info (E); end if; - elsif Ekind_In (E, E_Variable, E_Constant) then - if List_Representation_Info >= 2 then - List_Object_Info (E); - end if; + -- Note that formals are not annotated so we skip them here - elsif Ekind (E) = E_Loop_Parameter or else Is_Formal (E) then + elsif Ekind_In (E, E_Variable, E_Constant, E_Loop_Parameter) + then if List_Representation_Info >= 2 then List_Object_Info (E); end if; @@ -899,6 +894,8 @@ package body Repinfo is --------------- procedure List_Name (Ent : Entity_Id) is + C : Character; + begin -- List the qualified name recursively, except -- at compilation unit level in default mode. @@ -914,7 +911,16 @@ package body Repinfo is Get_Unqualified_Decoded_Name_String (Chars (Ent)); Set_Casing (Unit_Casing); - Write_Str (Name_Buffer (1 .. Name_Len)); + + -- The name of operators needs to be properly escaped for JSON + + for J in 1 .. Name_Len loop + C := Name_Buffer (J); + if C = '"' and then List_Representation_Info_To_JSON then + Write_Char ('\'); + end if; + Write_Char (C); + end loop; end List_Name; --------------------- -- cgit v1.1 From 16cc65b61a7c00920ff66d45d3b23a9e313dd1b8 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Tue, 9 Jul 2019 07:54:29 +0000 Subject: [Ada] Elaboration order v4.0 activation This patch enables the elaboration order v4.0 as the default elaboration order in GNATbind. The previous v3.0 elaboration order is now referred to as the "legacy elaboration order mechanism" and is available using binder switch -H. 2019-07-09 Hristian Kirtchev gcc/ada/ * bindo.adb: Remove with and use clauses for Debug. Add with and use clauses for Opt. (Find_Elaboration_Order): Enable the v4.0 elaboration order. The v3.0 mechanism is now available under binder switch -H. * bindusg.adb (Display): Enable switch -H. * debug.adb: Free compiler switch -gnatd_G. Free binder switch -d_N. * sem_elab.adb: Update the section on switches to remove -gnatd_G. (Invocation_Graph_Recording_OK): The invocation graph is now unconditionally recorded in ALI files. * switch-b.adb (Scan_Binder_Switches): Scan switch -H. * doc/gnat_ugn/building_executable_programs_with_gnat.rst: Update the documentation on compiler switches related to elaboration. Update the documentation on binder switches to include switch -H. * doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: Update the documentation on elaboration order handling in GNAT. * gnat_ugn.texi: Regenerate. From-SVN: r273280 --- gcc/ada/ChangeLog | 22 + gcc/ada/bindo.adb | 33 +- gcc/ada/bindusg.adb | 7 +- gcc/ada/debug.adb | 9 +- .../building_executable_programs_with_gnat.rst | 66 +- .../elaboration_order_handling_in_gnat.rst | 1405 ++++++++------------ gcc/ada/gnat_ugn.texi | 1320 ++++++++---------- gcc/ada/sem_elab.adb | 17 +- gcc/ada/switch-b.adb | 9 +- 9 files changed, 1150 insertions(+), 1738 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1dd1d70..738be61 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,25 @@ +2019-07-09 Hristian Kirtchev + + * bindo.adb: Remove with and use clauses for Debug. Add with + and use clauses for Opt. + (Find_Elaboration_Order): Enable the v4.0 elaboration order. The + v3.0 mechanism is now available under binder switch -H. + * bindusg.adb (Display): Enable switch -H. + * debug.adb: Free compiler switch -gnatd_G. Free binder switch + -d_N. + * sem_elab.adb: Update the section on switches to remove + -gnatd_G. + (Invocation_Graph_Recording_OK): The invocation graph is now + unconditionally recorded in ALI files. + * switch-b.adb (Scan_Binder_Switches): Scan switch -H. + * doc/gnat_ugn/building_executable_programs_with_gnat.rst: + Update the documentation on compiler switches related to + elaboration. Update the documentation on binder switches to + include switch -H. + * doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: Update + the documentation on elaboration order handling in GNAT. + * gnat_ugn.texi: Regenerate. + 2019-07-09 Eric Botcazou * repinfo.adb (List_Entities): Disregard formals altogether. diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index 897e746..519887d 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -24,7 +24,7 @@ ------------------------------------------------------------------------------ with Binde; -with Debug; use Debug; +with Opt; use Opt; with Bindo.Elaborators; use Bindo.Elaborators; @@ -426,9 +426,7 @@ package body Bindo is -- Units and routines of interest: -- Bindo.Elaborators -- Elaborate_Library_Graph - -- Elaborate_Units_Common - -- Elaborate_Units_Dynamic - -- Elaborate_Units_Static + -- Elaborate_Units -- -- * Invalid invocation graph -- @@ -490,40 +488,19 @@ package body Bindo is Main_Lib_File : File_Name_Type) is begin - -- ??? Enable the following code when switching from the old to the new - -- elaboration-order mechanism. - -- Use the library graph and heuristic-based elaboration order when -- switch -H (legacy elaboration-order mode enabled). - -- if Legacy_Elaboration_Order then - -- Binde.Find_Elab_Order (Order, Main_Lib_File); + if Legacy_Elaboration_Order then + Binde.Find_Elab_Order (Order, Main_Lib_File); -- Otherwise use the invocation and library-graph-based elaboration -- order. - -- else - -- Invocation_And_Library_Graph_Elaborators.Elaborate_Units - -- (Order => Order, - -- Main_Lib_File => Main_Lib_File); - -- end if; - - -- ??? Remove the following code when switching from the old to the new - -- elaboration-order mechanism. - - -- Use the invocation and library-graph-based elaboration order when - -- switch -d_N (new bindo order) is in effect. - - if Debug_Flag_Underscore_NN then + else Invocation_And_Library_Graph_Elaborators.Elaborate_Units (Order => Order, Main_Lib_File => Main_Lib_File); - - -- Otherwise use the library-graph and heuristic-based elaboration - -- order. - - else - Binde.Find_Elab_Order (Order, Main_Lib_File); end if; end Find_Elaboration_Order; diff --git a/gcc/ada/bindusg.adb b/gcc/ada/bindusg.adb index a4a9739..0207479 100644 --- a/gcc/ada/bindusg.adb +++ b/gcc/ada/bindusg.adb @@ -143,13 +143,10 @@ package body Bindusg is Write_Line (" -h Output this usage (help) information"); - -- ??? Enable the following code when switching from the old to the new - -- elaboration-order mechanism. - -- Line for -H switch - -- Write_Line - -- (" -H Legacy elaboration-order model enabled"); + Write_Line + (" -H Legacy elaboration order model enabled"); -- Lines for -I switch diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 680c38f..a4ff176 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -178,7 +178,7 @@ package body Debug is -- d_D -- d_E -- d_F Encode full invocation paths in ALI files - -- d_G Encode invocation graph in ALI files + -- d_G -- d_H -- d_I -- d_J @@ -388,7 +388,7 @@ package body Debug is -- d_K -- d_L Output library graph -- d_M - -- d_N New bindo order + -- d_N -- d_O -- d_P Output cycle paths -- d_Q @@ -1001,9 +1001,6 @@ package body Debug is -- an external target, offering additional information to GNATBIND for -- purposes of error diagnostics. - -- d_G The compiler encodes the invocation graph of a unit in its ALI - -- file. - -- d_L Output trace information on elaboration checking. This debug switch -- causes output to be generated showing each call or instantiation as -- it is checked, and the progress of the recursive trace through @@ -1164,8 +1161,6 @@ package body Debug is -- d_L GNATBIND outputs the contents of the library graph in textual -- format to standard output. - -- d_N GNATBIND utilizes the elaboration order provided by bindo - -- d_P GNATBIND outputs the cycle paths to standard output -- d_T GNATBIND outputs trace information of elaboration order and cycle diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index 93956be..98c3e16 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -1836,7 +1836,8 @@ Alphabetical List of All Switches .. index:: -gnatE (gcc) :switch:`-gnatE` - Full dynamic elaboration checks. + Dynamic elaboration checking mode enabled. For further details see + :ref:`Elaboration_Order_Handling_in_GNAT`. .. index:: -gnatf (gcc) @@ -1878,8 +1879,9 @@ Alphabetical List of All Switches .. index:: -gnatH (gcc) :switch:`-gnatH` - Legacy elaboration-checking mode enabled. When this switch is in effect, the - pre-18.x access-before-elaboration model becomes the de facto model. + Legacy elaboration-checking mode enabled. When this switch is in effect, + the pre-18.x access-before-elaboration model becomes the de facto model. + For further details see :ref:`Elaboration_Order_Handling_in_GNAT`. .. index:: -gnati (gcc) @@ -1935,7 +1937,8 @@ Alphabetical List of All Switches - Select statements - Synchronous task suspension - and does not emit compile-time diagnostics or run-time checks. + and does not emit compile-time diagnostics or run-time checks. For further + details see :ref:`Elaboration_Order_Handling_in_GNAT`. .. index:: -gnatk (gcc) @@ -6368,7 +6371,9 @@ be presented in subsequent sections. .. index:: -f (gnatbind) :switch:`-f{elab-order}` - Force elaboration order. + Force elaboration order. For further details see :ref:`Elaboration_Control` + and :ref:`Elaboration_Order_Handling_in_GNAT`. + .. index:: -F (gnatbind) @@ -6388,15 +6393,22 @@ be presented in subsequent sections. Output usage (help) information. - .. index:: -H32 (gnatbind) +.. index:: -H (gnatbind) + +:switch:`-H` + Legacy elaboration order model enabled. For further details see + :ref:`Elaboration_Order_Handling_in_GNAT`. + + +.. index:: -H32 (gnatbind) :switch:`-H32` Use 32-bit allocations for ``__gnat_malloc`` (and thus for access types). For further details see :ref:`Dynamic_Allocation_Control`. - .. index:: -H64 (gnatbind) - .. index:: __gnat_malloc +.. index:: -H64 (gnatbind) +.. index:: __gnat_malloc :switch:`-H64` Use 64-bit allocations for ``__gnat_malloc`` (and thus for access types). @@ -6816,7 +6828,7 @@ Elaboration Control ^^^^^^^^^^^^^^^^^^^ The following switches provide additional control over the elaboration -order. For full details see :ref:`Elaboration_Order_Handling_in_GNAT`. +order. For further details see :ref:`Elaboration_Order_Handling_in_GNAT`. .. index:: -f (gnatbind) @@ -6860,28 +6872,32 @@ order. For full details see :ref:`Elaboration_Order_Handling_in_GNAT`. ignored. - .. index:: -p (gnatbind) +.. index:: -p (gnatbind) :switch:`-p` - Normally the binder attempts to choose an elaboration order that is - likely to minimize the likelihood of an elaboration order error resulting - in raising a ``Program_Error`` exception. This switch reverses the - action of the binder, and requests that it deliberately choose an order - that is likely to maximize the likelihood of an elaboration error. - This is useful in ensuring portability and avoiding dependence on - accidental fortuitous elaboration ordering. - - Normally it only makes sense to use the :switch:`-p` - switch if dynamic + Pessimistic elaboration order + + This switch is only applicable to the pre-20.x legacy elaboration models. + The post-20.x elaboration model uses a more informed approach of ordering + the units. + + Normally the binder attempts to choose an elaboration order that is likely to + minimize the likelihood of an elaboration order error resulting in raising a + ``Program_Error`` exception. This switch reverses the action of the binder, + and requests that it deliberately choose an order that is likely to maximize + the likelihood of an elaboration error. This is useful in ensuring + portability and avoiding dependence on accidental fortuitous elaboration + ordering. + + Normally it only makes sense to use the :switch:`-p` switch if dynamic elaboration checking is used (:switch:`-gnatE` switch used for compilation). This is because in the default static elaboration mode, all necessary ``Elaborate`` and ``Elaborate_All`` pragmas are implicitly inserted. - These implicit pragmas are still respected by the binder in - :switch:`-p` mode, so a - safe elaboration order is assured. + These implicit pragmas are still respected by the binder in :switch:`-p` + mode, so a safe elaboration order is assured. - Note that :switch:`-p` is not intended for - production use; it is more for debugging/experimental use. + Note that :switch:`-p` is not intended for production use; it is more for + debugging/experimental use. .. _Output_Control: diff --git a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst index 336555c..160dbdf 100644 --- a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst @@ -50,9 +50,14 @@ Elaboration code is executed as follows: In addition to the Ada terminology, this appendix defines the following terms: +* *Invocation* + + The act of calling a subprogram, instantiating a generic, or activating a + task. + * *Scenario* - A construct that is elaborated or executed by elaboration code is referred to + A construct that is elaborated or invoked by elaboration code is referred to as an *elaboration scenario* or simply a **scenario**. GNAT recognizes the following scenarios: @@ -102,7 +107,7 @@ Elaboration code may appear in two distinct contexts: In the example above, the call to ``Server.Func`` is an elaboration scenario because it appears at the library level of package ``Client``. Note that the declaration of package ``Nested`` is ignored according to the definition - given above. As a result, the call to ``Server.Func`` will be executed when + given above. As a result, the call to ``Server.Func`` will be invoked when the spec of unit ``Client`` is elaborated. * *Package body statements* @@ -124,7 +129,7 @@ Elaboration code may appear in two distinct contexts: In the example above, the call to ``Proc`` is an elaboration scenario because it appears within the statement sequence of package body ``Client``. As a - result, the call to ``Proc`` will be executed when the body of ``Client`` is + result, the call to ``Proc`` will be invoked when the body of ``Client`` is elaborated. .. _Elaboration_Order: @@ -137,19 +142,19 @@ executed is referred to as **elaboration order**. Within a single unit, elaboration code is executed in sequential order. -:: + :: - package body Client is - Result : ... := Server.Func; + package body Client is + Result : ... := Server.Func; - procedure Proc is - package Inst is new Server.Gen; - begin - Inst.Eval (Result); - end Proc; - begin - Proc; - end Client; + procedure Proc is + package Inst is new Server.Gen; + begin + Inst.Eval (Result); + end Proc; + begin + Proc; + end Client; In the example above, the elaboration order within package body ``Client`` is as follows: @@ -173,52 +178,56 @@ factors: * |withed| units +* parent units + * purity of units * preelaborability of units * presence of elaboration control pragmas +* invocations performed in elaboration code + A program may have several elaboration orders depending on its structure. -:: + :: - package Server is - function Func (Index : Integer) return Integer; - end Server; + package Server is + function Func (Index : Integer) return Integer; + end Server; -:: + :: - package body Server is - Results : array (1 .. 5) of Integer := (1, 2, 3, 4, 5); + package body Server is + Results : array (1 .. 5) of Integer := (1, 2, 3, 4, 5); - function Func (Index : Integer) return Integer is - begin - return Results (Index); - end Func; - end Server; + function Func (Index : Integer) return Integer is + begin + return Results (Index); + end Func; + end Server; -:: + :: - with Server; - package Client is - Val : constant Integer := Server.Func (3); - end Client; + with Server; + package Client is + Val : constant Integer := Server.Func (3); + end Client; -:: + :: - with Client; - procedure Main is begin null; end Main; + with Client; + procedure Main is begin null; end Main; The following elaboration order exhibits a fundamental problem referred to as *access-before-elaboration* or simply **ABE**. -:: + :: - spec of Server - spec of Client - body of Server - body of Main + spec of Server + spec of Client + body of Server + body of Main The elaboration of ``Server``'s spec materializes function ``Func``, making it callable. The elaboration of ``Client``'s spec elaborates the declaration of @@ -236,19 +245,20 @@ vein as index or null exclusion checks. A failed ABE check raises exception The following elaboration order avoids the ABE problem and the program can be successfully elaborated. -:: + :: - spec of Server - body of Server - spec of Client - body of Main + spec of Server + body of Server + spec of Client + body of Main Ada states that a total elaboration order must exist, but it does not define what this order is. A compiler is thus tasked with choosing a suitable elaboration order which satisfies the dependencies imposed by |with| clauses, -unit categorization, and elaboration control pragmas. Ideally an order which -avoids ABE problems should be chosen, however a compiler may not always find -such an order due to complications with respect to control and data flow. +unit categorization, elaboration control pragmas, and invocations performed in +elaboration code. Ideally an order that avoids ABE problems should be chosen, +however a compiler may not always find such an order due to complications with +respect to control and data flow. .. _Checking_the_Elaboration_Order: @@ -268,7 +278,7 @@ provides three lines of defense: * *Dynamic semantics* Dynamic checks are performed at run time, to ensure that a target is - elaborated prior to a scenario that executes it, thus avoiding ABE problems. + elaborated prior to a scenario that invokes it, thus avoiding ABE problems. A failed run-time check raises exception ``Program_Error``. The following restrictions apply: @@ -290,8 +300,7 @@ provides three lines of defense: The restrictions above can be summarized by the following rule: *If a target has a body, then this body must be elaborated prior to the - execution of the scenario that invokes, instantiates, or activates the - target.* + scenario that invokes the target.* * *Elaboration control* @@ -346,7 +355,7 @@ the desired elaboration order and avoiding ABE problems altogether. Pragma ``Elaborate_Body`` requires that the body of a unit is elaborated immediately after its spec. This restriction guarantees that no client - scenario can execute a server target before the target body has been + scenario can invoke a server target before the target body has been elaborated because the spec and body are effectively "glued" together. :: @@ -601,24 +610,53 @@ elaboration order and to diagnose elaboration problems. * *Dynamic elaboration model* - This is the most permissive of the three elaboration models. When the - dynamic model is in effect, GNAT assumes that all code within all units in - a partition is elaboration code. GNAT performs very few diagnostics and - generates run-time checks to verify the elaboration order of a program. This - behavior is identical to that specified by the Ada Reference Manual. The - dynamic model is enabled with compiler switch :switch:`-gnatE`. + This is the most permissive of the three elaboration models and emulates the + behavior specified by the Ada Reference Manual. When the dynamic model is in + effect, GNAT makes the following assumptions: + + - All code within all units in a partition is considered to be elaboration + code. + + - Some of the invocations in elaboration code may not take place at runtime + due to conditional execution. + + GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios + that invoke internal targets. In addition, GNAT generates run-time checks for + all external targets and for all scenarios that may exhibit ABE problems. + + The elaboration order is obtained by honoring all |with| clauses, purity and + preelaborability of units, and elaboration control pragmas. The dynamic model + attempts to take all invocations in elaboration code into account. If an + invocation leads to a circularity, GNAT ignores the invocation based on the + assumptions stated above. An order obtained using the dynamic model may fail + an ABE check at runtime when GNAT ignored an invocation. + + The dynamic model is enabled with compiler switch :switch:`-gnatE`. .. index:: Static elaboration model * *Static elaboration model* This is the middle ground of the three models. When the static model is in - effect, GNAT performs extensive diagnostics on a unit-by-unit basis for all - scenarios that elaborate or execute internal targets. GNAT also generates - run-time checks for all external targets and for all scenarios that may - exhibit ABE problems. Finally, GNAT installs implicit ``Elaborate`` and - ``Elaborate_All`` pragmas for server units based on the dependencies of - client units. The static model is the default model in GNAT. + effect, GNAT makes the following assumptions: + + - Only code at the library level and in package body statements within all + units in a partition is considered to be elaboration code. + + - All invocations in elaboration will take place at runtime, regardless of + conditional execution. + + GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios + that invoke internal targets. In addition, GNAT generates run-time checks for + all external targets and for all scenarios that may exhibit ABE problems. + + The elaboration order is obtained by honoring all |with| clauses, purity and + preelaborability of units, presence of elaboration control pragmas, and all + invocations in elaboration code. An order obtained using the static model is + guaranteed to be ABE problem-free, excluding dispatching calls and + access-to-subprogram types. + + The static model is the default model in GNAT. .. index:: SPARK elaboration model @@ -627,17 +665,23 @@ elaboration order and to diagnose elaboration problems. This is the most conservative of the three models and enforces the SPARK rules of elaboration as defined in the SPARK Reference Manual, section 7.7. The SPARK model is in effect only when a scenario and a target reside in a - region subject to SPARK_Mode On, otherwise the dynamic or static model is in - effect. + region subject to ``SPARK_Mode On``, otherwise the dynamic or static model + is in effect. -.. index:: Legacy elaboration model + The SPARK model is enabled with compiler switch :switch:`-gnatd.v`. -* *Legacy elaboration model* +.. index:: Legacy elaboration models + +* *Legacy elaboration models* In addition to the three elaboration models outlined above, GNAT provides the - elaboration model of pre-18.x versions referred to as `legacy elaboration - model`. The legacy elaboration model is enabled with compiler switch - :switch:`-gnatH`. + following legacy models: + + - `Legacy elaboration-checking model` available in pre-18.x versions of GNAT. + This model is enabled with compiler switch :switch:`-gnatH`. + + - `Legacy elaboration-order model` available in pre-20.x versions of GNAT. + This model is enabled with binder switch :switch:`-H`. .. index:: Relaxed elaboration mode @@ -645,812 +689,430 @@ The dynamic, legacy, and static models can be relaxed using compiler switch :switch:`-gnatJ`, making them more permissive. Note that in this mode, GNAT may not diagnose certain elaboration issues or install run-time checks. -.. _Common_Elaboration_Model_Traits": +.. _Mixing_Elaboration_Models: -Common Elaboration-model Traits -=============================== +Mixing Elaboration Models +========================= -All three GNAT models are able to detect elaboration problems related to -dispatching calls and a particular kind of ABE referred to as *guaranteed ABE*. +It is possible to mix units compiled with a different elaboration model, +however the following rules must be observed: -* *Dispatching calls* +* A client unit compiled with the dynamic model can only |with| a server unit + that meets at least one of the following criteria: - GNAT installs run-time checks for each primitive subprogram of each tagged - type defined in a partition on the assumption that a dispatching call - invoked at elaboration time will execute one of these primitives. As a - result, a dispatching call that executes a primitive whose body has not - been elaborated yet will raise exception ``Program_Error`` at run time. The - checks can be suppressed using pragma ``Suppress (Elaboration_Check)``. + - The server unit is compiled with the dynamic model. -* *Guaranteed ABE* + - The server unit is a GNAT implementation unit from the ``Ada``, ``GNAT``, + ``Interfaces``, or ``System`` hierarchies. - A guaranteed ABE arises when the body of a target is not elaborated early - enough, and causes all scenarios that directly execute the target to fail. + - The server unit has pragma ``Pure`` or ``Preelaborate``. - :: + - The client unit has an explicit ``Elaborate_All`` pragma for the server + unit. - package body Guaranteed_ABE is - function ABE return Integer; +These rules ensure that elaboration checks are not omitted. If the rules are +violated, the binder emits a warning: - Val : constant Integer := ABE; + :: - function ABE return Integer is - begin - ... - end ABE; - end Guaranteed_ABE; + warning: "x.ads" has dynamic elaboration checks and with's + warning: "y.ads" which has static elaboration checks - In the example above, the elaboration of ``Guaranteed_ABE``'s body elaborates - the declaration of ``Val``. This invokes function ``ABE``, however the body - of ``ABE`` has not been elaborated yet. GNAT emits similar diagnostics in all - three models: +The warnings can be suppressed by binder switch :switch:`-ws`. - :: +.. _ABE_Diagnostics: - 1. package body Guaranteed_ABE is - 2. function ABE return Integer; - 3. - 4. Val : constant Integer := ABE; - | - >>> warning: cannot call "ABE" before body seen - >>> warning: Program_Error will be raised at run time +ABE Diagnostics +=============== - 5. - 6. function ABE return Integer is - 7. begin - 8. ... - 9. end ABE; - 10. end Guaranteed_ABE; +GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios +that invoke internal targets, regardless of whether the dynamic, SPARK, or +static model is in effect. Note that GNAT emits warnings rather than hard errors whenever it encounters an elaboration problem. This is because the elaboration model in effect may be too -conservative, or a particular scenario may not be elaborated or executed due to -data and control flow. The warnings can be suppressed selectively with ``pragma -Warnigns (Off)`` or globally with compiler switch :switch:`-gnatwL`. - -.. _Dynamic_Elaboration_Model_in_GNAT: - -Dynamic Elaboration Model in GNAT -================================= - -The dynamic model assumes that all code within all units in a partition is -elaboration code. As a result, run-time checks are installed for each scenario -regardless of whether the target is internal or external. The checks can be -suppressed using pragma ``Suppress (Elaboration_Check)``. This behavior is -identical to that specified by the Ada Reference Manual. The following example -showcases run-time checks installed by GNAT to verify the elaboration state of -package ``Dynamic_Model``. - -:: - - with Server; - package body Dynamic_Model is - procedure API is - begin - ... - end API; - - - package Inst is new Server.Gen; +conservative, or a particular scenario may not be invoked due conditional +execution. The warnings can be suppressed selectively with ``pragma Warnings +(Off)`` or globally with compiler switch :switch:`-gnatwL`. - T : Server.Task_Type; +A *guaranteed ABE* arises when the body of a target is not elaborated early +enough, and causes *all* scenarios that directly invoke the target to fail. - begin - - - - Server.Proc; - end Dynamic_Model; - -The checks verify that the body of a target has been successfully elaborated -before a scenario activates, calls, or instantiates a target. - -Note that no scenario within package ``Dynamic_Model`` calls procedure ``API``. -In fact, procedure ``API`` may not be invoked by elaboration code within the -partition, however the dynamic model assumes that this can happen. + :: -The dynamic model emits very few diagnostics, but can make suggestions on -missing ``Elaborate`` and ``Elaborate_All`` pragmas for library-level -scenarios. This information is available when compiler switch :switch:`-gnatel` -is in effect. + package body Guaranteed_ABE is + function ABE return Integer; -:: + Val : constant Integer := ABE; - 1. with Server; - 2. package body Dynamic_Model is - 3. Val : constant Integer := Server.Func; - | - >>> info: call to "Func" during elaboration - >>> info: missing pragma "Elaborate_All" for unit "Server" + function ABE return Integer is + begin + ... + end ABE; + end Guaranteed_ABE; - 4. end Dynamic_Model; +In the example above, the elaboration of ``Guaranteed_ABE``'s body elaborates +the declaration of ``Val``. This invokes function ``ABE``, however the body of +``ABE`` has not been elaborated yet. GNAT emits the following diagnostic: -.. _Static_Elaboration_Model_in_GNAT: + :: -Static Elaboration Model in GNAT -================================ + 4. Val : constant Integer := ABE; + | + >>> warning: cannot call "ABE" before body seen + >>> warning: Program_Error will be raised at run time -In contrast to the dynamic model, the static model is more precise in its -analysis of elaboration code. The model makes a clear distinction between -internal and external targets, and resorts to different diagnostics and -run-time checks based on the nature of the target. +A *conditional ABE* arises when the body of a target is not elaborated early +enough, and causes *some* scenarios that directly invoke the target to fail. -* *Internal targets* + :: - The static model performs extensive diagnostics on scenarios which elaborate - or execute internal targets. The warnings resulting from these diagnostics - are enabled by default, but can be suppressed selectively with ``pragma - Warnings (Off)`` or globally with compiler switch :switch:`-gnatwL`. + 1. package body Conditional_ABE is + 2. procedure Force_Body is null; + 3. + 4. generic + 5. with function Func return Integer; + 6. package Gen is + 7. Val : constant Integer := Func; + 8. end Gen; + 9. + 10. function ABE return Integer; + 11. + 12. function Cause_ABE return Boolean is + 13. package Inst is new Gen (ABE); + 14. begin + 15. ... + 16. end Cause_ABE; + 17. + 18. Val : constant Boolean := Cause_ABE; + 19. + 20. function ABE return Integer is + 21. begin + 22. ... + 23. end ABE; + 24. + 25. Safe : constant Boolean := Cause_ABE; + 26. end Conditional_ABE; + +In the example above, the elaboration of package body ``Conditional_ABE`` +elaborates the declaration of ``Val``. This invokes function ``Cause_ABE``, +which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of +``Inst`` invokes function ``ABE``, however the body of ``ABE`` has not been +elaborated yet. GNAT emits the following diagnostic: :: - 1. package body Static_Model is - 2. generic - 3. with function Func return Integer; - 4. package Gen is - 5. Val : constant Integer := Func; - 6. end Gen; - 7. - 8. function ABE return Integer; - 9. - 10. function Cause_ABE return Boolean is - 11. package Inst is new Gen (ABE); + 13. package Inst is new Gen (ABE); | - >>> warning: in instantiation at line 5 + >>> warning: in instantiation at line 7 >>> warning: cannot call "ABE" before body seen >>> warning: Program_Error may be raised at run time - >>> warning: body of unit "Static_Model" elaborated - >>> warning: function "Cause_ABE" called at line 16 - >>> warning: function "ABE" called at line 5, instance at line 11 - - 12. begin - 13. ... - 14. end Cause_ABE; - 15. - 16. Val : constant Boolean := Cause_ABE; - 17. - 18. function ABE return Integer is - 19. begin - 20. ... - 21. end ABE; - 22. end Static_Model; - - The example above illustrates an ABE problem within package ``Static_Model``, - which is hidden by several layers of indirection. The elaboration of package - body ``Static_Model`` elaborates the declaration of ``Val``. This invokes - function ``Cause_ABE``, which instantiates generic unit ``Gen`` as ``Inst``. - The elaboration of ``Inst`` invokes function ``ABE``, however the body of - ``ABE`` has not been elaborated yet. - -* *External targets* - - The static model installs run-time checks to verify the elaboration status - of server targets only when the scenario that elaborates or executes that - target is part of the elaboration code of the client unit. The checks can be - suppressed using pragma ``Suppress (Elaboration_Check)``. + >>> warning: body of unit "Conditional_ABE" elaborated + >>> warning: function "Cause_ABE" called at line 18 + >>> warning: function "ABE" called at line 7, instance at line 13 - :: +Note that the same ABE problem does not occur with the elaboration of +declaration ``Safe`` because the body of function ``ABE`` has already been +elaborated at that point. - with Server; - package body Static_Model is - generic - with function Func return Integer; - package Gen is - Val : constant Integer := Func; - end Gen; - - function Call_Func return Boolean is - - package Inst is new Gen (Server.Func); - begin - ... - end Call_Func; - - Val : constant Boolean := Call_Func; - end Static_Model; +.. _SPARK_Diagnostics: - In the example above, the elaboration of package body ``Static_Model`` - elaborates the declaration of ``Val``. This invokes function ``Call_Func``, - which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of - ``Inst`` invokes function ``Server.Func``. Since ``Server.Func`` is an - external target, GNAT installs a run-time check to verify that its body has - been elaborated. +SPARK Diagnostics +================= - In addition to checks, the static model installs implicit ``Elaborate`` and - ``Elaborate_All`` pragmas to guarantee safe elaboration use of server units. - This information is available when compiler switch :switch:`-gnatel` is in - effect. +GNAT enforces the SPARK rules of elaboration as defined in the SPARK Reference +Manual section 7.7 when compiler switch :switch:`-gnatd.v` is in effect. Note +that GNAT emits hard errors whenever it encounters a violation of the SPARK +rules. :: - 1. with Server; - 2. package body Static_Model is - 3. generic - 4. with function Func return Integer; - 5. package Gen is - 6. Val : constant Integer := Func; - 7. end Gen; - 8. - 9. function Call_Func return Boolean is - 10. package Inst is new Gen (Server.Func); - | - >>> info: instantiation of "Gen" during elaboration - >>> info: in instantiation at line 6 - >>> info: call to "Func" during elaboration - >>> info: in instantiation at line 6 - >>> info: implicit pragma "Elaborate_All" generated for unit "Server" - >>> info: body of unit "Static_Model" elaborated - >>> info: function "Call_Func" called at line 15 - >>> info: function "Func" called at line 6, instance at line 10 - - 11. begin - 12. ... - 13. end Call_Func; - 14. - 15. Val : constant Boolean := Call_Func; - | - >>> info: call to "Call_Func" during elaboration - - 16. end Static_Model; - - In the example above, the elaboration of package body ``Static_Model`` - elaborates the declaration of ``Val``. This invokes function ``Call_Func``, - which instantiates generic unit ``Gen`` as ``Inst``. The elaboration of - ``Inst`` invokes function ``Server.Func``. Since ``Server.Func`` is an - external target, GNAT installs an implicit ``Elaborate_All`` pragma for unit - ``Server``. The pragma guarantees that both the spec and body of ``Server``, - along with any additional dependencies that ``Server`` may require, are - elaborated prior to the body of ``Static_Model``. - -.. _SPARK_Elaboration_Model_in_GNAT: - -SPARK Elaboration Model in GNAT -=============================== - -The SPARK model is identical to the static model in its handling of internal -targets. The SPARK model, however, requires explicit ``Elaborate`` or -``Elaborate_All`` pragmas to be present in the program when a target is -external, and compiler switch :switch:`-gnatd.v` is in effect. - -:: - - 1. with Server; - 2. package body SPARK_Model with SPARK_Mode is - 3. Val : constant Integer := Server.Func; - | - >>> call to "Func" during elaboration in SPARK - >>> unit "SPARK_Model" requires pragma "Elaborate_All" for "Server" - >>> body of unit "SPARK_Model" elaborated - >>> function "Func" called at line 3 - - 4. end SPARK_Model; - -Legacy Elaboration Model in GNAT -================================ - -The legacy elaboration model is provided for compatibility with code bases -developed with pre-18.x versions of GNAT. It is similar in functionality to -the dynamic and static models of post-18.x version of GNAT, but may differ -in terms of diagnostics and run-time checks. The legacy elaboration model is -enabled with compiler switch :switch:`-gnatH`. + 1. with Server; + 2. package body SPARK_Diagnostics with SPARK_Mode is + 3. Val : constant Integer := Server.Func; + | + >>> call to "Func" during elaboration in SPARK + >>> unit "SPARK_Diagnostics" requires pragma "Elaborate_All" for "Server" + >>> body of unit "SPARK_Model" elaborated + >>> function "Func" called at line 3 -.. _Mixing_Elaboration_Models: + 4. end SPARK_Diagnostics; -Mixing Elaboration Models -========================= +.. _Elaboration_Circularities: -It is possible to mix units compiled with a different elaboration model, -however the following rules must be observed: +Elaboration Circularities +========================= -* A client unit compiled with the dynamic model can only |with| a server unit - that meets at least one of the following criteria: +An **elaboration circularity** occurs whenever the elaboration of a set of +units enters a deadlocked state, where each unit is waiting for another unit +to be elaborated. This situation may be the result of improper use of |with| +clauses, elaboration control pragmas, or invocations in elaboration code. - - The server unit is compiled with the dynamic model. +The following example showcases an elaboration circularity. - - The server unit is a GNAT implementation unit from the Ada, GNAT, - Interfaces, or System hierarchies. + :: - - The server unit has pragma ``Pure`` or ``Preelaborate``. + with B; pragma Elaborate (B); + package A is + end A; - - The client unit has an explicit ``Elaborate_All`` pragma for the server - unit. + :: -These rules ensure that elaboration checks are not omitted. If the rules are -violated, the binder emits a warning: + package B is + procedure Force_Body; + end B; -:: + :: - warning: "x.ads" has dynamic elaboration checks and with's - warning: "y.ads" which has static elaboration checks + with C; + package body B is + procedure Force_Body is null; -The warnings can be suppressed by binder switch :switch:`-ws`. + Elab : constant Integer := C.Func; + end B; -.. _Elaboration_Circularities: + :: -Elaboration Circularities -========================= + package C is + function Func return Integer; + end C; -If the binder cannot find an acceptable elaboration order, it outputs detailed -diagnostics describing an **elaboration circularity**. + :: -:: + with A; + package body C is + function Func return Integer is + begin + ... + end Func; + end C; - package Server is - function Func return Integer; - end Server; +The binder emits the following diagnostic: -:: + :: - with Client; - package body Server is - function Func return Integer is - begin - ... - end Func; - end Server; + error: Elaboration circularity detected + info: + info: Reason: + info: + info: unit "a (spec)" depends on its own elaboration + info: + info: Circularity: + info: + info: unit "a (spec)" has with clause and pragma Elaborate for unit "b (spec)" + info: unit "b (body)" is in the closure of pragma Elaborate + info: unit "b (body)" invokes a construct of unit "c (body)" at elaboration time + info: unit "c (body)" has with clause for unit "a (spec)" + info: + info: Suggestions: + info: + info: remove pragma Elaborate for unit "b (body)" in unit "a (spec)" + info: use the dynamic elaboration model (compiler switch -gnatE) -:: +The diagnostic consist of the following sections: - with Server; - package Client is - Val : constant Integer := Server.Func; - end Client; +* Reason -:: + This section provides a short explanation describing why the set of units + could not be ordered. - with Client; - procedure Main is begin null; end Main; +* Circularity -:: + This section enumerates the units comprising the deadlocked set, along with + their interdependencies. - error: elaboration circularity detected - info: "server (body)" must be elaborated before "client (spec)" - info: reason: implicit Elaborate_All in unit "client (spec)" - info: recompile "client (spec)" with -gnatel for full details - info: "server (body)" - info: must be elaborated along with its spec: - info: "server (spec)" - info: which is withed by: - info: "client (spec)" - info: "client (spec)" must be elaborated before "server (body)" - info: reason: with clause +* Suggestions -In the example above, ``Client`` must be elaborated prior to ``Main`` by virtue -of a |with| clause. The elaboration of ``Client`` invokes ``Server.Func``, and -static model generates an implicit ``Elaborate_All`` pragma for ``Server``. The -pragma implies that both the spec and body of ``Server``, along with any units -they |with|, must be elaborated prior to ``Client``. However, ``Server``'s body -|withs| ``Client``, implying that ``Client`` must be elaborated prior to -``Server``. The end result is that ``Client`` must be elaborated prior to -``Client``, and this leads to a circularity. + This section enumerates various tactics for eliminating the circularity. .. _Resolving_Elaboration_Circularities: Resolving Elaboration Circularities =================================== -When faced with an elaboration circularity, a programmer has several options -available. - -* *Fix the program* - - The most desirable option from the point of view of long-term maintenance - is to rearrange the program so that the elaboration problems are avoided. - One useful technique is to place the elaboration code into separate child - packages. Another is to move some of the initialization code to explicitly - invoked subprograms, where the program controls the order of initialization - explicitly. Although this is the most desirable option, it may be impractical - and involve too much modification, especially in the case of complex legacy - code. - -* *Switch to more permissive elaboration model* - - If the compilation was performed using the static model, enable the dynamic - model with compiler switch :switch:`-gnatE`. GNAT will no longer generate - implicit ``Elaborate`` and ``Elaborate_All`` pragmas, resulting in a behavior - identical to that specified by the Ada Reference Manual. The binder will - generate an executable program that may or may not raise ``Program_Error``, - and it is the programmer's responsibility to ensure that it does not raise - ``Program_Error``. +The most desirable option from the point of view of long-term maintenance is to +rearrange the program so that the elaboration problems are avoided. One useful +technique is to place the elaboration code into separate child packages. +Another is to move some of the initialization code to explicitly invoked +subprograms, where the program controls the order of initialization explicitly. +Although this is the most desirable option, it may be impractical and involve +too much modification, especially in the case of complex legacy code. - If the compilation was performed using a post-18.x version of GNAT, consider - using the legacy elaboration model, in the following order: +When faced with an elaboration circularity, the programmer should also consider +the tactics given in the suggestions section of the circularity diagnostic. +Depending on the units involved in the circularity, their |with| clauses, +purity, preelaborability, presence of elaboration control pragmas and +invocations at elaboration time, the binder may suggest one or more of the +following tactics to eliminate the circularity: - - Use the relaxed static elaboration model, with compiler switch - :switch:`-gnatJ`. +* Pragma Elaborate elimination - - Use the relaxed dynamic elaboration model, with compiler switches - :switch:`-gnatE` :switch:`-gnatJ`. - - - Use the legacy static elaboration model, with compiler switch - :switch:`-gnatH`. + :: - - Use the legacy dynamic elaboration model, with compiler switches - :switch:`-gnatE` :switch:`-gnatH`. + remove pragma Elaborate for unit "..." in unit "..." -* *Suppress all elaboration checks* + This tactic is suggested when the binder has determine that pragma + ``Elaborate`` - The drawback of run-time checks is that they generate overhead at run time, - both in space and time. If the programmer is absolutely sure that a program - will not raise an elaboration-related ``Program_Error``, then using the - pragma ``Suppress (Elaboration_Check)`` globally (as a configuration pragma) - will eliminate all run-time checks. + - Prevents a set of units from being elaborated. -* *Suppress elaboration checks selectively* + - The removal of the pragma will not eliminate the semantic effects of the + pragma. In other words, the argument of the pragma will still be elaborated + prior to the unit containing the pragma. - If a scenario cannot possibly lead to an elaboration ``Program_Error``, - and the binder nevertheless complains about implicit ``Elaborate`` and - ``Elaborate_All`` pragmas that lead to elaboration circularities, it - is possible to suppress the generation of implicit ``Elaborate`` and - ``Elaborate_All`` pragmas, as well as run-time checks. Clearly this can - be unsafe, and it is the responsibility of the programmer to make sure - that the resulting program has no elaboration anomalies. Pragma - ``Suppress (Elaboration_Check)`` can be used with different levels of - granularity to achieve these effects. + - The removal of the pragma will enable the successful ordering of the units. - - *Target suppression* + The programmer should remove the pragma as advised, and rebuild the program. - When the pragma is placed in a declarative part, without a second argument - naming an entity, it will suppress implicit ``Elaborate`` and - ``Elaborate_All`` pragma generation, as well as run-time checks, on all - targets within the region. +* Pragma Elaborate_All elimination - :: + :: - package Range_Suppress is - pragma Suppress (Elaboration_Check); + remove pragma Elaborate_All for unit "..." in unit "..." - function Func return Integer; + This tactic is suggested when the binder has determined that pragma + ``Elaborate_All`` - generic - procedure Gen; + - Prevents a set of units from being elaborated. - pragma Unsuppress (Elaboration_Check); + - The removal of the pragma will not eliminate the semantic effects of the + pragma. In other words, the argument of the pragma along with its |with| + closure will still be elaborated prior to the unit containing the pragma. - task type Tsk; - end Range_Suppress; + - The removal of the pragma will enable the successful ordering of the units. - In the example above, a pair of Suppress/Unsuppress pragmas define a region - of suppression within package ``Range_Suppress``. As a result, no implicit - ``Elaborate`` and ``Elaborate_All`` pragmas, nor any run-time checks, will - be generated by callers of ``Func`` and instantiators of ``Gen``. Note that - task type ``Tsk`` is not within this region. + The programmer should remove the pragma as advised, and rebuild the program. - An alternative to the region-based suppression is to use multiple - ``Suppress`` pragmas with arguments naming specific entities for which - elaboration checks should be suppressed: +* Pragma Elaborate_All downgrade - :: - - package Range_Suppress is - function Func return Integer; - pragma Suppress (Elaboration_Check, Func); + :: - generic - procedure Gen; - pragma Suppress (Elaboration_Check, Gen); + change pragma Elaborate_All for unit "..." to Elaborate in unit "..." - task type Tsk; - end Range_Suppress; + This tactic is always suggested with the pragma ``Elaborate_All`` elimination + tactic. It offers a different alernative of guaranteeing that the argument of + the pragma will still be elaborated prior to the unit containing the pragma. - - *Scenario suppression* + The programmer should update the pragma as advised, and rebuild the program. - When the pragma ``Suppress`` is placed in a declarative or statement - part, without an entity argument, it will suppress implicit ``Elaborate`` - and ``Elaborate_All`` pragma generation, as well as run-time checks, on - all scenarios within the region. +* Pragma Elaborate_Body elimination - :: + :: - with Server; - package body Range_Suppress is - pragma Suppress (Elaboration_Check); + remove pragma Elaborate_Body in unit "..." - function Func return Integer is - begin - return Server.Func; - end Func; + This tactic is suggested when the binder has determined that pragma + ``Elaborate_Body`` - procedure Gen is - begin - Server.Proc; - end Gen; + - Prevents a set of units from being elaborated. - pragma Unsuppress (Elaboration_Check); + - The removal of the pragma will enable the successful ordering of the units. - task body Tsk is - begin - Server.Proc; - end Tsk; - end Range_Suppress; - - In the example above, a pair of Suppress/Unsuppress pragmas define a region - of suppression within package body ``Range_Suppress``. As a result, the - calls to ``Server.Func`` in ``Func`` and ``Server.Proc`` in ``Gen`` will - not generate any implicit ``Elaborate`` and ``Elaborate_All`` pragmas or - run-time checks. - -.. _Resolving_Task_Issues: - -Resolving Task Issues -===================== - -The model of execution in Ada dictates that elaboration must first take place, -and only then can the main program be started. Tasks which are activated during -elaboration violate this model and may lead to serious concurrent problems at -elaboration time. - -A task can be activated in two different ways: - -* The task is created by an allocator in which case it is activated immediately - after the allocator is evaluated. - -* The task is declared at the library level or within some nested master in - which case it is activated before starting execution of the statement - sequence of the master defining the task. - -Since the elaboration of a partition is performed by the environment task -servicing that partition, any tasks activated during elaboration may be in -a race with the environment task, and lead to unpredictable state and behavior. -The static model seeks to avoid such interactions by assuming that all code in -the task body is executed at elaboration time, if the task was activated by -elaboration code. - -:: - - package Decls is - task Lib_Task is - entry Start; - end Lib_Task; - - type My_Int is new Integer; - - function Ident (M : My_Int) return My_Int; - end Decls; - -:: - - with Utils; - package body Decls is - task body Lib_Task is - begin - accept Start; - Utils.Put_Val (2); - end Lib_Task; - - function Ident (M : My_Int) return My_Int is - begin - return M; - end Ident; - end Decls; - -:: - - with Decls; - package Utils is - procedure Put_Val (Arg : Decls.My_Int); - end Utils; - -:: - - with Ada.Text_IO; use Ada.Text_IO; - package body Utils is - procedure Put_Val (Arg : Decls.My_Int) is - begin - Put_Line (Arg'Img); - end Put_Val; - end Utils; - -:: - - with Decls; - procedure Main is - begin - Decls.Lib_Task.Start; - end Main; - -When the above example is compiled with the static model, an elaboration -circularity arises: - -:: - - error: elaboration circularity detected - info: "decls (body)" must be elaborated before "decls (body)" - info: reason: implicit Elaborate_All in unit "decls (body)" - info: recompile "decls (body)" with -gnatel for full details - info: "decls (body)" - info: must be elaborated along with its spec: - info: "decls (spec)" - info: which is withed by: - info: "utils (spec)" - info: which is withed by: - info: "decls (body)" - -In the above example, ``Decls`` must be elaborated prior to ``Main`` by virtue -of a with clause. The elaboration of ``Decls`` activates task ``Lib_Task``. The -static model conservatibely assumes that all code within the body of -``Lib_Task`` is executed, and generates an implicit ``Elaborate_All`` pragma -for ``Units`` due to the call to ``Utils.Put_Val``. The pragma implies that -both the spec and body of ``Utils``, along with any units they |with|, -must be elaborated prior to ``Decls``. However, ``Utils``'s spec |withs| -``Decls``, implying that ``Decls`` must be elaborated before ``Utils``. The end -result is that ``Utils`` must be elaborated prior to ``Utils``, and this -leads to a circularity. - -In reality, the example above will not exhibit an ABE problem at run time. -When the body of task ``Lib_Task`` is activated, execution will wait for entry -``Start`` to be accepted, and the call to ``Utils.Put_Val`` will not take place -at elaboration time. Task ``Lib_Task`` will resume its execution after the main -program is executed because ``Main`` performs a rendezvous with -``Lib_Task.Start``, and at that point all units have already been elaborated. -As a result, the static model may seem overly conservative, partly because it -does not take control and data flow into account. - -When faced with a task elaboration circularity, a programmer has several -options available: - -* *Use the dynamic model* - - The dynamic model does not generate implicit ``Elaborate`` and - ``Elaborate_All`` pragmas. Instead, it will install checks prior to every - call in the example above, thus verifying the successful elaboration of - ``Utils.Put_Val`` in case the call to it takes place at elaboration time. - The dynamic model is enabled with compiler switch :switch:`-gnatE`. + Note that the binder cannot determine whether the pragma is required for + other purposes, such as guaranteeing the initialization of a variable + declared in the spec by elaboration code in the body. -* *Isolate the tasks* + The programmer should remove the pragma as advised, and rebuild the program. - Relocating tasks in their own separate package could decouple them from - dependencies that would otherwise cause an elaboration circularity. The - example above can be rewritten as follows: +* Use of dynamic elaboration model :: - package Decls1 is -- new - task Lib_Task is - entry Start; - end Lib_Task; - end Decls1; + use the dynamic elaboration model (compiler switch -gnatE) - :: + This tactic is suggested when the binder has determined that an invocation at + elaboration time - with Utils; - package body Decls1 is -- new - task body Lib_Task is - begin - accept Start; - Utils.Put_Val (2); - end Lib_Task; - end Decls1; + - Prevents a set of units from being elaborated. - :: + - The use of the dynamic model will enable the successful ordering of the + units. - package Decls2 is -- new - type My_Int is new Integer; - function Ident (M : My_Int) return My_Int; - end Decls2; + The programmer has two options: - :: + - Determine the units involved in the invocation using the detailed + invocation information, and add compiler switch :switch:`-gnatE` to the + compilation arguments of selected files only. This approach will yield + safer elaboration orders compared to the other option because it will + minimize the opportunities presented to the dynamic model for ignoring + invocations. - with Utils; - package body Decls2 is -- new - function Ident (M : My_Int) return My_Int is - begin - return M; - end Ident; - end Decls2; + - Add compiler switch :switch:`-gnatE` to the general compilation arguments. - :: - - with Decls2; - package Utils is - procedure Put_Val (Arg : Decls2.My_Int); - end Utils; +* Use of detailed invocation information :: - with Ada.Text_IO; use Ada.Text_IO; - package body Utils is - procedure Put_Val (Arg : Decls2.My_Int) is - begin - Put_Line (Arg'Img); - end Put_Val; - end Utils; + use detailed invocation information (compiler switch -gnatd_F) - :: + This tactic is always suggested with the use of the dynamic model tactic. It + causes the circularity section of the circularity diagnostic to describe the + flow of elaboration code from a unit to a unit, enumerating all such paths in + the process. - with Decls1; - procedure Main is - begin - Decls1.Lib_Task.Start; - end Main; - -* *Declare the tasks* + The programmer should analyze this information to determine which units + should be compiled with the dynamic model. - The original example uses a single task declaration for ``Lib_Task``. An - explicit task type declaration and a properly placed task object could avoid - the dependencies that would otherwise cause an elaboration circularity. The - example can be rewritten as follows: +* Forced dependency elimination :: - package Decls is - task type Lib_Task is -- new - entry Start; - end Lib_Task; + remove the dependency of unit "..." on unit "..." from the argument of switch -f - type My_Int is new Integer; + This tactic is suggested when the binder has determined that a dependency + present in the forced delboration order file indicated by binder switch + :switch:`-f` - function Ident (M : My_Int) return My_Int; - end Decls; + - Prevents a set of units from being elaborated. - :: + - The removal of the dependency will enable the successful ordering of the + units. - with Utils; - package body Decls is - task body Lib_Task is - begin - accept Start; - Utils.Put_Val (2); - end Lib_Task; + The programmer should edit the forced elaboration order file, remove the + dependency, and rebind the program. - function Ident (M : My_Int) return My_Int is - begin - return M; - end Ident; - end Decls; +* All forced dependency elimination :: - with Decls; - package Utils is - procedure Put_Val (Arg : Decls.My_Int); - end Utils; + remove switch -f - :: + This tactic is suggested in case editing the forced elaboration order file is + not an option. - with Ada.Text_IO; use Ada.Text_IO; - package body Utils is - procedure Put_Val (Arg : Decls.My_Int) is - begin - Put_Line (Arg'Img); - end Put_Val; - end Utils; - - :: + The programmer should remove binder switch :switch:`-f` from the binder + arguments, and rebind. - with Decls; - package Obj_Decls is -- new - Task_Obj : Decls.Lib_Task; - end Obj_Decls; +* Multiple circularities diagnostic :: - with Obj_Decls; - procedure Main is - begin - Obj_Decls.Task_Obj.Start; -- new - end Main; + diagnose all circularities (binder switch -d_C) -* *Use restriction No_Entry_Calls_In_Elaboration_Code* + By default, the binder will diagnose only the highest precedence circularity. + If the program contains multiple circularities, the binder will suggest the + use of binder switch :switch:`-d_C` in order to obtain the diagnostics of all + circularities. - The issue exhibited in the original example under this section revolves - around the body of ``Lib_Task`` blocking on an accept statement. There is - no rule to prevent elaboration code from performing entry calls, however in - practice this is highly unusual. In addition, the pattern of starting tasks - at elaboration time and then immediately blocking on accept or select - statements is quite common. + The programmer should add binder switch :switch:`-d_C` to the binder + arguments, and rebind. - If a programmer knows that elaboration code will not perform any entry - calls, then the programmer can indicate that the static model should not - process the remainder of a task body once an accept or select statement has - been encountered. This behavior can be specified by a configuration pragma: +If none of the tactics suggested by the binder eliminate the elaboration +circularity, the programmer should consider using one of the legacy elaboration +models, in the following order: - :: +* Use the pre-20.x legacy elaboration order model, with binder switch + :switch:`-H`. + +* Use both pre-18.x and pre-20.x legacy elaboration models, with compiler + switch :switch:`-gnatH` and binder switch :switch:`-H`. - pragma Restrictions (No_Entry_Calls_In_Elaboration_Code); +* Use the relaxed static elaboration model, with compiler switches + :switch:`-gnatH` :switch:`-gnatJ` and binder switch :switch:`-H`. - In addition to the change in behavior with respect to task bodies, the - static model will verify that no entry calls take place at elaboration time. +* Use the relaxed dynamic elaboration model, with compiler switches + :switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE` and binder switch + :switch:`-H`. .. _Elaboration_Related_Compiler_Switches: @@ -1465,13 +1127,17 @@ the elaboration order chosen by the binder. :switch:`-gnatE` Dynamic elaboration checking mode enabled - When this switch is in effect, GNAT activates the dynamic elaboration model. + When this switch is in effect, GNAT activates the dynamic model. .. index:: -gnatel (gnat) :switch:`-gnatel` Turn on info messages on generated Elaborate[_All] pragmas + This switch is only applicable to the pre-20.x legacy elaboration models. + The post-20.x elaboration model no longer relies on implicitly generated + ``Elaborate`` and ``Elaborate_All`` pragmas to order units. + When this switch is in effect, GNAT will emit the following supplementary information depending on the elaboration model in effect. @@ -1482,7 +1148,7 @@ the elaboration order chosen by the binder. - *Static model* - GNAT will indicate all scenarios executed during elaboration. In addition, + GNAT will indicate all scenarios invoked during elaboration. In addition, it will provide detailed traceback when an implicit ``Elaborate`` or ``Elaborate_All`` pragma is generated. @@ -1615,29 +1281,24 @@ options: as their origins. Elaboration warnings are enabled with compiler switch :switch:`-gnatwl`. -* Use switch :switch:`-gnatel` to obtain messages on generated implicit - ``Elaborate`` and ``Elaborate_All`` pragmas. The trace information could - indicate why a server unit must be elaborated prior to a client unit. - -* If the warnings produced by the static model indicate that a task is - involved, consider the options in section `Resolving Task Issues`_. +* Cosider the tactics given in the suggestions section of the circularity + diagnostic. * If none of the steps outlined above resolve the circularity, use a more permissive elaboration model, in the following order: - - Use the dynamic elaboration model, with compiler switch :switch:`-gnatE`. - - - Use the legacy static elaboration model, with compiler switch - :switch:`-gnatH`. + - Use the pre-20.x legacy elaboration order model, with binder switch + :switch:`-H`. - - Use the legacy dynamic elaboration model, with compiler switches - :switch:`-gnatH` :switch:`-gnatE`. + - Use both pre-18.x and pre-20.x legacy elaboration models, with compiler + switch :switch:`-gnatH` and binder switch :switch:`-H`. - - Use the relaxed legacy static elaboration model, with compiler switches - :switch:`-gnatH` :switch:`-gnatJ`. + - Use the relaxed static elaboration model, with compiler switches + :switch:`-gnatH` :switch:`-gnatJ` and binder switch :switch:`-H`. - - Use the relaxed legacy dynamic elaboration model, with compiler switches - :switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE`. + - Use the relaxed dynamic elaboration model, with compiler switches + :switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE` and binder switch + :switch:`-H`. .. _Inspecting_the_Chosen_Elaboration_Order: @@ -1650,128 +1311,128 @@ elaboration order appears as a sequence of calls to ``Elab_Body`` and ``Elab_Spec``, interspersed with assignments to `Exxx` which indicates that a particular unit is elaborated. For example: -:: - - System.Soft_Links'Elab_Body; - E14 := True; - System.Secondary_Stack'Elab_Body; - E18 := True; - System.Exception_Table'Elab_Body; - E24 := True; - Ada.Io_Exceptions'Elab_Spec; - E67 := True; - Ada.Tags'Elab_Spec; - Ada.Streams'Elab_Spec; - E43 := True; - Interfaces.C'Elab_Spec; - E69 := True; - System.Finalization_Root'Elab_Spec; - E60 := True; - System.Os_Lib'Elab_Body; - E71 := True; - System.Finalization_Implementation'Elab_Spec; - System.Finalization_Implementation'Elab_Body; - E62 := True; - Ada.Finalization'Elab_Spec; - E58 := True; - Ada.Finalization.List_Controller'Elab_Spec; - E76 := True; - System.File_Control_Block'Elab_Spec; - E74 := True; - System.File_Io'Elab_Body; - E56 := True; - Ada.Tags'Elab_Body; - E45 := True; - Ada.Text_Io'Elab_Spec; - Ada.Text_Io'Elab_Body; - E07 := True; + :: + + System.Soft_Links'Elab_Body; + E14 := True; + System.Secondary_Stack'Elab_Body; + E18 := True; + System.Exception_Table'Elab_Body; + E24 := True; + Ada.Io_Exceptions'Elab_Spec; + E67 := True; + Ada.Tags'Elab_Spec; + Ada.Streams'Elab_Spec; + E43 := True; + Interfaces.C'Elab_Spec; + E69 := True; + System.Finalization_Root'Elab_Spec; + E60 := True; + System.Os_Lib'Elab_Body; + E71 := True; + System.Finalization_Implementation'Elab_Spec; + System.Finalization_Implementation'Elab_Body; + E62 := True; + Ada.Finalization'Elab_Spec; + E58 := True; + Ada.Finalization.List_Controller'Elab_Spec; + E76 := True; + System.File_Control_Block'Elab_Spec; + E74 := True; + System.File_Io'Elab_Body; + E56 := True; + Ada.Tags'Elab_Body; + E45 := True; + Ada.Text_Io'Elab_Spec; + Ada.Text_Io'Elab_Body; + E07 := True; Note also binder switch :switch:`-l`, which outputs the chosen elaboration order and provides a more readable form of the above: -:: - - ada (spec) - interfaces (spec) - system (spec) - system.case_util (spec) - system.case_util (body) - system.concat_2 (spec) - system.concat_2 (body) - system.concat_3 (spec) - system.concat_3 (body) - system.htable (spec) - system.parameters (spec) - system.parameters (body) - system.crtl (spec) - interfaces.c_streams (spec) - interfaces.c_streams (body) - system.restrictions (spec) - system.restrictions (body) - system.standard_library (spec) - system.exceptions (spec) - system.exceptions (body) - system.storage_elements (spec) - system.storage_elements (body) - system.secondary_stack (spec) - system.stack_checking (spec) - system.stack_checking (body) - system.string_hash (spec) - system.string_hash (body) - system.htable (body) - system.strings (spec) - system.strings (body) - system.traceback (spec) - system.traceback (body) - system.traceback_entries (spec) - system.traceback_entries (body) - ada.exceptions (spec) - ada.exceptions.last_chance_handler (spec) - system.soft_links (spec) - system.soft_links (body) - ada.exceptions.last_chance_handler (body) - system.secondary_stack (body) - system.exception_table (spec) - system.exception_table (body) - ada.io_exceptions (spec) - ada.tags (spec) - ada.streams (spec) - interfaces.c (spec) - interfaces.c (body) - system.finalization_root (spec) - system.finalization_root (body) - system.memory (spec) - system.memory (body) - system.standard_library (body) - system.os_lib (spec) - system.os_lib (body) - system.unsigned_types (spec) - system.stream_attributes (spec) - system.stream_attributes (body) - system.finalization_implementation (spec) - system.finalization_implementation (body) - ada.finalization (spec) - ada.finalization (body) - ada.finalization.list_controller (spec) - ada.finalization.list_controller (body) - system.file_control_block (spec) - system.file_io (spec) - system.file_io (body) - system.val_uns (spec) - system.val_util (spec) - system.val_util (body) - system.val_uns (body) - system.wch_con (spec) - system.wch_con (body) - system.wch_cnv (spec) - system.wch_jis (spec) - system.wch_jis (body) - system.wch_cnv (body) - system.wch_stw (spec) - system.wch_stw (body) - ada.tags (body) - ada.exceptions (body) - ada.text_io (spec) - ada.text_io (body) - text_io (spec) - gdbstr (body) + :: + + ada (spec) + interfaces (spec) + system (spec) + system.case_util (spec) + system.case_util (body) + system.concat_2 (spec) + system.concat_2 (body) + system.concat_3 (spec) + system.concat_3 (body) + system.htable (spec) + system.parameters (spec) + system.parameters (body) + system.crtl (spec) + interfaces.c_streams (spec) + interfaces.c_streams (body) + system.restrictions (spec) + system.restrictions (body) + system.standard_library (spec) + system.exceptions (spec) + system.exceptions (body) + system.storage_elements (spec) + system.storage_elements (body) + system.secondary_stack (spec) + system.stack_checking (spec) + system.stack_checking (body) + system.string_hash (spec) + system.string_hash (body) + system.htable (body) + system.strings (spec) + system.strings (body) + system.traceback (spec) + system.traceback (body) + system.traceback_entries (spec) + system.traceback_entries (body) + ada.exceptions (spec) + ada.exceptions.last_chance_handler (spec) + system.soft_links (spec) + system.soft_links (body) + ada.exceptions.last_chance_handler (body) + system.secondary_stack (body) + system.exception_table (spec) + system.exception_table (body) + ada.io_exceptions (spec) + ada.tags (spec) + ada.streams (spec) + interfaces.c (spec) + interfaces.c (body) + system.finalization_root (spec) + system.finalization_root (body) + system.memory (spec) + system.memory (body) + system.standard_library (body) + system.os_lib (spec) + system.os_lib (body) + system.unsigned_types (spec) + system.stream_attributes (spec) + system.stream_attributes (body) + system.finalization_implementation (spec) + system.finalization_implementation (body) + ada.finalization (spec) + ada.finalization (body) + ada.finalization.list_controller (spec) + ada.finalization.list_controller (body) + system.file_control_block (spec) + system.file_io (spec) + system.file_io (body) + system.val_uns (spec) + system.val_util (spec) + system.val_util (body) + system.val_uns (body) + system.wch_con (spec) + system.wch_con (body) + system.wch_cnv (spec) + system.wch_jis (spec) + system.wch_jis (body) + system.wch_cnv (body) + system.wch_stw (spec) + system.wch_stw (body) + ada.tags (body) + ada.exceptions (body) + ada.text_io (spec) + ada.text_io (body) + text_io (spec) + gdbstr (body) diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 2867018..b0b3bdd 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -533,15 +533,11 @@ Elaboration Order Handling in GNAT * Checking the Elaboration Order:: * Controlling the Elaboration Order in Ada:: * Controlling the Elaboration Order in GNAT:: -* Common Elaboration-model Traits:: -* Dynamic Elaboration Model in GNAT:: -* Static Elaboration Model in GNAT:: -* SPARK Elaboration Model in GNAT:: -* Legacy Elaboration Model in GNAT:: * Mixing Elaboration Models:: +* ABE Diagnostics:: +* SPARK Diagnostics:: * Elaboration Circularities:: * Resolving Elaboration Circularities:: -* Resolving Task Issues:: * Elaboration-related Compiler Switches:: * Summary of Procedures for Elaboration Control:: * Inspecting the Chosen Elaboration Order:: @@ -9585,7 +9581,8 @@ checking options to be controlled from the command line. @item @code{-gnatE} -Full dynamic elaboration checks. +Dynamic elaboration checking mode enabled. For further details see +@ref{f,,Elaboration Order Handling in GNAT}. @end table @geindex -gnatf (gcc) @@ -9651,8 +9648,9 @@ Output usage information. The output is written to @code{stdout}. @item @code{-gnatH} -Legacy elaboration-checking mode enabled. When this switch is in effect, the -pre-18.x access-before-elaboration model becomes the de facto model. +Legacy elaboration-checking mode enabled. When this switch is in effect, +the pre-18.x access-before-elaboration model becomes the de facto model. +For further details see @ref{f,,Elaboration Order Handling in GNAT}. @end table @geindex -gnati (gcc) @@ -9749,7 +9747,8 @@ Select statements Synchronous task suspension @end itemize -and does not emit compile-time diagnostics or run-time checks. +and does not emit compile-time diagnostics or run-time checks. For further +details see @ref{f,,Elaboration Order Handling in GNAT}. @end table @geindex -gnatk (gcc) @@ -15747,7 +15746,8 @@ Currently the same as @code{-Ea}. @item @code{-f@emph{elab-order}} -Force elaboration order. +Force elaboration order. For further details see @ref{120,,Elaboration Control} +and @ref{f,,Elaboration Order Handling in GNAT}. @end table @geindex -F (gnatbind) @@ -15774,22 +15774,41 @@ flag checks are generated. @item @code{-h} Output usage (help) information. +@end table + +@geindex -H (gnatbind) + + +@table @asis + +@item @code{-H} + +Legacy elaboration order model enabled. For further details see +@ref{f,,Elaboration Order Handling in GNAT}. +@end table @geindex -H32 (gnatbind) + +@table @asis + @item @code{-H32} Use 32-bit allocations for @code{__gnat_malloc} (and thus for access types). -For further details see @ref{120,,Dynamic Allocation Control}. +For further details see @ref{121,,Dynamic Allocation Control}. +@end table @geindex -H64 (gnatbind) @geindex __gnat_malloc + +@table @asis + @item @code{-H64} Use 64-bit allocations for @code{__gnat_malloc} (and thus for access types). -For further details see @ref{120,,Dynamic Allocation Control}. +For further details see @ref{121,,Dynamic Allocation Control}. @geindex -I (gnatbind) @@ -16019,7 +16038,7 @@ Enable dynamic stack usage, with @code{n} results stored and displayed at program termination. A result is generated when a task terminates. Results that can't be stored are displayed on the fly, at task termination. This option is currently not supported on Itanium -platforms. (See @ref{121,,Dynamic Stack Usage Analysis} for details.) +platforms. (See @ref{122,,Dynamic Stack Usage Analysis} for details.) @geindex -v (gnatbind) @@ -16088,7 +16107,7 @@ no arguments. @end menu @node Consistency-Checking Modes,Binder Error Message Control,,Switches for gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat consistency-checking-modes}@anchor{122}@anchor{gnat_ugn/building_executable_programs_with_gnat id35}@anchor{123} +@anchor{gnat_ugn/building_executable_programs_with_gnat consistency-checking-modes}@anchor{123}@anchor{gnat_ugn/building_executable_programs_with_gnat id35}@anchor{124} @subsubsection Consistency-Checking Modes @@ -16142,7 +16161,7 @@ case the checking against sources has already been performed by @end table @node Binder Error Message Control,Elaboration Control,Consistency-Checking Modes,Switches for gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat id36}@anchor{124}@anchor{gnat_ugn/building_executable_programs_with_gnat binder-error-message-control}@anchor{125} +@anchor{gnat_ugn/building_executable_programs_with_gnat id36}@anchor{125}@anchor{gnat_ugn/building_executable_programs_with_gnat binder-error-message-control}@anchor{126} @subsubsection Binder Error Message Control @@ -16252,12 +16271,12 @@ with extreme care. @end table @node Elaboration Control,Output Control,Binder Error Message Control,Switches for gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat id37}@anchor{126}@anchor{gnat_ugn/building_executable_programs_with_gnat elaboration-control}@anchor{127} +@anchor{gnat_ugn/building_executable_programs_with_gnat id37}@anchor{127}@anchor{gnat_ugn/building_executable_programs_with_gnat elaboration-control}@anchor{120} @subsubsection Elaboration Control The following switches provide additional control over the elaboration -order. For full details see @ref{f,,Elaboration Order Handling in GNAT}. +order. For further details see @ref{f,,Elaboration Order Handling in GNAT}. @geindex -f (gnatbind) @@ -16302,30 +16321,38 @@ above forced elaboration order file. Blank lines and Ada-style comments are ignored. Unit names that do not exist in the program are ignored. Units in the GNAT predefined library are also ignored. +@end table @geindex -p (gnatbind) + +@table @asis + @item @code{-p} -Normally the binder attempts to choose an elaboration order that is -likely to minimize the likelihood of an elaboration order error resulting -in raising a @code{Program_Error} exception. This switch reverses the -action of the binder, and requests that it deliberately choose an order -that is likely to maximize the likelihood of an elaboration error. -This is useful in ensuring portability and avoiding dependence on -accidental fortuitous elaboration ordering. +Pessimistic elaboration order -Normally it only makes sense to use the @code{-p} -switch if dynamic +This switch is only applicable to the pre-20.x legacy elaboration models. +The post-20.x elaboration model uses a more informed approach of ordering +the units. + +Normally the binder attempts to choose an elaboration order that is likely to +minimize the likelihood of an elaboration order error resulting in raising a +@code{Program_Error} exception. This switch reverses the action of the binder, +and requests that it deliberately choose an order that is likely to maximize +the likelihood of an elaboration error. This is useful in ensuring +portability and avoiding dependence on accidental fortuitous elaboration +ordering. + +Normally it only makes sense to use the @code{-p} switch if dynamic elaboration checking is used (@code{-gnatE} switch used for compilation). This is because in the default static elaboration mode, all necessary @code{Elaborate} and @code{Elaborate_All} pragmas are implicitly inserted. -These implicit pragmas are still respected by the binder in -@code{-p} mode, so a -safe elaboration order is assured. +These implicit pragmas are still respected by the binder in @code{-p} +mode, so a safe elaboration order is assured. -Note that @code{-p} is not intended for -production use; it is more for debugging/experimental use. +Note that @code{-p} is not intended for production use; it is more for +debugging/experimental use. @end table @node Output Control,Dynamic Allocation Control,Elaboration Control,Switches for gnatbind @@ -16410,7 +16437,7 @@ be used to improve code generation in some cases. @end table @node Dynamic Allocation Control,Binding with Non-Ada Main Programs,Output Control,Switches for gnatbind -@anchor{gnat_ugn/building_executable_programs_with_gnat dynamic-allocation-control}@anchor{120}@anchor{gnat_ugn/building_executable_programs_with_gnat id39}@anchor{12a} +@anchor{gnat_ugn/building_executable_programs_with_gnat dynamic-allocation-control}@anchor{121}@anchor{gnat_ugn/building_executable_programs_with_gnat id39}@anchor{12a} @subsubsection Dynamic Allocation Control @@ -23169,7 +23196,7 @@ subprogram whose stack usage might be larger than the specified amount of bytes. The wording is in keeping with the qualifier documented above. @node Dynamic Stack Usage Analysis,,Static Stack Usage Analysis,Stack Related Facilities -@anchor{gnat_ugn/gnat_and_program_execution dynamic-stack-usage-analysis}@anchor{121}@anchor{gnat_ugn/gnat_and_program_execution id60}@anchor{1c6} +@anchor{gnat_ugn/gnat_and_program_execution dynamic-stack-usage-analysis}@anchor{122}@anchor{gnat_ugn/gnat_and_program_execution id60}@anchor{1c6} @subsection Dynamic Stack Usage Analysis @@ -27187,15 +27214,11 @@ GNAT, either automatically or with explicit programming features. * Checking the Elaboration Order:: * Controlling the Elaboration Order in Ada:: * Controlling the Elaboration Order in GNAT:: -* Common Elaboration-model Traits:: -* Dynamic Elaboration Model in GNAT:: -* Static Elaboration Model in GNAT:: -* SPARK Elaboration Model in GNAT:: -* Legacy Elaboration Model in GNAT:: * Mixing Elaboration Models:: +* ABE Diagnostics:: +* SPARK Diagnostics:: * Elaboration Circularities:: * Resolving Elaboration Circularities:: -* Resolving Task Issues:: * Elaboration-related Compiler Switches:: * Summary of Procedures for Elaboration Control:: * Inspecting the Chosen Elaboration Order:: @@ -27243,9 +27266,15 @@ In addition to the Ada terminology, this appendix defines the following terms: @itemize * @item +@emph{Invocation} + +The act of calling a subprogram, instantiating a generic, or activating a +task. + +@item @emph{Scenario} -A construct that is elaborated or executed by elaboration code is referred to +A construct that is elaborated or invoked by elaboration code is referred to as an @emph{elaboration scenario} or simply a @strong{scenario}. GNAT recognizes the following scenarios: @@ -27317,7 +27346,7 @@ end Client; In the example above, the call to @code{Server.Func} is an elaboration scenario because it appears at the library level of package @code{Client}. Note that the declaration of package @code{Nested} is ignored according to the definition -given above. As a result, the call to @code{Server.Func} will be executed when +given above. As a result, the call to @code{Server.Func} will be invoked when the spec of unit @code{Client} is elaborated. @item @@ -27340,7 +27369,7 @@ end Client; In the example above, the call to @code{Proc} is an elaboration scenario because it appears within the statement sequence of package body @code{Client}. As a -result, the call to @code{Proc} will be executed when the body of @code{Client} is +result, the call to @code{Proc} will be invoked when the body of @code{Client} is elaborated. @end itemize @@ -27354,6 +27383,8 @@ executed is referred to as @strong{elaboration order}. Within a single unit, elaboration code is executed in sequential order. +@quotation + @example package body Client is Result : ... := Server.Func; @@ -27367,6 +27398,7 @@ begin Proc; end Client; @end example +@end quotation In the example above, the elaboration order within package body @code{Client} is as follows: @@ -27414,6 +27446,9 @@ factors: @emph{with}ed units @item +parent units + +@item purity of units @item @@ -27421,10 +27456,15 @@ preelaborability of units @item presence of elaboration control pragmas + +@item +invocations performed in elaboration code @end itemize A program may have several elaboration orders depending on its structure. +@quotation + @example package Server is function Func (Index : Integer) return Integer; @@ -27453,16 +27493,20 @@ end Client; with Client; procedure Main is begin null; end Main; @end example +@end quotation The following elaboration order exhibits a fundamental problem referred to as @emph{access-before-elaboration} or simply @strong{ABE}. +@quotation + @example spec of Server spec of Client body of Server body of Main @end example +@end quotation The elaboration of @code{Server}'s spec materializes function @code{Func}, making it callable. The elaboration of @code{Client}'s spec elaborates the declaration of @@ -27480,19 +27524,23 @@ vein as index or null exclusion checks. A failed ABE check raises exception The following elaboration order avoids the ABE problem and the program can be successfully elaborated. +@quotation + @example spec of Server body of Server spec of Client body of Main @end example +@end quotation Ada states that a total elaboration order must exist, but it does not define what this order is. A compiler is thus tasked with choosing a suitable elaboration order which satisfies the dependencies imposed by @emph{with} clauses, -unit categorization, and elaboration control pragmas. Ideally an order which -avoids ABE problems should be chosen, however a compiler may not always find -such an order due to complications with respect to control and data flow. +unit categorization, elaboration control pragmas, and invocations performed in +elaboration code. Ideally an order that avoids ABE problems should be chosen, +however a compiler may not always find such an order due to complications with +respect to control and data flow. @node Checking the Elaboration Order,Controlling the Elaboration Order in Ada,Elaboration Order,Elaboration Order Handling in GNAT @anchor{gnat_ugn/elaboration_order_handling_in_gnat id4}@anchor{231}@anchor{gnat_ugn/elaboration_order_handling_in_gnat checking-the-elaboration-order}@anchor{232} @@ -27517,7 +27565,7 @@ always elaborated prior to Client. The same principle applies to child units @emph{Dynamic semantics} Dynamic checks are performed at run time, to ensure that a target is -elaborated prior to a scenario that executes it, thus avoiding ABE problems. +elaborated prior to a scenario that invokes it, thus avoiding ABE problems. A failed run-time check raises exception @code{Program_Error}. The following restrictions apply: @@ -27546,8 +27594,7 @@ associated task type has been elaborated. The restrictions above can be summarized by the following rule: @emph{If a target has a body, then this body must be elaborated prior to the -execution of the scenario that invokes, instantiates, or activates the -target.} +scenario that invokes the target.} @item @emph{Elaboration control} @@ -27623,7 +27670,7 @@ but still strong enough to prevent ABE problems within a unit. Pragma @code{Elaborate_Body} requires that the body of a unit is elaborated immediately after its spec. This restriction guarantees that no client -scenario can execute a server target before the target body has been +scenario can invoke a server target before the target body has been elaborated because the spec and body are effectively "glued" together. @example @@ -27884,7 +27931,7 @@ Note that one additional advantage of using @code{Elaborate} and @code{Elaborate is that the program continues to stay in the last state (one or more correct orders exist) even if maintenance changes the bodies of targets. -@node Controlling the Elaboration Order in GNAT,Common Elaboration-model Traits,Controlling the Elaboration Order in Ada,Elaboration Order Handling in GNAT +@node Controlling the Elaboration Order in GNAT,Mixing Elaboration Models,Controlling the Elaboration Order in Ada,Elaboration Order Handling in GNAT @anchor{gnat_ugn/elaboration_order_handling_in_gnat id6}@anchor{235}@anchor{gnat_ugn/elaboration_order_handling_in_gnat controlling-the-elaboration-order-in-gnat}@anchor{236} @section Controlling the Elaboration Order in GNAT @@ -27901,12 +27948,34 @@ elaboration order and to diagnose elaboration problems. @item @emph{Dynamic elaboration model} -This is the most permissive of the three elaboration models. When the -dynamic model is in effect, GNAT assumes that all code within all units in -a partition is elaboration code. GNAT performs very few diagnostics and -generates run-time checks to verify the elaboration order of a program. This -behavior is identical to that specified by the Ada Reference Manual. The -dynamic model is enabled with compiler switch @code{-gnatE}. +This is the most permissive of the three elaboration models and emulates the +behavior specified by the Ada Reference Manual. When the dynamic model is in +effect, GNAT makes the following assumptions: + + +@itemize - + +@item +All code within all units in a partition is considered to be elaboration +code. + +@item +Some of the invocations in elaboration code may not take place at runtime +due to conditional execution. +@end itemize + +GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios +that invoke internal targets. In addition, GNAT generates run-time checks for +all external targets and for all scenarios that may exhibit ABE problems. + +The elaboration order is obtained by honoring all @emph{with} clauses, purity and +preelaborability of units, and elaboration control pragmas. The dynamic model +attempts to take all invocations in elaboration code into account. If an +invocation leads to a circularity, GNAT ignores the invocation based on the +assumptions stated above. An order obtained using the dynamic model may fail +an ABE check at runtime when GNAT ignored an invocation. + +The dynamic model is enabled with compiler switch @code{-gnatE}. @end itemize @geindex Static elaboration model @@ -27918,12 +27987,31 @@ dynamic model is enabled with compiler switch @code{-gnatE}. @emph{Static elaboration model} This is the middle ground of the three models. When the static model is in -effect, GNAT performs extensive diagnostics on a unit-by-unit basis for all -scenarios that elaborate or execute internal targets. GNAT also generates -run-time checks for all external targets and for all scenarios that may -exhibit ABE problems. Finally, GNAT installs implicit @code{Elaborate} and -@code{Elaborate_All} pragmas for server units based on the dependencies of -client units. The static model is the default model in GNAT. +effect, GNAT makes the following assumptions: + + +@itemize - + +@item +Only code at the library level and in package body statements within all +units in a partition is considered to be elaboration code. + +@item +All invocations in elaboration will take place at runtime, regardless of +conditional execution. +@end itemize + +GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios +that invoke internal targets. In addition, GNAT generates run-time checks for +all external targets and for all scenarios that may exhibit ABE problems. + +The elaboration order is obtained by honoring all @emph{with} clauses, purity and +preelaborability of units, presence of elaboration control pragmas, and all +invocations in elaboration code. An order obtained using the static model is +guaranteed to be ABE problem-free, excluding dispatching calls and +access-to-subprogram types. + +The static model is the default model in GNAT. @end itemize @geindex SPARK elaboration model @@ -27937,21 +28025,34 @@ client units. The static model is the default model in GNAT. This is the most conservative of the three models and enforces the SPARK rules of elaboration as defined in the SPARK Reference Manual, section 7.7. The SPARK model is in effect only when a scenario and a target reside in a -region subject to SPARK_Mode On, otherwise the dynamic or static model is in -effect. +region subject to @code{SPARK_Mode On}, otherwise the dynamic or static model +is in effect. + +The SPARK model is enabled with compiler switch @code{-gnatd.v}. @end itemize -@geindex Legacy elaboration model +@geindex Legacy elaboration models @itemize * @item -@emph{Legacy elaboration model} +@emph{Legacy elaboration models} In addition to the three elaboration models outlined above, GNAT provides the -elaboration model of pre-18.x versions referred to as @cite{legacy elaboration model}. The legacy elaboration model is enabled with compiler switch -@code{-gnatH}. +following legacy models: + + +@itemize - + +@item +@cite{Legacy elaboration-checking model} available in pre-18.x versions of GNAT. +This model is enabled with compiler switch @code{-gnatH}. + +@item +@cite{Legacy elaboration-order model} available in pre-20.x versions of GNAT. +This model is enabled with binder switch @code{-H}. +@end itemize @end itemize @geindex Relaxed elaboration mode @@ -27960,878 +28061,536 @@ The dynamic, legacy, and static models can be relaxed using compiler switch @code{-gnatJ}, making them more permissive. Note that in this mode, GNAT may not diagnose certain elaboration issues or install run-time checks. -@node Common Elaboration-model Traits,Dynamic Elaboration Model in GNAT,Controlling the Elaboration Order in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat common-elaboration-model-traits}@anchor{237}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{238} -@section Common Elaboration-model Traits +@node Mixing Elaboration Models,ABE Diagnostics,Controlling the Elaboration Order in GNAT,Elaboration Order Handling in GNAT +@anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{237}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id7}@anchor{238} +@section Mixing Elaboration Models -All three GNAT models are able to detect elaboration problems related to -dispatching calls and a particular kind of ABE referred to as @emph{guaranteed ABE}. +It is possible to mix units compiled with a different elaboration model, +however the following rules must be observed: @itemize * @item -@emph{Dispatching calls} +A client unit compiled with the dynamic model can only @emph{with} a server unit +that meets at least one of the following criteria: -GNAT installs run-time checks for each primitive subprogram of each tagged -type defined in a partition on the assumption that a dispatching call -invoked at elaboration time will execute one of these primitives. As a -result, a dispatching call that executes a primitive whose body has not -been elaborated yet will raise exception @code{Program_Error} at run time. The -checks can be suppressed using pragma @code{Suppress (Elaboration_Check)}. + +@itemize - @item -@emph{Guaranteed ABE} +The server unit is compiled with the dynamic model. -A guaranteed ABE arises when the body of a target is not elaborated early -enough, and causes all scenarios that directly execute the target to fail. +@item +The server unit is a GNAT implementation unit from the @code{Ada}, @code{GNAT}, +@code{Interfaces}, or @code{System} hierarchies. -@example -package body Guaranteed_ABE is - function ABE return Integer; +@item +The server unit has pragma @code{Pure} or @code{Preelaborate}. - Val : constant Integer := ABE; +@item +The client unit has an explicit @code{Elaborate_All} pragma for the server +unit. +@end itemize +@end itemize - function ABE return Integer is - begin - ... - end ABE; -end Guaranteed_ABE; -@end example +These rules ensure that elaboration checks are not omitted. If the rules are +violated, the binder emits a warning: -In the example above, the elaboration of @code{Guaranteed_ABE}'s body elaborates -the declaration of @code{Val}. This invokes function @code{ABE}, however the body -of @code{ABE} has not been elaborated yet. GNAT emits similar diagnostics in all -three models: +@quotation @example -1. package body Guaranteed_ABE is -2. function ABE return Integer; -3. -4. Val : constant Integer := ABE; - | - >>> warning: cannot call "ABE" before body seen - >>> warning: Program_Error will be raised at run time - -5. -6. function ABE return Integer is -7. begin -8. ... -9. end ABE; -10. end Guaranteed_ABE; +warning: "x.ads" has dynamic elaboration checks and with's +warning: "y.ads" which has static elaboration checks @end example -@end itemize +@end quotation -Note that GNAT emits warnings rather than hard errors whenever it encounters an -elaboration problem. This is because the elaboration model in effect may be too -conservative, or a particular scenario may not be elaborated or executed due to -data and control flow. The warnings can be suppressed selectively with @code{pragma -Warnigns (Off)} or globally with compiler switch @code{-gnatwL}. +The warnings can be suppressed by binder switch @code{-ws}. -@node Dynamic Elaboration Model in GNAT,Static Elaboration Model in GNAT,Common Elaboration-model Traits,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat dynamic-elaboration-model-in-gnat}@anchor{239}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id8}@anchor{23a} -@section Dynamic Elaboration Model in GNAT +@node ABE Diagnostics,SPARK Diagnostics,Mixing Elaboration Models,Elaboration Order Handling in GNAT +@anchor{gnat_ugn/elaboration_order_handling_in_gnat abe-diagnostics}@anchor{239}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id8}@anchor{23a} +@section ABE Diagnostics -The dynamic model assumes that all code within all units in a partition is -elaboration code. As a result, run-time checks are installed for each scenario -regardless of whether the target is internal or external. The checks can be -suppressed using pragma @code{Suppress (Elaboration_Check)}. This behavior is -identical to that specified by the Ada Reference Manual. The following example -showcases run-time checks installed by GNAT to verify the elaboration state of -package @code{Dynamic_Model}. +GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios +that invoke internal targets, regardless of whether the dynamic, SPARK, or +static model is in effect. -@example -with Server; -package body Dynamic_Model is - procedure API is - begin - ... - end API; +Note that GNAT emits warnings rather than hard errors whenever it encounters an +elaboration problem. This is because the elaboration model in effect may be too +conservative, or a particular scenario may not be invoked due conditional +execution. The warnings can be suppressed selectively with @code{pragma Warnings +(Off)} or globally with compiler switch @code{-gnatwL}. - - package Inst is new Server.Gen; +A @emph{guaranteed ABE} arises when the body of a target is not elaborated early +enough, and causes @emph{all} scenarios that directly invoke the target to fail. - T : Server.Task_Type; +@quotation -begin - +@example +package body Guaranteed_ABE is + function ABE return Integer; - - Server.Proc; -end Dynamic_Model; -@end example + Val : constant Integer := ABE; -The checks verify that the body of a target has been successfully elaborated -before a scenario activates, calls, or instantiates a target. + function ABE return Integer is + begin + ... + end ABE; +end Guaranteed_ABE; +@end example +@end quotation -Note that no scenario within package @code{Dynamic_Model} calls procedure @code{API}. -In fact, procedure @code{API} may not be invoked by elaboration code within the -partition, however the dynamic model assumes that this can happen. +In the example above, the elaboration of @code{Guaranteed_ABE}'s body elaborates +the declaration of @code{Val}. This invokes function @code{ABE}, however the body of +@code{ABE} has not been elaborated yet. GNAT emits the following diagnostic: -The dynamic model emits very few diagnostics, but can make suggestions on -missing @code{Elaborate} and @code{Elaborate_All} pragmas for library-level -scenarios. This information is available when compiler switch @code{-gnatel} -is in effect. +@quotation @example -1. with Server; -2. package body Dynamic_Model is -3. Val : constant Integer := Server.Func; - | - >>> info: call to "Func" during elaboration - >>> info: missing pragma "Elaborate_All" for unit "Server" - -4. end Dynamic_Model; +4. Val : constant Integer := ABE; + | + >>> warning: cannot call "ABE" before body seen + >>> warning: Program_Error will be raised at run time @end example +@end quotation -@node Static Elaboration Model in GNAT,SPARK Elaboration Model in GNAT,Dynamic Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat static-elaboration-model-in-gnat}@anchor{23b}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{23c} -@section Static Elaboration Model in GNAT - - -In contrast to the dynamic model, the static model is more precise in its -analysis of elaboration code. The model makes a clear distinction between -internal and external targets, and resorts to different diagnostics and -run-time checks based on the nature of the target. - - -@itemize * - -@item -@emph{Internal targets} +A @emph{conditional ABE} arises when the body of a target is not elaborated early +enough, and causes @emph{some} scenarios that directly invoke the target to fail. -The static model performs extensive diagnostics on scenarios which elaborate -or execute internal targets. The warnings resulting from these diagnostics -are enabled by default, but can be suppressed selectively with @code{pragma -Warnings (Off)} or globally with compiler switch @code{-gnatwL}. +@quotation @example - 1. package body Static_Model is - 2. generic - 3. with function Func return Integer; - 4. package Gen is - 5. Val : constant Integer := Func; - 6. end Gen; - 7. - 8. function ABE return Integer; + 1. package body Conditional_ABE is + 2. procedure Force_Body is null; + 3. + 4. generic + 5. with function Func return Integer; + 6. package Gen is + 7. Val : constant Integer := Func; + 8. end Gen; 9. -10. function Cause_ABE return Boolean is -11. package Inst is new Gen (ABE); - | - >>> warning: in instantiation at line 5 - >>> warning: cannot call "ABE" before body seen - >>> warning: Program_Error may be raised at run time - >>> warning: body of unit "Static_Model" elaborated - >>> warning: function "Cause_ABE" called at line 16 - >>> warning: function "ABE" called at line 5, instance at line 11 - -12. begin -13. ... -14. end Cause_ABE; -15. -16. Val : constant Boolean := Cause_ABE; +10. function ABE return Integer; +11. +12. function Cause_ABE return Boolean is +13. package Inst is new Gen (ABE); +14. begin +15. ... +16. end Cause_ABE; 17. -18. function ABE return Integer is -19. begin -20. ... -21. end ABE; -22. end Static_Model; +18. Val : constant Boolean := Cause_ABE; +19. +20. function ABE return Integer is +21. begin +22. ... +23. end ABE; +24. +25. Safe : constant Boolean := Cause_ABE; +26. end Conditional_ABE; @end example +@end quotation -The example above illustrates an ABE problem within package @code{Static_Model}, -which is hidden by several layers of indirection. The elaboration of package -body @code{Static_Model} elaborates the declaration of @code{Val}. This invokes -function @code{Cause_ABE}, which instantiates generic unit @code{Gen} as @code{Inst}. -The elaboration of @code{Inst} invokes function @code{ABE}, however the body of -@code{ABE} has not been elaborated yet. - -@item -@emph{External targets} +In the example above, the elaboration of package body @code{Conditional_ABE} +elaborates the declaration of @code{Val}. This invokes function @code{Cause_ABE}, +which instantiates generic unit @code{Gen} as @code{Inst}. The elaboration of +@code{Inst} invokes function @code{ABE}, however the body of @code{ABE} has not been +elaborated yet. GNAT emits the following diagnostic: -The static model installs run-time checks to verify the elaboration status -of server targets only when the scenario that elaborates or executes that -target is part of the elaboration code of the client unit. The checks can be -suppressed using pragma @code{Suppress (Elaboration_Check)}. +@quotation @example -with Server; -package body Static_Model is - generic - with function Func return Integer; - package Gen is - Val : constant Integer := Func; - end Gen; - - function Call_Func return Boolean is - - package Inst is new Gen (Server.Func); - begin - ... - end Call_Func; - - Val : constant Boolean := Call_Func; -end Static_Model; -@end example - -In the example above, the elaboration of package body @code{Static_Model} -elaborates the declaration of @code{Val}. This invokes function @code{Call_Func}, -which instantiates generic unit @code{Gen} as @code{Inst}. The elaboration of -@code{Inst} invokes function @code{Server.Func}. Since @code{Server.Func} is an -external target, GNAT installs a run-time check to verify that its body has -been elaborated. - -In addition to checks, the static model installs implicit @code{Elaborate} and -@code{Elaborate_All} pragmas to guarantee safe elaboration use of server units. -This information is available when compiler switch @code{-gnatel} is in -effect. - -@example - 1. with Server; - 2. package body Static_Model is - 3. generic - 4. with function Func return Integer; - 5. package Gen is - 6. Val : constant Integer := Func; - 7. end Gen; - 8. - 9. function Call_Func return Boolean is -10. package Inst is new Gen (Server.Func); +13. package Inst is new Gen (ABE); | - >>> info: instantiation of "Gen" during elaboration - >>> info: in instantiation at line 6 - >>> info: call to "Func" during elaboration - >>> info: in instantiation at line 6 - >>> info: implicit pragma "Elaborate_All" generated for unit "Server" - >>> info: body of unit "Static_Model" elaborated - >>> info: function "Call_Func" called at line 15 - >>> info: function "Func" called at line 6, instance at line 10 - -11. begin -12. ... -13. end Call_Func; -14. -15. Val : constant Boolean := Call_Func; - | - >>> info: call to "Call_Func" during elaboration - -16. end Static_Model; + >>> warning: in instantiation at line 7 + >>> warning: cannot call "ABE" before body seen + >>> warning: Program_Error may be raised at run time + >>> warning: body of unit "Conditional_ABE" elaborated + >>> warning: function "Cause_ABE" called at line 18 + >>> warning: function "ABE" called at line 7, instance at line 13 @end example +@end quotation -In the example above, the elaboration of package body @code{Static_Model} -elaborates the declaration of @code{Val}. This invokes function @code{Call_Func}, -which instantiates generic unit @code{Gen} as @code{Inst}. The elaboration of -@code{Inst} invokes function @code{Server.Func}. Since @code{Server.Func} is an -external target, GNAT installs an implicit @code{Elaborate_All} pragma for unit -@code{Server}. The pragma guarantees that both the spec and body of @code{Server}, -along with any additional dependencies that @code{Server} may require, are -elaborated prior to the body of @code{Static_Model}. -@end itemize +Note that the same ABE problem does not occur with the elaboration of +declaration @code{Safe} because the body of function @code{ABE} has already been +elaborated at that point. -@node SPARK Elaboration Model in GNAT,Legacy Elaboration Model in GNAT,Static Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{23d}@anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-elaboration-model-in-gnat}@anchor{23e} -@section SPARK Elaboration Model in GNAT +@node SPARK Diagnostics,Elaboration Circularities,ABE Diagnostics,Elaboration Order Handling in GNAT +@anchor{gnat_ugn/elaboration_order_handling_in_gnat spark-diagnostics}@anchor{23b}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id9}@anchor{23c} +@section SPARK Diagnostics -The SPARK model is identical to the static model in its handling of internal -targets. The SPARK model, however, requires explicit @code{Elaborate} or -@code{Elaborate_All} pragmas to be present in the program when a target is -external, and compiler switch @code{-gnatd.v} is in effect. +GNAT enforces the SPARK rules of elaboration as defined in the SPARK Reference +Manual section 7.7 when compiler switch @code{-gnatd.v} is in effect. Note +that GNAT emits hard errors whenever it encounters a violation of the SPARK +rules. + +@quotation @example 1. with Server; -2. package body SPARK_Model with SPARK_Mode is +2. package body SPARK_Diagnostics with SPARK_Mode is 3. Val : constant Integer := Server.Func; | >>> call to "Func" during elaboration in SPARK - >>> unit "SPARK_Model" requires pragma "Elaborate_All" for "Server" + >>> unit "SPARK_Diagnostics" requires pragma "Elaborate_All" for "Server" >>> body of unit "SPARK_Model" elaborated >>> function "Func" called at line 3 -4. end SPARK_Model; +4. end SPARK_Diagnostics; @end example +@end quotation -@node Legacy Elaboration Model in GNAT,Mixing Elaboration Models,SPARK Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat legacy-elaboration-model-in-gnat}@anchor{23f} -@section Legacy Elaboration Model in GNAT - - -The legacy elaboration model is provided for compatibility with code bases -developed with pre-18.x versions of GNAT. It is similar in functionality to -the dynamic and static models of post-18.x version of GNAT, but may differ -in terms of diagnostics and run-time checks. The legacy elaboration model is -enabled with compiler switch @code{-gnatH}. - -@node Mixing Elaboration Models,Elaboration Circularities,Legacy Elaboration Model in GNAT,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat mixing-elaboration-models}@anchor{240}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id11}@anchor{241} -@section Mixing Elaboration Models - - -It is possible to mix units compiled with a different elaboration model, -however the following rules must be observed: - - -@itemize * - -@item -A client unit compiled with the dynamic model can only @emph{with} a server unit -that meets at least one of the following criteria: - +@node Elaboration Circularities,Resolving Elaboration Circularities,SPARK Diagnostics,Elaboration Order Handling in GNAT +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id10}@anchor{23d}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{23e} +@section Elaboration Circularities -@itemize - -@item -The server unit is compiled with the dynamic model. - -@item -The server unit is a GNAT implementation unit from the Ada, GNAT, -Interfaces, or System hierarchies. +An @strong{elaboration circularity} occurs whenever the elaboration of a set of +units enters a deadlocked state, where each unit is waiting for another unit +to be elaborated. This situation may be the result of improper use of @emph{with} +clauses, elaboration control pragmas, or invocations in elaboration code. -@item -The server unit has pragma @code{Pure} or @code{Preelaborate}. - -@item -The client unit has an explicit @code{Elaborate_All} pragma for the server -unit. -@end itemize -@end itemize +The following example showcases an elaboration circularity. -These rules ensure that elaboration checks are not omitted. If the rules are -violated, the binder emits a warning: +@quotation @example -warning: "x.ads" has dynamic elaboration checks and with's -warning: "y.ads" which has static elaboration checks +with B; pragma Elaborate (B); +package A is +end A; @end example -The warnings can be suppressed by binder switch @code{-ws}. - -@node Elaboration Circularities,Resolving Elaboration Circularities,Mixing Elaboration Models,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{242}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-circularities}@anchor{243} -@section Elaboration Circularities +@example +package B is + procedure Force_Body; +end B; +@end example +@example +with C; +package body B is + procedure Force_Body is null; -If the binder cannot find an acceptable elaboration order, it outputs detailed -diagnostics describing an @strong{elaboration circularity}. + Elab : constant Integer := C.Func; +end B; +@end example @example -package Server is +package C is function Func return Integer; -end Server; +end C; @end example @example -with Client; -package body Server is +with A; +package body C is function Func return Integer is begin ... end Func; -end Server; +end C; @end example +@end quotation -@example -with Server; -package Client is - Val : constant Integer := Server.Func; -end Client; -@end example +The binder emits the following diagnostic: -@example -with Client; -procedure Main is begin null; end Main; -@end example +@quotation @example -error: elaboration circularity detected -info: "server (body)" must be elaborated before "client (spec)" -info: reason: implicit Elaborate_All in unit "client (spec)" -info: recompile "client (spec)" with -gnatel for full details -info: "server (body)" -info: must be elaborated along with its spec: -info: "server (spec)" -info: which is withed by: -info: "client (spec)" -info: "client (spec)" must be elaborated before "server (body)" -info: reason: with clause +error: Elaboration circularity detected +info: +info: Reason: +info: +info: unit "a (spec)" depends on its own elaboration +info: +info: Circularity: +info: +info: unit "a (spec)" has with clause and pragma Elaborate for unit "b (spec)" +info: unit "b (body)" is in the closure of pragma Elaborate +info: unit "b (body)" invokes a construct of unit "c (body)" at elaboration time +info: unit "c (body)" has with clause for unit "a (spec)" +info: +info: Suggestions: +info: +info: remove pragma Elaborate for unit "b (body)" in unit "a (spec)" +info: use the dynamic elaboration model (compiler switch -gnatE) @end example +@end quotation -In the example above, @code{Client} must be elaborated prior to @code{Main} by virtue -of a @emph{with} clause. The elaboration of @code{Client} invokes @code{Server.Func}, and -static model generates an implicit @code{Elaborate_All} pragma for @code{Server}. The -pragma implies that both the spec and body of @code{Server}, along with any units -they @emph{with}, must be elaborated prior to @code{Client}. However, @code{Server}'s body -@emph{with}s @code{Client}, implying that @code{Client} must be elaborated prior to -@code{Server}. The end result is that @code{Client} must be elaborated prior to -@code{Client}, and this leads to a circularity. - -@node Resolving Elaboration Circularities,Resolving Task Issues,Elaboration Circularities,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id13}@anchor{244}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-elaboration-circularities}@anchor{245} -@section Resolving Elaboration Circularities - - -When faced with an elaboration circularity, a programmer has several options -available. +The diagnostic consist of the following sections: @itemize * @item -@emph{Fix the program} +Reason -The most desirable option from the point of view of long-term maintenance -is to rearrange the program so that the elaboration problems are avoided. -One useful technique is to place the elaboration code into separate child -packages. Another is to move some of the initialization code to explicitly -invoked subprograms, where the program controls the order of initialization -explicitly. Although this is the most desirable option, it may be impractical -and involve too much modification, especially in the case of complex legacy -code. +This section provides a short explanation describing why the set of units +could not be ordered. @item -@emph{Switch to more permissive elaboration model} +Circularity -If the compilation was performed using the static model, enable the dynamic -model with compiler switch @code{-gnatE}. GNAT will no longer generate -implicit @code{Elaborate} and @code{Elaborate_All} pragmas, resulting in a behavior -identical to that specified by the Ada Reference Manual. The binder will -generate an executable program that may or may not raise @code{Program_Error}, -and it is the programmer's responsibility to ensure that it does not raise -@code{Program_Error}. +This section enumerates the units comprising the deadlocked set, along with +their interdependencies. -If the compilation was performed using a post-18.x version of GNAT, consider -using the legacy elaboration model, in the following order: +@item +Suggestions +This section enumerates various tactics for eliminating the circularity. +@end itemize -@itemize - +@node Resolving Elaboration Circularities,Elaboration-related Compiler Switches,Elaboration Circularities,Elaboration Order Handling in GNAT +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id11}@anchor{23f}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-elaboration-circularities}@anchor{240} +@section Resolving Elaboration Circularities -@item -Use the relaxed static elaboration model, with compiler switch -@code{-gnatJ}. -@item -Use the relaxed dynamic elaboration model, with compiler switches -@code{-gnatE} @code{-gnatJ}. +The most desirable option from the point of view of long-term maintenance is to +rearrange the program so that the elaboration problems are avoided. One useful +technique is to place the elaboration code into separate child packages. +Another is to move some of the initialization code to explicitly invoked +subprograms, where the program controls the order of initialization explicitly. +Although this is the most desirable option, it may be impractical and involve +too much modification, especially in the case of complex legacy code. -@item -Use the legacy static elaboration model, with compiler switch -@code{-gnatH}. - -@item -Use the legacy dynamic elaboration model, with compiler switches -@code{-gnatE} @code{-gnatH}. -@end itemize +When faced with an elaboration circularity, the programmer should also consider +the tactics given in the suggestions section of the circularity diagnostic. +Depending on the units involved in the circularity, their @emph{with} clauses, +purity, preelaborability, presence of elaboration control pragmas and +invocations at elaboration time, the binder may suggest one or more of the +following tactics to eliminate the circularity: -@item -@emph{Suppress all elaboration checks} -The drawback of run-time checks is that they generate overhead at run time, -both in space and time. If the programmer is absolutely sure that a program -will not raise an elaboration-related @code{Program_Error}, then using the -pragma @code{Suppress (Elaboration_Check)} globally (as a configuration pragma) -will eliminate all run-time checks. +@itemize * @item -@emph{Suppress elaboration checks selectively} +Pragma Elaborate elimination -If a scenario cannot possibly lead to an elaboration @code{Program_Error}, -and the binder nevertheless complains about implicit @code{Elaborate} and -@code{Elaborate_All} pragmas that lead to elaboration circularities, it -is possible to suppress the generation of implicit @code{Elaborate} and -@code{Elaborate_All} pragmas, as well as run-time checks. Clearly this can -be unsafe, and it is the responsibility of the programmer to make sure -that the resulting program has no elaboration anomalies. Pragma -@code{Suppress (Elaboration_Check)} can be used with different levels of -granularity to achieve these effects. +@example +remove pragma Elaborate for unit "..." in unit "..." +@end example + +This tactic is suggested when the binder has determine that pragma +@code{Elaborate} @itemize - @item -@emph{Target suppression} +Prevents a set of units from being elaborated. -When the pragma is placed in a declarative part, without a second argument -naming an entity, it will suppress implicit @code{Elaborate} and -@code{Elaborate_All} pragma generation, as well as run-time checks, on all -targets within the region. - -@example -package Range_Suppress is - pragma Suppress (Elaboration_Check); +@item +The removal of the pragma will not eliminate the semantic effects of the +pragma. In other words, the argument of the pragma will still be elaborated +prior to the unit containing the pragma. - function Func return Integer; +@item +The removal of the pragma will enable the successful ordering of the units. +@end itemize - generic - procedure Gen; +The programmer should remove the pragma as advised, and rebuild the program. - pragma Unsuppress (Elaboration_Check); +@item +Pragma Elaborate_All elimination - task type Tsk; -end Range_Suppress; +@example +remove pragma Elaborate_All for unit "..." in unit "..." @end example -In the example above, a pair of Suppress/Unsuppress pragmas define a region -of suppression within package @code{Range_Suppress}. As a result, no implicit -@code{Elaborate} and @code{Elaborate_All} pragmas, nor any run-time checks, will -be generated by callers of @code{Func} and instantiators of @code{Gen}. Note that -task type @code{Tsk} is not within this region. +This tactic is suggested when the binder has determined that pragma +@code{Elaborate_All} -An alternative to the region-based suppression is to use multiple -@code{Suppress} pragmas with arguments naming specific entities for which -elaboration checks should be suppressed: -@example -package Range_Suppress is - function Func return Integer; - pragma Suppress (Elaboration_Check, Func); - - generic - procedure Gen; - pragma Suppress (Elaboration_Check, Gen); - - task type Tsk; -end Range_Suppress; -@end example +@itemize - @item -@emph{Scenario suppression} +Prevents a set of units from being elaborated. -When the pragma @code{Suppress} is placed in a declarative or statement -part, without an entity argument, it will suppress implicit @code{Elaborate} -and @code{Elaborate_All} pragma generation, as well as run-time checks, on -all scenarios within the region. - -@example -with Server; -package body Range_Suppress is - pragma Suppress (Elaboration_Check); +@item +The removal of the pragma will not eliminate the semantic effects of the +pragma. In other words, the argument of the pragma along with its @emph{with} +closure will still be elaborated prior to the unit containing the pragma. - function Func return Integer is - begin - return Server.Func; - end Func; +@item +The removal of the pragma will enable the successful ordering of the units. +@end itemize - procedure Gen is - begin - Server.Proc; - end Gen; +The programmer should remove the pragma as advised, and rebuild the program. - pragma Unsuppress (Elaboration_Check); +@item +Pragma Elaborate_All downgrade - task body Tsk is - begin - Server.Proc; - end Tsk; -end Range_Suppress; +@example +change pragma Elaborate_All for unit "..." to Elaborate in unit "..." @end example -In the example above, a pair of Suppress/Unsuppress pragmas define a region -of suppression within package body @code{Range_Suppress}. As a result, the -calls to @code{Server.Func} in @code{Func} and @code{Server.Proc} in @code{Gen} will -not generate any implicit @code{Elaborate} and @code{Elaborate_All} pragmas or -run-time checks. -@end itemize -@end itemize +This tactic is always suggested with the pragma @code{Elaborate_All} elimination +tactic. It offers a different alernative of guaranteeing that the argument of +the pragma will still be elaborated prior to the unit containing the pragma. -@node Resolving Task Issues,Elaboration-related Compiler Switches,Resolving Elaboration Circularities,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat id14}@anchor{246}@anchor{gnat_ugn/elaboration_order_handling_in_gnat resolving-task-issues}@anchor{247} -@section Resolving Task Issues +The programmer should update the pragma as advised, and rebuild the program. +@item +Pragma Elaborate_Body elimination -The model of execution in Ada dictates that elaboration must first take place, -and only then can the main program be started. Tasks which are activated during -elaboration violate this model and may lead to serious concurrent problems at -elaboration time. +@example +remove pragma Elaborate_Body in unit "..." +@end example -A task can be activated in two different ways: +This tactic is suggested when the binder has determined that pragma +@code{Elaborate_Body} -@itemize * +@itemize - @item -The task is created by an allocator in which case it is activated immediately -after the allocator is evaluated. +Prevents a set of units from being elaborated. @item -The task is declared at the library level or within some nested master in -which case it is activated before starting execution of the statement -sequence of the master defining the task. +The removal of the pragma will enable the successful ordering of the units. @end itemize -Since the elaboration of a partition is performed by the environment task -servicing that partition, any tasks activated during elaboration may be in -a race with the environment task, and lead to unpredictable state and behavior. -The static model seeks to avoid such interactions by assuming that all code in -the task body is executed at elaboration time, if the task was activated by -elaboration code. - -@example -package Decls is - task Lib_Task is - entry Start; - end Lib_Task; +Note that the binder cannot determine whether the pragma is required for +other purposes, such as guaranteeing the initialization of a variable +declared in the spec by elaboration code in the body. - type My_Int is new Integer; +The programmer should remove the pragma as advised, and rebuild the program. - function Ident (M : My_Int) return My_Int; -end Decls; -@end example - -@example -with Utils; -package body Decls is - task body Lib_Task is - begin - accept Start; - Utils.Put_Val (2); - end Lib_Task; - - function Ident (M : My_Int) return My_Int is - begin - return M; - end Ident; -end Decls; -@end example - -@example -with Decls; -package Utils is - procedure Put_Val (Arg : Decls.My_Int); -end Utils; -@end example +@item +Use of dynamic elaboration model @example -with Ada.Text_IO; use Ada.Text_IO; -package body Utils is - procedure Put_Val (Arg : Decls.My_Int) is - begin - Put_Line (Arg'Img); - end Put_Val; -end Utils; +use the dynamic elaboration model (compiler switch -gnatE) @end example -@example -with Decls; -procedure Main is -begin - Decls.Lib_Task.Start; -end Main; -@end example +This tactic is suggested when the binder has determined that an invocation at +elaboration time -When the above example is compiled with the static model, an elaboration -circularity arises: -@example -error: elaboration circularity detected -info: "decls (body)" must be elaborated before "decls (body)" -info: reason: implicit Elaborate_All in unit "decls (body)" -info: recompile "decls (body)" with -gnatel for full details -info: "decls (body)" -info: must be elaborated along with its spec: -info: "decls (spec)" -info: which is withed by: -info: "utils (spec)" -info: which is withed by: -info: "decls (body)" -@end example +@itemize - -In the above example, @code{Decls} must be elaborated prior to @code{Main} by virtue -of a with clause. The elaboration of @code{Decls} activates task @code{Lib_Task}. The -static model conservatibely assumes that all code within the body of -@code{Lib_Task} is executed, and generates an implicit @code{Elaborate_All} pragma -for @code{Units} due to the call to @code{Utils.Put_Val}. The pragma implies that -both the spec and body of @code{Utils}, along with any units they @emph{with}, -must be elaborated prior to @code{Decls}. However, @code{Utils}'s spec @emph{with}s -@code{Decls}, implying that @code{Decls} must be elaborated before @code{Utils}. The end -result is that @code{Utils} must be elaborated prior to @code{Utils}, and this -leads to a circularity. +@item +Prevents a set of units from being elaborated. -In reality, the example above will not exhibit an ABE problem at run time. -When the body of task @code{Lib_Task} is activated, execution will wait for entry -@code{Start} to be accepted, and the call to @code{Utils.Put_Val} will not take place -at elaboration time. Task @code{Lib_Task} will resume its execution after the main -program is executed because @code{Main} performs a rendezvous with -@code{Lib_Task.Start}, and at that point all units have already been elaborated. -As a result, the static model may seem overly conservative, partly because it -does not take control and data flow into account. +@item +The use of the dynamic model will enable the successful ordering of the +units. +@end itemize -When faced with a task elaboration circularity, a programmer has several -options available: +The programmer has two options: -@itemize * +@itemize - @item -@emph{Use the dynamic model} - -The dynamic model does not generate implicit @code{Elaborate} and -@code{Elaborate_All} pragmas. Instead, it will install checks prior to every -call in the example above, thus verifying the successful elaboration of -@code{Utils.Put_Val} in case the call to it takes place at elaboration time. -The dynamic model is enabled with compiler switch @code{-gnatE}. +Determine the units involved in the invocation using the detailed +invocation information, and add compiler switch @code{-gnatE} to the +compilation arguments of selected files only. This approach will yield +safer elaboration orders compared to the other option because it will +minimize the opportunities presented to the dynamic model for ignoring +invocations. @item -@emph{Isolate the tasks} +Add compiler switch @code{-gnatE} to the general compilation arguments. +@end itemize -Relocating tasks in their own separate package could decouple them from -dependencies that would otherwise cause an elaboration circularity. The -example above can be rewritten as follows: +@item +Use of detailed invocation information @example -package Decls1 is -- new - task Lib_Task is - entry Start; - end Lib_Task; -end Decls1; +use detailed invocation information (compiler switch -gnatd_F) @end example -@example -with Utils; -package body Decls1 is -- new - task body Lib_Task is - begin - accept Start; - Utils.Put_Val (2); - end Lib_Task; -end Decls1; -@end example +This tactic is always suggested with the use of the dynamic model tactic. It +causes the circularity section of the circularity diagnostic to describe the +flow of elaboration code from a unit to a unit, enumerating all such paths in +the process. -@example -package Decls2 is -- new - type My_Int is new Integer; - function Ident (M : My_Int) return My_Int; -end Decls2; -@end example +The programmer should analyze this information to determine which units +should be compiled with the dynamic model. -@example -with Utils; -package body Decls2 is -- new - function Ident (M : My_Int) return My_Int is - begin - return M; - end Ident; -end Decls2; -@end example +@item +Forced dependency elimination @example -with Decls2; -package Utils is - procedure Put_Val (Arg : Decls2.My_Int); -end Utils; +remove the dependency of unit "..." on unit "..." from the argument of switch -f @end example -@example -with Ada.Text_IO; use Ada.Text_IO; -package body Utils is - procedure Put_Val (Arg : Decls2.My_Int) is - begin - Put_Line (Arg'Img); - end Put_Val; -end Utils; -@end example +This tactic is suggested when the binder has determined that a dependency +present in the forced delboration order file indicated by binder switch +@code{-f} -@example -with Decls1; -procedure Main is -begin - Decls1.Lib_Task.Start; -end Main; -@end example + +@itemize - @item -@emph{Declare the tasks} +Prevents a set of units from being elaborated. -The original example uses a single task declaration for @code{Lib_Task}. An -explicit task type declaration and a properly placed task object could avoid -the dependencies that would otherwise cause an elaboration circularity. The -example can be rewritten as follows: +@item +The removal of the dependency will enable the successful ordering of the +units. +@end itemize -@example -package Decls is - task type Lib_Task is -- new - entry Start; - end Lib_Task; +The programmer should edit the forced elaboration order file, remove the +dependency, and rebind the program. - type My_Int is new Integer; +@item +All forced dependency elimination - function Ident (M : My_Int) return My_Int; -end Decls; +@example +remove switch -f @end example -@example -with Utils; -package body Decls is - task body Lib_Task is - begin - accept Start; - Utils.Put_Val (2); - end Lib_Task; +This tactic is suggested in case editing the forced elaboration order file is +not an option. - function Ident (M : My_Int) return My_Int is - begin - return M; - end Ident; -end Decls; -@end example +The programmer should remove binder switch @code{-f} from the binder +arguments, and rebind. -@example -with Decls; -package Utils is - procedure Put_Val (Arg : Decls.My_Int); -end Utils; -@end example +@item +Multiple circularities diagnostic @example -with Ada.Text_IO; use Ada.Text_IO; -package body Utils is - procedure Put_Val (Arg : Decls.My_Int) is - begin - Put_Line (Arg'Img); - end Put_Val; -end Utils; +diagnose all circularities (binder switch -d_C) @end example -@example -with Decls; -package Obj_Decls is -- new - Task_Obj : Decls.Lib_Task; -end Obj_Decls; -@end example +By default, the binder will diagnose only the highest precedence circularity. +If the program contains multiple circularities, the binder will suggest the +use of binder switch @code{-d_C} in order to obtain the diagnostics of all +circularities. -@example -with Obj_Decls; -procedure Main is -begin - Obj_Decls.Task_Obj.Start; -- new -end Main; -@end example +The programmer should add binder switch @code{-d_C} to the binder +arguments, and rebind. +@end itemize -@item -@emph{Use restriction No_Entry_Calls_In_Elaboration_Code} +If none of the tactics suggested by the binder eliminate the elaboration +circularity, the programmer should consider using one of the legacy elaboration +models, in the following order: -The issue exhibited in the original example under this section revolves -around the body of @code{Lib_Task} blocking on an accept statement. There is -no rule to prevent elaboration code from performing entry calls, however in -practice this is highly unusual. In addition, the pattern of starting tasks -at elaboration time and then immediately blocking on accept or select -statements is quite common. -If a programmer knows that elaboration code will not perform any entry -calls, then the programmer can indicate that the static model should not -process the remainder of a task body once an accept or select statement has -been encountered. This behavior can be specified by a configuration pragma: +@itemize * -@example -pragma Restrictions (No_Entry_Calls_In_Elaboration_Code); -@end example +@item +Use the pre-20.x legacy elaboration order model, with binder switch +@code{-H}. -In addition to the change in behavior with respect to task bodies, the -static model will verify that no entry calls take place at elaboration time. +@item +Use both pre-18.x and pre-20.x legacy elaboration models, with compiler +switch @code{-gnatH} and binder switch @code{-H}. + +@item +Use the relaxed static elaboration model, with compiler switches +@code{-gnatH} @code{-gnatJ} and binder switch @code{-H}. + +@item +Use the relaxed dynamic elaboration model, with compiler switches +@code{-gnatH} @code{-gnatJ} @code{-gnatE} and binder switch +@code{-H}. @end itemize -@node Elaboration-related Compiler Switches,Summary of Procedures for Elaboration Control,Resolving Task Issues,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{248}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id15}@anchor{249} +@node Elaboration-related Compiler Switches,Summary of Procedures for Elaboration Control,Resolving Elaboration Circularities,Elaboration Order Handling in GNAT +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id12}@anchor{241}@anchor{gnat_ugn/elaboration_order_handling_in_gnat elaboration-related-compiler-switches}@anchor{242} @section Elaboration-related Compiler Switches @@ -28847,7 +28606,7 @@ the elaboration order chosen by the binder. Dynamic elaboration checking mode enabled -When this switch is in effect, GNAT activates the dynamic elaboration model. +When this switch is in effect, GNAT activates the dynamic model. @end table @geindex -gnatel (gnat) @@ -28859,6 +28618,10 @@ When this switch is in effect, GNAT activates the dynamic elaboration model. Turn on info messages on generated Elaborate[_All] pragmas +This switch is only applicable to the pre-20.x legacy elaboration models. +The post-20.x elaboration model no longer relies on implicitly generated +@code{Elaborate} and @code{Elaborate_All} pragmas to order units. + When this switch is in effect, GNAT will emit the following supplementary information depending on the elaboration model in effect. @@ -28874,7 +28637,7 @@ all library-level scenarios within the partition. @item @emph{Static model} -GNAT will indicate all scenarios executed during elaboration. In addition, +GNAT will indicate all scenarios invoked during elaboration. In addition, it will provide detailed traceback when an implicit @code{Elaborate} or @code{Elaborate_All} pragma is generated. @@ -29008,7 +28771,7 @@ checks. The example above will still fail at run time with an ABE. @end table @node Summary of Procedures for Elaboration Control,Inspecting the Chosen Elaboration Order,Elaboration-related Compiler Switches,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat summary-of-procedures-for-elaboration-control}@anchor{24a}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id16}@anchor{24b} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id13}@anchor{243}@anchor{gnat_ugn/elaboration_order_handling_in_gnat summary-of-procedures-for-elaboration-control}@anchor{244} @section Summary of Procedures for Elaboration Control @@ -29036,13 +28799,8 @@ as their origins. Elaboration warnings are enabled with compiler switch @code{-gnatwl}. @item -Use switch @code{-gnatel} to obtain messages on generated implicit -@code{Elaborate} and @code{Elaborate_All} pragmas. The trace information could -indicate why a server unit must be elaborated prior to a client unit. - -@item -If the warnings produced by the static model indicate that a task is -involved, consider the options in section @ref{246,,Resolving Task Issues}. +Cosider the tactics given in the suggestions section of the circularity +diagnostic. @item If none of the steps outlined above resolve the circularity, use a more @@ -29052,28 +28810,26 @@ permissive elaboration model, in the following order: @itemize - @item -Use the dynamic elaboration model, with compiler switch @code{-gnatE}. +Use the pre-20.x legacy elaboration order model, with binder switch +@code{-H}. @item -Use the legacy static elaboration model, with compiler switch -@code{-gnatH}. +Use both pre-18.x and pre-20.x legacy elaboration models, with compiler +switch @code{-gnatH} and binder switch @code{-H}. @item -Use the legacy dynamic elaboration model, with compiler switches -@code{-gnatH} @code{-gnatE}. +Use the relaxed static elaboration model, with compiler switches +@code{-gnatH} @code{-gnatJ} and binder switch @code{-H}. @item -Use the relaxed legacy static elaboration model, with compiler switches -@code{-gnatH} @code{-gnatJ}. - -@item -Use the relaxed legacy dynamic elaboration model, with compiler switches -@code{-gnatH} @code{-gnatJ} @code{-gnatE}. +Use the relaxed dynamic elaboration model, with compiler switches +@code{-gnatH} @code{-gnatJ} @code{-gnatE} and binder switch +@code{-H}. @end itemize @end itemize @node Inspecting the Chosen Elaboration Order,,Summary of Procedures for Elaboration Control,Elaboration Order Handling in GNAT -@anchor{gnat_ugn/elaboration_order_handling_in_gnat inspecting-the-chosen-elaboration-order}@anchor{24c}@anchor{gnat_ugn/elaboration_order_handling_in_gnat id17}@anchor{24d} +@anchor{gnat_ugn/elaboration_order_handling_in_gnat id14}@anchor{245}@anchor{gnat_ugn/elaboration_order_handling_in_gnat inspecting-the-chosen-elaboration-order}@anchor{246} @section Inspecting the Chosen Elaboration Order @@ -29083,6 +28839,8 @@ elaboration order appears as a sequence of calls to @code{Elab_Body} and @code{Elab_Spec}, interspersed with assignments to @cite{Exxx} which indicates that a particular unit is elaborated. For example: +@quotation + @example System.Soft_Links'Elab_Body; E14 := True; @@ -29118,10 +28876,13 @@ Ada.Text_Io'Elab_Spec; Ada.Text_Io'Elab_Body; E07 := True; @end example +@end quotation Note also binder switch @code{-l}, which outputs the chosen elaboration order and provides a more readable form of the above: +@quotation + @example ada (spec) interfaces (spec) @@ -29208,9 +28969,10 @@ ada.text_io (body) text_io (spec) gdbstr (body) @end example +@end quotation @node Inline Assembler,GNU Free Documentation License,Elaboration Order Handling in GNAT,Top -@anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10}@anchor{gnat_ugn/inline_assembler doc}@anchor{24e}@anchor{gnat_ugn/inline_assembler id1}@anchor{24f} +@anchor{gnat_ugn/inline_assembler inline-assembler}@anchor{10}@anchor{gnat_ugn/inline_assembler doc}@anchor{247}@anchor{gnat_ugn/inline_assembler id1}@anchor{248} @chapter Inline Assembler @@ -29269,7 +29031,7 @@ and with assembly language programming. @end menu @node Basic Assembler Syntax,A Simple Example of Inline Assembler,,Inline Assembler -@anchor{gnat_ugn/inline_assembler id2}@anchor{250}@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{251} +@anchor{gnat_ugn/inline_assembler id2}@anchor{249}@anchor{gnat_ugn/inline_assembler basic-assembler-syntax}@anchor{24a} @section Basic Assembler Syntax @@ -29385,7 +29147,7 @@ Intel: Destination first; for example @code{mov eax, 4}@w{ } @node A Simple Example of Inline Assembler,Output Variables in Inline Assembler,Basic Assembler Syntax,Inline Assembler -@anchor{gnat_ugn/inline_assembler a-simple-example-of-inline-assembler}@anchor{252}@anchor{gnat_ugn/inline_assembler id3}@anchor{253} +@anchor{gnat_ugn/inline_assembler a-simple-example-of-inline-assembler}@anchor{24b}@anchor{gnat_ugn/inline_assembler id3}@anchor{24c} @section A Simple Example of Inline Assembler @@ -29534,7 +29296,7 @@ If there are no errors, @code{as} will generate an object file @code{nothing.out}. @node Output Variables in Inline Assembler,Input Variables in Inline Assembler,A Simple Example of Inline Assembler,Inline Assembler -@anchor{gnat_ugn/inline_assembler id4}@anchor{254}@anchor{gnat_ugn/inline_assembler output-variables-in-inline-assembler}@anchor{255} +@anchor{gnat_ugn/inline_assembler id4}@anchor{24d}@anchor{gnat_ugn/inline_assembler output-variables-in-inline-assembler}@anchor{24e} @section Output Variables in Inline Assembler @@ -29901,7 +29663,7 @@ end Get_Flags_3; @end quotation @node Input Variables in Inline Assembler,Inlining Inline Assembler Code,Output Variables in Inline Assembler,Inline Assembler -@anchor{gnat_ugn/inline_assembler id5}@anchor{256}@anchor{gnat_ugn/inline_assembler input-variables-in-inline-assembler}@anchor{257} +@anchor{gnat_ugn/inline_assembler id5}@anchor{24f}@anchor{gnat_ugn/inline_assembler input-variables-in-inline-assembler}@anchor{250} @section Input Variables in Inline Assembler @@ -29990,7 +29752,7 @@ _increment__incr.1: @end quotation @node Inlining Inline Assembler Code,Other Asm Functionality,Input Variables in Inline Assembler,Inline Assembler -@anchor{gnat_ugn/inline_assembler id6}@anchor{258}@anchor{gnat_ugn/inline_assembler inlining-inline-assembler-code}@anchor{259} +@anchor{gnat_ugn/inline_assembler id6}@anchor{251}@anchor{gnat_ugn/inline_assembler inlining-inline-assembler-code}@anchor{252} @section Inlining Inline Assembler Code @@ -30061,7 +29823,7 @@ movl %esi,%eax thus saving the overhead of stack frame setup and an out-of-line call. @node Other Asm Functionality,,Inlining Inline Assembler Code,Inline Assembler -@anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{25a}@anchor{gnat_ugn/inline_assembler id7}@anchor{25b} +@anchor{gnat_ugn/inline_assembler other-asm-functionality}@anchor{253}@anchor{gnat_ugn/inline_assembler id7}@anchor{254} @section Other @code{Asm} Functionality @@ -30076,7 +29838,7 @@ and @code{Volatile}, which inhibits unwanted optimizations. @end menu @node The Clobber Parameter,The Volatile Parameter,,Other Asm Functionality -@anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{25c}@anchor{gnat_ugn/inline_assembler id8}@anchor{25d} +@anchor{gnat_ugn/inline_assembler the-clobber-parameter}@anchor{255}@anchor{gnat_ugn/inline_assembler id8}@anchor{256} @subsection The @code{Clobber} Parameter @@ -30140,7 +29902,7 @@ Use 'register' name @code{memory} if you changed a memory location @end itemize @node The Volatile Parameter,,The Clobber Parameter,Other Asm Functionality -@anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{25e}@anchor{gnat_ugn/inline_assembler id9}@anchor{25f} +@anchor{gnat_ugn/inline_assembler the-volatile-parameter}@anchor{257}@anchor{gnat_ugn/inline_assembler id9}@anchor{258} @subsection The @code{Volatile} Parameter @@ -30176,7 +29938,7 @@ to @code{True} only if the compiler's optimizations have created problems. @node GNU Free Documentation License,Index,Inline Assembler,Top -@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{260}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{261} +@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{259}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{25a} @chapter GNU Free Documentation License diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb index 8612428..3145559 100644 --- a/gcc/ada/sem_elab.adb +++ b/gcc/ada/sem_elab.adb @@ -496,12 +496,6 @@ package body Sem_Elab is -- actual subprograms through generic formal subprograms. As a -- result, the calls are not recorded or processed. -- - -- -gnatd_G encode invocation graph in ALI files - -- - -- The ABE mechanism encodes the invocation graph of the main - -- unit. This includes elaboration code, as well as invocation - -- constructs. - -- -- -gnatd_i ignore activations and calls to instances for elaboration -- -- The ABE mechanism ignores calls and task activations when they @@ -12192,19 +12186,10 @@ package body Sem_Elab is Main_Cunit : constant Node_Id := Cunit (Main_Unit); begin - -- ??? Remove the following use of the debug flag when switching from - -- the old to the new elaboration-order mechanism. - - -- Nothing to do when switch -gnatd_G (encode invocation graph in ALI - -- files) is not in effect. - - if not Debug_Flag_Underscore_GG then - return False; - -- Nothing to do when compiling for GNATprove because the invocation -- graph is not needed. - elsif GNATprove_Mode then + if GNATprove_Mode then return False; -- Nothing to do when the compilation will not produce an ALI file diff --git a/gcc/ada/switch-b.adb b/gcc/ada/switch-b.adb index eefd225..3902b66 100644 --- a/gcc/ada/switch-b.adb +++ b/gcc/ada/switch-b.adb @@ -353,14 +353,11 @@ package body Switch.B is Ptr := Ptr + 1; Usage_Requested := True; - -- ??? Enable the following code when switching from the old to the - -- new elaboration-order mechanism. - -- Processing for H switch - -- when 'H' => - -- Ptr := Ptr + 1; - -- Legacy_Elaboration_Order := True; + when 'H' => + Ptr := Ptr + 1; + Legacy_Elaboration_Order := True; -- Processing for i switch -- cgit v1.1 From 0ce858310c2bba03fc030f34f4217cb405020bcf Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Tue, 9 Jul 2019 07:54:35 +0000 Subject: [Ada] Wrong resolution of equality operator with overloaded operand This patch fixes a code generation error on an equality operation one of whose operands is an overloaded call, and several equality operators are visible. The resolution would succes but in some cases the wrong entity was lwfton the equality node, leading to expansion with the wrong interpretation. If the equality operation is the operand of a negation, the resolution of the negation must make direct use of the equality resolution, 2019-07-09 Ed Schonberg gcc/ada/ * sem_res.adb (Resolve_Equality_Op): If the node was overloaded, set properly the entity to which the node has been resolved. The original entity is the first one found during analysis, and is not necessarily the resolved one. (Resolve_Op_Not): If the argument of negation is an overloaded equality operation, call its resolution directly given that the context type does not participate in overload resolution. gcc/testsuite/ * gnat.dg/equal7.adb, gnat.dg/equal7_pkg.adb, gnat.dg/equal7_pkg.ads: New testcase. From-SVN: r273281 --- gcc/ada/ChangeLog | 10 ++++++ gcc/ada/sem_res.adb | 70 ++++++++++++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gnat.dg/equal7.adb | 15 ++++++++ gcc/testsuite/gnat.dg/equal7_pkg.adb | 14 ++++++++ gcc/testsuite/gnat.dg/equal7_pkg.ads | 16 +++++++++ 6 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/equal7.adb create mode 100644 gcc/testsuite/gnat.dg/equal7_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/equal7_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 738be61..adb8622 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-07-09 Ed Schonberg + + * sem_res.adb (Resolve_Equality_Op): If the node was overloaded, + set properly the entity to which the node has been resolved. The + original entity is the first one found during analysis, and is + not necessarily the resolved one. + (Resolve_Op_Not): If the argument of negation is an overloaded + equality operation, call its resolution directly given that the + context type does not participate in overload resolution. + 2019-07-09 Hristian Kirtchev * bindo.adb: Remove with and use clauses for Debug. Add with diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index b86e7cc..e32d547 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -8437,6 +8437,45 @@ package body Sem_Res is Explain_Redundancy (Original_Node (R)); end if; + -- If the equality is overloaded and the operands have resolved + -- properly, set the proper equality operator on the node. The + -- current setting is the first one found during analysis, which + -- is not necessarily the one to which the node has resolved. + + if Is_Overloaded (N) then + declare + I : Interp_Index; + It : Interp; + begin + Get_First_Interp (N, I, It); + + -- If the equality is user-defined, the type of the operands + -- matches that of the formals. For a predefined operqtor, + -- it is the scope that matters, given that the predefined + -- equality has Any_Type formals. In either case the result + -- type (most often Booleam) must match the context . + + while Present (It.Typ) loop + if Etype (It.Nam) = Typ + and then + (Etype (First_Entity (It.Nam)) = Etype (L) + or else Scope (It.Nam) = Scope (T)) + then + Set_Entity (N, It.Nam); + + Set_Is_Overloaded (N, False); + exit; + end if; + + Get_Next_Interp (I, It); + end loop; + + if Present (Alias (Entity (N))) then + Set_Entity (N, Alias (Entity (N))); + end if; + end; + end if; + Check_Unset_Reference (L); Check_Unset_Reference (R); Generate_Operator_Reference (N, T); @@ -10034,9 +10073,36 @@ package body Sem_Res is end if; -- Complete resolution and evaluation of NOT + -- If argument is an equality and expected type is boolean, that + -- expected type has no effect on resolution, and there are + -- special rules for resolution of Eq, Neq in the presence of + -- overloaded operands, so we directly call its resolution routines. + + declare + Opnd : constant Node_Id := Right_Opnd (N); + begin + if B_Typ = Standard_Boolean + and then Nkind_In (Opnd, N_Op_Eq, N_Op_Ne) + and then Is_Overloaded (Opnd) + then + Resolve_Equality_Op (Opnd, B_Typ); + if Ekind (Entity (Opnd)) = E_Function then + Rewrite_Operator_As_Call (Opnd, Entity (Opnd)); + end if; + + if not Inside_A_Generic or else Is_Entity_Name (Opnd) then + Freeze_Expression (Opnd); + end if; + + Expand (Opnd); + + else + Resolve (Opnd, B_Typ); + end if; + + Check_Unset_Reference (Opnd); + end; - Resolve (Right_Opnd (N), B_Typ); - Check_Unset_Reference (Right_Opnd (N)); Set_Etype (N, B_Typ); Generate_Operator_Reference (N, B_Typ); Eval_Op_Not (N); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e1f1678..d50b7b2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Ed Schonberg + + * gnat.dg/equal7.adb, gnat.dg/equal7_pkg.adb, + gnat.dg/equal7_pkg.ads: New testcase. + 2019-07-09 Javier Miranda * gnat.dg/range_check3.adb, gnat.dg/range_check3_pkg.adb, diff --git a/gcc/testsuite/gnat.dg/equal7.adb b/gcc/testsuite/gnat.dg/equal7.adb new file mode 100644 index 0000000..2b27842 --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal7.adb @@ -0,0 +1,15 @@ +-- { dg-do run } + +with Equal7_Pkg; use Equal7_Pkg; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +procedure Equal7 is + X : constant Integer := 42; + +begin + if F (X) /= "" & ASCII.LF then + null; + end if; + if not (F (X) = "" & ASCII.LF) then + null; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/equal7_pkg.adb b/gcc/testsuite/gnat.dg/equal7_pkg.adb new file mode 100644 index 0000000..171343f --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal7_pkg.adb @@ -0,0 +1,14 @@ +package body Equal7_Pkg is + + function F (X : Integer) return String is + begin + return To_String (F (X)); + end F; + + function F (X : Integer) return Unbounded_String is + Result : Unbounded_String; + begin + Append (Result, "hello" & X'Img); + return Result; + end; +end; diff --git a/gcc/testsuite/gnat.dg/equal7_pkg.ads b/gcc/testsuite/gnat.dg/equal7_pkg.ads new file mode 100644 index 0000000..8fd601c --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal7_pkg.ads @@ -0,0 +1,16 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Finalization; use Ada.Finalization; +package Equal7_Pkg is + + type Editor_Location is abstract new Controlled with null record; + Nil_Editor_Location : constant Editor_Location'Class; + + function F (X : Integer) return Unbounded_String; + function F (X : Integer) return String; + +private + type Dummy_Editor_Location is new Editor_Location with null record; + + Nil_Editor_Location : constant Editor_Location'Class := + Dummy_Editor_Location'(Controlled with null record); +end; -- cgit v1.1 From 134f52b9c4f45076efe6a3c345e6e01e95998cc1 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Tue, 9 Jul 2019 07:54:40 +0000 Subject: [Ada] Minor reformatting 2019-07-09 Hristian Kirtchev gcc/ada/ * exp_ch9.adb, exp_util.adb, repinfo.adb, sem_ch12.adb, sem_prag.adb, sem_res.adb, sem_spark.adb, sem_util.adb: Minor reformatting. From-SVN: r273282 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/exp_ch9.adb | 11 ++++++----- gcc/ada/exp_util.adb | 8 +++----- gcc/ada/repinfo.adb | 12 +++++++----- gcc/ada/sem_ch12.adb | 12 +++++------- gcc/ada/sem_prag.adb | 3 +-- gcc/ada/sem_res.adb | 2 ++ gcc/ada/sem_spark.adb | 7 ++++--- gcc/ada/sem_util.adb | 3 ++- 9 files changed, 36 insertions(+), 28 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index adb8622..7d8ea33 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Hristian Kirtchev + + * exp_ch9.adb, exp_util.adb, repinfo.adb, sem_ch12.adb, + sem_prag.adb, sem_res.adb, sem_spark.adb, sem_util.adb: Minor + reformatting. + 2019-07-09 Ed Schonberg * sem_res.adb (Resolve_Equality_Op): If the node was overloaded, diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index e742ec3..48b4090 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -10712,7 +10712,7 @@ package body Exp_Ch9 is Make_Defining_Identifier (Eloc, New_External_Name (Chars (Ename), 'A', Num_Accept)); - -- Link the acceptor to the original receiving entry. + -- Link the acceptor to the original receiving entry Set_Ekind (PB_Ent, E_Procedure); Set_Receiving_Entry (PB_Ent, Eent); @@ -12666,8 +12666,9 @@ package body Exp_Ch9 is -- to Build_Simple_Entry_Call. if Is_Disp_Select then - -- Compute the delay at this stage because the evaluation of - -- its expression must not occur earlier (see ACVC C97302A). + + -- Compute the delay at this stage because the evaluation of its + -- expression must not occur earlier (see ACVC C97302A). Append_To (Stmts, Make_Assignment_Statement (Loc, @@ -14882,8 +14883,8 @@ package body Exp_Ch9 is -- Ditto for a package declaration or a full type declaration, etc. - elsif - (Nkind (N) = N_Package_Declaration and then N /= Specification (N)) + elsif (Nkind (N) = N_Package_Declaration + and then N /= Specification (N)) or else Nkind (N) in N_Declaration or else Nkind (N) in N_Renaming_Declaration then diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 77809bc..9769d68 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -5073,9 +5073,7 @@ package body Exp_Util is -- is necessary both for passing legality checks in GNAT and for precise -- analysis in GNATprove. - if GNATprove_Mode - and then not Is_Static_Expression (Exp) - then + if GNATprove_Mode and then not Is_Static_Expression (Exp) then return; end if; @@ -5100,7 +5098,7 @@ package body Exp_Util is -- This subtype indication may be used later for constraint checks -- we better make sure that if a variable was used as a bound of - -- of the original slice, its value is frozen. + -- the original slice, its value is frozen. Evaluate_Slice_Bounds (Exp); end; @@ -11693,7 +11691,7 @@ package body Exp_Util is Set_Assignment_OK (Res, Assignment_OK (Exp)); - -- Preserve the Do_Range_Check flag in all copies. + -- Preserve the Do_Range_Check flag in all copies Set_Do_Range_Check (Res, Do_Range_Check (Exp)); diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 1ba7e11..c378fb6 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -559,7 +559,9 @@ package body Repinfo is -- Note that formals are not annotated so we skip them here - elsif Ekind_In (E, E_Variable, E_Constant, E_Loop_Parameter) + elsif Ekind_In (E, E_Constant, + E_Loop_Parameter, + E_Variable) then if List_Representation_Info >= 2 then List_Object_Info (E); @@ -577,12 +579,12 @@ package body Repinfo is -- Recurse into bodies - elsif Ekind_In (E, E_Protected_Type, - E_Task_Type, + elsif Ekind_In (E, E_Package_Body, + E_Protected_Body, + E_Protected_Type, E_Subprogram_Body, - E_Package_Body, E_Task_Body, - E_Protected_Body) + E_Task_Type) then List_Entities (E, Bytes_Big_Endian); diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 9afa095..3aa4975 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -10315,7 +10315,7 @@ package body Sem_Ch12 is -- such as a parent generic within the body of a generic child. if not Is_Entity_Name (Actual) - or else not Ekind_In (Entity (Actual), E_Package, E_Generic_Package) + or else not Ekind_In (Entity (Actual), E_Generic_Package, E_Package) then Error_Msg_N ("expect package instance to instantiate formal", Actual); @@ -10354,13 +10354,11 @@ package body Sem_Ch12 is ("previous error in declaration of formal package", Actual); Abandon_Instantiation (Actual); - elsif - Is_Instance_Of (Parent_Spec, Get_Instance_Of (Gen_Parent)) - then + elsif Is_Instance_Of (Parent_Spec, Get_Instance_Of (Gen_Parent)) then null; - -- If this is the current instance of an enclosing generic, that - -- unit is the generic package we need. + -- If this is the current instance of an enclosing generic, that unit + -- is the generic package we need. elsif In_Open_Scopes (Actual_Pack) and then Ekind (Actual_Pack) = E_Generic_Package @@ -10425,7 +10423,7 @@ package body Sem_Ch12 is Actual_Ent := First_Entity (Actual_Pack); Actual_Of_Formal := - First (Visible_Declarations (Specification (Analyzed_Formal))); + First (Visible_Declarations (Specification (Analyzed_Formal))); while Present (Actual_Ent) and then Actual_Ent /= First_Private_Entity (Actual_Pack) loop diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 7f20221..97cf3fe 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -8963,8 +8963,7 @@ package body Sem_Prag is Mark_Rewrite_Insertion (Decl); else - Error_Pragma_Arg ("no matching type found for pragma%", - Arg2); + Error_Pragma_Arg ("no matching type found for pragma%", Arg2); end if; end Process_Import_Predefined_Type; diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index e32d547..c151e7a 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -8446,6 +8446,7 @@ package body Sem_Res is declare I : Interp_Index; It : Interp; + begin Get_First_Interp (N, I, It); @@ -10086,6 +10087,7 @@ package body Sem_Res is and then Is_Overloaded (Opnd) then Resolve_Equality_Op (Opnd, B_Typ); + if Ekind (Entity (Opnd)) = E_Function then Rewrite_Operator_As_Call (Opnd, Entity (Opnd)); end if; diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index bbd7279..70953b5 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -1612,7 +1612,7 @@ package body Sem_SPARK is Move_Expression_List (Expressions (Expr)); - -- Handle the named components next. + -- Handle the named components next while Present (Assoc) loop CL := Choices (Assoc); @@ -1636,8 +1636,9 @@ package body Sem_SPARK is if Is_Deep (Etype (Expression (Assoc))) and then not Is_Singleton_Choice (CL) then - Error_Msg_F ("singleton choice required" - & " to prevent aliasing", First (CL)); + Error_Msg_F + ("singleton choice required to prevent aliasing", + First (CL)); end if; -- The subexpressions of an aggregate are moved as part diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 7b7d044..19e0026 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -24269,8 +24269,9 @@ package body Sem_Util is Outer : Entity_Id) return Boolean is Curr : Entity_Id := Inner; + begin - -- Similar to the above, but check for scope identity first. + -- Similar to the above, but check for scope identity first while Present (Curr) and then Curr /= Standard_Standard loop if Curr = Outer then -- cgit v1.1 From c7854dbd0fedde0bb15e56cc9b4f120d80f3ef41 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Tue, 9 Jul 2019 07:54:45 +0000 Subject: [Ada] Missing error on generic type with representation clause The compiler does not report an error on a generic type that has a representation clause when its ultimate parent is not a generic formal. 2019-07-09 Javier Miranda gcc/ada/ * sem_ch13.adb (Rep_Item_Too_Early): Representation clauses are not allowed for a derivation of a generic type. Extend the current test to check that none of the parents is a generic type. gcc/testsuite/ * gnat.dg/rep_clause8.adb: New testcase. From-SVN: r273283 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch13.adb | 20 +++++++++++++++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/rep_clause8.adb | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/rep_clause8.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7d8ea33..d8f7de6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-09 Javier Miranda + + * sem_ch13.adb (Rep_Item_Too_Early): Representation clauses are + not allowed for a derivation of a generic type. Extend the + current test to check that none of the parents is a generic + type. + 2019-07-09 Hristian Kirtchev * exp_ch9.adb, exp_util.adb, repinfo.adb, sem_ch12.adb, diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index cbae9c8..6e52272 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -12548,6 +12548,24 @@ package body Sem_Ch13 is ------------------------ function Rep_Item_Too_Early (T : Entity_Id; N : Node_Id) return Boolean is + function Has_Generic_Parent (E : Entity_Id) return Boolean; + -- Return True if any ancestor is a generic type + + function Has_Generic_Parent (E : Entity_Id) return Boolean is + Ancestor_Type : Entity_Id := Etype (E); + + begin + while Present (Ancestor_Type) + and then not Is_Generic_Type (Ancestor_Type) + and then Etype (Ancestor_Type) /= Ancestor_Type + loop + Ancestor_Type := Etype (Ancestor_Type); + end loop; + + return Present (Ancestor_Type) + and then Is_Generic_Type (Ancestor_Type); + end Has_Generic_Parent; + begin -- Cannot apply non-operational rep items to generic types @@ -12555,7 +12573,7 @@ package body Sem_Ch13 is return False; elsif Is_Type (T) - and then Is_Generic_Type (Root_Type (T)) + and then Has_Generic_Parent (T) and then (Nkind (N) /= N_Pragma or else Get_Pragma_Id (N) /= Pragma_Convention) then diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d50b7b2..fa53a2f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-09 Javier Miranda + + * gnat.dg/rep_clause8.adb: New testcase. + 2019-07-09 Ed Schonberg * gnat.dg/equal7.adb, gnat.dg/equal7_pkg.adb, diff --git a/gcc/testsuite/gnat.dg/rep_clause8.adb b/gcc/testsuite/gnat.dg/rep_clause8.adb new file mode 100644 index 0000000..11d1266 --- /dev/null +++ b/gcc/testsuite/gnat.dg/rep_clause8.adb @@ -0,0 +1,19 @@ +procedure Rep_Clause8 is + package Pack is + type Root is tagged record + Comp : Integer; + end record; + end Pack; + use Pack; + + generic + type Formal_Root is new Root with private; + package Gen_Derived is + type Deriv is new Formal_Root with null record + with Size => 300; -- { dg-error "representation item not allowed for generic type" } + end Gen_Derived; + + package Inst_Derived is new Gen_Derived (Root); +begin + null; +end; -- cgit v1.1 From 0024315552cacb8cb38d913e1caa8506121654ef Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Tue, 9 Jul 2019 07:54:50 +0000 Subject: [Ada] Disable calls to Abort defer/undefer when ZCX_By_Default 2019-07-09 Arnaud Charlet gcc/ada/ * libgnat/s-memory.adb: Disable calls to Abort defer/undefer when ZCX_By_Default. From-SVN: r273284 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/libgnat/s-memory.adb | 17 +++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d8f7de6..3832b31 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Arnaud Charlet + + * libgnat/s-memory.adb: Disable calls to Abort defer/undefer + when ZCX_By_Default. + 2019-07-09 Javier Miranda * sem_ch13.adb (Rep_Item_Too_Early): Representation clauses are diff --git a/gcc/ada/libgnat/s-memory.adb b/gcc/ada/libgnat/s-memory.adb index f34a92b..ebc168e 100644 --- a/gcc/ada/libgnat/s-memory.adb +++ b/gcc/ada/libgnat/s-memory.adb @@ -33,13 +33,10 @@ -- This implementation assumes that the underlying malloc/free/realloc -- implementation is thread safe, and thus, no additional lock is required. --- Note that we still need to defer abort because on most systems, an --- asynchronous signal (as used for implementing asynchronous abort of --- task) cannot safely be handled while malloc is executing. - --- If you are not using Ada constructs containing the "abort" keyword, then --- you can remove the calls to Abort_Defer.all and Abort_Undefer.all from --- this unit. +-- Note that when using sjlj exception handling, we still need to defer abort +-- because an asynchronous signal (as used for implementing asynchronous abort +-- of task on sjlj runtimes) cannot safely be handled while malloc is +-- executing. pragma Compiler_Unit_Warning; @@ -80,7 +77,7 @@ package body System.Memory is raise Storage_Error with "object too large"; end if; - if Parameters.No_Abort then + if ZCX_By_Default or else Parameters.No_Abort then Result := c_malloc (System.CRTL.size_t (Size)); else Abort_Defer.all; @@ -121,7 +118,7 @@ package body System.Memory is procedure Free (Ptr : System.Address) is begin - if Parameters.No_Abort then + if ZCX_By_Default or else Parameters.No_Abort then c_free (Ptr); else Abort_Defer.all; @@ -145,7 +142,7 @@ package body System.Memory is raise Storage_Error with "object too large"; end if; - if Parameters.No_Abort then + if ZCX_By_Default or else Parameters.No_Abort then Result := c_realloc (Ptr, System.CRTL.size_t (Size)); else Abort_Defer.all; -- cgit v1.1 From 727e4d37be92715947de468ebf26b4f1cddc2e66 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 9 Jul 2019 07:54:55 +0000 Subject: [Ada] Exp_Util: minor refactoring 2019-07-09 Piotr Trojanek gcc/ada/ * exp_util.adb (Containing_Package_With_Ext_Axioms): Replace low-level Ekind test with a high-level wrapper. From-SVN: r273285 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_util.adb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 3832b31..b89bb8f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Piotr Trojanek + + * exp_util.adb (Containing_Package_With_Ext_Axioms): Replace + low-level Ekind test with a high-level wrapper. + 2019-07-09 Arnaud Charlet * libgnat/s-memory.adb: Disable calls to Abort defer/undefer diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 9769d68..f131080 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -4492,7 +4492,7 @@ package body Exp_Util is begin -- E is the package or generic package which is externally axiomatized - if Ekind_In (E, E_Generic_Package, E_Package) + if Is_Package_Or_Generic_Package (E) and then Has_Annotate_Pragma_For_External_Axiomatization (E) then return E; -- cgit v1.1 From 75cfda8b4aa2cee4e62bcbc74f08f7628224b860 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Tue, 9 Jul 2019 07:55:00 +0000 Subject: [Ada] Task-related circularities in Elaboration order v4.0 This patch adds another suggestion to the elaboration order diagnostics. An elaboration circularity involving a task activation may be resolved through pragma Restrictions (No_Entry_Calls_In_Elaboration_Code). ------------ -- Source -- ------------ -- no_entry_calls.txt pragma Restrictions (No_Entry_Calls_In_Elaboration_Code); -- a.ads package A is task type Task_Typ is entry Start; end Task_Typ; procedure Proc; end A; -- a.adb with B; package body A is task body Task_Typ is begin accept Start; B.Proc; end Task_Typ; Elab : Task_Typ; procedure Proc is null; end A; -- b.ads package B is procedure Proc; end B; -- b.adb with A; package body B is procedure Proc is begin A.Proc; end Proc; end B; -- main.adb with A; -- +--> A spec B spec -- | ^ ^ ^ -- | | with | | -- | sbb | +----------------+ | sbb -- | | | | -- | | | Invocation | -- | A body ------------> B body -- | ^ | | -- | | Invocation | | -- | +------------------+ | -- | | -- | Invocation | -- +---------------------------+ -- -- The cycle is: -- -- A body --> A body procedure Main is begin null; end Main; ---------------------------- -- Compilation and output -- ---------------------------- $ gnatmake -f -q main.adb -gnatd_F $ gnatmake -f -q main.adb -gnatec=no_entry_calls.txt error: Elaboration circularity detected info: info: Reason: info: info: unit "a (body)" depends on its own elaboration info: info: Circularity: info: info: unit "a (body)" invokes a construct of unit "a (body)" at elaboration time info: path 1: info: elaboration of unit "a (body)" info: activation of local task declared at "a.ads":2:14 info: call to subprogram "proc" declared at "b.ads":2:14 info: call to subprogram "proc" declared at "a.ads":6:14 info: info: Suggestions: info: info: use pragma Restrictions (No_Entry_Calls_In_Elaboration_Code) info: use the dynamic elaboration model (compiler switch -gnatE) info: gnatmake: *** bind failed. 2019-07-09 Hristian Kirtchev gcc/ada/ * bindo.ads: Move type Precedence_Kind from the private to the visible part of the unit. * bindo-augmentors.adb: Remove the use of global data as it is bad practice. (Augment_Library_Graph): Update the parameter profile. (Is_Visited, Set_Is_Visited): Remove. (Visit_Elaboration_Root, Visit_Elaboration_Roots): Update the parameter profile and comment on usage. (Visit_Vertex): Likewise. Also keep track of which invocation edge activates a task. * bindo-augmentors.ads (Augment_Library_Graph): Update the parameter profile and comment on usage. * bindo-builders.adb (Create_Forced_Edge, Create_Spec_And_Body_Edge, Create_With_Edge): Update the call to Add_Edge. * bindo-diagnostics.adb: Add with end use clauses for Restrict and Rident. (Output_Dynamic_Model_Suggestions): Remove. (Output_Invocation_Related_Suggestions): New routine. (Output_Suggestions): Output all invocation-related suggestions together. * bindo-elaborators.adb: Remove types Comparator_Ptr and Predicate_Ptr. (Find_Best_Vertex): Update the parameter profile. * bindo-graphs.adb (Activates_Task): New routine. (Add_Body_Before_Spec_Edge): Update the call to Add_Edge_With_Return. (Add_Edge): Update the parameter profile and the call to Add_Edge_With_Return. (Add_Edge_With_Return): Update the parameter profile and comment on usage. (At_Least_One_Edge_Satisfies): New routine. (Contains_Elaborate_All_Edge): Reimplement. (Contains_Static_Successor_Edge, Contains_Task_Activation): New routine. (Contains_Weak_Static_Successor): Remove. (Is_Static_Successor_Edge): New routine. * bindo-graphs.ads: Add types LGE_Predicate_Ptr, LGV_Comparator_Ptr, and LGV_Predicate_Ptr. Update type Library_Graph_Edge_Attributes to capture whether an invocation edge activates a task. Update the value of No_Library_Graph_Edge_Attributes. (Activates_Task): Update the parameter profile and comment on usage. (Contains_Static_Successor_Edge, Contains_Task_Activation): New routines. (Contains_Weak_Static_Successor): Remove. * doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: Update the documentation to reflect the new task-related advice. * gnat_ugn.texi: Regenerate. From-SVN: r273286 --- gcc/ada/ChangeLog | 53 +++++ gcc/ada/bindo-augmentors.adb | 146 ++++++------- gcc/ada/bindo-augmentors.ads | 8 +- gcc/ada/bindo-builders.adb | 36 ++-- gcc/ada/bindo-diagnostics.adb | 90 ++++---- gcc/ada/bindo-elaborators.adb | 17 +- gcc/ada/bindo-graphs.adb | 230 ++++++++++++++------- gcc/ada/bindo-graphs.ads | 52 ++++- gcc/ada/bindo.ads | 18 +- .../elaboration_order_handling_in_gnat.rst | 17 ++ gcc/ada/gnat_ugn.texi | 23 +++ 11 files changed, 441 insertions(+), 249 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b89bb8f..66de527 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,56 @@ +2019-07-09 Hristian Kirtchev + + * bindo.ads: Move type Precedence_Kind from the private to the + visible part of the unit. + * bindo-augmentors.adb: Remove the use of global data as it is + bad practice. + (Augment_Library_Graph): Update the parameter profile. + (Is_Visited, Set_Is_Visited): Remove. + (Visit_Elaboration_Root, Visit_Elaboration_Roots): Update the + parameter profile and comment on usage. + (Visit_Vertex): Likewise. Also keep track of which invocation + edge activates a task. + * bindo-augmentors.ads (Augment_Library_Graph): Update the + parameter profile and comment on usage. + * bindo-builders.adb (Create_Forced_Edge, + Create_Spec_And_Body_Edge, Create_With_Edge): Update the call to + Add_Edge. + * bindo-diagnostics.adb: Add with end use clauses for Restrict + and Rident. + (Output_Dynamic_Model_Suggestions): Remove. + (Output_Invocation_Related_Suggestions): New routine. + (Output_Suggestions): Output all invocation-related suggestions + together. + * bindo-elaborators.adb: Remove types Comparator_Ptr and + Predicate_Ptr. + (Find_Best_Vertex): Update the parameter profile. + * bindo-graphs.adb (Activates_Task): New routine. + (Add_Body_Before_Spec_Edge): Update the call to + Add_Edge_With_Return. + (Add_Edge): Update the parameter profile and the call to + Add_Edge_With_Return. + (Add_Edge_With_Return): Update the parameter profile and comment + on usage. + (At_Least_One_Edge_Satisfies): New routine. + (Contains_Elaborate_All_Edge): Reimplement. + (Contains_Static_Successor_Edge, Contains_Task_Activation): New + routine. + (Contains_Weak_Static_Successor): Remove. + (Is_Static_Successor_Edge): New routine. + * bindo-graphs.ads: Add types LGE_Predicate_Ptr, + LGV_Comparator_Ptr, and LGV_Predicate_Ptr. Update type + Library_Graph_Edge_Attributes to capture whether an invocation + edge activates a task. Update the value of + No_Library_Graph_Edge_Attributes. + (Activates_Task): Update the parameter profile and comment on + usage. + (Contains_Static_Successor_Edge, Contains_Task_Activation): New + routines. + (Contains_Weak_Static_Successor): Remove. + * doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: + Update the documentation to reflect the new task-related advice. + * gnat_ugn.texi: Regenerate. + 2019-07-09 Piotr Trojanek * exp_util.adb (Containing_Package_With_Ext_Axioms): Replace diff --git a/gcc/ada/bindo-augmentors.adb b/gcc/ada/bindo-augmentors.adb index af39464..bb68a2e 100644 --- a/gcc/ada/bindo-augmentors.adb +++ b/gcc/ada/bindo-augmentors.adb @@ -37,14 +37,6 @@ package body Bindo.Augmentors is package body Library_Graph_Augmentors is - ----------------- - -- Global data -- - ----------------- - - Inv_Graph : Invocation_Graph := Invocation_Graphs.Nil; - Lib_Graph : Library_Graph := Library_Graphs.Nil; - Visited : IGV_Sets.Membership_Set := IGV_Sets.Nil; - ---------------- -- Statistics -- ---------------- @@ -61,20 +53,10 @@ package body Bindo.Augmentors is -- Local subprograms -- ----------------------- - function Is_Visited - (Vertex : Invocation_Graph_Vertex_Id) return Boolean; - pragma Inline (Is_Visited); - -- Determine whether invocation graph vertex Vertex has been visited - -- during the traversal. - - procedure Set_Is_Visited - (Vertex : Invocation_Graph_Vertex_Id; - Val : Boolean := True); - pragma Inline (Set_Is_Visited); - -- Mark invocation graph vertex Vertex as visited during the traversal - -- depending on value Val. - - procedure Visit_Elaboration_Root (Root : Invocation_Graph_Vertex_Id); + procedure Visit_Elaboration_Root + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Root : Invocation_Graph_Vertex_Id); pragma Inline (Visit_Elaboration_Root); -- Start a DFS traversal from elaboration root Root to: -- @@ -83,7 +65,9 @@ package body Bindo.Augmentors is -- * Create invocation edges for each such transition where the -- successor is Root. - procedure Visit_Elaboration_Roots; + procedure Visit_Elaboration_Roots + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph); pragma Inline (Visit_Elaboration_Roots); -- Start a DFS traversal from all elaboration roots to: -- @@ -93,9 +77,13 @@ package body Bindo.Augmentors is -- successor is the current root. procedure Visit_Vertex - (Invoker : Invocation_Graph_Vertex_Id; + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Invoker : Invocation_Graph_Vertex_Id; Last_Vertex : Library_Graph_Vertex_Id; Root_Vertex : Library_Graph_Vertex_Id; + Visited_Invokers : IGV_Sets.Membership_Set; + Activates_Task : Boolean; Internal_Controlled_Action : Boolean; Path : Natural); pragma Inline (Visit_Vertex); @@ -124,86 +112,56 @@ package body Bindo.Augmentors is --------------------------- procedure Augment_Library_Graph - (Inv_G : Invocation_Graph; - Lib_G : Library_Graph) + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph) is begin - pragma Assert (Present (Lib_G)); + pragma Assert (Present (Lib_Graph)); -- Nothing to do when there is no invocation graph - if not Present (Inv_G) then + if not Present (Inv_Graph) then return; end if; - -- Prepare the global data. Note that Visited is initialized for each - -- elaboration root. + -- Prepare the statistics data - Inv_Graph := Inv_G; - Lib_Graph := Lib_G; Longest_Path := 0; Total_Visited := 0; - Visit_Elaboration_Roots; + Visit_Elaboration_Roots (Inv_Graph, Lib_Graph); Write_Statistics; end Augment_Library_Graph; - ---------------- - -- Is_Visited -- - ---------------- - - function Is_Visited - (Vertex : Invocation_Graph_Vertex_Id) return Boolean - is - begin - pragma Assert (IGV_Sets.Present (Visited)); - pragma Assert (Present (Vertex)); - - return IGV_Sets.Contains (Visited, Vertex); - end Is_Visited; - - -------------------- - -- Set_Is_Visited -- - -------------------- - - procedure Set_Is_Visited - (Vertex : Invocation_Graph_Vertex_Id; - Val : Boolean := True) - is - begin - pragma Assert (IGV_Sets.Present (Visited)); - pragma Assert (Present (Vertex)); - - if Val then - IGV_Sets.Insert (Visited, Vertex); - else - IGV_Sets.Delete (Visited, Vertex); - end if; - end Set_Is_Visited; - ---------------------------- -- Visit_Elaboration_Root -- ---------------------------- - procedure Visit_Elaboration_Root (Root : Invocation_Graph_Vertex_Id) is + procedure Visit_Elaboration_Root + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Root : Invocation_Graph_Vertex_Id) + is pragma Assert (Present (Inv_Graph)); - pragma Assert (Present (Root)); pragma Assert (Present (Lib_Graph)); + pragma Assert (Present (Root)); Root_Vertex : constant Library_Graph_Vertex_Id := Body_Vertex (Inv_Graph, Root); - pragma Assert (Present (Root_Vertex)); + Visited : IGV_Sets.Membership_Set; begin - -- Prepare the global data - Visited := IGV_Sets.Create (Number_Of_Vertices (Inv_Graph)); Visit_Vertex - (Invoker => Root, + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Invoker => Root, Last_Vertex => Root_Vertex, Root_Vertex => Root_Vertex, + Visited_Invokers => Visited, + Activates_Task => False, Internal_Controlled_Action => False, Path => 0); @@ -214,18 +172,25 @@ package body Bindo.Augmentors is -- Visit_Elaboration_Roots -- ----------------------------- - procedure Visit_Elaboration_Roots is + procedure Visit_Elaboration_Roots + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph) + is Iter : Elaboration_Root_Iterator; Root : Invocation_Graph_Vertex_Id; begin pragma Assert (Present (Inv_Graph)); + pragma Assert (Present (Lib_Graph)); Iter := Iterate_Elaboration_Roots (Inv_Graph); while Has_Next (Iter) loop Next (Iter, Root); - Visit_Elaboration_Root (Root); + Visit_Elaboration_Root + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Root => Root); end loop; end Visit_Elaboration_Roots; @@ -234,15 +199,20 @@ package body Bindo.Augmentors is ------------------ procedure Visit_Vertex - (Invoker : Invocation_Graph_Vertex_Id; + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph; + Invoker : Invocation_Graph_Vertex_Id; Last_Vertex : Library_Graph_Vertex_Id; Root_Vertex : Library_Graph_Vertex_Id; + Visited_Invokers : IGV_Sets.Membership_Set; + Activates_Task : Boolean; Internal_Controlled_Action : Boolean; Path : Natural) is New_Path : constant Natural := Path + 1; Edge : Invocation_Graph_Edge_Id; + Edge_Kind : Invocation_Kind; Invoker_Vertex : Library_Graph_Vertex_Id; Iter : Edges_To_Targets_Iterator; @@ -252,15 +222,16 @@ package body Bindo.Augmentors is pragma Assert (Present (Invoker)); pragma Assert (Present (Last_Vertex)); pragma Assert (Present (Root_Vertex)); + pragma Assert (IGV_Sets.Present (Visited_Invokers)); -- Nothing to do when the current invocation graph vertex has already -- been visited. - if Is_Visited (Invoker) then + if IGV_Sets.Contains (Visited_Invokers, Invoker) then return; end if; - Set_Is_Visited (Invoker); + IGV_Sets.Insert (Visited_Invokers, Invoker); -- Update the statistics @@ -294,10 +265,11 @@ package body Bindo.Augmentors is else Add_Edge - (G => Lib_Graph, - Pred => Invoker_Vertex, - Succ => Root_Vertex, - Kind => Invocation_Edge); + (G => Lib_Graph, + Pred => Invoker_Vertex, + Succ => Root_Vertex, + Kind => Invocation_Edge, + Activates_Task => Activates_Task); end if; end if; @@ -307,15 +279,21 @@ package body Bindo.Augmentors is Iter := Iterate_Edges_To_Targets (Inv_Graph, Invoker); while Has_Next (Iter) loop Next (Iter, Edge); + Edge_Kind := Kind (Inv_Graph, Edge); Visit_Vertex - (Invoker => Target (Inv_Graph, Edge), + (Inv_Graph => Inv_Graph, + Lib_Graph => Lib_Graph, + Invoker => Target (Inv_Graph, Edge), Last_Vertex => Invoker_Vertex, Root_Vertex => Root_Vertex, + Visited_Invokers => Visited_Invokers, + Activates_Task => + Activates_Task + or else Edge_Kind = Task_Activation, Internal_Controlled_Action => Internal_Controlled_Action - or else Kind (Inv_Graph, Edge) in - Internal_Controlled_Invocation_Kind, + or else Edge_Kind in Internal_Controlled_Invocation_Kind, Path => New_Path); end loop; end Visit_Vertex; diff --git a/gcc/ada/bindo-augmentors.ads b/gcc/ada/bindo-augmentors.ads index de6317c..c00d5c0 100644 --- a/gcc/ada/bindo-augmentors.ads +++ b/gcc/ada/bindo-augmentors.ads @@ -43,10 +43,10 @@ package Bindo.Augmentors is package Library_Graph_Augmentors is procedure Augment_Library_Graph - (Inv_G : Invocation_Graph; - Lib_G : Library_Graph); - -- Augment library graph Lib_G with information from invocation graph - -- Inv_G as follows: + (Inv_Graph : Invocation_Graph; + Lib_Graph : Library_Graph); + -- Augment library graph Lib_Graph with information from invocation + -- graph Inv_Graph as follows: -- -- 1) Traverse the invocation graph starting from each elaboration -- procedure of unit Root. diff --git a/gcc/ada/bindo-builders.adb b/gcc/ada/bindo-builders.adb index 233891d..351b10d 100644 --- a/gcc/ada/bindo-builders.adb +++ b/gcc/ada/bindo-builders.adb @@ -415,10 +415,11 @@ package body Bindo.Builders is Write_Eol; Add_Edge - (G => Lib_Graph, - Pred => Pred_Vertex, - Succ => Succ_Vertex, - Kind => Forced_Edge); + (G => Lib_Graph, + Pred => Pred_Vertex, + Succ => Succ_Vertex, + Kind => Forced_Edge, + Activates_Task => False); end Create_Forced_Edge; ------------------------- @@ -497,10 +498,11 @@ package body Bindo.Builders is Set_Corresponding_Item (Lib_Graph, Vertex, Extra_Vertex); Add_Edge - (G => Lib_Graph, - Pred => Extra_Vertex, - Succ => Vertex, - Kind => Spec_Before_Body_Edge); + (G => Lib_Graph, + Pred => Extra_Vertex, + Succ => Vertex, + Kind => Spec_Before_Body_Edge, + Activates_Task => False); -- The unit denotes a spec with a completing body. Link the spec and -- body. @@ -570,12 +572,13 @@ package body Bindo.Builders is if Is_Spec_With_Body (Lib_Graph, Withed_Vertex) then Add_Edge - (G => Lib_Graph, - Pred => + (G => Lib_Graph, + Pred => Corresponding_Vertex (Lib_Graph, Corresponding_Body (Withed_U_Id)), - Succ => Succ, - Kind => Kind); + Succ => Succ, + Kind => Kind, + Activates_Task => False); end if; -- The with comes with pragma Elaborate_All. Treat the edge as a with @@ -597,10 +600,11 @@ package body Bindo.Builders is -- successor. Add_Edge - (G => Lib_Graph, - Pred => Withed_Vertex, - Succ => Succ, - Kind => Kind); + (G => Lib_Graph, + Pred => Withed_Vertex, + Succ => Succ, + Kind => Kind, + Activates_Task => False); end Create_With_Edge; ----------------------- diff --git a/gcc/ada/bindo-diagnostics.adb b/gcc/ada/bindo-diagnostics.adb index 9cd9d68..9dbdfc0 100644 --- a/gcc/ada/bindo-diagnostics.adb +++ b/gcc/ada/bindo-diagnostics.adb @@ -23,9 +23,11 @@ -- -- ------------------------------------------------------------------------------ -with Binderr; use Binderr; -with Debug; use Debug; -with Types; use Types; +with Binderr; use Binderr; +with Debug; use Debug; +with Restrict; use Restrict; +with Rident; use Rident; +with Types; use Types; with Bindo.Validators; use Bindo.Validators; @@ -77,13 +79,6 @@ package body Bindo.Diagnostics is -- Suggest the diagnostic of all cycles in library graph G if circumstances -- allow it. - procedure Output_Dynamic_Model_Suggestions - (G : Library_Graph; - Cycle : Library_Graph_Cycle_Id); - pragma Inline (Output_Dynamic_Model_Suggestions); - -- Suggest the use of the dynamic elaboration model to break cycle Cycle of - -- library graph G if circumstances allow it. - procedure Output_Elaborate_All_Suggestions (G : Library_Graph; Pred : Library_Graph_Vertex_Id; @@ -192,6 +187,13 @@ package body Bindo.Diagnostics is -- Output a transition through edge Edge of invocation graph G, which is -- part of an invocation path. Lib_Graph is the related library graph. + procedure Output_Invocation_Related_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Output_Invocation_Related_Suggestions); + -- Suggest ways to break cycle Cycle of library graph G that involves at + -- least one invocation edge. + procedure Output_Invocation_Transition (Inv_Graph : Invocation_Graph; Lib_Graph : Library_Graph; @@ -523,30 +525,6 @@ package body Bindo.Diagnostics is end Output_All_Cycles_Suggestions; -------------------------------------- - -- Output_Dynamic_Model_Suggestions -- - -------------------------------------- - - procedure Output_Dynamic_Model_Suggestions - (G : Library_Graph; - Cycle : Library_Graph_Cycle_Id) - is - begin - pragma Assert (Present (G)); - pragma Assert (Present (Cycle)); - - -- The cycle contains at least one invocation edge where the successor - -- was statically elaborated. Using the dynamic model may eliminate an - -- invocation edge, and thus the cycle. - - if Invocation_Edge_Count (G, Cycle) > 0 - and then Contains_Weak_Static_Successor (G, Cycle) - then - Error_Msg_Info - (" use the dynamic elaboration model (compiler switch -gnatE)"); - end if; - end Output_Dynamic_Model_Suggestions; - - -------------------------------------- -- Output_Elaborate_All_Suggestions -- -------------------------------------- @@ -1155,6 +1133,48 @@ package body Bindo.Diagnostics is end case; end Output_Invocation_Path_Transition; + ------------------------------------------- + -- Output_Invocation_Related_Suggestions -- + ------------------------------------------- + + procedure Output_Invocation_Related_Suggestions + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + + -- Nothing to do when the cycle does not contain an invocation edge + + if Invocation_Edge_Count (G, Cycle) = 0 then + return; + end if; + + -- The cycle contains at least one invocation edge, where at least + -- one of the paths the edge represents activates a task. The use of + -- restriction No_Entry_Calls_In_Elaboration_Code may halt the flow + -- within the task body on a select or accept statement, eliminating + -- subsequent invocation edges, thus breaking the cycle. + + if not Restriction_Active (No_Entry_Calls_In_Elaboration_Code) + and then Contains_Task_Activation (G, Cycle) + then + Error_Msg_Info + (" use pragma Restrictions " + & "(No_Entry_Calls_In_Elaboration_Code)"); + end if; + + -- The cycle contains at least one invocation edge where the successor + -- was statically elaborated. The use of the dynamic model may remove + -- one of the invocation edges in the cycle, thus breaking the cycle. + + if Contains_Static_Successor_Edge (G, Cycle) then + Error_Msg_Info + (" use the dynamic elaboration model (compiler switch -gnatE)"); + end if; + end Output_Invocation_Related_Suggestions; + ---------------------------------- -- Output_Invocation_Transition -- ---------------------------------- @@ -1257,7 +1277,7 @@ package body Bindo.Diagnostics is -- Output general purpose suggestions - Output_Dynamic_Model_Suggestions + Output_Invocation_Related_Suggestions (G => G, Cycle => Cycle); diff --git a/gcc/ada/bindo-elaborators.adb b/gcc/ada/bindo-elaborators.adb index 192e4a2..6d3a1e24 100644 --- a/gcc/ada/bindo-elaborators.adb +++ b/gcc/ada/bindo-elaborators.adb @@ -180,20 +180,11 @@ package body Bindo.Elaborators is -- can be elaborated. Step is the current step in the elaboration order. -- Indent is the desired indentation level for tracing. - type Comparator_Ptr is access function - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; - - type Predicate_Ptr is access function - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id) return Boolean; - function Find_Best_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; - Is_Suitable_Vertex : Predicate_Ptr; - Compare_Vertices : Comparator_Ptr; + Is_Suitable_Vertex : LGV_Predicate_Ptr; + Compare_Vertices : LGV_Comparator_Ptr; Initial_Best_Msg : String; Subsequent_Best_Msg : String; Step : Elaboration_Order_Step; @@ -917,8 +908,8 @@ package body Bindo.Elaborators is function Find_Best_Vertex (G : Library_Graph; Set : LGV_Sets.Membership_Set; - Is_Suitable_Vertex : Predicate_Ptr; - Compare_Vertices : Comparator_Ptr; + Is_Suitable_Vertex : LGV_Predicate_Ptr; + Compare_Vertices : LGV_Comparator_Ptr; Initial_Best_Msg : String; Subsequent_Best_Msg : String; Step : Elaboration_Order_Step; diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index 5443b79..840f01a 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -1058,15 +1058,17 @@ package body Bindo.Graphs is -- for tracing. function Add_Edge_With_Return - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - Succ : Library_Graph_Vertex_Id; - Kind : Library_Graph_Edge_Kind) return Library_Graph_Edge_Id; + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id; + Kind : Library_Graph_Edge_Kind; + Activates_Task : Boolean) return Library_Graph_Edge_Id; pragma Inline (Add_Edge_With_Return); -- Create a new edge in library graph G with source vertex Pred and -- destination vertex Succ, and return its handle. Kind denotes the - -- nature of the edge. If Pred and Succ are already related, no edge - -- is created and No_Library_Graph_Edge is returned. + -- nature of the edge. Activates_Task should be set when the edge + -- involves a task activation. If Pred and Succ are already related, + -- no edge is created and No_Library_Graph_Edge is returned. procedure Add_Vertex_And_Complement (G : Library_Graph; @@ -1078,6 +1080,14 @@ package body Bindo.Graphs is -- part of an Elaborate_Body pair, or flag Do_Complement is set, add -- the complementary vertex to the set. + function At_Least_One_Edge_Satisfies + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Predicate : LGE_Predicate_Ptr) return Boolean; + pragma Inline (At_Least_One_Edge_Satisfies); + -- Determine whether at least one edge of cycle Cycle of library graph G + -- satisfies predicate Predicate. + function Copy_Cycle_Path (Cycle_Path : LGE_Lists.Doubly_Linked_List) return LGE_Lists.Doubly_Linked_List; @@ -1306,6 +1316,13 @@ package body Bindo.Graphs is -- Determine whether a predecessor vertex and a successor vertex -- described by relation Rel are already linked in library graph G. + function Is_Static_Successor_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Static_Successor_Edge); + -- Determine whether the successor of invocation edge Edge represents a + -- unit that was compile with the static model. + function Links_Vertices_In_Same_Component (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Boolean; @@ -1491,6 +1508,23 @@ package body Bindo.Graphs is -- LGE_Is's successor vertex of library graph G must wait on before -- it can be elaborated. + -------------------- + -- Activates_Task -- + -------------------- + + function Activates_Task + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Kind (G, Edge) = Invocation_Edge + and then Get_LGE_Attributes (G, Edge).Activates_Task; + end Activates_Task; + ------------------------------- -- Add_Body_Before_Spec_Edge -- ------------------------------- @@ -1533,20 +1567,22 @@ package body Bindo.Graphs is if Is_Body_With_Spec (G, Vertex) then Edge := Add_Edge_With_Return - (G => G, - Pred => Vertex, -- body - Succ => Corresponding_Item (G, Vertex), -- spec - Kind => Body_Before_Spec_Edge); + (G => G, + Pred => Vertex, + Succ => Corresponding_Item (G, Vertex), + Kind => Body_Before_Spec_Edge, + Activates_Task => False); -- A spec with a completing body elsif Is_Spec_With_Body (G, Vertex) then Edge := Add_Edge_With_Return - (G => G, - Pred => Corresponding_Item (G, Vertex), -- body - Succ => Vertex, -- spec - Kind => Body_Before_Spec_Edge); + (G => G, + Pred => Corresponding_Item (G, Vertex), + Succ => Vertex, + Kind => Body_Before_Spec_Edge, + Activates_Task => False); end if; if Present (Edge) then @@ -1623,10 +1659,11 @@ package body Bindo.Graphs is -------------- procedure Add_Edge - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - Succ : Library_Graph_Vertex_Id; - Kind : Library_Graph_Edge_Kind) + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id; + Kind : Library_Graph_Edge_Kind; + Activates_Task : Boolean) is Edge : Library_Graph_Edge_Id; pragma Unreferenced (Edge); @@ -1636,13 +1673,15 @@ package body Bindo.Graphs is pragma Assert (Present (Pred)); pragma Assert (Present (Succ)); pragma Assert (Kind /= No_Edge); + pragma Assert (not Activates_Task or else Kind = Invocation_Edge); Edge := Add_Edge_With_Return - (G => G, - Pred => Pred, - Succ => Succ, - Kind => Kind); + (G => G, + Pred => Pred, + Succ => Succ, + Kind => Kind, + Activates_Task => Activates_Task); end Add_Edge; -------------------------- @@ -1650,10 +1689,11 @@ package body Bindo.Graphs is -------------------------- function Add_Edge_With_Return - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - Succ : Library_Graph_Vertex_Id; - Kind : Library_Graph_Edge_Kind) return Library_Graph_Edge_Id + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id; + Kind : Library_Graph_Edge_Kind; + Activates_Task : Boolean) return Library_Graph_Edge_Id is pragma Assert (Present (G)); pragma Assert (Present (Pred)); @@ -1691,7 +1731,9 @@ package body Bindo.Graphs is Set_LGE_Attributes (G => G, Edge => Edge, - Val => (Kind => Kind)); + Val => + (Activates_Task => Activates_Task, + Kind => Kind)); -- Mark the predecessor and successor as related by the new edge. -- This prevents all further attempts to link the same predecessor @@ -1785,6 +1827,43 @@ package body Bindo.Graphs is end if; end Add_Vertex_And_Complement; + --------------------------------- + -- At_Least_One_Edge_Satisfies -- + --------------------------------- + + function At_Least_One_Edge_Satisfies + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Predicate : LGE_Predicate_Ptr) return Boolean + is + Edge : Library_Graph_Edge_Id; + Iter : Edges_Of_Cycle_Iterator; + Satisfied : Boolean; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + pragma Assert (Predicate /= null); + + -- Assume that the predicate cannot be satisfied + + Satisfied := False; + + -- IMPORTANT: + -- + -- * The iteration must run to completion in order to unlock the + -- edges of the cycle. + + Iter := Iterate_Edges_Of_Cycle (G, Cycle); + while Has_Next (Iter) loop + Next (Iter, Edge); + + Satisfied := Satisfied or else Predicate.all (G, Edge); + end loop; + + return Satisfied; + end At_Least_One_Edge_Satisfies; + -------------------------- -- Complementary_Vertex -- -------------------------- @@ -1848,76 +1927,54 @@ package body Bindo.Graphs is (G : Library_Graph; Cycle : Library_Graph_Cycle_Id) return Boolean is - Edge : Library_Graph_Edge_Id; - Iter : Edges_Of_Cycle_Iterator; - Seen : Boolean; - begin pragma Assert (Present (G)); pragma Assert (Present (Cycle)); - -- Assume that no Elaborate_All edge has been seen - - Seen := False; - - -- IMPORTANT: - -- - -- * The iteration must run to completion in order to unlock the - -- edges of the cycle. - - Iter := Iterate_Edges_Of_Cycle (G, Cycle); - while Has_Next (Iter) loop - Next (Iter, Edge); - - if not Seen - and then Is_Elaborate_All_Edge (G, Edge) - then - Seen := True; - end if; - end loop; - - return Seen; + return + At_Least_One_Edge_Satisfies + (G => G, + Cycle => Cycle, + Predicate => Is_Elaborate_All_Edge'Access); end Contains_Elaborate_All_Edge; ------------------------------------ - -- Contains_Weak_Static_Successor -- + -- Contains_Static_Successor_Edge -- ------------------------------------ - function Contains_Weak_Static_Successor + function Contains_Static_Successor_Edge (G : Library_Graph; Cycle : Library_Graph_Cycle_Id) return Boolean is - Edge : Library_Graph_Edge_Id; - Iter : Edges_Of_Cycle_Iterator; - Seen : Boolean; - begin pragma Assert (Present (G)); pragma Assert (Present (Cycle)); - -- Assume that no weak static successor has been seen - - Seen := False; - - -- IMPORTANT: - -- - -- * The iteration must run to completion in order to unlock the - -- edges of the cycle. + return + At_Least_One_Edge_Satisfies + (G => G, + Cycle => Cycle, + Predicate => Is_Static_Successor_Edge'Access); + end Contains_Static_Successor_Edge; - Iter := Iterate_Edges_Of_Cycle (G, Cycle); - while Has_Next (Iter) loop - Next (Iter, Edge); + ------------------------------ + -- Contains_Task_Activation -- + ------------------------------ - if not Seen - and then Is_Invocation_Edge (G, Edge) - and then not Is_Dynamically_Elaborated (G, Successor (G, Edge)) - then - Seen := True; - end if; - end loop; + function Contains_Task_Activation + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); - return Seen; - end Contains_Weak_Static_Successor; + return + At_Least_One_Edge_Satisfies + (G => G, + Cycle => Cycle, + Predicate => Activates_Task'Access); + end Contains_Task_Activation; --------------------- -- Copy_Cycle_Path -- @@ -3632,6 +3689,23 @@ package body Bindo.Graphs is and then Has_Elaborate_Body (G, Vertex); end Is_Spec_With_Elaborate_Body; + ------------------------------ + -- Is_Static_Successor_Edge -- + ------------------------------ + + function Is_Static_Successor_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return + Is_Invocation_Edge (G, Edge) + and then not Is_Dynamically_Elaborated (G, Successor (G, Edge)); + end Is_Static_Successor_Edge; + --------------------------------- -- Is_Weakly_Elaborable_Vertex -- ---------------------------------- diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads index 84e83b9..53bc4ee 100644 --- a/gcc/ada/bindo-graphs.ads +++ b/gcc/ada/bindo-graphs.ads @@ -732,18 +732,33 @@ package Bindo.Graphs is type Library_Graph is private; Nil : constant Library_Graph; + type LGE_Predicate_Ptr is access function + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + + type LGV_Comparator_Ptr is access function + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; + + type LGV_Predicate_Ptr is access function + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + ---------------------- -- Graph operations -- ---------------------- procedure Add_Edge - (G : Library_Graph; - Pred : Library_Graph_Vertex_Id; - Succ : Library_Graph_Vertex_Id; - Kind : Library_Graph_Edge_Kind); + (G : Library_Graph; + Pred : Library_Graph_Vertex_Id; + Succ : Library_Graph_Vertex_Id; + Kind : Library_Graph_Edge_Kind; + Activates_Task : Boolean); pragma Inline (Add_Edge); -- Create a new edge in library graph G with source vertex Pred and - -- destination vertex Succ. Kind denotes the nature of the edge. + -- destination vertex Succ. Kind denotes the nature of the edge. Flag + -- Activates_Task should be set when the edge involves task activation. procedure Add_Vertex (G : Library_Graph; @@ -895,6 +910,12 @@ package Bindo.Graphs is -- Edge attributes -- --------------------- + function Activates_Task + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Activates_Task); + -- Determine whether edge Edge of library graph G activates a task + function Kind (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind; @@ -987,13 +1008,21 @@ package Bindo.Graphs is -- Determine whether cycle Cycle of library graph G contains an -- Elaborate_All edge. - function Contains_Weak_Static_Successor + function Contains_Static_Successor_Edge (G : Library_Graph; Cycle : Library_Graph_Cycle_Id) return Boolean; - pragma Inline (Contains_Weak_Static_Successor); - -- Determine whether cycle Cycle of library graph G contains a weak edge + pragma Inline (Contains_Static_Successor_Edge); + -- Determine whether cycle Cycle of library graph G contains an edge -- where the successor was compiled using the static model. + function Contains_Task_Activation + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) return Boolean; + pragma Inline (Contains_Task_Activation); + -- Determine whether cycle Cycle of library graph G contains an + -- invocation edge where the path it represents involves a task + -- activation. + function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean; pragma Inline (Has_Elaborate_All_Cycle); -- Determine whether library graph G contains a cycle involving pragma @@ -1439,13 +1468,18 @@ package Bindo.Graphs is -- The following type represents the attributes of a library graph edge type Library_Graph_Edge_Attributes is record + Activates_Task : Boolean := False; + -- Set for an invocation edge, where at least one of the paths the + -- edge represents activates a task. + Kind : Library_Graph_Edge_Kind := No_Edge; -- The nature of the library graph edge end record; No_Library_Graph_Edge_Attributes : constant Library_Graph_Edge_Attributes := - (Kind => No_Edge); + (Activates_Task => False, + Kind => No_Edge); procedure Destroy_Library_Graph_Edge_Attributes (Attrs : in out Library_Graph_Edge_Attributes); diff --git a/gcc/ada/bindo.ads b/gcc/ada/bindo.ads index 940b752..b0ebe62 100644 --- a/gcc/ada/bindo.ads +++ b/gcc/ada/bindo.ads @@ -31,6 +31,14 @@ with Namet; use Namet; package Bindo is + -- The following type represents the various kinds of precedence between + -- two items. + + type Precedence_Kind is + (Lower_Precedence, + Equal_Precedence, + Higher_Precedence); + procedure Find_Elaboration_Order (Order : out Unit_Id_Table; Main_Lib_File : File_Name_Type); @@ -41,14 +49,4 @@ package Bindo is -- exists, it is returned in Order, otherwise Unrecoverable_Error is -- raised. -private - - -- The following type represents the various kinds of precedence between - -- two items. - - type Precedence_Kind is - (Lower_Precedence, - Equal_Precedence, - Higher_Precedence); - end Bindo; diff --git a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst index 160dbdf..b27aa73 100644 --- a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst @@ -1014,6 +1014,23 @@ following tactics to eliminate the circularity: The programmer should remove the pragma as advised, and rebuild the program. +* Use of pragma Restrictions + + :: + + use pragma Restrictions (No_Entry_Calls_In_Elaboration_Code) + + This tactic is suggested when the binder has determined that a task + activation at elaboration time + + - Prevents a set of units from being elaborated. + + Note that the binder cannot determine with certainty whether the task will + block at elaboration time. + + The programmer should create a configuration file, place the pragma within, + update the general compilation arguments, and rebuild the program. + * Use of dynamic elaboration model :: diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index b0b3bdd..2d565cc 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -28458,6 +28458,29 @@ declared in the spec by elaboration code in the body. The programmer should remove the pragma as advised, and rebuild the program. @item +Use of pragma Restrictions + +@example +use pragma Restrictions (No_Entry_Calls_In_Elaboration_Code) +@end example + +This tactic is suggested when the binder has determined that a task +activation at elaboration time + + +@itemize - + +@item +Prevents a set of units from being elaborated. +@end itemize + +Note that the binder cannot determine with certainty whether the task will +block at elaboration time. + +The programmer should create a configuration file, place the pragma within, +update the general compilation arguments, and rebuild the program. + +@item Use of dynamic elaboration model @example -- cgit v1.1 From 64ac53f4c4e1ecbf753ce764bfd9083aa0141323 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Tue, 9 Jul 2019 07:55:06 +0000 Subject: [Ada] Reformat comments Replace ". " (i.e. a period followed by two spaces) with ". "; this is meant to avoid distraction when reading comments, except for the license section, where apparently this makes the formating nicer. Some comments have been refilled, in particular those that could fit into fewer lines. Also, some occurences of this patter in code has also been removed, e.g. in "J in 1 .. 3". 2019-07-09 Piotr Trojanek gcc/ada/ * ali.ads, bindo-graphs.adb, bindo-validators.adb, clean.adb, doc/gnat_ugn/elaboration_order_handling_in_gnat.rst, einfo.ads, exp_aggr.adb, exp_ch13.adb, exp_ch4.adb, exp_ch5.adb, exp_ch6.adb, exp_ch7.adb, exp_ch9.adb, exp_pakd.adb, fname-uf.ads, gnatlink.adb, inline.adb, lib.ads, make.adb, namet.ads, opt.ads, par-ch4.adb, par-ch6.adb, par-labl.adb, prep.adb, sem_aggr.adb, sem_ch13.adb, sem_ch4.adb, sem_ch5.adb, sem_ch6.adb, sem_ch6.ads, sem_ch7.adb, sem_ch8.adb, sem_dim.adb, sem_disp.adb, sem_prag.adb, sem_res.adb, sem_warn.adb, sinfo.ads: Replace ". " with ". ". Minor reformatting and typo corrections. * gnat_ugn.texi: Generate. From-SVN: r273287 --- gcc/ada/ChangeLog | 15 ++++++ gcc/ada/ali.ads | 2 +- gcc/ada/bindo-graphs.adb | 2 +- gcc/ada/bindo-validators.adb | 2 +- gcc/ada/clean.adb | 2 +- .../elaboration_order_handling_in_gnat.rst | 60 +++++++++++----------- gcc/ada/einfo.ads | 2 +- gcc/ada/exp_aggr.adb | 4 +- gcc/ada/exp_ch13.adb | 4 +- gcc/ada/exp_ch4.adb | 2 +- gcc/ada/exp_ch5.adb | 2 +- gcc/ada/exp_ch6.adb | 4 +- gcc/ada/exp_ch7.adb | 2 +- gcc/ada/exp_ch9.adb | 18 +++---- gcc/ada/exp_pakd.adb | 2 +- gcc/ada/fname-uf.ads | 2 +- gcc/ada/gnat_ugn.texi | 60 +++++++++++----------- gcc/ada/gnatlink.adb | 4 +- gcc/ada/inline.adb | 2 +- gcc/ada/lib.ads | 2 +- gcc/ada/make.adb | 2 +- gcc/ada/namet.ads | 2 +- gcc/ada/opt.ads | 2 +- gcc/ada/par-ch4.adb | 2 +- gcc/ada/par-ch6.adb | 2 +- gcc/ada/par-labl.adb | 2 +- gcc/ada/prep.adb | 2 +- gcc/ada/sem_aggr.adb | 2 +- gcc/ada/sem_ch13.adb | 4 +- gcc/ada/sem_ch4.adb | 4 +- gcc/ada/sem_ch5.adb | 8 +-- gcc/ada/sem_ch6.adb | 2 +- gcc/ada/sem_ch6.ads | 2 +- gcc/ada/sem_ch7.adb | 2 +- gcc/ada/sem_ch8.adb | 2 +- gcc/ada/sem_dim.adb | 8 +-- gcc/ada/sem_disp.adb | 2 +- gcc/ada/sem_prag.adb | 2 +- gcc/ada/sem_res.adb | 2 +- gcc/ada/sem_warn.adb | 2 +- gcc/ada/sinfo.ads | 2 +- 41 files changed, 132 insertions(+), 119 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 66de527..a2c6066 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,18 @@ +2019-07-09 Piotr Trojanek + + * ali.ads, bindo-graphs.adb, bindo-validators.adb, clean.adb, + doc/gnat_ugn/elaboration_order_handling_in_gnat.rst, einfo.ads, + exp_aggr.adb, exp_ch13.adb, exp_ch4.adb, exp_ch5.adb, + exp_ch6.adb, exp_ch7.adb, exp_ch9.adb, exp_pakd.adb, + fname-uf.ads, gnatlink.adb, inline.adb, lib.ads, make.adb, + namet.ads, opt.ads, par-ch4.adb, par-ch6.adb, par-labl.adb, + prep.adb, sem_aggr.adb, sem_ch13.adb, sem_ch4.adb, sem_ch5.adb, + sem_ch6.adb, sem_ch6.ads, sem_ch7.adb, sem_ch8.adb, sem_dim.adb, + sem_disp.adb, sem_prag.adb, sem_res.adb, sem_warn.adb, + sinfo.ads: Replace ". " with ". ". Minor reformatting and typo + corrections. + * gnat_ugn.texi: Generate. + 2019-07-09 Hristian Kirtchev * bindo.ads: Move type Precedence_Kind from the private to the diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads index 3fa527e..fc6e592 100644 --- a/gcc/ada/ali.ads +++ b/gcc/ada/ali.ads @@ -226,7 +226,7 @@ package ALI is No_Component_Reordering : Boolean; -- Set to True if file was compiled with a configuration pragma file - -- containing pragma No_Component_Reordering. Not set if 'P' appears + -- containing pragma No_Component_Reordering. Not set if 'P' appears -- in Ignore_Lines. No_Object : Boolean; diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index 840f01a..26b0c27 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -1321,7 +1321,7 @@ package body Bindo.Graphs is Edge : Library_Graph_Edge_Id) return Boolean; pragma Inline (Is_Static_Successor_Edge); -- Determine whether the successor of invocation edge Edge represents a - -- unit that was compile with the static model. + -- unit that was compiled with the static model. function Links_Vertices_In_Same_Component (G : Library_Graph; diff --git a/gcc/ada/bindo-validators.adb b/gcc/ada/bindo-validators.adb index 88be2e8..b711a91 100644 --- a/gcc/ada/bindo-validators.adb +++ b/gcc/ada/bindo-validators.adb @@ -378,7 +378,7 @@ package body Bindo.Validators is -- Validate each unit in the elaboration order against the set of -- units that need to be elaborated. - for Index in Unit_Id_Tables.First .. Unit_Id_Tables.Last (Order) loop + for Index in Unit_Id_Tables.First .. Unit_Id_Tables.Last (Order) loop Validate_Unit (U_Id => Order.Table (Index), Elab_Set => Elab_Set); diff --git a/gcc/ada/clean.adb b/gcc/ada/clean.adb index fa522ee..565d22e 100644 --- a/gcc/ada/clean.adb +++ b/gcc/ada/clean.adb @@ -854,7 +854,7 @@ package body Clean is then Project_File_Name := new String' - (Prj (Prj'First + 1 .. Prj'Last)); + (Prj (Prj'First + 1 .. Prj'Last)); else Project_File_Name := new String'(Prj); end if; diff --git a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst index b27aa73..eb0f905 100644 --- a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst @@ -184,7 +184,7 @@ factors: * preelaborability of units -* presence of elaboration control pragmas +* presence of elaboration-control pragmas * invocations performed in elaboration code @@ -255,7 +255,7 @@ successfully elaborated. Ada states that a total elaboration order must exist, but it does not define what this order is. A compiler is thus tasked with choosing a suitable elaboration order which satisfies the dependencies imposed by |with| clauses, -unit categorization, elaboration control pragmas, and invocations performed in +unit categorization, elaboration-control pragmas, and invocations performed in elaboration code. Ideally an order that avoids ABE problems should be chosen, however a compiler may not always find such an order due to complications with respect to control and data flow. @@ -265,7 +265,7 @@ respect to control and data flow. Checking the Elaboration Order ============================== -To avoid placing the entire elaboration order burden on the programmer, Ada +To avoid placing the entire elaboration-order burden on the programmer, Ada provides three lines of defense: * *Static semantics* @@ -545,7 +545,7 @@ depend on. be elaborated prior to ``Client``. Removing pragma ``Elaborate_All`` could result in the following incorrect - elaboration order + elaboration order: :: @@ -617,7 +617,7 @@ elaboration order and to diagnose elaboration problems. - All code within all units in a partition is considered to be elaboration code. - - Some of the invocations in elaboration code may not take place at runtime + - Some of the invocations in elaboration code may not take place at run time due to conditional execution. GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios @@ -625,11 +625,11 @@ elaboration order and to diagnose elaboration problems. all external targets and for all scenarios that may exhibit ABE problems. The elaboration order is obtained by honoring all |with| clauses, purity and - preelaborability of units, and elaboration control pragmas. The dynamic model + preelaborability of units, and elaboration-control pragmas. The dynamic model attempts to take all invocations in elaboration code into account. If an invocation leads to a circularity, GNAT ignores the invocation based on the assumptions stated above. An order obtained using the dynamic model may fail - an ABE check at runtime when GNAT ignored an invocation. + an ABE check at run time when GNAT ignored an invocation. The dynamic model is enabled with compiler switch :switch:`-gnatE`. @@ -643,7 +643,7 @@ elaboration order and to diagnose elaboration problems. - Only code at the library level and in package body statements within all units in a partition is considered to be elaboration code. - - All invocations in elaboration will take place at runtime, regardless of + - All invocations in elaboration will take place at run time, regardless of conditional execution. GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios @@ -651,7 +651,7 @@ elaboration order and to diagnose elaboration problems. all external targets and for all scenarios that may exhibit ABE problems. The elaboration order is obtained by honoring all |with| clauses, purity and - preelaborability of units, presence of elaboration control pragmas, and all + preelaborability of units, presence of elaboration-control pragmas, and all invocations in elaboration code. An order obtained using the static model is guaranteed to be ABE problem-free, excluding dispatching calls and access-to-subprogram types. @@ -846,9 +846,9 @@ Elaboration Circularities An **elaboration circularity** occurs whenever the elaboration of a set of units enters a deadlocked state, where each unit is waiting for another unit to be elaborated. This situation may be the result of improper use of |with| -clauses, elaboration control pragmas, or invocations in elaboration code. +clauses, elaboration-control pragmas, or invocations in elaboration code. -The following example showcases an elaboration circularity. +The following example exhibits an elaboration circularity. :: @@ -941,7 +941,7 @@ too much modification, especially in the case of complex legacy code. When faced with an elaboration circularity, the programmer should also consider the tactics given in the suggestions section of the circularity diagnostic. Depending on the units involved in the circularity, their |with| clauses, -purity, preelaborability, presence of elaboration control pragmas and +purity, preelaborability, presence of elaboration-control pragmas and invocations at elaboration time, the binder may suggest one or more of the following tactics to eliminate the circularity: @@ -951,8 +951,8 @@ following tactics to eliminate the circularity: remove pragma Elaborate for unit "..." in unit "..." - This tactic is suggested when the binder has determine that pragma - ``Elaborate`` + This tactic is suggested when the binder has determined that pragma + ``Elaborate``: - Prevents a set of units from being elaborated. @@ -971,7 +971,7 @@ following tactics to eliminate the circularity: remove pragma Elaborate_All for unit "..." in unit "..." This tactic is suggested when the binder has determined that pragma - ``Elaborate_All`` + ``Elaborate_All``: - Prevents a set of units from being elaborated. @@ -1002,7 +1002,7 @@ following tactics to eliminate the circularity: remove pragma Elaborate_Body in unit "..." This tactic is suggested when the binder has determined that pragma - ``Elaborate_Body`` + ``Elaborate_Body``: - Prevents a set of units from being elaborated. @@ -1021,7 +1021,7 @@ following tactics to eliminate the circularity: use pragma Restrictions (No_Entry_Calls_In_Elaboration_Code) This tactic is suggested when the binder has determined that a task - activation at elaboration time + activation at elaboration time: - Prevents a set of units from being elaborated. @@ -1038,7 +1038,7 @@ following tactics to eliminate the circularity: use the dynamic elaboration model (compiler switch -gnatE) This tactic is suggested when the binder has determined that an invocation at - elaboration time + elaboration time: - Prevents a set of units from being elaborated. @@ -1070,43 +1070,43 @@ following tactics to eliminate the circularity: The programmer should analyze this information to determine which units should be compiled with the dynamic model. -* Forced dependency elimination +* Forced-dependency elimination :: remove the dependency of unit "..." on unit "..." from the argument of switch -f This tactic is suggested when the binder has determined that a dependency - present in the forced delboration order file indicated by binder switch - :switch:`-f` + present in the forced-elaboration-order file indicated by binder switch + :switch:`-f`: - Prevents a set of units from being elaborated. - The removal of the dependency will enable the successful ordering of the units. - The programmer should edit the forced elaboration order file, remove the + The programmer should edit the forced-elaboration-order file, remove the dependency, and rebind the program. -* All forced dependency elimination +* All forced-dependency elimination :: remove switch -f - This tactic is suggested in case editing the forced elaboration order file is + This tactic is suggested in case editing the forced-elaboration-order file is not an option. The programmer should remove binder switch :switch:`-f` from the binder arguments, and rebind. -* Multiple circularities diagnostic +* Multiple-circularities diagnostic :: diagnose all circularities (binder switch -d_C) - By default, the binder will diagnose only the highest precedence circularity. + By default, the binder will diagnose only the highest-precedence circularity. If the program contains multiple circularities, the binder will suggest the use of binder switch :switch:`-d_C` in order to obtain the diagnostics of all circularities. @@ -1118,16 +1118,16 @@ If none of the tactics suggested by the binder eliminate the elaboration circularity, the programmer should consider using one of the legacy elaboration models, in the following order: -* Use the pre-20.x legacy elaboration order model, with binder switch +* Use the pre-20.x legacy elaboration-order model, with binder switch :switch:`-H`. * Use both pre-18.x and pre-20.x legacy elaboration models, with compiler switch :switch:`-gnatH` and binder switch :switch:`-H`. -* Use the relaxed static elaboration model, with compiler switches +* Use the relaxed static-elaboration model, with compiler switches :switch:`-gnatH` :switch:`-gnatJ` and binder switch :switch:`-H`. -* Use the relaxed dynamic elaboration model, with compiler switches +* Use the relaxed dynamic-elaboration model, with compiler switches :switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE` and binder switch :switch:`-H`. @@ -1304,7 +1304,7 @@ options: * If none of the steps outlined above resolve the circularity, use a more permissive elaboration model, in the following order: - - Use the pre-20.x legacy elaboration order model, with binder switch + - Use the pre-20.x legacy elaboration-order model, with binder switch :switch:`-H`. - Use both pre-18.x and pre-20.x legacy elaboration models, with compiler diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index d948151..f69a94a 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -320,7 +320,7 @@ package Einfo is -- an attempt to set the attribute on a subtype will raise an assert error. -- Other attributes are noted as applying to the [implementation base type --- only]. These are representation attributes which must always apply to a +-- only]. These are representation attributes which must always apply to a -- full non-private type, and where the attributes are always on the full -- type. The attribute can be referenced on a subtype (and automatically -- retrieves the value from the implementation base type). However, it is an diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 7c41477..c944db6 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -192,7 +192,7 @@ package body Exp_Aggr is procedure Convert_To_Assignments (N : Node_Id; Typ : Entity_Id); -- Transform a record aggregate into a sequence of assignments performed - -- component by component. N is an N_Aggregate or N_Extension_Aggregate. + -- component by component. N is an N_Aggregate or N_Extension_Aggregate. -- Typ is the type of the record aggregate. procedure Expand_Record_Aggregate @@ -8751,7 +8751,7 @@ package body Exp_Aggr is Val := 0; Packed_Num := 0; - -- Account for endianness. See corresponding comment in + -- Account for endianness. See corresponding comment in -- Packed_Array_Aggregate_Handled concerning the following. if Bytes_Big_Endian diff --git a/gcc/ada/exp_ch13.adb b/gcc/ada/exp_ch13.adb index 6ee7f75..f3c2c01 100644 --- a/gcc/ada/exp_ch13.adb +++ b/gcc/ada/exp_ch13.adb @@ -232,7 +232,7 @@ package body Exp_Ch13 is Convert_To (RTE (RE_Size_Type), Expression (N))); -- If the clause is not generated by an aspect, insert - -- the assignment here. Freezing rules ensure that this + -- the assignment here. Freezing rules ensure that this -- is safe, or clause will have been rejected already. if Is_List_Member (N) then @@ -724,7 +724,7 @@ package body Exp_Ch13 is end if; -- If the record representation clause has no components, then - -- completely remove it. Note that we also have to remove + -- completely remove it. Note that we also have to remove -- ourself from the Rep Item list. if Is_Empty_List (Component_Clauses (N)) then diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index eb35845..99bde93 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -7404,7 +7404,7 @@ package body Exp_Ch4 is -- Obj1 : Enclosing_Non_UU_Type; -- Obj2 : Enclosing_Non_UU_Type (1); - -- ... Obj1 = Obj2 ... + -- ... Obj1 = Obj2 ... -- Generated code: diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 664ede8..f1d12cb 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -3919,7 +3919,7 @@ package body Exp_Ch5 is -- -- Default_Iterator aspect of Vector. This increments Lock, -- -- disallowing tampering with cursors. Unfortunately, it does not -- -- increment Busy. The result of Iterate is Limited_Controlled; - -- -- finalization will decrement Lock. This is a build-in-place + -- -- finalization will decrement Lock. This is a build-in-place -- -- dispatching call to Iterate. -- Cur : Cursor := First (Iter); -- or Last diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index ae17a5b..364acd9 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -3203,7 +3203,7 @@ package body Exp_Ch6 is -- ??? -- A further case that requires special handling - -- is the common idiom E.all'access. If E is a + -- is the common idiom E.all'access. If E is a -- formal of the enclosing subprogram, the -- accessibility of the expression is that of E. @@ -8525,7 +8525,7 @@ package body Exp_Ch6 is -- The presence of an address clause complicates the build-in-place -- expansion because the indicated address must be processed before -- the indirect call is generated (including the definition of a - -- local pointer to the object). The address clause may come from + -- local pointer to the object). The address clause may come from -- an aspect specification or from an explicit attribute -- specification appearing after the object declaration. These two -- cases require different processing. diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 4526af6..2ca4109 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -393,7 +393,7 @@ package body Exp_Ch7 is -- name. Before generating the proper call to one of these operations we -- check whether Typ is known to be controlled at the point of definition. -- If it is not then we must retrieve the hidden operation of the parent - -- and use it instead. This is one case that might be solved more cleanly + -- and use it instead. This is one case that might be solved more cleanly -- once Overriding pragmas or declarations are in place. function Contains_Subprogram (Blk : Entity_Id) return Boolean; diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 48b4090..7eb6eb5 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -477,12 +477,11 @@ package body Exp_Ch9 is -- := P.; procedure Reset_Scopes_To (Bod : Node_Id; E : Entity_Id); - -- Reset the scope of declarations and blocks at the top level of Bod - -- to be E. Bod is either a block or a subprogram body. Used after - -- expanding various kinds of entry bodies into their corresponding - -- constructs. This is needed during unnesting to determine whether a - -- body generated for an entry or an accept alternative includes uplevel - -- references. + -- Reset the scope of declarations and blocks at the top level of Bod to + -- be E. Bod is either a block or a subprogram body. Used after expanding + -- various kinds of entry bodies into their corresponding constructs. This + -- is needed during unnesting to determine whether a body generated for an + -- entry or an accept alternative includes uplevel references. function Trivial_Accept_OK return Boolean; -- If there is no DO-END block for an accept, or if the DO-END block has @@ -12943,10 +12942,9 @@ package body Exp_Ch9 is Analyze (N); - -- Some items in Decls used to be in the N_Block in E_Call that - -- is constructed in Expand_Entry_Call, and are now in the new - -- Block into which N has been rewritten. Adjust their scopes - -- to reflect that. + -- Some items in Decls used to be in the N_Block in E_Call that is + -- constructed in Expand_Entry_Call, and are now in the new Block + -- into which N has been rewritten. Adjust their scopes to reflect that. if Nkind (E_Call) = N_Block_Statement then Obj := First_Entity (Entity (Identifier (E_Call))); diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb index f6a7eed..2f45a72 100644 --- a/gcc/ada/exp_pakd.adb +++ b/gcc/ada/exp_pakd.adb @@ -1127,7 +1127,7 @@ package body Exp_Pakd is -- If we are building the initialization procedure for a packed array, -- and Initialize_Scalars is enabled, each component assignment is an - -- out-of-range value by design. Compile this value without checks, + -- out-of-range value by design. Compile this value without checks, -- because a call to the array init_proc must not raise an exception. -- Condition is not consistent with description above, Within_Init_Proc diff --git a/gcc/ada/fname-uf.ads b/gcc/ada/fname-uf.ads index 90b2ef3..3e62c47 100644 --- a/gcc/ada/fname-uf.ads +++ b/gcc/ada/fname-uf.ads @@ -105,7 +105,7 @@ package Fname.UF is Dot : String_Ptr; Cas : Casing_Type); -- This is called to process a Source_File_Name pragma whose first - -- argument is a file name pattern string. Pat is this pattern string, + -- argument is a file name pattern string. Pat is this pattern string, -- which contains an asterisk to correspond to the unit. Typ is one of -- 'b'/'s'/'u' for body/spec/subunit, Dot is the separator string -- for child/subunit names, and Cas is one of Lower/Upper/Mixed diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 2d565cc..124c289 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -27455,7 +27455,7 @@ purity of units preelaborability of units @item -presence of elaboration control pragmas +presence of elaboration-control pragmas @item invocations performed in elaboration code @@ -27537,7 +27537,7 @@ body of Main Ada states that a total elaboration order must exist, but it does not define what this order is. A compiler is thus tasked with choosing a suitable elaboration order which satisfies the dependencies imposed by @emph{with} clauses, -unit categorization, elaboration control pragmas, and invocations performed in +unit categorization, elaboration-control pragmas, and invocations performed in elaboration code. Ideally an order that avoids ABE problems should be chosen, however a compiler may not always find such an order due to complications with respect to control and data flow. @@ -27547,7 +27547,7 @@ respect to control and data flow. @section Checking the Elaboration Order -To avoid placing the entire elaboration order burden on the programmer, Ada +To avoid placing the entire elaboration-order burden on the programmer, Ada provides three lines of defense: @@ -27870,7 +27870,7 @@ Note that there are several allowable suborders for the specs and bodies of be elaborated prior to @code{Client}. Removing pragma @code{Elaborate_All} could result in the following incorrect -elaboration order +elaboration order: @example spec of Math @@ -27960,7 +27960,7 @@ All code within all units in a partition is considered to be elaboration code. @item -Some of the invocations in elaboration code may not take place at runtime +Some of the invocations in elaboration code may not take place at run time due to conditional execution. @end itemize @@ -27969,11 +27969,11 @@ that invoke internal targets. In addition, GNAT generates run-time checks for all external targets and for all scenarios that may exhibit ABE problems. The elaboration order is obtained by honoring all @emph{with} clauses, purity and -preelaborability of units, and elaboration control pragmas. The dynamic model +preelaborability of units, and elaboration-control pragmas. The dynamic model attempts to take all invocations in elaboration code into account. If an invocation leads to a circularity, GNAT ignores the invocation based on the assumptions stated above. An order obtained using the dynamic model may fail -an ABE check at runtime when GNAT ignored an invocation. +an ABE check at run time when GNAT ignored an invocation. The dynamic model is enabled with compiler switch @code{-gnatE}. @end itemize @@ -27997,7 +27997,7 @@ Only code at the library level and in package body statements within all units in a partition is considered to be elaboration code. @item -All invocations in elaboration will take place at runtime, regardless of +All invocations in elaboration will take place at run time, regardless of conditional execution. @end itemize @@ -28006,7 +28006,7 @@ that invoke internal targets. In addition, GNAT generates run-time checks for all external targets and for all scenarios that may exhibit ABE problems. The elaboration order is obtained by honoring all @emph{with} clauses, purity and -preelaborability of units, presence of elaboration control pragmas, and all +preelaborability of units, presence of elaboration-control pragmas, and all invocations in elaboration code. An order obtained using the static model is guaranteed to be ABE problem-free, excluding dispatching calls and access-to-subprogram types. @@ -28249,9 +28249,9 @@ rules. An @strong{elaboration circularity} occurs whenever the elaboration of a set of units enters a deadlocked state, where each unit is waiting for another unit to be elaborated. This situation may be the result of improper use of @emph{with} -clauses, elaboration control pragmas, or invocations in elaboration code. +clauses, elaboration-control pragmas, or invocations in elaboration code. -The following example showcases an elaboration circularity. +The following example exhibits an elaboration circularity. @quotation @@ -28357,7 +28357,7 @@ too much modification, especially in the case of complex legacy code. When faced with an elaboration circularity, the programmer should also consider the tactics given in the suggestions section of the circularity diagnostic. Depending on the units involved in the circularity, their @emph{with} clauses, -purity, preelaborability, presence of elaboration control pragmas and +purity, preelaborability, presence of elaboration-control pragmas and invocations at elaboration time, the binder may suggest one or more of the following tactics to eliminate the circularity: @@ -28371,8 +28371,8 @@ Pragma Elaborate elimination remove pragma Elaborate for unit "..." in unit "..." @end example -This tactic is suggested when the binder has determine that pragma -@code{Elaborate} +This tactic is suggested when the binder has determined that pragma +@code{Elaborate}: @itemize - @@ -28399,7 +28399,7 @@ remove pragma Elaborate_All for unit "..." in unit "..." @end example This tactic is suggested when the binder has determined that pragma -@code{Elaborate_All} +@code{Elaborate_All}: @itemize - @@ -28439,7 +28439,7 @@ remove pragma Elaborate_Body in unit "..." @end example This tactic is suggested when the binder has determined that pragma -@code{Elaborate_Body} +@code{Elaborate_Body}: @itemize - @@ -28465,7 +28465,7 @@ use pragma Restrictions (No_Entry_Calls_In_Elaboration_Code) @end example This tactic is suggested when the binder has determined that a task -activation at elaboration time +activation at elaboration time: @itemize - @@ -28488,7 +28488,7 @@ use the dynamic elaboration model (compiler switch -gnatE) @end example This tactic is suggested when the binder has determined that an invocation at -elaboration time +elaboration time: @itemize - @@ -28534,15 +28534,15 @@ The programmer should analyze this information to determine which units should be compiled with the dynamic model. @item -Forced dependency elimination +Forced-dependency elimination @example remove the dependency of unit "..." on unit "..." from the argument of switch -f @end example This tactic is suggested when the binder has determined that a dependency -present in the forced delboration order file indicated by binder switch -@code{-f} +present in the forced-elaboration-order file indicated by binder switch +@code{-f}: @itemize - @@ -28555,30 +28555,30 @@ The removal of the dependency will enable the successful ordering of the units. @end itemize -The programmer should edit the forced elaboration order file, remove the +The programmer should edit the forced-elaboration-order file, remove the dependency, and rebind the program. @item -All forced dependency elimination +All forced-dependency elimination @example remove switch -f @end example -This tactic is suggested in case editing the forced elaboration order file is +This tactic is suggested in case editing the forced-elaboration-order file is not an option. The programmer should remove binder switch @code{-f} from the binder arguments, and rebind. @item -Multiple circularities diagnostic +Multiple-circularities diagnostic @example diagnose all circularities (binder switch -d_C) @end example -By default, the binder will diagnose only the highest precedence circularity. +By default, the binder will diagnose only the highest-precedence circularity. If the program contains multiple circularities, the binder will suggest the use of binder switch @code{-d_C} in order to obtain the diagnostics of all circularities. @@ -28595,7 +28595,7 @@ models, in the following order: @itemize * @item -Use the pre-20.x legacy elaboration order model, with binder switch +Use the pre-20.x legacy elaboration-order model, with binder switch @code{-H}. @item @@ -28603,11 +28603,11 @@ Use both pre-18.x and pre-20.x legacy elaboration models, with compiler switch @code{-gnatH} and binder switch @code{-H}. @item -Use the relaxed static elaboration model, with compiler switches +Use the relaxed static-elaboration model, with compiler switches @code{-gnatH} @code{-gnatJ} and binder switch @code{-H}. @item -Use the relaxed dynamic elaboration model, with compiler switches +Use the relaxed dynamic-elaboration model, with compiler switches @code{-gnatH} @code{-gnatJ} @code{-gnatE} and binder switch @code{-H}. @end itemize @@ -28833,7 +28833,7 @@ permissive elaboration model, in the following order: @itemize - @item -Use the pre-20.x legacy elaboration order model, with binder switch +Use the pre-20.x legacy elaboration-order model, with binder switch @code{-H}. @item diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb index 5e5ede0..69462e9 100644 --- a/gcc/ada/gnatlink.adb +++ b/gcc/ada/gnatlink.adb @@ -459,7 +459,7 @@ procedure Gnatlink is when 'v' => - -- Support "double" verbose mode. Second -v + -- Support "double" verbose mode. Second -v -- gets sent to the linker and binder phases. if Verbose_Mode then @@ -2068,7 +2068,7 @@ begin end Link_Step; -- Only keep the binder output file and it's associated object - -- file if compiling with the -g option. These files are only + -- file if compiling with the -g option. These files are only -- useful if debugging. if not Debug_Flag_Present then diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb index 907975e..5b7fefc 100644 --- a/gcc/ada/inline.adb +++ b/gcc/ada/inline.adb @@ -1751,7 +1751,7 @@ package body Inline is -- occurrences of pragmas referencing the formals are removed since -- they have no meaning when the body is inlined and the formals are -- rewritten (the analysis of the non-inlined body will handle these - -- pragmas). A new internal name is associated with Body_To_Inline. + -- pragmas). A new internal name is associated with Body_To_Inline. ------------------------------ -- Generate_Subprogram_Body -- diff --git a/gcc/ada/lib.ads b/gcc/ada/lib.ads index c6c11c1..504120e 100644 --- a/gcc/ada/lib.ads +++ b/gcc/ada/lib.ads @@ -993,7 +993,7 @@ private -- clause. The First entry is the main unit. The second entry, if present -- is a unit on which the first unit depends, etc. This stack is used to -- generate error messages showing the dependency chain if a file is not - -- found, or whether a true circular dependency exists. The Load_Unit + -- found, or whether a true circular dependency exists. The Load_Unit -- function makes an entry in this table when it is called, and removes -- the entry just before it returns. diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb index 750e62f..805addb 100644 --- a/gcc/ada/make.adb +++ b/gcc/ada/make.adb @@ -502,7 +502,7 @@ package body Make is -- linker). For the sake of convenience, some program specific switches -- can be passed directly on the gnatmake command line. This procedure -- records these switches so that gnatmake can pass them to the right - -- program. S is the switch to be added at the end of the command line + -- program. S is the switch to be added at the end of the command line -- for Program if Append_Switch is True. If Append_Switch is False S is -- added at the beginning of the command line. diff --git a/gcc/ada/namet.ads b/gcc/ada/namet.ads index a54735a..bdd3dad 100644 --- a/gcc/ada/namet.ads +++ b/gcc/ada/namet.ads @@ -431,7 +431,7 @@ package Namet is -- Uhh encoding (hh = hex code), other 16-bit wide character values are -- stored using the Whhhh (hhhh = hex code) encoding, and other 32-bit wide -- wide character values are stored using the WWhhhhhhhh (hhhhhhhh = hex - -- code). Note that this procedure does not fold upper case letters (they + -- code). Note that this procedure does not fold upper case letters (they -- are stored using the Uhh encoding). procedure Set_Character_Literal_Name diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads index 0b62af8..4c1cf6f 100644 --- a/gcc/ada/opt.ads +++ b/gcc/ada/opt.ads @@ -1984,7 +1984,7 @@ package Opt is -- set by the command line switches -gnat83/95/2005/2012, and possibly -- modified by the use of configuration pragmas Ada_*. This switch is used -- to set the initial value for Ada_Version mode at the start of analysis - -- of a unit. Note however that the setting of this flag is ignored for + -- of a unit. Note however that the setting of this flag is ignored for -- internal and predefined units (which are always compiled in the most up -- to date version of Ada). diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb index 9de9a60..b9b0214 100644 --- a/gcc/ada/par-ch4.adb +++ b/gcc/ada/par-ch4.adb @@ -2262,7 +2262,7 @@ package body Ch4 is -- capacity-exceeded error. The purpose of this trick is to avoid -- creating a deeply nested tree, which would cause deep recursion -- during semantics, causing stack overflow. This way, we can handle - -- enormous concatenations in the normal case of predefined "&". We + -- enormous concatenations in the normal case of predefined "&". We -- first build up the normal tree, and then rewrite it if -- appropriate. diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb index 0c4672c..0fc7109 100644 --- a/gcc/ada/par-ch6.adb +++ b/gcc/ada/par-ch6.adb @@ -1442,7 +1442,7 @@ package body Ch6 is Look_Ahead : loop -- If we run into a semicolon, then assume that a - -- colon was missing, e.g. Parms (X Y; ...). Also + -- colon was missing, e.g. Parms (X Y; ...). Also -- assume missing colon on EOF (a real disaster) -- and on a right paren, e.g. Parms (X Y), and also -- on an assignment symbol, e.g. Parms (X Y := ..) diff --git a/gcc/ada/par-labl.adb b/gcc/ada/par-labl.adb index 1edc803..899905e 100644 --- a/gcc/ada/par-labl.adb +++ b/gcc/ada/par-labl.adb @@ -79,7 +79,7 @@ procedure Labl is -- then we have an error. -- Note that in the worst case, this is quadratic in the number - -- of labels. However, labels are not all that common, and this + -- of labels. However, labels are not all that common, and this -- is only called for explicit labels. -- ???Nonetheless, the efficiency could be improved. For example, diff --git a/gcc/ada/prep.adb b/gcc/ada/prep.adb index 42ff57b..8549f79 100644 --- a/gcc/ada/prep.adb +++ b/gcc/ada/prep.adb @@ -825,7 +825,7 @@ package body Prep is ------------------ procedure List_Symbols (Foreword : String) is - Order : array (0 .. Integer (Symbol_Table.Last (Mapping))) + Order : array (0 .. Integer (Symbol_Table.Last (Mapping))) of Symbol_Id; -- After alphabetical sorting, this array stores the indexes of the -- symbols in the order they are displayed. diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index d03af55..2143cc4 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -904,7 +904,7 @@ package body Sem_Aggr is -- If the aggregate has box-initialized components, its type must be -- frozen so that initialization procedures can properly be called - -- in the resolution that follows. The replacement of boxes with + -- in the resolution that follows. The replacement of boxes with -- initialization calls is properly an expansion activity but it must -- be done during resolution. diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 6e52272..1ccbb52 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -11562,7 +11562,7 @@ package body Sem_Ch13 is begin -- A representation item is either subtype-specific (Size and Alignment - -- clauses) or type-related (all others). Subtype-specific aspects may + -- clauses) or type-related (all others). Subtype-specific aspects may -- differ for different subtypes of the same type (RM 13.1.8). -- A derived type inherits each type-related representation aspect of @@ -12623,7 +12623,7 @@ package body Sem_Ch13 is function Is_Derived_Type_With_Constraint return Boolean; -- Check whether T is a derived type with an explicit constraint, in -- which case the constraint has frozen the type and the item is too - -- late. This compensates for the fact that for derived scalar types + -- late. This compensates for the fact that for derived scalar types -- we freeze the base type unconditionally on account of a long-standing -- issue in gigi. diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 3328f96..b937fc4 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -1699,7 +1699,7 @@ package body Sem_Ch4 is -- If the case expression is a formal object of mode in out, then -- treat it as having a nonstatic subtype by forcing use of the base - -- type (which has to get passed to Check_Case_Choices below). Also + -- type (which has to get passed to Check_Case_Choices below). Also -- use base type when the case expression is parenthesized. if Paren_Count (Expr) > 0 @@ -7806,7 +7806,7 @@ package body Sem_Ch4 is -- In_Parameter, but for now we examine the formal that -- corresponds to the indexing, and assume that variable -- indexing is required if some interpretation has an - -- assignable formal at that position. Still does not + -- assignable formal at that position. Still does not -- cover the most complex cases ??? if Is_Overloaded (Name (Parent (Par))) then diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index 88fd204..b77bd7e 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -3080,7 +3080,7 @@ package body Sem_Ch5 is else -- A quantified expression that appears in a pre/post condition - -- is preanalyzed several times. If the range is given by an + -- is preanalyzed several times. If the range is given by an -- attribute reference it is rewritten as a range, and this is -- done even with expansion disabled. If the type is already set -- do not reanalyze, because a range with static bounds may be @@ -3904,7 +3904,7 @@ package body Sem_Ch5 is -- If the expander is not active then we want to analyze the loop body -- now even in the Ada 2012 iterator case, since the rewriting will not -- be done. Insert the loop variable in the current scope, if not done - -- when analysing the iteration scheme. Set its kind properly to detect + -- when analysing the iteration scheme. Set its kind properly to detect -- improper uses in the loop body. -- In GNATprove mode, we do one of the above depending on the kind of @@ -3998,7 +3998,7 @@ package body Sem_Ch5 is -- Variables referenced within a loop subject to possible OpenACC -- offloading may be implicitly written to as part of the OpenACC - -- transaction. Clear flags possibly conveying that they are constant, + -- transaction. Clear flags possibly conveying that they are constant, -- set for example when the code does not explicitly assign them. if Is_OpenAcc_Environment (Stmt) then @@ -4062,7 +4062,7 @@ package body Sem_Ch5 is end if; -- If we failed to find a label, it means the implicit declaration - -- of the label was hidden. A for-loop parameter can do this to + -- of the label was hidden. A for-loop parameter can do this to -- a label with the same name inside the loop, since the implicit -- label declaration is in the innermost enclosing body or block -- statement. diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index d238b9d..f98e60f 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -10155,7 +10155,7 @@ package body Sem_Ch6 is -- Here, S is "function ... return T;" declared in -- the private part, not overriding some visible - -- operation. That's illegal in the tagged case + -- operation. That's illegal in the tagged case -- (but not if the private type is untagged). if ((Present (Partial_View) diff --git a/gcc/ada/sem_ch6.ads b/gcc/ada/sem_ch6.ads index 9e7f858..f069947 100644 --- a/gcc/ada/sem_ch6.ads +++ b/gcc/ada/sem_ch6.ads @@ -100,7 +100,7 @@ package Sem_Ch6 is Overridden_Subp : Entity_Id; Is_Primitive : Boolean); -- Verify the consistency of an overriding_indicator given for subprogram - -- declaration, body, renaming, or instantiation. Overridden_Subp is set + -- declaration, body, renaming, or instantiation. Overridden_Subp is set -- if the scope where we are introducing the subprogram contains a -- type-conformant subprogram that becomes hidden by the new subprogram. -- Is_Primitive indicates whether the subprogram is primitive. diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb index 6f5126e..e97f15e 100644 --- a/gcc/ada/sem_ch7.adb +++ b/gcc/ada/sem_ch7.adb @@ -1757,7 +1757,7 @@ package body Sem_Ch7 is end if; -- There may be inherited private subprograms that need to be declared, - -- even in the absence of an explicit private part. If there are any + -- even in the absence of an explicit private part. If there are any -- public declarations in the package and the package is a public child -- unit, then an implicit private part is assumed. diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index b58ad64..03b6235 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -8733,7 +8733,7 @@ package body Sem_Ch8 is if Scope_Stack.Last > Scope_Stack.First then SST.Component_Alignment_Default := Scope_Stack.Table - (Scope_Stack.Last - 1). Component_Alignment_Default; + (Scope_Stack.Last - 1).Component_Alignment_Default; -- Otherwise, this is the first scope being pushed on the scope -- stack. Inherit the component alignment from the configuration diff --git a/gcc/ada/sem_dim.adb b/gcc/ada/sem_dim.adb index 9f15174..2bcccd2 100644 --- a/gcc/ada/sem_dim.adb +++ b/gcc/ada/sem_dim.adb @@ -115,7 +115,7 @@ package body Sem_Dim is type Symbol_Array is array (Dimension_Position range - Low_Position_Bound .. High_Position_Bound) of String_Id; + Low_Position_Bound .. High_Position_Bound) of String_Id; -- Store the symbols of all units within a system No_Symbols : constant Symbol_Array := (others => No_String); @@ -151,7 +151,7 @@ package body Sem_Dim is type Dimension_Type is array (Dimension_Position range - Low_Position_Bound .. High_Position_Bound) of Rational; + Low_Position_Bound .. High_Position_Bound) of Rational; Null_Dimension : constant Dimension_Type := (others => Zero); @@ -2906,7 +2906,7 @@ package body Sem_Dim is New_Aspects := Empty_List; List_Of_Dims := New_List; - for Position in Dims_Of_N'First .. System.Count loop + for Position in Dims_Of_N'First .. System.Count loop Dim_Power := Dims_Of_N (Position); Append_To (List_Of_Dims, Make_Op_Divide (Loc, @@ -3023,7 +3023,7 @@ package body Sem_Dim is -- System.Dim.Float_IO or System.Dim.Integer_IO, the default string -- parameter is rewritten to include the unit symbol (or the dimension -- symbols if not a defined quantity) in the output of a dimensioned - -- object. If a value is already supplied by the user for the parameter + -- object. If a value is already supplied by the user for the parameter -- Symbol, it is used as is. -- Case 1. Item is dimensionless diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb index 475092b..5deba18 100644 --- a/gcc/ada/sem_disp.adb +++ b/gcc/ada/sem_disp.adb @@ -596,7 +596,7 @@ package body Sem_Disp is -- We need to determine whether the context of the call -- provides a tag to make the call dispatching. This requires -- the call to be the actual in an enclosing call, and that - -- actual must be controlling. If the call is an operand of + -- actual must be controlling. If the call is an operand of -- equality, the other operand must not ve abstract. if not Is_Tagged_Type (Typ) diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 97cf3fe..7a4857f 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -25787,7 +25787,7 @@ package body Sem_Prag is -- Otherwise we have a call to an overridden primitive, and we -- will create a common class-wide clone for the body of - -- original operation and its eventual inherited versions. If + -- original operation and its eventual inherited versions. If -- the original operation dispatches on result it is never -- inherited and there is no need for a clone. There is not -- need for a clone either in GNATprove mode, as cases that diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index c151e7a..d505bc5 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -159,7 +159,7 @@ package body Sem_Res is Typ : Entity_Id; Is_Comp : Boolean); -- Internal procedure for Resolve_Op_Concat to resolve one operand of - -- concatenation operator. The operand is either of the array type or of + -- concatenation operator. The operand is either of the array type or of -- the component type. If the operand is an aggregate, and the component -- type is composite, this is ambiguous if component type has aggregates. diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb index 7e13aa5..16a772a 100644 --- a/gcc/ada/sem_warn.adb +++ b/gcc/ada/sem_warn.adb @@ -2698,7 +2698,7 @@ package body Sem_Warn is -- Flag any unused with clauses. For a subunit, check only the units -- in its context, not those of the parent, which may be needed by other - -- subunits. We will get the full warnings when we compile the parent, + -- subunits. We will get the full warnings when we compile the parent, -- but the following is helpful when compiling a subunit by itself. if Nkind (Unit (Cunit (Main_Unit))) = N_Subunit then diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index 7be56cb..6310016 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -1252,7 +1252,7 @@ package Sinfo is -- conversion node is introduced to represent the required check. -- A special case arises for the arguments of the Pred/Succ attributes. - -- Here the range check needed is against First + 1 .. Last (Pred) or + -- Here the range check needed is against First + 1 .. Last (Pred) or -- First .. Last - 1 (Succ) of the corresponding base type. Essentially -- these checks are what would be performed within the implicit body of -- the functions that correspond to these attributes. In these cases, -- cgit v1.1 From f0bfd1f91fdba41a6d9fa7ada6e02ea8121f604c Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Tue, 9 Jul 2019 07:55:12 +0000 Subject: [Ada] Elaboration order v4.0 and generic instantiations This patch updates the library graph augmentation mechanism of the elaboration order v4.0 to emulate a particular behavior of the v3.0 scheme involving generic instantiations. If a unit without any elaboration code instantiates a generic without any elaboration code, the invocation edge from the instance to the generic body is not considered for library graph augmentation. ------------ -- Source -- ------------ -- gen_pack1.ads generic type Element_Type is private; package Gen_Pack1 is procedure Read; end Gen_Pack1; -- gen_pack1.adb with Types1; package body Gen_Pack1 is procedure Read is null; end Gen_Pack1; -- types1.ads with Gen_Pack1; package Types1 is procedure Read; package Optional_Numbers is new Gen_Pack1 (Positive); end Types1; -- main1.adb with Types1; procedure Main1 is begin Types1.Optional_Numbers.Read; end Main1; ----------------- -- Compilation -- ----------------- $ gnatmake -q main1.adb 2019-07-09 Hristian Kirtchev gcc/ada/ * bindo-augmentors.adb (Visit_Elaboration_Root): Do not start a DFS from an elaboration root whose corresponding unit lacks elaboration code. This behavior mimics that of the old elaboration order mechanism. * bindo-graphs.adb (Find_All_Cycles_Through_Vertex): Move the vertex tracing within the functional branches of the routine. This prevents spurious trace output. (Has_No_Elaboration_Code): New routine. (Trace_Cycle, Trace_Edge): Update the various Ids to use the "standard" trace format. * bindo-graphs.ads (Has_No_Elaboration_Code): New routine. * bindo-units.ads, bindo-units.adb (Has_No_Elaboration_Code): New routine. From-SVN: r273288 --- gcc/ada/ChangeLog | 16 ++++++++++++++++ gcc/ada/bindo-augmentors.adb | 11 +++++++++++ gcc/ada/bindo-graphs.adb | 30 +++++++++++++++++++++++------- gcc/ada/bindo-graphs.ads | 7 +++++++ gcc/ada/bindo-units.adb | 13 +++++++++++++ gcc/ada/bindo-units.ads | 4 ++++ 6 files changed, 74 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a2c6066..b191e2d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,19 @@ +2019-07-09 Hristian Kirtchev + + * bindo-augmentors.adb (Visit_Elaboration_Root): Do not start a + DFS from an elaboration root whose corresponding unit lacks + elaboration code. This behavior mimics that of the old + elaboration order mechanism. + * bindo-graphs.adb (Find_All_Cycles_Through_Vertex): Move the + vertex tracing within the functional branches of the routine. + This prevents spurious trace output. + (Has_No_Elaboration_Code): New routine. + (Trace_Cycle, Trace_Edge): Update the various Ids to use the + "standard" trace format. + * bindo-graphs.ads (Has_No_Elaboration_Code): New routine. + * bindo-units.ads, bindo-units.adb (Has_No_Elaboration_Code): + New routine. + 2019-07-09 Piotr Trojanek * ali.ads, bindo-graphs.adb, bindo-validators.adb, clean.adb, diff --git a/gcc/ada/bindo-augmentors.adb b/gcc/ada/bindo-augmentors.adb index bb68a2e..e0e2338 100644 --- a/gcc/ada/bindo-augmentors.adb +++ b/gcc/ada/bindo-augmentors.adb @@ -152,6 +152,17 @@ package body Bindo.Augmentors is Visited : IGV_Sets.Membership_Set; begin + -- Nothing to do when the unit where the elaboration root resides + -- lacks elaboration code. This implies that any invocation edges + -- going out of the unit are unwanted. This behavior emulates the + -- old elaboration order mechanism. + + if Has_No_Elaboration_Code (Lib_Graph, Root_Vertex) then + return; + end if; + + -- Prepare the global data + Visited := IGV_Sets.Create (Number_Of_Vertices (Inv_Graph)); Visit_Vertex diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index 26b0c27..c3ae738 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -2356,13 +2356,13 @@ package body Bindo.Graphs is return; end if; - Trace_Vertex (G, Vertex, Indent); - -- The current vertex denotes the end vertex of the cycle and closes -- the circuit. Normalize the cycle such that it is rotated with its -- most significant edge first, and record it for diagnostics. if LGV_Sets.Contains (End_Vertices, Vertex) then + Trace_Vertex (G, Vertex, Indent); + Normalize_And_Add_Cycle (G => G, Most_Significant_Edge => Most_Significant_Edge, @@ -2374,6 +2374,7 @@ package body Bindo.Graphs is -- not been visited yet. elsif not LGV_Sets.Contains (Visited_Vertices, Vertex) then + Trace_Vertex (G, Vertex, Indent); -- Prepare for vertex backtracking @@ -2859,6 +2860,21 @@ package body Bindo.Graphs is return DG.Has_Next (DG.Outgoing_Edge_Iterator (Iter)); end Has_Next; + ----------------------------- + -- Has_No_Elaboration_Code -- + ----------------------------- + + function Has_No_Elaboration_Code + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + return Has_No_Elaboration_Code (Unit (G, Vertex)); + end Has_No_Elaboration_Code; + ----------------------------------------- -- Hash_Library_Graph_Cycle_Attributes -- ----------------------------------------- @@ -4878,7 +4894,7 @@ package body Bindo.Graphs is Next (Iter, Edge); Indent_By (Edge_Indent); - Write_Str ("library graph edge (Edge_"); + Write_Str ("library graph edge (LGE_Id_"); Write_Int (Int (Edge)); Write_Str (")"); Write_Eol; @@ -4912,7 +4928,7 @@ package body Bindo.Graphs is end if; Indent_By (Indent); - Write_Str ("library graph edge (Edge_"); + Write_Str ("library graph edge (LGE_Id_"); Write_Int (Int (Edge)); Write_Str (")"); Write_Eol; @@ -4923,14 +4939,14 @@ package body Bindo.Graphs is Write_Eol; Indent_By (Attr_Indent); - Write_Str ("Predecessor (Vertex_"); + Write_Str ("Predecessor (LGV_Id_"); Write_Int (Int (Pred)); Write_Str (") name = "); Write_Name (Name (G, Pred)); Write_Eol; Indent_By (Attr_Indent); - Write_Str ("Successor (Vertex_"); + Write_Str ("Successor (LGV_Id_"); Write_Int (Int (Succ)); Write_Str (") name = "); Write_Name (Name (G, Succ)); @@ -4977,7 +4993,7 @@ package body Bindo.Graphs is end if; Indent_By (Indent); - Write_Str ("library graph vertex (Vertex_"); + Write_Str ("library graph vertex (LGV_Id_"); Write_Int (Int (Vertex)); Write_Str (")"); Write_Eol; diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads index 53bc4ee..86ba823 100644 --- a/gcc/ada/bindo-graphs.ads +++ b/gcc/ada/bindo-graphs.ads @@ -1028,6 +1028,13 @@ package Bindo.Graphs is -- Determine whether library graph G contains a cycle involving pragma -- Elaborate_All. + function Has_No_Elaboration_Code + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Has_No_Elaboration_Code); + -- Determine whether vertex Vertex of library graph G represents a unit + -- that lacks elaboration code. + function In_Same_Component (G : Library_Graph; Left : Library_Graph_Vertex_Id; diff --git a/gcc/ada/bindo-units.adb b/gcc/ada/bindo-units.adb index 05b5250..8b8fc28 100644 --- a/gcc/ada/bindo-units.adb +++ b/gcc/ada/bindo-units.adb @@ -199,6 +199,19 @@ package body Bindo.Units is return Unit_Sets.Has_Next (Unit_Sets.Iterator (Iter)); end Has_Next; + ----------------------------- + -- Has_No_Elaboration_Code -- + ----------------------------- + + function Has_No_Elaboration_Code (U_Id : Unit_Id) return Boolean is + pragma Assert (Present (U_Id)); + + U_Rec : Unit_Record renames ALI.Units.Table (U_Id); + + begin + return U_Rec.No_Elab; + end Has_No_Elaboration_Code; + ------------------------------- -- Hash_Invocation_Signature -- ------------------------------- diff --git a/gcc/ada/bindo-units.ads b/gcc/ada/bindo-units.ads index 3749393..5f045c8 100644 --- a/gcc/ada/bindo-units.ads +++ b/gcc/ada/bindo-units.ads @@ -81,6 +81,10 @@ package Bindo.Units is pragma Inline (For_Each_Unit); -- Invoke Processor on each unit in the bind + function Has_No_Elaboration_Code (U_Id : Unit_Id) return Boolean; + pragma Inline (Has_No_Elaboration_Code); + -- Determine whether unit U_Id lacks elaboration code + function Hash_Invocation_Signature (IS_Id : Invocation_Signature_Id) return Bucket_Range_Type; pragma Inline (Hash_Invocation_Signature); -- cgit v1.1 From a9e470285b505c4eb28cfd4960a4f1541db5dad9 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Tue, 9 Jul 2019 07:55:17 +0000 Subject: [Ada] Crash/infinite loop on program with multiple visibility errors This patch fixes the behavior of the compiler on a program with multiple visibility errors. Previous to this fix the compiler would either crash or enter an infinite loop on a declaration for the formal in a subprogram declaration, when the parameter type was given by a selected component that does not denote an entity. This patch also specializes the error message when a local overloadable name has a homonym that is a child package, which may containt an otherwise hidden interpreatation. No simple reproducer. 2019-07-09 Ed Schonberg gcc/ada/ * sem_ch4.adb (Diagnose_Call): Improve error recovery when a local subprogram name hides a possible candidate name declared in a child package in the context of the current unit. * sem_ch6.adb (Process_Formals): Protect against malformed formal types when the parameter type does not denote an entity. From-SVN: r273289 --- gcc/ada/ChangeLog | 8 +++++++ gcc/ada/sem_ch4.adb | 62 ++++++++++++++++++++++++++++++++++++++--------------- gcc/ada/sem_ch6.adb | 8 ++++++- 3 files changed, 60 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b191e2d..1dd2a38 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-09 Ed Schonberg + + * sem_ch4.adb (Diagnose_Call): Improve error recovery when a + local subprogram name hides a possible candidate name declared + in a child package in the context of the current unit. + * sem_ch6.adb (Process_Formals): Protect against malformed + formal types when the parameter type does not denote an entity. + 2019-07-09 Hristian Kirtchev * bindo-augmentors.adb (Visit_Elaboration_Root): Do not start a diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index b937fc4..8806cbf 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -6173,26 +6173,54 @@ package body Sem_Ch4 is if Nkind (N) = N_Function_Call then Get_First_Interp (Nam, X, It); - while Present (It.Nam) loop - if Ekind_In (It.Nam, E_Function, E_Operator) then - return; - else - Get_Next_Interp (X, It); - end if; - end loop; - -- If all interpretations are procedures, this deserves a - -- more precise message. Ditto if this appears as the prefix - -- of a selected component, which may be a lexical error. + if No (It.Typ) + and then Ekind (Entity (Name (N))) = E_Function + and then Present (Homonym (Entity (Name (N)))) + then - Error_Msg_N - ("\context requires function call, found procedure name", Nam); + -- A name may appear overloaded if it has a homonym, even if + -- that homonym is non-overloadable, in which case the overload + -- list is in fact empty. This specialized case deserves a + -- special message if the homonym is a child package. - if Nkind (Parent (N)) = N_Selected_Component - and then N = Prefix (Parent (N)) - then - Error_Msg_N -- CODEFIX - ("\period should probably be semicolon", Parent (N)); + declare + Nam : constant Node_Id := Name (N); + H : constant Entity_Id := Homonym (Entity (Nam)); + + begin + if Ekind (H) = E_Package + and then Is_Child_Unit (H) + then + Error_Msg_Qual_Level := 2; + Error_Msg_NE ("if an entity in package& is meant, ", Nam, H); + Error_Msg_NE ("\use a fully qualified name", Nam, H); + Error_Msg_Qual_Level := 0; + end if; + end; + + else + while Present (It.Nam) loop + if Ekind_In (It.Nam, E_Function, E_Operator) then + return; + else + Get_Next_Interp (X, It); + end if; + end loop; + + -- If all interpretations are procedures, this deserves a + -- more precise message. Ditto if this appears as the prefix + -- of a selected component, which may be a lexical error. + + Error_Msg_N + ("\context requires function call, found procedure name", Nam); + + if Nkind (Parent (N)) = N_Selected_Component + and then N = Prefix (Parent (N)) + then + Error_Msg_N -- CODEFIX + ("\period should probably be semicolon", Parent (N)); + end if; end if; elsif Nkind (N) = N_Procedure_Call_Statement diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index f98e60f..119a2ee 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -11342,7 +11342,13 @@ package body Sem_Ch6 is goto Continue; end if; - Formal_Type := Entity (Ptype); + -- Protect against malformed parameter types. + + if Nkind (Ptype) not in N_Has_Entity then + Formal_Type := Any_Type; + else + Formal_Type := Entity (Ptype); + end if; if Is_Incomplete_Type (Formal_Type) or else -- cgit v1.1 From b3889ffffcde1e75def60c6967247eb56baeb3b8 Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Tue, 9 Jul 2019 07:55:22 +0000 Subject: [Ada] Warning needed on anonymous access type allocators This patch enhances the compiler to add an optional warning for allocators of anonymous access types due to the somewhat confusing runtime accessibility checks that they generate. For more details see RM 3.10.2 sections 14/3, 14.1/3, and 14.2/3. These warnings can now be enabled with -gnatw_a, disabled with -gnatw_A and are part of the "all warnings" flag -gnatwa. ------------ -- Source -- ------------ -- main.adb procedure Main is type Int_Ptr is access all Integer; Ptr_Obj : Int_Ptr; Ptr_Not_Null_Obj : not null Int_Ptr := new Integer; Ptr_Anon_Acc_Obj : not null access Integer := new Integer; -- WARNING procedure Update_Ptr (Item : access Integer) is begin Ptr_Obj := Int_Ptr (Item); -- RUNTIME ERROR end; procedure Update_Ptr_With_Anonymous_Allocator is Item : access Integer := new Integer; begin Update_Ptr (Item); end; type Rec_With_Coextension_A (Disc : access Integer) is null record; type Rec_With_Coextension_B (Disc : access Integer) is record Comp : Integer; end record; Obj : Rec_With_Coextension_A := (Disc => new Integer'(32)); -- WARNING procedure Test_Param (Param : access Integer) is begin null; end; function Test_Simple_Return return access Integer is begin return new Integer; -- WARNING end; function Test_Coextension_Return_A return Rec_With_Coextension_A is begin return (Disc => new Integer); -- WARNING end; function Test_Coextension_Return_B return Rec_With_Coextension_B is begin return (new Integer, 32); -- WARNING end; begin Test_Param (new Integer); -- WARNING Test_Param (Param => new Integer); -- WARNING Update_Ptr_With_Anonymous_Allocator; end; ----------------- -- Compilation -- ----------------- $ gnatmake -q -gnatw_a main.adb $ rm *.ali $ gnatmake -q -gnatwa -gnatw_A main.adb $ rm *.ali $ gnatmake -q -gnatwa main.adb $ main main.adb:8:06: warning: use of an anonymous access type allocator main.adb:16:32: warning: use of an anonymous access type allocator main.adb:29:15: warning: use of an anonymous access type allocator main.adb:38:14: warning: use of an anonymous access type allocator main.adb:43:23: warning: coextension will not be deallocated when its associated owner is deallocated main.adb:43:23: warning: use of an anonymous access type allocator main.adb:48:15: warning: coextension will not be deallocated when its associated owner is deallocated main.adb:48:15: warning: use of an anonymous access type allocator main.adb:52:16: warning: use of an anonymous access type allocator main.adb:53:25: warning: use of an anonymous access type allocator main.adb:5:04: warning: variable "Ptr_Obj" is assigned but never read main.adb:6:04: warning: variable "Ptr_Not_Null_Obj" is not referenced main.adb:7:04: warning: variable "Ptr_Anon_Acc_Obj" is not referenced main.adb:16:07: warning: "Item" is not modified, could be declared constant main.adb:28:04: warning: variable "Obj" is not referenced main.adb:36:13: warning: function "Test_Simple_Return" is not referenced main.adb:41:13: warning: function "Test_Coextension_Return_A" is not referenced main.adb:43:23: warning: coextension will not be deallocated when its associated owner is deallocated main.adb:46:13: warning: function "Test_Coextension_Return_B" is not referenced main.adb:48:15: warning: coextension will not be deallocated when its associated owner is deallocated main.adb:5:04: warning: variable "Ptr_Obj" is assigned but never read main.adb:6:04: warning: variable "Ptr_Not_Null_Obj" is not referenced main.adb:7:04: warning: variable "Ptr_Anon_Acc_Obj" is not referenced main.adb:8:06: warning: use of an anonymous access type allocator main.adb:16:07: warning: "Item" is not modified, could be declared constant main.adb:16:32: warning: use of an anonymous access type allocator main.adb:28:04: warning: variable "Obj" is not referenced main.adb:29:15: warning: use of an anonymous access type allocator main.adb:36:13: warning: function "Test_Simple_Return" is not referenced main.adb:38:14: warning: use of an anonymous access type allocator main.adb:41:13: warning: function "Test_Coextension_Return_A" is not referenced main.adb:43:23: warning: coextension will not be deallocated when its associated owner is deallocated main.adb:43:23: warning: use of an anonymous access type allocator main.adb:46:13: warning: function "Test_Coextension_Return_B" is not referenced main.adb:48:15: warning: coextension will not be deallocated when its associated owner is deallocated main.adb:48:15: warning: use of an anonymous access type allocator main.adb:52:16: warning: use of an anonymous access type allocator main.adb:53:25: warning: use of an anonymous access type allocator raised PROGRAM_ERROR : main.adb:12 accessibility check failed 2019-07-09 Justin Squirek gcc/ada/ * exp_ch4.adb (Expand_N_Allocator): Add conditional to detect the presence of anoymous access type allocators and issue a warning if the appropriate warning flag is enabled. * warnsw.ads: Add new warning flag for anonymous allocators * warnsw.adb (All_Warnings, Restore_Warnings, Save_Warnings, Set_Underscore_Warning_Switch): Register new flags. (WA_Warnings): Register new flag as an "all warnings" switch * usage.adb, doc/gnat_ugn/building_executable_programs_with_gnat.rst: Document new warning switches -gnatw_a and -gnatw_A. * gnat_ugn.texi: Regenerate. From-SVN: r273290 --- gcc/ada/ChangeLog | 14 ++++++++++ .../building_executable_programs_with_gnat.rst | 23 ++++++++++++++++ gcc/ada/exp_ch4.adb | 10 +++++++ gcc/ada/gnat_ugn.texi | 31 ++++++++++++++++++++++ gcc/ada/usage.adb | 2 ++ gcc/ada/warnsw.adb | 12 +++++++++ gcc/ada/warnsw.ads | 7 +++++ 7 files changed, 99 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1dd2a38..ee00d1f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,17 @@ +2019-07-09 Justin Squirek + + * exp_ch4.adb (Expand_N_Allocator): Add conditional to detect + the presence of anoymous access type allocators and issue a + warning if the appropriate warning flag is enabled. + * warnsw.ads: Add new warning flag for anonymous allocators + * warnsw.adb (All_Warnings, Restore_Warnings, Save_Warnings, + Set_Underscore_Warning_Switch): Register new flags. + (WA_Warnings): Register new flag as an "all warnings" switch + * usage.adb, + doc/gnat_ugn/building_executable_programs_with_gnat.rst: + Document new warning switches -gnatw_a and -gnatw_A. + * gnat_ugn.texi: Regenerate. + 2019-07-09 Ed Schonberg * sem_ch4.adb (Diagnose_Call): Improve error recovery when a diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index 98c3e16..af8f8a4 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -2842,6 +2842,29 @@ of the pragma in the :title:`GNAT_Reference_manual`). compile time that the assertion will fail. +.. index:: -gnatw_a + +:switch:`-gnatw_a` + *Activate warnings on anonymous allocators.* + + .. index:: Anonymous allocators + + This switch activates warnings for allocators of anonymous access types, + which can involve run-time accessibility checks and lead to unexpected + accessibility violations. For more details on the rules involved, see + RM 3.10.2 (14). + + +.. index:: -gnatw_A + +:switch:`-gnatw_A` + *Supress warnings on anonymous allocators.* + + .. index:: Anonymous allocators + + This switch suppresses warnings for anonymous access type allocators. + + .. index:: -gnatwb (gcc) :switch:`-gnatwb` diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 99bde93..b4159a7 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -72,6 +72,7 @@ with Ttypes; use Ttypes; with Uintp; use Uintp; with Urealp; use Urealp; with Validsw; use Validsw; +with Warnsw; use Warnsw; package body Exp_Ch4 is @@ -4354,6 +4355,15 @@ package body Exp_Ch4 is -- Start of processing for Expand_N_Allocator begin + -- Warn on the presence of an allocator of an anonymous access type when + -- enabled. + + if Warn_On_Anonymous_Allocators + and then Ekind (PtrT) = E_Anonymous_Access_Type + then + Error_Msg_N ("?use of an anonymous access type allocator", N); + end if; + -- RM E.2.3(22). We enforce that the expected type of an allocator -- shall not be a remote access-to-class-wide-limited-private type diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 124c289..db2adaf 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -11040,6 +11040,37 @@ This switch suppresses warnings for assertions where the compiler can tell at compile time that the assertion will fail. @end table +@geindex -gnatw_a + + +@table @asis + +@item @code{-gnatw_a} + +@emph{Activate warnings on anonymous allocators.} + +@geindex Anonymous allocators + +This switch activates warnings for allocators of anonymous access types, +which can involve run-time accessibility checks and lead to unexpected +accessibility violations. For more details on the rules involved, see +RM 3.10.2 (14). +@end table + +@geindex -gnatw_A + + +@table @asis + +@item @code{-gnatw_A} + +@emph{Supress warnings on anonymous allocators.} + +@geindex Anonymous allocators + +This switch suppresses warnings for anonymous access type allocators. +@end table + @geindex -gnatwb (gcc) diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb index 1eace05..fb261e5 100644 --- a/gcc/ada/usage.adb +++ b/gcc/ada/usage.adb @@ -483,6 +483,8 @@ begin Write_Line (" A turn off all optional info/warnings"); Write_Line (" .a*+ turn on warnings for failing assertion"); Write_Line (" .A turn off warnings for failing assertion"); + Write_Line (" _a*+ turn on warnings for anonymous allocators"); + Write_Line (" _A turn off warnings for anonymous allocators"); Write_Line (" b+ turn on warnings for bad fixed value " & "(not multiple of small)"); Write_Line (" B* turn off warnings for bad fixed value " & diff --git a/gcc/ada/warnsw.adb b/gcc/ada/warnsw.adb index 472f1df..219d440 100644 --- a/gcc/ada/warnsw.adb +++ b/gcc/ada/warnsw.adb @@ -56,6 +56,7 @@ package body Warnsw is Warn_On_Ada_2005_Compatibility := Setting; Warn_On_Ada_2012_Compatibility := Setting; Warn_On_All_Unread_Out_Parameters := Setting; + Warn_On_Anonymous_Allocators := Setting; Warn_On_Assertion_Failure := Setting; Warn_On_Assumed_Low_Bound := Setting; Warn_On_Atomic_Synchronization := Setting; @@ -129,6 +130,8 @@ package body Warnsw is W.Warn_On_Ada_2012_Compatibility; Warn_On_All_Unread_Out_Parameters := W.Warn_On_All_Unread_Out_Parameters; + Warn_On_Anonymous_Allocators := + W.Warn_On_Anonymous_Allocators; Warn_On_Assertion_Failure := W.Warn_On_Assertion_Failure; Warn_On_Assumed_Low_Bound := @@ -235,6 +238,8 @@ package body Warnsw is Warn_On_Ada_2012_Compatibility; W.Warn_On_All_Unread_Out_Parameters := Warn_On_All_Unread_Out_Parameters; + W.Warn_On_Anonymous_Allocators := + Warn_On_Anonymous_Allocators; W.Warn_On_Assertion_Failure := Warn_On_Assertion_Failure; W.Warn_On_Assumed_Low_Bound := @@ -478,6 +483,12 @@ package body Warnsw is function Set_Underscore_Warning_Switch (C : Character) return Boolean is begin case C is + when 'a' => + Warn_On_Anonymous_Allocators := True; + + when 'A' => + Warn_On_Anonymous_Allocators := False; + when others => if Ignore_Unrecognized_VWY_Switches then Write_Line ("unrecognized switch -gnatw_" & C & " ignored"); @@ -705,6 +716,7 @@ package body Warnsw is Ineffective_Inline_Warnings := True; -- -gnatwp Warn_On_Ada_2005_Compatibility := True; -- -gnatwy Warn_On_Ada_2012_Compatibility := True; -- -gnatwy + Warn_On_Anonymous_Allocators := True; -- -gnatw_a Warn_On_Assertion_Failure := True; -- -gnatw.a Warn_On_Assumed_Low_Bound := True; -- -gnatww Warn_On_Bad_Fixed_Value := True; -- -gnatwb diff --git a/gcc/ada/warnsw.ads b/gcc/ada/warnsw.ads index 23970a9..5875ecd 100644 --- a/gcc/ada/warnsw.ads +++ b/gcc/ada/warnsw.ads @@ -38,6 +38,12 @@ package Warnsw is -- here as time goes by. And in fact a really nice idea would be to put -- them all in a Warn_Record so that they would be easy to save/restore. + Warn_On_Anonymous_Allocators : Boolean := False; + -- Warn when allocators for anonymous access types are present, which, + -- although not illegal in Ada, may be confusing to users due to how + -- accessibility checks get generated. Off by default, modified by use of + -- -gnatw_a/_A and set as part of -gnatwa. + Warn_On_Late_Primitives : Boolean := False; -- Warn when tagged type public primitives are defined after its private -- extensions. @@ -90,6 +96,7 @@ package Warnsw is Warn_On_Ada_2005_Compatibility : Boolean; Warn_On_Ada_2012_Compatibility : Boolean; Warn_On_All_Unread_Out_Parameters : Boolean; + Warn_On_Anonymous_Allocators : Boolean; Warn_On_Assertion_Failure : Boolean; Warn_On_Assumed_Low_Bound : Boolean; Warn_On_Atomic_Synchronization : Boolean; -- cgit v1.1 From 18934a8d0feb60be26513cfbb4b9d34a908a7602 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 9 Jul 2019 07:55:28 +0000 Subject: [Ada] System.OS_Interface: fix Critical_Section.SpinCount type 2019-07-09 Eric Botcazou gcc/ada/ * libgnarl/s-osinte__mingw.ads (CRITICAL_SECTION): Use proper type for SpinCount component. From-SVN: r273291 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/libgnarl/s-osinte__mingw.ads | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ee00d1f..cfbdf89 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Eric Botcazou + + * libgnarl/s-osinte__mingw.ads (CRITICAL_SECTION): Use proper + type for SpinCount component. + 2019-07-09 Justin Squirek * exp_ch4.adb (Expand_N_Allocator): Add conditional to detect diff --git a/gcc/ada/libgnarl/s-osinte__mingw.ads b/gcc/ada/libgnarl/s-osinte__mingw.ads index 2cf47b7..2a98664 100644 --- a/gcc/ada/libgnarl/s-osinte__mingw.ads +++ b/gcc/ada/libgnarl/s-osinte__mingw.ads @@ -369,7 +369,7 @@ private -- section for the resource. LockSemaphore : Win32.HANDLE; - SpinCount : Win32.DWORD; + SpinCount : Interfaces.C.size_t; end record; end System.OS_Interface; -- cgit v1.1 From 924e3532dcdabde43f5b49f1ef1a95656f4e37dc Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Tue, 9 Jul 2019 07:55:33 +0000 Subject: [Ada] Crash on 'Img attribute This patch fixes and issue whereby applying 'Img to a constant enumerated character type would result in a compiler crash when assertions are enabled and infinite recursion when they are not. 2019-07-09 Justin Squirek gcc/ada/ * sem_eval.adb (Expr_Value_E): Add conditional to correctly handle constant enumerated character types. gcc/testsuite/ * gnat.dg/image1.adb: New testcase. From-SVN: r273292 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_eval.adb | 10 +++++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/image1.adb | 12 ++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/image1.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cfbdf89..524adfd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Justin Squirek + + * sem_eval.adb (Expr_Value_E): Add conditional to correctly + handle constant enumerated character types. + 2019-07-09 Eric Botcazou * libgnarl/s-osinte__mingw.ads (CRITICAL_SECTION): Use proper diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index ff3359f..e140fa7 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -4281,7 +4281,15 @@ package body Sem_Eval is return Ent; else pragma Assert (Ekind (Ent) = E_Constant); - return Expr_Value_E (Constant_Value (Ent)); + + -- We may be dealing with a enumerated character type constant, so + -- handle that case here. + + if Nkind (Constant_Value (Ent)) = N_Character_Literal then + return Ent; + else + return Expr_Value_E (Constant_Value (Ent)); + end if; end if; end Expr_Value_E; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fa53a2f..d2b1c6b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-09 Justin Squirek + + * gnat.dg/image1.adb: New testcase. + 2019-07-09 Javier Miranda * gnat.dg/rep_clause8.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/image1.adb b/gcc/testsuite/gnat.dg/image1.adb new file mode 100644 index 0000000..ae8d680 --- /dev/null +++ b/gcc/testsuite/gnat.dg/image1.adb @@ -0,0 +1,12 @@ +-- { dg-do run } + +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Characters.Latin_1; + +procedure Image1 is + Str : String := Ada.Characters.Latin_1.LF'Img; +begin + if Str /= "LF" then + raise Program_Error; + end if; +end Image1; -- cgit v1.1 From 5e0f7ab2fb33372f298ad9333dd2dd2e44cf01cc Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Tue, 9 Jul 2019 07:55:38 +0000 Subject: [Ada] Access to uninitialized memory by predicate check This patch fixes an exception or erroneous execution, when the declaration for an object of a composite type that has a dynanic predicate is initialized with an aggregate that requires expansion into individual components. Prior to this patch the predicate check for the object appeared before intialization was performed, thus accessing uninitialized memory. 2019-07-09 Ed Schonberg gcc/ada/ * sem_ch3.adb (Analyze_Object_Declaration): If the object type is a composite type that has a dynamic predicate and, the expression in the declaration is an aggregate, the generated predicate check must appear after the expanded code for the aggregate, which will appear after the rewritten object declarastion. gcc/testsuite/ * gnat.dg/predicate10.adb, gnat.dg/predicate10_pkg.adb, gnat.dg/predicate10_pkg.ads: New testcase. From-SVN: r273293 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/sem_ch3.adb | 28 ++++++++++++++++++++++++---- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/predicate10.adb | 9 +++++++++ gcc/testsuite/gnat.dg/predicate10_pkg.adb | 10 ++++++++++ gcc/testsuite/gnat.dg/predicate10_pkg.ads | 13 +++++++++++++ 6 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/predicate10.adb create mode 100644 gcc/testsuite/gnat.dg/predicate10_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/predicate10_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 524adfd..cb2acf3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-09 Ed Schonberg + + * sem_ch3.adb (Analyze_Object_Declaration): If the object type + is a composite type that has a dynamic predicate and, the + expression in the declaration is an aggregate, the generated + predicate check must appear after the expanded code for the + aggregate, which will appear after the rewritten object + declarastion. + 2019-07-09 Justin Squirek * sem_eval.adb (Expr_Value_E): Add conditional to correctly diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 38fab90..9e32cea 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -3649,8 +3649,10 @@ package body Sem_Ch3 is -- Ghost mode. procedure Analyze_Object_Declaration (N : Node_Id) is - Loc : constant Source_Ptr := Sloc (N); - Id : constant Entity_Id := Defining_Identifier (N); + Loc : constant Source_Ptr := Sloc (N); + Id : constant Entity_Id := Defining_Identifier (N); + Next_Decl : constant Node_Id := Next (N); + Act_T : Entity_Id; T : Entity_Id; @@ -3912,6 +3914,11 @@ package body Sem_Ch3 is A_Id := Get_Aspect_Id (Chars (Identifier (A))); while Present (A) loop if A_Id = Aspect_Alignment or else A_Id = Aspect_Address then + + -- Set flag on object entity, for later processing at + -- the freeze point. + + Set_Has_Delayed_Aspects (Id); return True; end if; @@ -4495,8 +4502,21 @@ package body Sem_Ch3 is null; else - Insert_After (N, - Make_Predicate_Check (T, New_Occurrence_Of (Id, Loc))); + -- The check must be inserted after the expanded aggregate + -- expansion code, if any. + + declare + Check : constant Node_Id := + Make_Predicate_Check (T, New_Occurrence_Of (Id, Loc)); + + begin + if No (Next_Decl) then + Append_To (List_Containing (N), Check); + + else + Insert_Before (Next_Decl, Check); + end if; + end; end if; end if; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d2b1c6b..91fa381 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Ed Schonberg + + * gnat.dg/predicate10.adb, gnat.dg/predicate10_pkg.adb, + gnat.dg/predicate10_pkg.ads: New testcase. + 2019-07-09 Justin Squirek * gnat.dg/image1.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/predicate10.adb b/gcc/testsuite/gnat.dg/predicate10.adb new file mode 100644 index 0000000..019038d --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate10.adb @@ -0,0 +1,9 @@ +-- { dg-do run } + +with Predicate10_Pkg; use Predicate10_Pkg; + +procedure Predicate10 is + X : I_Pointer := new Integer'(0); +begin + Foo (1, X); +end; diff --git a/gcc/testsuite/gnat.dg/predicate10_pkg.adb b/gcc/testsuite/gnat.dg/predicate10_pkg.adb new file mode 100644 index 0000000..159530f --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate10_pkg.adb @@ -0,0 +1,10 @@ +package body Predicate10_Pkg is + procedure Foo ( + Length : Natural; + Initial : I_Pointer + ) is + A : NI_Array := (1 .. Length => Initial); + begin + null; + end Foo; +end; diff --git a/gcc/testsuite/gnat.dg/predicate10_pkg.ads b/gcc/testsuite/gnat.dg/predicate10_pkg.ads new file mode 100644 index 0000000..e48cfe0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate10_pkg.ads @@ -0,0 +1,13 @@ +package Predicate10_Pkg is + type I_Array is array (Positive range <>) of access Integer; + + subtype NI_Array is I_Array with Dynamic_Predicate => + (for all I of NI_Array => I /= null); + + type I_Pointer is access Integer; + + procedure Foo ( + Length : Natural; + Initial : I_Pointer + ); +end; -- cgit v1.1 From c2851dc2896bfc0d27b32c90cafc873f67cd6727 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 9 Jul 2019 08:04:37 +0000 Subject: tree-ssa-sccvn.c (struct vn_walk_cb_data): Add orig_ref member. 2019-07-09 Richard Biener * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add orig_ref member. (vn_reference_lookup_3): If the main ref has no access path recorded but orig_ref has use it to do access-path based disambiguation. (vn_reference_lookup_pieces): Adjust. (vn_reference_lookup): Pass down original ref if we valueized. * gcc.dg/tree-ssa/alias-access-path-1.c: Scan fre1 dump. * gcc.dg/tree-ssa/alias-access-path-2.c: Likewise. * gcc.dg/tree-ssa/alias-access-path-8.c: Likewise. From-SVN: r273294 --- gcc/ChangeLog | 8 ++++ gcc/testsuite/ChangeLog | 6 +++ .../gcc.dg/tree-ssa/alias-access-path-1.c | 4 +- .../gcc.dg/tree-ssa/alias-access-path-2.c | 4 +- .../gcc.dg/tree-ssa/alias-access-path-8.c | 4 +- gcc/tree-ssa-sccvn.c | 44 +++++++++++++++++++--- 6 files changed, 58 insertions(+), 12 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a3c7971..8fccc6b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-09 Richard Biener + + * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add orig_ref member. + (vn_reference_lookup_3): If the main ref has no access path recorded + but orig_ref has use it to do access-path based disambiguation. + (vn_reference_lookup_pieces): Adjust. + (vn_reference_lookup): Pass down original ref if we valueized. + 2019-07-09 Martin Liska * lto-compress.c (lto_normalized_zstd_level): Do not use diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 91fa381..e9d0195 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Richard Biener + + * gcc.dg/tree-ssa/alias-access-path-1.c: Scan fre1 dump. + * gcc.dg/tree-ssa/alias-access-path-2.c: Likewise. + * gcc.dg/tree-ssa/alias-access-path-8.c: Likewise. + 2019-07-09 Ed Schonberg * gnat.dg/predicate10.adb, gnat.dg/predicate10_pkg.adb, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c index ba90b56..7676aa6 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-fre3" } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ struct foo { int val; @@ -18,4 +18,4 @@ test () return barptr->val2; } -/* { dg-final { scan-tree-dump-times "return 123" 1 "fre3"} } */ +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre1"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c index 974cdb0..fdc3055 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-fre3" } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ struct a { int val; }; @@ -19,4 +19,4 @@ test (int i, int j, int k, int l) dptr->c.b[k].a2[l].val=2; return cptr->b[i].a[j].val; } -/* { dg-final { scan-tree-dump-times "return 123" 1 "fre3"} } */ +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre1"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c index 1d5b57a..85f2c6a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-8.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-fre3" } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ struct a { int val; }; @@ -18,4 +18,4 @@ test (int i, int j, int k, int l) cptr2->b[k].a2[l].val=2; return cptr->b[i].a[j].val; } -/* { dg-final { scan-tree-dump-times "return 123" 1 "fre3"} } */ +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre1"} } */ diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 854222a..627ee8f 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1670,15 +1670,18 @@ struct pd_data struct vn_walk_cb_data { - vn_walk_cb_data (vn_reference_t vr_, tree *last_vuse_ptr_, + vn_walk_cb_data (vn_reference_t vr_, tree orig_ref_, tree *last_vuse_ptr_, vn_lookup_kind vn_walk_kind_, bool tbaa_p_) - : vr (vr_), last_vuse_ptr (last_vuse_ptr_), vn_walk_kind (vn_walk_kind_), - tbaa_p (tbaa_p_), known_ranges (NULL) - {} + : vr (vr_), last_vuse_ptr (last_vuse_ptr_), + vn_walk_kind (vn_walk_kind_), tbaa_p (tbaa_p_), known_ranges (NULL) + { + ao_ref_init (&orig_ref, orig_ref_); + } ~vn_walk_cb_data (); void *push_partial_def (const pd_data& pd, tree, HOST_WIDE_INT); vn_reference_t vr; + ao_ref orig_ref; tree *last_vuse_ptr; vn_lookup_kind vn_walk_kind; bool tbaa_p; @@ -2246,6 +2249,28 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, lhs_ref_ok = true; } + /* Besides valueizing the LHS we can also use access-path based + disambiguation on the original non-valueized ref. */ + if (!ref->ref + && lhs_ref_ok + && data->orig_ref.ref) + { + /* We want to use the non-valueized LHS for this, but avoid redundant + work. */ + ao_ref *lref = &lhs_ref; + ao_ref lref_alt; + if (valueized_anything) + { + ao_ref_init (&lref_alt, lhs); + lref = &lref_alt; + } + if (!refs_may_alias_p_1 (&data->orig_ref, lref, data->tbaa_p)) + { + *disambiguate_only = true; + return NULL; + } + } + /* If we reach a clobbering statement try to skip it and see if we find a VN result with exactly the same value as the possible clobber. In this case we can ignore the clobber @@ -2763,6 +2788,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, /* Do not update last seen VUSE after translating. */ data->last_vuse_ptr = NULL; + /* Invalidate the original access path since it now contains + the wrong base. */ + data->orig_ref.ref = NULL_TREE; /* Keep looking for the adjusted *REF / VR pair. */ return NULL; @@ -2923,6 +2951,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, /* Do not update last seen VUSE after translating. */ data->last_vuse_ptr = NULL; + /* Invalidate the original access path since it now contains + the wrong base. */ + data->orig_ref.ref = NULL_TREE; /* Keep looking for the adjusted *REF / VR pair. */ return NULL; @@ -2983,7 +3014,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type, { ao_ref r; unsigned limit = PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS); - vn_walk_cb_data data (&vr1, NULL, kind, true); + vn_walk_cb_data data (&vr1, NULL_TREE, NULL, kind, true); if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands)) *vnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, true, @@ -3040,7 +3071,8 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, || !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type, vr1.operands)) ao_ref_init (&r, op); - vn_walk_cb_data data (&vr1, last_vuse_ptr, kind, tbaa_p); + vn_walk_cb_data data (&vr1, r.ref ? NULL_TREE : op, + last_vuse_ptr, kind, tbaa_p); wvnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, tbaa_p, vn_reference_lookup_2, -- cgit v1.1 From b52db15861e60f5ca82b63caabed6a00da98c7d7 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Tue, 9 Jul 2019 11:22:30 +0200 Subject: Document and test __builtin_expect_with_probability. 2019-07-09 Martin Liska * doc/extend.texi: Document influence on loop optimizers. 2019-07-09 Martin Liska * gcc.dg/predict-17.c: Test loop optimizer assumption about loop iterations. From-SVN: r273295 --- gcc/ChangeLog | 5 +++++ gcc/doc/extend.texi | 5 ++++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/predict-17.c | 4 +++- 4 files changed, 17 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8fccc6b..5072a03 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -8,6 +8,11 @@ 2019-07-09 Martin Liska + * doc/extend.texi: Document influence on loop + optimizers. + +2019-07-09 Martin Liska + * lto-compress.c (lto_normalized_zstd_level): Do not use ZSTD_CLEVEL_DEFAULT as it is not default in old releases of libzstd. One can use 0 as a default compression level. diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index f2619e1..0616074 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -13045,8 +13045,11 @@ when testing pointer or floating-point values. For the purposes of branch prediction optimizations, the probability that a @code{__builtin_expect} expression is @code{true} is controlled by GCC's @code{builtin-expect-probability} parameter, which defaults to 90%. + You can also use @code{__builtin_expect_with_probability} to explicitly -assign a probability value to individual expressions. +assign a probability value to individual expressions. If the built-in +is used in a loop construct, the provided probability will influence +the expected number of iterations made by loop optimizations. @end deftypefn @deftypefn {Built-in Function} long __builtin_expect_with_probability diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e9d0195..ce78f77 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Martin Liska + + * gcc.dg/predict-17.c: Test loop optimizer assumption + about loop iterations. + 2019-07-09 Richard Biener * gcc.dg/tree-ssa/alias-access-path-1.c: Scan fre1 dump. diff --git a/gcc/testsuite/gcc.dg/predict-17.c b/gcc/testsuite/gcc.dg/predict-17.c index 5069aa4..45b618a 100644 --- a/gcc/testsuite/gcc.dg/predict-17.c +++ b/gcc/testsuite/gcc.dg/predict-17.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-profile_estimate" } */ +/* { dg-options "-O2 -fdump-tree-profile_estimate-details" } */ extern int global; @@ -11,3 +11,5 @@ void foo (int base) /* { dg-final { scan-tree-dump "first match heuristics: 5.00%" "profile_estimate"} } */ /* { dg-final { scan-tree-dump "__builtin_expect_with_probability heuristics of edge .*->.*: 5.00%" "profile_estimate"} } */ +/* { dg-final { scan-tree-dump "is probably executed at most 19" "profile_estimate"} } */ + -- cgit v1.1 From 4c12dc0556605578f4f35c4be27cff9fef28877b Mon Sep 17 00:00:00 2001 From: Sylvia Taylor Date: Tue, 9 Jul 2019 09:28:09 +0000 Subject: [arm]: redefine aes patterns This patch removes the arch-common aese/aesmc and aesd/aesimc fusions (i.e. aes fusion) implemented in the scheduling phase through the aarch_crypto_can_dual function. The reason is due to observing undesired behaviour in cases such as: - when register allocation goes bad (e.g. extra movs) - aes operations with xor and zeroed keys among interleaved operations A more stable version should be provided by instead doing the aes fusion during the combine pass. As such, new combine patterns have been added to enable this. The second change is the aese and aesd patterns have been rewritten as encapsulating a xor operation. The purpose is to simplify the need of having additional combine patterns for cases like the ones below: For AESE (though it also applies to AESD as both have a xor operation): data = data ^ key; data = vaeseq_u8(data, zero); --- veor q1, q0, q1 aese.8 q1, q9 Should mean and generate the same as: data = vaeseq_u8(data, key); --- aese.8 q1, q0 2019-07-09 Sylvia Taylor * config/arm/crypto.md: (crypto_): Redefine aese/aesd pattern with xor. (crypto_): Remove attribute enabled for aesmc. (crypto_): Split CRYPTO_BINARY into 2 patterns. (*aarch32_crypto_aese_fused, *aarch32_crypto_aesd_fused): New. * config/arm/arm.c (aarch_macro_fusion_pair_p): Remove aes/aesmc fusion check. * config/arm/aarch-common-protos.h (aarch_crypto_can_dual_issue): Remove. * config/arm/aarch-common.c (aarch_crypto_can_dual_issue): Likewise. * config/arm/exynos-m1.md: Remove aese/aesmc fusion. * config/arm/cortex-a53.md: Likewise. * config/arm/cortex-a57.md: Likewise. * config/arm/iterators.md: (CRYPTO_BINARY): Redefine. (CRYPTO_UNARY): Removed. (CRYPTO_AES, CRYPTO_AESMC): New. * gcc.target/arm/aes-fuse-1.c: New. * gcc.target/arm/aes-fuse-2.c: New. * gcc.target/arm/aes_xor_combine.c: New. From-SVN: r273296 --- gcc/ChangeLog | 21 +++++++ gcc/config/arm/aarch-common-protos.h | 1 - gcc/config/arm/aarch-common.c | 40 ------------- gcc/config/arm/arm.c | 4 -- gcc/config/arm/cortex-a57.md | 6 -- gcc/config/arm/crypto.md | 83 +++++++++++++++++++------- gcc/config/arm/exynos-m1.md | 5 -- gcc/config/arm/iterators.md | 7 ++- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.target/arm/aes-fuse-1.c | 66 ++++++++++++++++++++ gcc/testsuite/gcc.target/arm/aes-fuse-2.c | 66 ++++++++++++++++++++ gcc/testsuite/gcc.target/arm/aes_xor_combine.c | 43 +++++++++++++ 12 files changed, 269 insertions(+), 79 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/aes-fuse-1.c create mode 100644 gcc/testsuite/gcc.target/arm/aes-fuse-2.c create mode 100644 gcc/testsuite/gcc.target/arm/aes_xor_combine.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5072a03..21d7c1c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2019-07-09 Sylvia Taylor + + * config/arm/crypto.md: + (crypto_): Redefine aese/aesd pattern with xor. + (crypto_): Remove attribute enabled for aesmc. + (crypto_): Split CRYPTO_BINARY into 2 patterns. + (*aarch32_crypto_aese_fused, *aarch32_crypto_aesd_fused): New. + * config/arm/arm.c + (aarch_macro_fusion_pair_p): Remove aes/aesmc fusion check. + * config/arm/aarch-common-protos.h + (aarch_crypto_can_dual_issue): Remove. + * config/arm/aarch-common.c + (aarch_crypto_can_dual_issue): Likewise. + * config/arm/exynos-m1.md: Remove aese/aesmc fusion. + * config/arm/cortex-a53.md: Likewise. + * config/arm/cortex-a57.md: Likewise. + * config/arm/iterators.md: + (CRYPTO_BINARY): Redefine. + (CRYPTO_UNARY): Removed. + (CRYPTO_AES, CRYPTO_AESMC): New. + 2019-07-09 Richard Biener * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add orig_ref member. diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h index 11cd514..3bf38a1 100644 --- a/gcc/config/arm/aarch-common-protos.h +++ b/gcc/config/arm/aarch-common-protos.h @@ -24,7 +24,6 @@ #define GCC_AARCH_COMMON_PROTOS_H extern int aarch_accumulator_forwarding (rtx_insn *, rtx_insn *); -extern int aarch_crypto_can_dual_issue (rtx_insn *, rtx_insn *); extern bool aarch_rev16_p (rtx); extern bool aarch_rev16_shleft_mask_imm_p (rtx, machine_mode); extern bool aarch_rev16_shright_mask_imm_p (rtx, machine_mode); diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c index c7af12d..965a07a 100644 --- a/gcc/config/arm/aarch-common.c +++ b/gcc/config/arm/aarch-common.c @@ -31,46 +31,6 @@ #include "rtl-iter.h" #include "memmodel.h" -/* In ARMv8-A there's a general expectation that AESE/AESMC - and AESD/AESIMC sequences of the form: - - AESE Vn, _ - AESMC Vn, Vn - - will issue both instructions in a single cycle on super-scalar - implementations. This function identifies such pairs. */ - -int -aarch_crypto_can_dual_issue (rtx_insn *producer_insn, rtx_insn *consumer_insn) -{ - rtx producer_set, consumer_set; - rtx producer_src, consumer_src; - - producer_set = single_set (producer_insn); - consumer_set = single_set (consumer_insn); - - producer_src = producer_set ? SET_SRC (producer_set) : NULL; - consumer_src = consumer_set ? SET_SRC (consumer_set) : NULL; - - if (producer_src && consumer_src - && GET_CODE (producer_src) == UNSPEC && GET_CODE (consumer_src) == UNSPEC - && ((XINT (producer_src, 1) == UNSPEC_AESE - && XINT (consumer_src, 1) == UNSPEC_AESMC) - || (XINT (producer_src, 1) == UNSPEC_AESD - && XINT (consumer_src, 1) == UNSPEC_AESIMC))) - { - unsigned int regno = REGNO (SET_DEST (producer_set)); - - /* Before reload the registers are virtual, so the destination of - consumer_set doesn't need to match. */ - - return (REGNO (SET_DEST (consumer_set)) == regno || !reload_completed) - && REGNO (XVECEXP (consumer_src, 0, 0)) == regno; - } - - return 0; -} - /* Return TRUE if X is either an arithmetic shift left, or is a multiplication by a power of two. */ bool diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 820502a..f42a7b1 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -30606,10 +30606,6 @@ aarch_macro_fusion_pair_p (rtx_insn* prev, rtx_insn* curr) if (!arm_macro_fusion_p ()) return false; - if (current_tune->fusible_ops & tune_params::FUSE_AES_AESMC - && aarch_crypto_can_dual_issue (prev, curr)) - return true; - if (current_tune->fusible_ops & tune_params::FUSE_MOVW_MOVT && arm_sets_movw_movt_fusible_p (prev_set, curr_set)) return true; diff --git a/gcc/config/arm/cortex-a57.md b/gcc/config/arm/cortex-a57.md index a5f0b10..2d96a9c 100644 --- a/gcc/config/arm/cortex-a57.md +++ b/gcc/config/arm/cortex-a57.md @@ -801,9 +801,3 @@ ;; help. (define_bypass 1 "cortex_a57_*" "cortex_a57_call,cortex_a57_branch") - -;; AESE+AESMC and AESD+AESIMC pairs forward with zero latency -(define_bypass 0 "cortex_a57_crypto_simple" - "cortex_a57_crypto_simple" - "aarch_crypto_can_dual_issue") - diff --git a/gcc/config/arm/crypto.md b/gcc/config/arm/crypto.md index 63d9d9f..bf34f69 100644 --- a/gcc/config/arm/crypto.md +++ b/gcc/config/arm/crypto.md @@ -19,33 +19,76 @@ ;; . -;; When AES/AESMC fusion is enabled we want the register allocation to -;; look like: -;; AESE Vn, _ -;; AESMC Vn, Vn -;; So prefer to tie operand 1 to operand 0 when fusing. - (define_insn "crypto_" - [(set (match_operand: 0 "register_operand" "=w,w") - (unspec: [(match_operand: 1 - "register_operand" "0,w")] - CRYPTO_UNARY))] + [(set (match_operand: 0 "register_operand" "=w") + (unspec: + [(match_operand: 1 "register_operand" "w")] + CRYPTO_AESMC))] "TARGET_CRYPTO" ".\\t%q0, %q1" - [(set_attr "type" "") - (set_attr_alternative "enabled" - [(if_then_else (match_test - "arm_fusion_enabled_p (tune_params::FUSE_AES_AESMC)") - (const_string "yes" ) - (const_string "no")) - (const_string "yes")])] + [(set_attr "type" "")] +) + +(define_insn "crypto_" + [(set (match_operand:V16QI 0 "register_operand" "=w") + (unspec:V16QI + [(xor:V16QI + (match_operand:V16QI 1 "register_operand" "%0") + (match_operand:V16QI 2 "register_operand" "w"))] + CRYPTO_AES))] + "TARGET_CRYPTO" + ".\\t%q0, %q2" + [(set_attr "type" "")] +) + +;; When AESE/AESMC fusion is enabled we really want to keep the two together +;; and enforce the register dependency without scheduling or register +;; allocation messing up the order or introducing moves inbetween. +;; Mash the two together during combine. + +(define_insn "*aarch32_crypto_aese_fused" + [(set (match_operand:V16QI 0 "register_operand" "=w") + (unspec:V16QI + [(unspec:V16QI + [(xor:V16QI + (match_operand:V16QI 1 "register_operand" "%0") + (match_operand:V16QI 2 "register_operand" "w"))] + UNSPEC_AESE)] + UNSPEC_AESMC))] + "TARGET_CRYPTO + && arm_fusion_enabled_p (tune_params::FUSE_AES_AESMC)" + "aese.8\\t%q0, %q2\;aesmc.8\\t%q0, %q0" + [(set_attr "type" "crypto_aese") + (set_attr "length" "8")] +) + +;; When AESD/AESIMC fusion is enabled we really want to keep the two together +;; and enforce the register dependency without scheduling or register +;; allocation messing up the order or introducing moves inbetween. +;; Mash the two together during combine. + +(define_insn "*aarch32_crypto_aesd_fused" + [(set (match_operand:V16QI 0 "register_operand" "=w") + (unspec:V16QI + [(unspec:V16QI + [(xor:V16QI + (match_operand:V16QI 1 "register_operand" "%0") + (match_operand:V16QI 2 "register_operand" "w"))] + UNSPEC_AESD)] + UNSPEC_AESIMC))] + "TARGET_CRYPTO + && arm_fusion_enabled_p (tune_params::FUSE_AES_AESMC)" + "aesd.8\\t%q0, %q2\;aesimc.8\\t%q0, %q0" + [(set_attr "type" "crypto_aese") + (set_attr "length" "8")] ) (define_insn "crypto_" [(set (match_operand: 0 "register_operand" "=w") - (unspec: [(match_operand: 1 "register_operand" "0") - (match_operand: 2 "register_operand" "w")] - CRYPTO_BINARY))] + (unspec: + [(match_operand: 1 "register_operand" "0") + (match_operand: 2 "register_operand" "w")] + CRYPTO_BINARY))] "TARGET_CRYPTO" ".\\t%q0, %q2" [(set_attr "type" "")] diff --git a/gcc/config/arm/exynos-m1.md b/gcc/config/arm/exynos-m1.md index 3d04a52..150ac85 100644 --- a/gcc/config/arm/exynos-m1.md +++ b/gcc/config/arm/exynos-m1.md @@ -950,11 +950,6 @@ "exynos_m1_crypto_simple, exynos_m1_crypto_complex,\ exynos_m1_crypto_poly*") -;; AES{D,E}/AESMC pairs can feed each other instantly. -(define_bypass 0 "exynos_m1_crypto_simple" - "exynos_m1_crypto_simple" - "aarch_crypto_can_dual_issue") - ;; Predicted branches take no time, but mispredicted ones take forever anyway. (define_bypass 1 "exynos_m1_*" "exynos_m1_call, exynos_m1_branch") diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 2462b8c..e03a720 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -413,10 +413,11 @@ (define_int_iterator CRC [UNSPEC_CRC32B UNSPEC_CRC32H UNSPEC_CRC32W UNSPEC_CRC32CB UNSPEC_CRC32CH UNSPEC_CRC32CW]) -(define_int_iterator CRYPTO_UNARY [UNSPEC_AESMC UNSPEC_AESIMC]) +(define_int_iterator CRYPTO_AESMC [UNSPEC_AESMC UNSPEC_AESIMC]) -(define_int_iterator CRYPTO_BINARY [UNSPEC_AESD UNSPEC_AESE - UNSPEC_SHA1SU1 UNSPEC_SHA256SU0]) +(define_int_iterator CRYPTO_AES [UNSPEC_AESD UNSPEC_AESE]) + +(define_int_iterator CRYPTO_BINARY [UNSPEC_SHA1SU1 UNSPEC_SHA256SU0]) (define_int_iterator CRYPTO_TERNARY [UNSPEC_SHA1SU0 UNSPEC_SHA256H UNSPEC_SHA256H2 UNSPEC_SHA256SU1]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ce78f77..995076b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Sylvia Taylor + + * gcc.target/arm/aes-fuse-1.c: New. + * gcc.target/arm/aes-fuse-2.c: New. + * gcc.target/arm/aes_xor_combine.c: New. + 2019-07-09 Martin Liska * gcc.dg/predict-17.c: Test loop optimizer assumption diff --git a/gcc/testsuite/gcc.target/arm/aes-fuse-1.c b/gcc/testsuite/gcc.target/arm/aes-fuse-1.c new file mode 100644 index 0000000..27b08ae --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aes-fuse-1.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_crypto_ok } */ +/* { dg-add-options arm_crypto } */ +/* { dg-additional-options "-mcpu=cortex-a72 -O3 -dp" } */ + +#include + +#define AESE(r, v, key) (r = vaeseq_u8 ((v), (key))); +#define AESMC(r, i) (r = vaesmcq_u8 (i)) + +const uint8x16_t zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +uint8x16_t dummy; +uint8x16_t a; +uint8x16_t b; +uint8x16_t c; +uint8x16_t d; +uint8x16_t x; +uint8x16_t y; +uint8x16_t k; + +void foo (void) +{ + AESE (a, a, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESE (b, b, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESE (c, c, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESE (d, d, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + x = x ^ k; + AESE (x, x, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + y = y ^ k; + AESE (y, y, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESMC (d, d); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (c, c); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (b, b); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (a, a); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESMC (y, y); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (x, x); +} + +/* { dg-final { scan-assembler-times "crypto_aese_fused" 6 } } */ +/* { dg-final { scan-assembler-not "veor" } } */ diff --git a/gcc/testsuite/gcc.target/arm/aes-fuse-2.c b/gcc/testsuite/gcc.target/arm/aes-fuse-2.c new file mode 100644 index 0000000..1266a28 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aes-fuse-2.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_crypto_ok } */ +/* { dg-add-options arm_crypto } */ +/* { dg-additional-options "-mcpu=cortex-a72 -O3 -dp" } */ + +#include + +#define AESD(r, v, key) (r = vaesdq_u8 ((v), (key))); +#define AESIMC(r, i) (r = vaesimcq_u8 (i)) + +const uint8x16_t zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +uint8x16_t dummy; +uint8x16_t a; +uint8x16_t b; +uint8x16_t c; +uint8x16_t d; +uint8x16_t x; +uint8x16_t y; +uint8x16_t k; + +void foo (void) +{ + AESD (a, a, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESD (b, b, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESD (c, c, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESD (d, d, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + x = x ^ k; + AESD (x, x, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + y = y ^ k; + AESD (y, y, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESIMC (d, d); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (c, c); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (b, b); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (a, a); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESIMC (y, y); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (x, x); +} + +/* { dg-final { scan-assembler-times "crypto_aesd_fused" 6 } } */ +/* { dg-final { scan-assembler-not "veor" } } */ diff --git a/gcc/testsuite/gcc.target/arm/aes_xor_combine.c b/gcc/testsuite/gcc.target/arm/aes_xor_combine.c new file mode 100644 index 0000000..17ae1c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/aes_xor_combine.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_crypto_ok } */ +/* { dg-add-options arm_crypto } */ +/* { dg-additional-options "-O3" } */ + +#include + +#define AESE(r, v, key) (r = vaeseq_u8 ((v), (key))); +#define AESD(r, v, key) (r = vaesdq_u8 ((v), (key))); + +const uint8x16_t zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +uint8x16_t foo_key_0 (uint8x16_t dummy, uint8x16_t foo, uint8x16_t bar) +{ + dummy = dummy ^ foo; + AESE(dummy, dummy, zero); + dummy = dummy ^ bar; + AESE(dummy, dummy, zero); + + dummy = dummy ^ foo; + AESD(dummy, dummy, zero); + dummy = dummy ^ bar; + AESD(dummy, dummy, zero); + + return dummy; +} + +uint8x16_t foo_data_0 (uint8x16_t dummy, uint8x16_t foo, uint8x16_t bar) +{ + dummy = dummy ^ foo; + AESE(dummy, zero, dummy); + dummy = dummy ^ bar; + AESE(dummy, zero, dummy); + + dummy = dummy ^ foo; + AESD(dummy, zero, dummy); + dummy = dummy ^ bar; + AESD(dummy, zero, dummy); + + return dummy; +} + +/* { dg-final { scan-assembler-not "veor" } } */ -- cgit v1.1 From 495079550e135c7ad0605e9c549202c35625cde7 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 9 Jul 2019 09:58:51 +0000 Subject: * ira-emit.c (emit_moves): Skip DEBUG_INSNs when setting the location. From-SVN: r273297 --- gcc/ChangeLog | 4 ++++ gcc/ira-emit.c | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21d7c1c..5a6a7f4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2019-07-09 Eric Botcazou + + * ira-emit.c (emit_moves): Skip DEBUG_INSNs when setting the location. + 2019-07-09 Sylvia Taylor * config/arm/crypto.md: diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c index c42acad..255af30 100644 --- a/gcc/ira-emit.c +++ b/gcc/ira-emit.c @@ -997,27 +997,30 @@ emit_moves (void) basic_block bb; edge_iterator ei; edge e; - rtx_insn *insns, *tmp; + rtx_insn *insns, *tmp, *next; FOR_EACH_BB_FN (bb, cfun) { if (at_bb_start[bb->index] != NULL) { at_bb_start[bb->index] = modify_move_list (at_bb_start[bb->index]); - insns = emit_move_list (at_bb_start[bb->index], - REG_FREQ_FROM_BB (bb)); + insns + = emit_move_list (at_bb_start[bb->index], REG_FREQ_FROM_BB (bb)); tmp = BB_HEAD (bb); if (LABEL_P (tmp)) tmp = NEXT_INSN (tmp); if (NOTE_INSN_BASIC_BLOCK_P (tmp)) tmp = NEXT_INSN (tmp); - /* Propagate the location of the current first instruction to the - moves so that they don't inherit a random location. */ - if (tmp != NULL_RTX && INSN_P (tmp)) - set_insn_locations (insns, INSN_LOCATION (tmp)); + /* Make sure to put the location of TMP or a subsequent instruction + to avoid inheriting the location of the previous instruction. */ + next = tmp; + while (next && !NONDEBUG_INSN_P (next)) + next = NEXT_INSN (next); + if (next) + set_insn_locations (insns, INSN_LOCATION (next)); if (tmp == BB_HEAD (bb)) emit_insn_before (insns, tmp); - else if (tmp != NULL_RTX) + else if (tmp) emit_insn_after (insns, PREV_INSN (tmp)); else emit_insn_after (insns, get_last_insn ()); -- cgit v1.1 From b7fe158a1b3d96a4b001d9373db93678455546cb Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 9 Jul 2019 12:22:10 +0000 Subject: gimple-match.h (gimple_match_op::resimplify): New. 2019-07-09 Richard Biener * gimple-match.h (gimple_match_op::resimplify): New. (gimple_resimplify1, gimple_resimplify2, gimple_resimplify3, gimple_resimplify4, gimple_resimplify5): Remove. * gimple-match-head.c (gimple_resimplify1, gimple_resimplify2, gimple_resimplify3, gimple_resimplify4, gimple_resimplify5): Make static. (gimple_match_op::resimplify): New. * tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Valueize according to availability. Use gimple_match_op::resimplify. From-SVN: r273302 --- gcc/ChangeLog | 12 ++++++++++++ gcc/gimple-match-head.c | 44 +++++++++++++++++++++++++++++++++++++++----- gcc/gimple-match.h | 7 ++----- gcc/tree-ssa-sccvn.c | 28 ++++++++++++++++------------ 4 files changed, 69 insertions(+), 22 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5a6a7f4..271a27a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2019-07-09 Richard Biener + + * gimple-match.h (gimple_match_op::resimplify): New. + (gimple_resimplify1, gimple_resimplify2, gimple_resimplify3, + gimple_resimplify4, gimple_resimplify5): Remove. + * gimple-match-head.c (gimple_resimplify1, gimple_resimplify2, + gimple_resimplify3, gimple_resimplify4, gimple_resimplify5): + Make static. + (gimple_match_op::resimplify): New. + * tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Valueize + according to availability. Use gimple_match_op::resimplify. + 2019-07-09 Eric Botcazou * ira-emit.c (emit_moves): Skip DEBUG_INSNs when setting the location. diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index df9f0c5..5327816 100644 --- a/gcc/gimple-match-head.c +++ b/gcc/gimple-match-head.c @@ -57,6 +57,16 @@ static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), code_helper, tree, tree, tree, tree, tree); static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree), code_helper, tree, tree, tree, tree, tree, tree); +static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, + tree (*)(tree)); +static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, + tree (*)(tree)); +static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, + tree (*)(tree)); +static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, + tree (*)(tree)); +static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, + tree (*)(tree)); const unsigned int gimple_match_op::MAX_NUM_OPS; @@ -173,7 +183,7 @@ maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op, RES_OP with a simplified and/or canonicalized result and returns whether any change was made. */ -bool +static bool gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op, tree (*valueize)(tree)) { @@ -233,7 +243,7 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op, RES_OP with a simplified and/or canonicalized result and returns whether any change was made. */ -bool +static bool gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op, tree (*valueize)(tree)) { @@ -305,7 +315,7 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op, RES_OP with a simplified and/or canonicalized result and returns whether any change was made. */ -bool +static bool gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op, tree (*valueize)(tree)) { @@ -376,7 +386,7 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op, RES_OP with a simplified and/or canonicalized result and returns whether any change was made. */ -bool +static bool gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, tree (*valueize)(tree)) { @@ -417,7 +427,7 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op, RES_OP with a simplified and/or canonicalized result and returns whether any change was made. */ -bool +static bool gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, tree (*valueize)(tree)) { @@ -439,6 +449,30 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op, return false; } +/* Match and simplify the toplevel valueized operation THIS. + Replaces THIS with a simplified and/or canonicalized result and + returns whether any change was made. */ + +bool +gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree)) +{ + switch (num_ops) + { + case 1: + return gimple_resimplify1 (seq, this, valueize); + case 2: + return gimple_resimplify2 (seq, this, valueize); + case 3: + return gimple_resimplify3 (seq, this, valueize); + case 4: + return gimple_resimplify4 (seq, this, valueize); + case 5: + return gimple_resimplify5 (seq, this, valueize); + default: + gcc_unreachable (); + } +} + /* If in GIMPLE the operation described by RES_OP should be single-rhs, build a GENERIC tree for that expression and update RES_OP accordingly. */ diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h index 22fa86c..ad7f730 100644 --- a/gcc/gimple-match.h +++ b/gcc/gimple-match.h @@ -105,6 +105,8 @@ struct gimple_match_op tree op_or_null (unsigned int) const; + bool resimplify (gimple_seq *, tree (*)(tree)); + /* The maximum value of NUM_OPS. */ static const unsigned int MAX_NUM_OPS = 5; @@ -331,11 +333,6 @@ extern tree (*mprts_hook) (gimple_match_op *); bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *, tree (*)(tree), tree (*)(tree)); -bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, tree (*)(tree)); -bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, tree (*)(tree)); -bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, tree (*)(tree)); -bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, tree (*)(tree)); -bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, tree (*)(tree)); tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *, tree res = NULL_TREE); void maybe_build_generic_op (gimple_match_op *); diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 627ee8f..9186f15 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1968,21 +1968,25 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert) RCODE (OPS...). So first simplify and lookup this expression to see if it is already available. */ - mprts_hook = vn_lookup_simplify_result; + /* For simplification valueize. */ + unsigned i; + for (i = 0; i < res_op->num_ops; ++i) + if (TREE_CODE (res_op->ops[i]) == SSA_NAME) + { + tree tem = vn_valueize (res_op->ops[i]); + if (!tem) + break; + res_op->ops[i] = tem; + } + /* If valueization of an operand fails (it is not available), skip + simplification. */ bool res = false; - switch (TREE_CODE_LENGTH ((tree_code) res_op->code)) + if (i == res_op->num_ops) { - case 1: - res = gimple_resimplify1 (NULL, res_op, vn_valueize); - break; - case 2: - res = gimple_resimplify2 (NULL, res_op, vn_valueize); - break; - case 3: - res = gimple_resimplify3 (NULL, res_op, vn_valueize); - break; + mprts_hook = vn_lookup_simplify_result; + res = res_op->resimplify (NULL, vn_valueize); + mprts_hook = NULL; } - mprts_hook = NULL; gimple *new_stmt = NULL; if (res && gimple_simplified_result_is_gimple_val (res_op)) -- cgit v1.1 From b61184875ec454875b5a47f3bfa94a6d45f5b845 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Tue, 9 Jul 2019 12:26:21 +0000 Subject: [ARM][testsuite] Fix address of sg stubs in CMSE tests 2019-07-09 Christophe Lyon * gcc.target/arm/cmse/bitfield-1.c: Fix address of .gnu.sgstubs section. * gcc.target/arm/cmse/bitfield-2.c: Likewise. * gcc.target/arm/cmse/bitfield-3.c: Likewise. * gcc.target/arm/cmse/struct-1.c: Likewise. From-SVN: r273303 --- gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c | 2 +- gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c | 2 +- gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c | 2 +- gcc/testsuite/gcc.target/arm/cmse/struct-1.c | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 995076b..6f334ef 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-07-09 Christophe Lyon + + * gcc.target/arm/cmse/bitfield-1.c: Fix address of .gnu.sgstubs + section. + * gcc.target/arm/cmse/bitfield-2.c: Likewise. + * gcc.target/arm/cmse/bitfield-3.c: Likewise. + * gcc.target/arm/cmse/struct-1.c: Likewise. + 2019-07-09 Sylvia Taylor * gcc.target/arm/aes-fuse-1.c: New. diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c index fccc51d..0fc191e 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c +++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x20400000" } */ +/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x00400000" } */ typedef struct { diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c index e6aee3c..f8327c8 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c +++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x20400000" } */ +/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x00400000" } */ typedef struct { diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c index 285a2b9..d0550db 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c +++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x20400000" } */ +/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x00400000" } */ typedef struct { diff --git a/gcc/testsuite/gcc.target/arm/cmse/struct-1.c b/gcc/testsuite/gcc.target/arm/cmse/struct-1.c index 2d366a9..874da3c 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/struct-1.c +++ b/gcc/testsuite/gcc.target/arm/cmse/struct-1.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x20400000" } */ +/* { dg-options "--save-temps -mcmse -Wl,--section-start,.gnu.sgstubs=0x00400000" } */ typedef struct { -- cgit v1.1 From 5169fa77322e36dd4783bc5126185159c35a3584 Mon Sep 17 00:00:00 2001 From: Sylvia Taylor Date: Tue, 9 Jul 2019 12:51:55 +0000 Subject: [aarch64]: redefine aes patterns This first patch removes aarch64 usage of the aese/aesmc and aesd/aesimc fusions (i.e. aes fusion) implemented in the scheduler due to unpredictable behaviour observed in cases such as: - when register allocation goes bad (e.g. extra movs) - aes operations with xor and zeroed keys among interleaved operations A more stable version should be provided by instead doing the aes fusion during the combine pass. Since the aese and aesd patterns have been rewritten as encapsulating a xor operation, the existing combine fusion patterns have also been updated. The purpose is to simplify the need of having additional combine patterns for cases like the ones below: For AESE (though it also applies to AESD as both have a xor operation): data = data ^ key; data = vaeseq_u8(data, zero); --- eor v1.16b, v0.16b, v1.16b aese v1.16b, v2.16b Should mean and generate the same as: data = vaeseq_u8(data, key); --- aese v1.16b, v0.16b 2019-07-09 Sylvia Taylor * config/aarch64/aarch64-simd.md (aarch64_crypto_aesv16qi): Redefine pattern with xor. (aarch64_crypto_aesv16qi): Remove attribute enabled. (*aarch64_crypto_aesv16qi_xor_combine): Remove both. (*aarch64_crypto_aese_fused, *aarch64_crypto_aesd_fused): Update to new definition. * config/aarch64/aarch64.c (aarch_macro_fusion_pair_p): Remove aese/aesmc fusion check. * gcc.target/aarch64/crypto-fuse-1.c: Remove. * gcc.target/aarch64/crypto-fuse-2.c: Remove. * gcc.target/aarch64/aes-fuse-1.c: New testcase. * gcc.target/aarch64/aes-fuse-2.c: New testcase. From-SVN: r273304 --- gcc/ChangeLog | 11 ++++ gcc/config/aarch64/aarch64-simd.md | 67 +++++++----------------- gcc/config/aarch64/aarch64.c | 4 -- gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.target/aarch64/aes-fuse-1.c | 66 +++++++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/aes-fuse-2.c | 65 +++++++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/crypto-fuse-1.c | 45 ---------------- gcc/testsuite/gcc.target/aarch64/crypto-fuse-2.c | 45 ---------------- 8 files changed, 168 insertions(+), 142 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/aes-fuse-1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/aes-fuse-2.c delete mode 100644 gcc/testsuite/gcc.target/aarch64/crypto-fuse-1.c delete mode 100644 gcc/testsuite/gcc.target/aarch64/crypto-fuse-2.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 271a27a..25959b94 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2019-07-09 Sylvia Taylor + + * config/aarch64/aarch64-simd.md + (aarch64_crypto_aesv16qi): Redefine pattern with xor. + (aarch64_crypto_aesv16qi): Remove attribute enabled. + (*aarch64_crypto_aesv16qi_xor_combine): Remove both. + (*aarch64_crypto_aese_fused, + *aarch64_crypto_aesd_fused): Update to new definition. + * config/aarch64/aarch64.c + (aarch_macro_fusion_pair_p): Remove aese/aesmc fusion check. + 2019-07-09 Richard Biener * gimple-match.h (gimple_match_op::resimplify): New. diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 837242c..0c2600f 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -6053,56 +6053,23 @@ (define_insn "aarch64_crypto_aesv16qi" [(set (match_operand:V16QI 0 "register_operand" "=w") - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "%0") - (match_operand:V16QI 2 "register_operand" "w")] + (unspec:V16QI + [(xor:V16QI + (match_operand:V16QI 1 "register_operand" "%0") + (match_operand:V16QI 2 "register_operand" "w"))] CRYPTO_AES))] "TARGET_SIMD && TARGET_AES" "aes\\t%0.16b, %2.16b" [(set_attr "type" "crypto_aese")] ) -(define_insn "*aarch64_crypto_aesv16qi_xor_combine" - [(set (match_operand:V16QI 0 "register_operand" "=w") - (unspec:V16QI [(xor:V16QI - (match_operand:V16QI 1 "register_operand" "%0") - (match_operand:V16QI 2 "register_operand" "w")) - (match_operand:V16QI 3 "aarch64_simd_imm_zero" "")] - CRYPTO_AES))] - "TARGET_SIMD && TARGET_AES" - "aes\\t%0.16b, %2.16b" - [(set_attr "type" "crypto_aese")] -) - -(define_insn "*aarch64_crypto_aesv16qi_xor_combine" - [(set (match_operand:V16QI 0 "register_operand" "=w") - (unspec:V16QI [(match_operand:V16QI 3 "aarch64_simd_imm_zero" "") - (xor:V16QI (match_operand:V16QI 1 "register_operand" "%0") - (match_operand:V16QI 2 "register_operand" "w"))] - CRYPTO_AES))] - "TARGET_SIMD && TARGET_AES" - "aes\\t%0.16b, %2.16b" - [(set_attr "type" "crypto_aese")] -) - -;; When AES/AESMC fusion is enabled we want the register allocation to -;; look like: -;; AESE Vn, _ -;; AESMC Vn, Vn -;; So prefer to tie operand 1 to operand 0 when fusing. - (define_insn "aarch64_crypto_aesv16qi" - [(set (match_operand:V16QI 0 "register_operand" "=w,w") - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "0,w")] + [(set (match_operand:V16QI 0 "register_operand" "=w") + (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "w")] CRYPTO_AESMC))] "TARGET_SIMD && TARGET_AES" "aes\\t%0.16b, %1.16b" - [(set_attr "type" "crypto_aesmc") - (set_attr_alternative "enabled" - [(if_then_else (match_test - "aarch64_fusion_enabled_p (AARCH64_FUSE_AES_AESMC)") - (const_string "yes" ) - (const_string "no")) - (const_string "yes")])] + [(set_attr "type" "crypto_aesmc")] ) ;; When AESE/AESMC fusion is enabled we really want to keep the two together @@ -6111,12 +6078,14 @@ ;; Mash the two together during combine. (define_insn "*aarch64_crypto_aese_fused" - [(set (match_operand:V16QI 0 "register_operand" "=&w") + [(set (match_operand:V16QI 0 "register_operand" "=w") (unspec:V16QI [(unspec:V16QI - [(match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "register_operand" "w")] UNSPEC_AESE) - ] UNSPEC_AESMC))] + [(xor:V16QI + (match_operand:V16QI 1 "register_operand" "%0") + (match_operand:V16QI 2 "register_operand" "w"))] + UNSPEC_AESE)] + UNSPEC_AESMC))] "TARGET_SIMD && TARGET_AES && aarch64_fusion_enabled_p (AARCH64_FUSE_AES_AESMC)" "aese\\t%0.16b, %2.16b\;aesmc\\t%0.16b, %0.16b" @@ -6130,12 +6099,14 @@ ;; Mash the two together during combine. (define_insn "*aarch64_crypto_aesd_fused" - [(set (match_operand:V16QI 0 "register_operand" "=&w") + [(set (match_operand:V16QI 0 "register_operand" "=w") (unspec:V16QI [(unspec:V16QI - [(match_operand:V16QI 1 "register_operand" "0") - (match_operand:V16QI 2 "register_operand" "w")] UNSPEC_AESD) - ] UNSPEC_AESIMC))] + [(xor:V16QI + (match_operand:V16QI 1 "register_operand" "%0") + (match_operand:V16QI 2 "register_operand" "w"))] + UNSPEC_AESD)] + UNSPEC_AESIMC))] "TARGET_SIMD && TARGET_AES && aarch64_fusion_enabled_p (AARCH64_FUSE_AES_AESMC)" "aesd\\t%0.16b, %2.16b\;aesimc\\t%0.16b, %0.16b" diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index a18fbd0..e4e9e3f 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -17965,10 +17965,6 @@ aarch_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) } } - if (aarch64_fusion_enabled_p (AARCH64_FUSE_AES_AESMC) - && aarch_crypto_can_dual_issue (prev, curr)) - return true; - if (aarch64_fusion_enabled_p (AARCH64_FUSE_CMP_BRANCH) && any_condjump_p (curr)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f334ef..3e36c0a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-07-09 Sylvia Taylor + + * gcc.target/aarch64/crypto-fuse-1.c: Remove. + * gcc.target/aarch64/crypto-fuse-2.c: Remove. + * gcc.target/aarch64/aes-fuse-1.c: New testcase. + * gcc.target/aarch64/aes-fuse-2.c: New testcase. + 2019-07-09 Christophe Lyon * gcc.target/arm/cmse/bitfield-1.c: Fix address of .gnu.sgstubs diff --git a/gcc/testsuite/gcc.target/aarch64/aes-fuse-1.c b/gcc/testsuite/gcc.target/aarch64/aes-fuse-1.c new file mode 100644 index 0000000..d7b4f89 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/aes-fuse-1.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mcpu=cortex-a72+crypto -dp" } */ +/* { dg-additional-options "-march=armv8-a+crypto" { target { aarch64*-*-* } } }*/ + +#include + +#define AESE(r, v, key) (r = vaeseq_u8 ((v), (key))); +#define AESMC(r, i) (r = vaesmcq_u8 (i)) + +const uint8x16_t zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +uint8x16_t dummy; +uint8x16_t a; +uint8x16_t b; +uint8x16_t c; +uint8x16_t d; +uint8x16_t x; +uint8x16_t y; +uint8x16_t k; + +void foo (void) + +{ + AESE (a, a, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESE (b, b, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESE (c, c, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESE (d, d, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + x = x ^ k; + AESE (x, x, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + y = y ^ k; + AESE (y, y, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESMC (d, d); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (c, c); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (b, b); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (a, a); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESMC (y, y); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESMC (x, x); +} + +/* { dg-final { scan-assembler-times "crypto_aese_fused" 6 } } */ +/* { dg-final { scan-assembler-not "veor" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/aes-fuse-2.c b/gcc/testsuite/gcc.target/aarch64/aes-fuse-2.c new file mode 100644 index 0000000..dfe01b0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/aes-fuse-2.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mcpu=cortex-a72+crypto -dp" } */ +/* { dg-additional-options "-march=armv8-a+crypto" { target { aarch64*-*-* } } }*/ + +#include + +#define AESD(r, v, key) (r = vaesdq_u8 ((v), (key))); +#define AESIMC(r, i) (r = vaesimcq_u8 (i)) + +const uint8x16_t zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +uint8x16_t dummy; +uint8x16_t a; +uint8x16_t b; +uint8x16_t c; +uint8x16_t d; +uint8x16_t x; +uint8x16_t y; +uint8x16_t k; + +void foo (void) +{ + AESD (a, a, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESD (b, b, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESD (c, c, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESD (d, d, k); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + x = x ^ k; + AESD (x, x, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + y = y ^ k; + AESD (y, y, zero); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESIMC (d, d); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (c, c); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (b, b); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (a, a); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + + AESIMC (y, y); + dummy = vaddq_u8 (dummy, dummy); + dummy = vaddq_u8 (dummy, dummy); + AESIMC (x, x); +} + +/* { dg-final { scan-assembler-times "crypto_aesd_fused" 6 } } */ +/* { dg-final { scan-assembler-not "veor" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/crypto-fuse-1.c b/gcc/testsuite/gcc.target/aarch64/crypto-fuse-1.c deleted file mode 100644 index d8adc89..0000000 --- a/gcc/testsuite/gcc.target/aarch64/crypto-fuse-1.c +++ /dev/null @@ -1,45 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -mcpu=cortex-a72+crypto -dp" } */ - -#include - -#define AESE(r, v, key) (r = vaeseq_u8 ((v), (key))); -#define AESMC(r, i) (r = vaesmcq_u8 (i)) - -uint8x16_t dummy; -uint8x16_t a; -uint8x16_t b; -uint8x16_t c; -uint8x16_t d; -uint8x16_t e; - -void -foo (void) -{ - AESE (a, a, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESE (b, b, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESE (c, c, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESE (d, d, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - - AESMC (a, a); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESMC (b, b); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESMC (c, c); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESMC (d, d); -} - -/* { dg-final { scan-assembler-times "crypto_aese_fused" 4 } } */ - diff --git a/gcc/testsuite/gcc.target/aarch64/crypto-fuse-2.c b/gcc/testsuite/gcc.target/aarch64/crypto-fuse-2.c deleted file mode 100644 index b12df2d..0000000 --- a/gcc/testsuite/gcc.target/aarch64/crypto-fuse-2.c +++ /dev/null @@ -1,45 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O3 -mcpu=cortex-a72+crypto -dp" } */ - -#include - -#define AESE(r, v, key) (r = vaesdq_u8 ((v), (key))); -#define AESMC(r, i) (r = vaesimcq_u8 (i)) - -uint8x16_t dummy; -uint8x16_t a; -uint8x16_t b; -uint8x16_t c; -uint8x16_t d; -uint8x16_t e; - -void -foo (void) -{ - AESE (a, a, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESE (b, b, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESE (c, c, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESE (d, d, e); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - - AESMC (a, a); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESMC (b, b); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESMC (c, c); - dummy = vaddq_u8 (dummy, dummy); - dummy = vaddq_u8 (dummy, dummy); - AESMC (d, d); -} - -/* { dg-final { scan-assembler-times "crypto_aesd_fused" 4 } } */ - -- cgit v1.1 From 801c9ae963cba7e3c0ac671d6d26ac5c396a41ac Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Tue, 9 Jul 2019 13:23:49 +0000 Subject: Commit missing hunk from r273296 From-SVN: r273305 --- gcc/config/arm/cortex-a53.md | 6 ------ 1 file changed, 6 deletions(-) (limited to 'gcc') diff --git a/gcc/config/arm/cortex-a53.md b/gcc/config/arm/cortex-a53.md index b55d34e..58619aa 100644 --- a/gcc/config/arm/cortex-a53.md +++ b/gcc/config/arm/cortex-a53.md @@ -723,9 +723,3 @@ "cortex_a53_fpmac" "aarch_accumulator_forwarding") -;; We want AESE and AESMC to end up consecutive to one another. - -(define_bypass 0 "cortex_a53_crypto_aese" - "cortex_a53_crypto_aesmc" - "aarch_crypto_can_dual_issue") - -- cgit v1.1 From 1f88cc260c67c8492ac15490184b8faead4b6f62 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 9 Jul 2019 13:26:43 +0000 Subject: re PR tree-optimization/91114 (ICE in vect_analyze_loop, at tree-vect-loop.c:2415) 2019-07-09 Richard Biener PR tree-optimization/91114 * tree-vect-data-refs.c (vect_analyze_data_refs): Failure to find a vector type isn't fatal. * gcc.dg/vect/pr91114.c: New testcase. From-SVN: r273306 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/vect/pr91114.c | 12 ++++++++++++ gcc/tree-vect-data-refs.c | 2 ++ 4 files changed, 25 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/vect/pr91114.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 25959b94..63f50e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Richard Biener + + PR tree-optimization/91114 + * tree-vect-data-refs.c (vect_analyze_data_refs): Failure to + find a vector type isn't fatal. + 2019-07-09 Sylvia Taylor * config/aarch64/aarch64-simd.md diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3e36c0a..31e8a83 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Richard Biener + + PR tree-optimization/91114 + * gcc.dg/vect/pr91114.c: New testcase. + 2019-07-09 Sylvia Taylor * gcc.target/aarch64/crypto-fuse-1.c: Remove. diff --git a/gcc/testsuite/gcc.dg/vect/pr91114.c b/gcc/testsuite/gcc.dg/vect/pr91114.c new file mode 100644 index 0000000..3343d1e --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr91114.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fopenmp-simd" } */ + +void +ne (double *zu) +{ + int h3; + +#pragma omp simd simdlen (4) + for (h3 = 0; h3 < 4; ++h3) + zu[h3] = 0; +} diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index cf9cee5..1af36d8 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -4360,6 +4360,8 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf, bool *fatal) STMT_VINFO_VECTORIZABLE (stmt_info) = false; continue; } + if (fatal) + *fatal = false; return opt_result::failure_at (stmt_info->stmt, "not vectorized:" " no vectype for stmt: %G" -- cgit v1.1 From 6c1dae73cd2ceb6a326f786f6d4e8674863de45e Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 9 Jul 2019 16:36:00 +0000 Subject: PR c++/61339 - add mismatch between struct and class [-Wmismatched-tags] to non-bugs gcc/c/ChangeLog: PR c++/61339 * c-decl.c: Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. * gimple-parser.c: Same. gcc/c-family/ChangeLog: PR c++/61339 * c-format.c (check_argument_type): Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. * c-pretty-print.h: Same. gcc/cp/ChangeLog: PR c++/61339 * constexpr.c (cxx_eval_call_expression): Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. * constraint.cc (get_concept_definition): Same. * cp-tree.h: Same. * cxx-pretty-print.h: Same. * error.c: Same. * logic.cc (term_list::replace): Same. * name-lookup.c (find_local_binding): Same. * pt.c (tsubst_binary_right_fold): Same. * search.c (field_accessor_p): Same. * semantics.c (expand_or_defer_fn): Same. gcc/lto/ChangeLog: PR c++/61339 * lto-dump.c: Change class-key from classi to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. gcc/ChangeLog: PR c++/61339 * align.h: Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. * alloc-pool.h: Same. * asan.c (shadow_mem_size): Same. * auto-profile.c: Same. * basic-block.h: Same. * bitmap.h: Same. * cfgexpand.c (set_rtl): Same. (expand_one_stack_var_at): Same. * cfghooks.h: Same. * cfgloop.h: Same. * cgraph.h: Same. * config/i386/i386.h: Same. * df-problems.c (df_print_bb_index): Same. * df-scan.c: Same. * df.h (df_single_use): Same. * diagnostic-show-locus.c (layout::print_annotation_line): Same. (layout::annotation_line_showed_range_p): Same. (get_printed_columns): Same. (correction::ensure_terminated): Same. (line_corrections::~line_corrections): Same. * dojump.h: Same. * dse.c: Same. * dump-context.h: Same. * dumpfile.h: Same. * dwarf2out.c: Same. * edit-context.c: Same. * fibonacci_heap.c (test_union_of_equal_heaps): Same. * flags.h: Same. * function.c (assign_stack_local): Same. * function.h: Same. * gcc.c: Same. * gcov.c (block_info::block_info): Same. * genattrtab.c: Same. * genextract.c: Same. * genmatch.c (comparison_code_p): Same. (id_base::id_base): Same. (decision_tree::print): Same. * genoutput.c: Same. * genpreds.c (write_one_predicate_function): Same. * genrecog.c (validate_pattern): Same. (find_operand_positions): Same. (optimize_subroutine_group): Same. (merge_pattern_transition::merge_pattern_transition): Same. (merge_pattern_info::merge_pattern_info): Same. (merge_state_result::merge_state_result): Same. (merge_into_state): Same. * gensupport.c: Same. * gensupport.h: Same. * ggc-common.c (init_ggc_heuristics): Same. * ggc-tests.c (test_union): Same. * gimple-loop-interchange.cc (dump_induction): Same. * gimple-loop-versioning.cc: Same. * gimple-match.h (gimple_match_cond::any_else): Same. * gimple-ssa-backprop.c: Same. * gimple-ssa-sprintf.c: Same. * gimple-ssa-store-merging.c (store_operand_info::store_operand_info): Same. (store_immediate_info::store_immediate_info): Same. (merged_store_group::apply_stores): Same. (get_location_for_stmts): Same. * gimple-ssa-strength-reduction.c: Same. * gimple-ssa-warn-alloca.c: Same. * gimple-ssa-warn-restrict.c (pass_wrestrict::execute): Same. * godump.c (go_type_decl): Same. * hash-map-tests.c (test_map_of_strings_to_int): Same. * hash-map.h: Same. * hash-set-tests.c (test_set_of_strings): Same. * hsa-brig.c: Same. * hsa-common.h: Same. * hsa-gen.c (transformable_switch_to_sbr_p): Same. * input.c (assert_loceq): Same. * input.h: Same. * ipa-cp.c: Same. * ipa-devirt.c (possible_polymorphic_call_targets_1): Same. * ipa-fnsummary.h: Same. * ipa-inline.h: Same. * ipa-prop.h: Same. * ipa-split.c (visit_bb): Same. * ira-int.h (minmax_set_iter_next): Same. * loop-invariant.c: Same. * loop-iv.c: Same. * lra-eliminations.c: Same. * lra-int.h: Same. * lra-lives.c (mark_regno_dead): Same. * lra-remat.c: Same. * lra-spills.c: Same. * lto-streamer.h: Same. * mem-stats.h: Same. * omp-grid.c (omp_grid_lastprivate_predicate): Same. * omp-low.c (omp_clause_aligned_alignment): Same. * optabs-query.h (get_vcond_eq_icode): Same. * optabs.h: Same. * opts.c (wrap_help): Same. * poly-int.h: Same. * predict.c (predict_paths_leading_to_edge): Same. * pretty-print.h: Same. * profile-count.h: Same. * read-md.h: Same. * read-rtl-function.c: Same. * ree.c: Same. * reginfo.c: Same. * regrename.c: Same. * regrename.h: Same. * reload.h: Same. * rtl-iter.h: Same. * rtl.h (costs_add_n_insns): Same. * sanopt.c: Same. * sched-int.h: Same. * sel-sched-ir.h: Same. * selftest.h: Same. * sese.h (vec_find): Same. * stmt.c: Same. * target-globals.h: Same. * tree-affine.c (aff_combination_find_elt): Same. * tree-affine.h: Same. * tree-data-ref.h: Same. * tree-outof-ssa.c (ssa_is_replaceable_p): Same. * tree-predcom.c: Same. * tree-scalar-evolution.c (find_var_scev_info): Same. * tree-ssa-alias.h: Same. * tree-ssa-ccp.c: Same. * tree-ssa-coalesce.c (ssa_conflicts_dump): Same. * tree-ssa-loop-im.c (for_all_locs_in_loop): Same. (rewrite_mem_refs): Same. (execute_sm_if_changed): Same. (hoist_memory_references): Same. * tree-ssa-loop-ivopts.c (operator<=): Same. * tree-ssa-loop.h: Same. * tree-ssa-pre.c (get_or_alloc_expr_for_name): Same. * tree-ssa-structalias.c: Same. * tree-switch-conversion.h (cluster::cluster): Same. (simple_cluster::simple_cluster): Same. * tree-vect-patterns.c (type_conversion_p): Same. * tree-vectorizer.c (dump_stmt_cost): Same. * tree-vectorizer.h (loop_vec_info_for_loop): Same. * tree.c (protected_set_expr_location): Same. * tree.h (desired_pro_or_demotion_p): Same. (fndecl_built_in_p): Same. * unique-ptr-tests.cc: Same. * var-tracking.c (delete_variable_part): Same. * varasm.c (assemble_real): Same. (tree_output_constant_def): Same. * vec.c: Same. * wide-int-bitmask.h: Same. * wide-int.h (decompose): Same. From-SVN: r273308 --- gcc/ChangeLog | 149 ++++++++++++++++++++++++++++++++++++ gcc/align.h | 3 +- gcc/alloc-pool.h | 3 +- gcc/asan.c | 3 +- gcc/auto-profile.c | 3 +- gcc/basic-block.h | 3 +- gcc/bitmap.h | 6 +- gcc/c-family/ChangeLog | 8 ++ gcc/c-family/c-format.c | 6 +- gcc/c-family/c-pretty-print.h | 3 +- gcc/c/ChangeLog | 7 ++ gcc/c/c-decl.c | 3 +- gcc/c/gimple-parser.c | 6 +- gcc/cfgexpand.c | 6 +- gcc/cfghooks.h | 3 +- gcc/cfgloop.h | 15 ++-- gcc/cgraph.h | 20 +++-- gcc/config/i386/i386.h | 3 +- gcc/cp/ChangeLog | 16 ++++ gcc/cp/constexpr.c | 3 +- gcc/cp/constraint.cc | 3 +- gcc/cp/cp-tree.h | 21 +++-- gcc/cp/cxx-pretty-print.h | 3 +- gcc/cp/error.c | 3 +- gcc/cp/logic.cc | 9 ++- gcc/cp/name-lookup.c | 2 +- gcc/cp/pt.c | 3 +- gcc/cp/search.c | 3 +- gcc/cp/semantics.c | 3 +- gcc/df-problems.c | 3 +- gcc/df-scan.c | 3 +- gcc/df.h | 23 ++++-- gcc/diagnostic-show-locus.c | 18 +++-- gcc/dojump.h | 3 +- gcc/dse.c | 6 +- gcc/dump-context.h | 3 +- gcc/dumpfile.h | 3 +- gcc/dwarf2out.c | 3 +- gcc/edit-context.c | 3 +- gcc/fibonacci_heap.c | 3 +- gcc/flags.h | 3 +- gcc/function.c | 3 +- gcc/function.h | 6 +- gcc/gcc.c | 4 +- gcc/gcov.c | 15 ++-- gcc/genattrtab.c | 9 ++- gcc/genextract.c | 3 +- gcc/genmatch.c | 57 +++++++++----- gcc/genoutput.c | 6 +- gcc/genpreds.c | 3 +- gcc/genrecog.c | 54 ++++++++----- gcc/gensupport.c | 3 +- gcc/gensupport.h | 3 +- gcc/ggc-common.c | 3 +- gcc/ggc-tests.c | 3 +- gcc/gimple-loop-interchange.cc | 3 +- gcc/gimple-loop-versioning.cc | 6 +- gcc/gimple-match.h | 6 +- gcc/gimple-ssa-backprop.c | 3 +- gcc/gimple-ssa-sprintf.c | 3 +- gcc/gimple-ssa-store-merging.c | 15 ++-- gcc/gimple-ssa-strength-reduction.c | 6 +- gcc/gimple-ssa-warn-alloca.c | 3 +- gcc/gimple-ssa-warn-restrict.c | 3 +- gcc/godump.c | 3 +- gcc/hash-map-tests.c | 3 +- gcc/hash-map.h | 3 +- gcc/hash-set-tests.c | 3 +- gcc/hsa-brig.c | 3 +- gcc/hsa-common.h | 6 +- gcc/hsa-gen.c | 3 +- gcc/input.c | 12 ++- gcc/input.h | 3 +- gcc/ipa-cp.c | 9 ++- gcc/ipa-devirt.c | 6 +- gcc/ipa-fnsummary.h | 9 ++- gcc/ipa-inline.h | 3 +- gcc/ipa-prop.h | 9 ++- gcc/ipa-split.c | 9 ++- gcc/ira-int.h | 6 +- gcc/loop-invariant.c | 3 +- gcc/loop-iv.c | 3 +- gcc/lra-eliminations.c | 3 +- gcc/lra-int.h | 6 +- gcc/lra-lives.c | 3 +- gcc/lra-remat.c | 3 +- gcc/lra-spills.c | 3 +- gcc/lto-streamer.h | 3 +- gcc/lto/ChangeLog | 6 ++ gcc/lto/lto-dump.c | 9 ++- gcc/mem-stats.h | 9 ++- gcc/omp-grid.c | 3 +- gcc/omp-low.c | 3 +- gcc/optabs-query.h | 3 +- gcc/optabs.h | 3 +- gcc/opts.c | 6 +- gcc/poly-int.h | 2 +- gcc/predict.c | 6 +- gcc/pretty-print.h | 6 +- gcc/profile-count.h | 2 +- gcc/read-md.h | 3 +- gcc/read-rtl-function.c | 3 +- gcc/ree.c | 3 +- gcc/reginfo.c | 3 +- gcc/regrename.c | 3 +- gcc/regrename.h | 3 +- gcc/reload.h | 3 +- gcc/rtl-iter.h | 3 +- gcc/rtl.h | 38 +++++---- gcc/sanopt.c | 3 +- gcc/sched-int.h | 3 +- gcc/sel-sched-ir.h | 3 +- gcc/selftest.h | 3 +- gcc/sese.h | 6 +- gcc/stmt.c | 3 +- gcc/target-globals.h | 3 +- gcc/tree-affine.c | 3 +- gcc/tree-affine.h | 6 +- gcc/tree-data-ref.h | 6 +- gcc/tree-outof-ssa.c | 3 +- gcc/tree-predcom.c | 3 +- gcc/tree-scalar-evolution.c | 3 +- gcc/tree-ssa-alias.h | 3 +- gcc/tree-ssa-ccp.c | 3 +- gcc/tree-ssa-coalesce.c | 3 +- gcc/tree-ssa-loop-im.c | 15 ++-- gcc/tree-ssa-loop-ivopts.c | 12 ++- gcc/tree-ssa-loop.h | 3 +- gcc/tree-ssa-pre.c | 3 +- gcc/tree-ssa-structalias.c | 3 +- gcc/tree-switch-conversion.h | 30 +++++--- gcc/tree-vect-patterns.c | 3 +- gcc/tree-vectorizer.c | 3 +- gcc/tree-vectorizer.h | 24 ++++-- gcc/tree.c | 3 +- gcc/tree.h | 6 +- gcc/unique-ptr-tests.cc | 6 +- gcc/var-tracking.c | 6 +- gcc/varasm.c | 6 +- gcc/vec.c | 3 +- gcc/wide-int-bitmask.h | 3 +- gcc/wide-int.h | 10 ++- 142 files changed, 750 insertions(+), 296 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 63f50e8..1606b91 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,152 @@ +2019-07-09 Martin Sebor + + PR c++/61339 + * align.h: Change class-key from class to struct and vice versa + to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. + * alloc-pool.h: Same. + * asan.c (shadow_mem_size): Same. + * auto-profile.c: Same. + * basic-block.h: Same. + * bitmap.h: Same. + * cfgexpand.c (set_rtl): Same. + (expand_one_stack_var_at): Same. + * cfghooks.h: Same. + * cfgloop.h: Same. + * cgraph.h: Same. + * config/i386/i386.h: Same. + * df-problems.c (df_print_bb_index): Same. + * df-scan.c: Same. + * df.h (df_single_use): Same. + * diagnostic-show-locus.c (layout::print_annotation_line): Same. + (layout::annotation_line_showed_range_p): Same. + (get_printed_columns): Same. + (correction::ensure_terminated): Same. + (line_corrections::~line_corrections): Same. + * dojump.h: Same. + * dse.c: Same. + * dump-context.h: Same. + * dumpfile.h: Same. + * dwarf2out.c: Same. + * edit-context.c: Same. + * fibonacci_heap.c (test_union_of_equal_heaps): Same. + * flags.h: Same. + * function.c (assign_stack_local): Same. + * function.h: Same. + * gcc.c: Same. + * gcov.c (block_info::block_info): Same. + * genattrtab.c: Same. + * genextract.c: Same. + * genmatch.c (comparison_code_p): Same. + (id_base::id_base): Same. + (decision_tree::print): Same. + * genoutput.c: Same. + * genpreds.c (write_one_predicate_function): Same. + * genrecog.c (validate_pattern): Same. + (find_operand_positions): Same. + (optimize_subroutine_group): Same. + (merge_pattern_transition::merge_pattern_transition): Same. + (merge_pattern_info::merge_pattern_info): Same. + (merge_state_result::merge_state_result): Same. + (merge_into_state): Same. + * gensupport.c: Same. + * gensupport.h: Same. + * ggc-common.c (init_ggc_heuristics): Same. + * ggc-tests.c (test_union): Same. + * gimple-loop-interchange.cc (dump_induction): Same. + * gimple-loop-versioning.cc: Same. + * gimple-match.h (gimple_match_cond::any_else): Same. + * gimple-ssa-backprop.c: Same. + * gimple-ssa-sprintf.c: Same. + * gimple-ssa-store-merging.c (store_operand_info::store_operand_info): Same. + (store_immediate_info::store_immediate_info): Same. + (merged_store_group::apply_stores): Same. + (get_location_for_stmts): Same. + * gimple-ssa-strength-reduction.c: Same. + * gimple-ssa-warn-alloca.c: Same. + * gimple-ssa-warn-restrict.c (pass_wrestrict::execute): Same. + * godump.c (go_type_decl): Same. + * hash-map-tests.c (test_map_of_strings_to_int): Same. + * hash-map.h: Same. + * hash-set-tests.c (test_set_of_strings): Same. + * hsa-brig.c: Same. + * hsa-common.h: Same. + * hsa-gen.c (transformable_switch_to_sbr_p): Same. + * input.c (assert_loceq): Same. + * input.h: Same. + * ipa-cp.c: Same. + * ipa-devirt.c (possible_polymorphic_call_targets_1): Same. + * ipa-fnsummary.h: Same. + * ipa-inline.h: Same. + * ipa-prop.h: Same. + * ipa-split.c (visit_bb): Same. + * ira-int.h (minmax_set_iter_next): Same. + * loop-invariant.c: Same. + * loop-iv.c: Same. + * lra-eliminations.c: Same. + * lra-int.h: Same. + * lra-lives.c (mark_regno_dead): Same. + * lra-remat.c: Same. + * lra-spills.c: Same. + * lto-streamer.h: Same. + * mem-stats.h: Same. + * omp-grid.c (omp_grid_lastprivate_predicate): Same. + * omp-low.c (omp_clause_aligned_alignment): Same. + * optabs-query.h (get_vcond_eq_icode): Same. + * optabs.h: Same. + * opts.c (wrap_help): Same. + * poly-int.h: Same. + * predict.c (predict_paths_leading_to_edge): Same. + * pretty-print.h: Same. + * profile-count.h: Same. + * read-md.h: Same. + * read-rtl-function.c: Same. + * ree.c: Same. + * reginfo.c: Same. + * regrename.c: Same. + * regrename.h: Same. + * reload.h: Same. + * rtl-iter.h: Same. + * rtl.h (costs_add_n_insns): Same. + * sanopt.c: Same. + * sched-int.h: Same. + * sel-sched-ir.h: Same. + * selftest.h: Same. + * sese.h (vec_find): Same. + * stmt.c: Same. + * target-globals.h: Same. + * tree-affine.c (aff_combination_find_elt): Same. + * tree-affine.h: Same. + * tree-data-ref.h: Same. + * tree-outof-ssa.c (ssa_is_replaceable_p): Same. + * tree-predcom.c: Same. + * tree-scalar-evolution.c (find_var_scev_info): Same. + * tree-ssa-alias.h: Same. + * tree-ssa-ccp.c: Same. + * tree-ssa-coalesce.c (ssa_conflicts_dump): Same. + * tree-ssa-loop-im.c (for_all_locs_in_loop): Same. + (rewrite_mem_refs): Same. + (execute_sm_if_changed): Same. + (hoist_memory_references): Same. + * tree-ssa-loop-ivopts.c (operator<=): Same. + * tree-ssa-loop.h: Same. + * tree-ssa-pre.c (get_or_alloc_expr_for_name): Same. + * tree-ssa-structalias.c: Same. + * tree-switch-conversion.h (cluster::cluster): Same. + (simple_cluster::simple_cluster): Same. + * tree-vect-patterns.c (type_conversion_p): Same. + * tree-vectorizer.c (dump_stmt_cost): Same. + * tree-vectorizer.h (loop_vec_info_for_loop): Same. + * tree.c (protected_set_expr_location): Same. + * tree.h (desired_pro_or_demotion_p): Same. + (fndecl_built_in_p): Same. + * unique-ptr-tests.cc: Same. + * var-tracking.c (delete_variable_part): Same. + * varasm.c (assemble_real): Same. + (tree_output_constant_def): Same. + * vec.c: Same. + * wide-int-bitmask.h: Same. + * wide-int.h (decompose): Same. + 2019-07-09 Richard Biener PR tree-optimization/91114 diff --git a/gcc/align.h b/gcc/align.h index 6768451..6c98e2d 100644 --- a/gcc/align.h +++ b/gcc/align.h @@ -45,8 +45,9 @@ struct align_flags_tuple /* Alignment flags is structure used as value of -align-* options. It's used in target-dependant code. */ -struct align_flags +class align_flags { +public: /* Default constructor. */ align_flags (int log0 = 0, int maxskip0 = 0, int log1 = 0, int maxskip1 = 0) { diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h index d320810..d8878b6 100644 --- a/gcc/alloc-pool.h +++ b/gcc/alloc-pool.h @@ -34,8 +34,9 @@ typedef unsigned long ALLOC_POOL_ID_TYPE; extern ALLOC_POOL_ID_TYPE last_id; /* Pool allocator memory usage. */ -struct pool_usage: public mem_usage +class pool_usage: public mem_usage { +public: /* Default contructor. */ pool_usage (): m_element_size (0), m_pool_name ("") {} /* Constructor. */ diff --git a/gcc/asan.c b/gcc/asan.c index 605d04f..a731bd4 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1225,8 +1225,9 @@ shadow_mem_size (unsigned HOST_WIDE_INT size) #define RZ_BUFFER_SIZE 4 /* ASAN redzone buffer container that handles emission of shadow bytes. */ -struct asan_redzone_buffer +class asan_redzone_buffer { +public: /* Constructor. */ asan_redzone_buffer (rtx shadow_mem, HOST_WIDE_INT prev_offset): m_shadow_mem (shadow_mem), m_prev_offset (prev_offset), diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c index 26353a2..59100a0 100644 --- a/gcc/auto-profile.c +++ b/gcc/auto-profile.c @@ -136,8 +136,9 @@ typedef std::map icall_target_map; typedef std::set stmt_set; /* Represent count info of an inline stack. */ -struct count_info +class count_info { +public: /* Sampled count of the inline stack. */ gcov_type count; diff --git a/gcc/basic-block.h b/gcc/basic-block.h index fba5526..964f2bd 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -23,7 +23,8 @@ along with GCC; see the file COPYING3. If not see #include /* Control flow edge information. */ -struct GTY((user)) edge_def { +class GTY((user)) edge_def { +public: /* The two blocks at the ends of the edge. */ basic_block src; basic_block dest; diff --git a/gcc/bitmap.h b/gcc/bitmap.h index 39f509d..0e3ffc8 100644 --- a/gcc/bitmap.h +++ b/gcc/bitmap.h @@ -212,8 +212,9 @@ along with GCC; see the file COPYING3. If not see #include "obstack.h" /* Bitmap memory usage. */ -struct bitmap_usage: public mem_usage +class bitmap_usage: public mem_usage { +public: /* Default contructor. */ bitmap_usage (): m_nsearches (0), m_search_iter (0) {} /* Constructor. */ @@ -321,7 +322,8 @@ struct GTY((chain_next ("%h.next"))) bitmap_element { /* Head of bitmap linked list. The 'current' member points to something already pointed to by the chain started by first, so GTY((skip)) it. */ -struct GTY(()) bitmap_head { +class GTY(()) bitmap_head { +public: static bitmap_obstack crashme; /* Poison obstack to not make it not a valid initialized GC bitmap. */ CONSTEXPR bitmap_head() diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 84d1f2e..4d8f967 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2019-07-09 Martin Sebor + + PR c++/61339 + * c-format.c (check_argument_type): Change class-key from class to + struct and vice versa to match convention and avoid -Wclass-is-pod + and -Wstruct-no-pod. + * c-pretty-print.h: Same. + 2019-07-03 Martin Liska * c-common.c (try_to_locate_new_include_insertion_point): Remove diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index 6363fa4..d134116 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -1839,8 +1839,9 @@ class flag_chars_t /* Support struct for argument_parser and check_format_info_main. Encapsulates any length modifier applied to the current argument. */ -struct length_modifier +class length_modifier { +public: length_modifier () : chars (NULL), val (FMT_LEN_none), std (STD_C89), scalar_identity_flag (0) @@ -2853,8 +2854,9 @@ check_argument_type (const format_char_info *fci, /* Describes "paired tokens" within the format string that are expected to be balanced. */ -struct baltoks_t +class baltoks_t { +public: baltoks_t (): singlequote (), doublequote () { } typedef auto_vec balanced_tokens_t; diff --git a/gcc/c-family/c-pretty-print.h b/gcc/c-family/c-pretty-print.h index 6084dcf..8c516c3 100644 --- a/gcc/c-family/c-pretty-print.h +++ b/gcc/c-family/c-pretty-print.h @@ -47,8 +47,9 @@ typedef void (*c_pretty_print_fn) (c_pretty_printer *, tree); facilities provided here. A derived pretty-printer can override any function listed in the vtable below. See cp/cxx-pretty-print.h and cp/cxx-pretty-print.c for an example of derivation. */ -struct c_pretty_printer : pretty_printer +class c_pretty_printer : public pretty_printer { +public: c_pretty_printer (); // Format string, possibly translated. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 271ed4ba..d2645a8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2019-07-09 Martin Sebor + + PR c++/61339 + * c-decl.c: Change class-key from class to struct and vice versa + to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. + * gimple-parser.c: Same. + 2019-07-01 Richard Biener * gimple-parser.c (c_parser_gimple_postfix_expression): Handle diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index cb2f49f..35e15ba 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -574,8 +574,9 @@ typedef struct c_binding *c_binding_ptr; /* Information that we keep for a struct or union while it is being parsed. */ -struct c_struct_parse_info +class c_struct_parse_info { +public: /* If warn_cxx_compat, a list of types defined within this struct. */ auto_vec struct_types; diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index b2b364c..e388d93 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -68,8 +68,9 @@ along with GCC; see the file COPYING3. If not see /* GIMPLE parser state. */ -struct gimple_parser +class gimple_parser { +public: gimple_parser (c_parser *p) : parser (p), edges(), current_bb(NULL) {} /* c_parser is not visible here, use composition and fake inheritance via a conversion operator. */ @@ -77,8 +78,9 @@ struct gimple_parser c_parser *parser; /* CFG build state. */ - struct gimple_parser_edge + class gimple_parser_edge { + public: int src; int dest; int flags; diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 1e84d2c..0128fca 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -305,8 +305,9 @@ set_rtl (tree t, rtx x) /* This structure holds data relevant to one variable that will be placed in a stack slot. */ -struct stack_var +class stack_var { +public: /* The Variable. */ tree decl; @@ -1021,8 +1022,9 @@ expand_one_stack_var_at (tree decl, rtx base, unsigned base_align, set_rtl (decl, x); } -struct stack_vars_data +class stack_vars_data { +public: /* Vector of offset pairs, always end of some padding followed by start of the padding that needs Address Sanitizer protection. The vector is in reversed, highest offset pairs come first. */ diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h index e9385c9..9ed0c36 100644 --- a/gcc/cfghooks.h +++ b/gcc/cfghooks.h @@ -58,8 +58,9 @@ typedef int_hash dependence_hash; /* Optional data for duplicate_block. */ -struct copy_bb_data +class copy_bb_data { +public: copy_bb_data() : dependence_map (NULL) {} ~copy_bb_data () { delete dependence_map; } diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 2f8ab10..9414070 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -46,7 +46,8 @@ enum iv_extend_code /* The structure describing a bound on number of iterations of a loop. */ -struct GTY ((chain_next ("%h.next"))) nb_iter_bound { +class GTY ((chain_next ("%h.next"))) nb_iter_bound { +public: /* The statement STMT is executed at most ... */ gimple *stmt; @@ -113,7 +114,8 @@ struct GTY ((chain_next ("%h.next"))) control_iv { }; /* Structure to hold information for each natural loop. */ -struct GTY ((chain_next ("%h.next"))) loop { +class GTY ((chain_next ("%h.next"))) loop { +public: /* Index into loops array. Note indices will never be reused after loop is destroyed. */ int num; @@ -422,8 +424,9 @@ void mark_loop_for_removal (loop_p); computation is done, which would enable it to be different from the outer one? */ -struct rtx_iv +class rtx_iv { +public: /* Its base and step (mode of base and step is supposed to be extend_mode, see the description above). */ rtx base, step; @@ -448,8 +451,9 @@ struct rtx_iv /* The description of an exit from the loop and of the number of iterations till we take the exit. */ -struct GTY(()) niter_desc +class GTY(()) niter_desc { +public: /* The edge out of the loop. */ edge out_edge; @@ -651,8 +655,9 @@ enum li_flags /* The iterator for loops. */ -struct loop_iterator +class loop_iterator { +public: loop_iterator (function *fn, loop_p *loop, unsigned flags); ~loop_iterator (); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 18839a4..e5fd6dd 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -100,8 +100,8 @@ enum symbol_partitioning_class /* Base of all entries in the symbol table. The symtab_node is inherited by cgraph and varpol nodes. */ -class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"), - chain_next ("%h.next"), chain_prev ("%h.previous"))) +struct GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"), + chain_next ("%h.next"), chain_prev ("%h.previous"))) symtab_node { public: @@ -912,7 +912,8 @@ struct cgraph_edge_hasher : ggc_ptr_hash /* The cgraph data structure. Each function decl has assigned cgraph_node listing callees and callers. */ -struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node { +class GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node +{ public: friend class symbol_table; @@ -1632,8 +1633,9 @@ private: /* Structure containing additional information about an indirect call. */ -struct GTY(()) cgraph_indirect_call_info +class GTY(()) cgraph_indirect_call_info { +public: /* When agg_content is set, an offset where the call pointer is located within the aggregate. */ HOST_WIDE_INT offset; @@ -1673,8 +1675,10 @@ struct GTY(()) cgraph_indirect_call_info unsigned vptr_changed : 1; }; -struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"), - for_user)) cgraph_edge { +class GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"), + for_user)) cgraph_edge +{ +public: friend class cgraph_node; friend class symbol_table; @@ -1856,8 +1860,8 @@ private: /* The varpool data structure. Each static variable decl has assigned varpool_node. */ -class GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node { -public: +struct GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node +{ /* Dump given varpool node to F. */ void dump (FILE *f); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 1f70844..a2fcdd4 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2417,8 +2417,9 @@ const wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW #include "insn-attr-common.h" -struct pta +class pta { +public: const char *const name; /* processor name or nickname. */ const enum processor_type processor; const enum attr_cpu schedule; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0fcbfe5..2dd3893 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2019-07-09 Martin Sebor + + PR c++/61339 + * constexpr.c (cxx_eval_call_expression): Change class-key from class + to struct and vice versa to match convention and avoid -Wclass-is-pod + and -Wstruct-no-pod. + * constraint.cc (get_concept_definition): Same. + * cp-tree.h: Same. + * cxx-pretty-print.h: Same. + * error.c: Same. + * logic.cc (term_list::replace): Same. + * name-lookup.c (find_local_binding): Same. + * pt.c (tsubst_binary_right_fold): Same. + * search.c (field_accessor_p): Same. + * semantics.c (expand_or_defer_fn): Same. + 2019-07-08 Jakub Jelinek PR c++/91110 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index d11e7af..c1b8b9b 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1753,8 +1753,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, /* We build up the bindings list before we know whether we already have this call cached. If we don't end up saving these bindings, ggc_free them when this function exits. */ - struct free_bindings + class free_bindings { + public: tree &bindings; bool do_free; free_bindings (tree &b): bindings (b), do_free(true) { } diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index ed39ecc..cc578bb 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -517,8 +517,9 @@ get_concept_definition (tree decl) int expansion_level = 0; -struct expanding_concept_sentinel +class expanding_concept_sentinel { +public: expanding_concept_sentinel () { ++expansion_level; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e814bc9..970296d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -873,8 +873,9 @@ struct named_decl_hash : ggc_remove /* Simplified unique_ptr clone to release a tree vec on exit. */ -struct releasing_vec +class releasing_vec { +public: typedef vec vec_t; releasing_vec (vec_t *v): v(v) { } @@ -1728,8 +1729,9 @@ extern GTY(()) struct saved_scope *scope_chain; /* RAII sentinel to handle clearing processing_template_decl and restoring it when done. */ -struct processing_template_decl_sentinel +class processing_template_decl_sentinel { +public: int saved; processing_template_decl_sentinel (bool reset = true) : saved (processing_template_decl) @@ -1746,8 +1748,9 @@ struct processing_template_decl_sentinel /* RAII sentinel to disable certain warnings during template substitution and elsewhere. */ -struct warning_sentinel +class warning_sentinel { +public: int &flag; int val; warning_sentinel(int& flag, bool suppress=true) @@ -5267,8 +5270,9 @@ extern int cp_unevaluated_operand; /* RAII class used to inhibit the evaluation of operands during parsing and template instantiation. Evaluation warnings are also inhibited. */ -struct cp_unevaluated +class cp_unevaluated { +public: cp_unevaluated (); ~cp_unevaluated (); }; @@ -5276,8 +5280,9 @@ struct cp_unevaluated /* The reverse: an RAII class used for nested contexts that are evaluated even if the enclosing context is not. */ -struct cp_evaluated +class cp_evaluated { +public: int uneval; int inhibit; cp_evaluated () @@ -5304,8 +5309,9 @@ enum unification_kind_t { // specializations. When the stack goes out of scope, the // previous pointer map is restored. enum lss_policy { lss_blank, lss_copy }; -struct local_specialization_stack +class local_specialization_stack { +public: local_specialization_stack (lss_policy = lss_blank); ~local_specialization_stack (); @@ -6973,8 +6979,9 @@ extern bool perform_or_defer_access_check (tree, tree, tree, /* RAII sentinel to ensures that deferred access checks are popped before a function returns. */ -struct deferring_access_check_sentinel +class deferring_access_check_sentinel { +public: deferring_access_check_sentinel (enum deferring_kind kind = dk_deferred) { push_deferring_access_checks (kind); diff --git a/gcc/cp/cxx-pretty-print.h b/gcc/cp/cxx-pretty-print.h index aba3e84..347811f 100644 --- a/gcc/cp/cxx-pretty-print.h +++ b/gcc/cp/cxx-pretty-print.h @@ -29,8 +29,9 @@ enum cxx_pretty_printer_flags pp_cxx_flag_default_argument = 1 << pp_c_flag_last_bit }; -struct cxx_pretty_printer : c_pretty_printer +class cxx_pretty_printer : public c_pretty_printer { +public: cxx_pretty_printer (); void constant (tree); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index baeba7e..5943762 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -107,8 +107,9 @@ static bool cp_printer (pretty_printer *, text_info *, const char *, /* Struct for handling %H or %I, which require delaying printing the type until a postprocessing stage. */ -struct deferred_printed_type +class deferred_printed_type { +public: deferred_printed_type () : m_tree (NULL_TREE), m_buffer_ptr (NULL), m_verbose (false), m_quote (false) {} diff --git a/gcc/cp/logic.cc b/gcc/cp/logic.cc index 2ace8c3..13cc321 100644 --- a/gcc/cp/logic.cc +++ b/gcc/cp/logic.cc @@ -104,8 +104,9 @@ struct term_hasher : ggc_ptr_hash Each term list maintains an iterator that refers to the current term. This can be used by various tactics to support iteration and stateful manipulation of the list. */ -struct term_list +class term_list { +public: typedef std::list::iterator iterator; term_list (); @@ -220,8 +221,9 @@ term_list::replace (iterator iter, tree t1, tree t2) conclusions written as propositions in the constraint language (i.e., lists of trees). */ -struct proof_goal +class proof_goal { +public: term_list assumptions; term_list conclusions; }; @@ -230,8 +232,9 @@ struct proof_goal current sub-goal. The class also provides facilities for managing subgoals and constructing term lists. */ -struct proof_state : std::list +class proof_state : public std::list { +public: proof_state (); iterator branch (iterator i); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index f4c34ed..ad86629 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -157,7 +157,7 @@ find_local_binding (cp_binding_level *b, tree name) return NULL; } -struct name_lookup +class name_lookup { public: typedef std::pair using_pair; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c5161a7..c0a0487 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12032,8 +12032,9 @@ tsubst_binary_right_fold (tree t, tree args, tsubst_flags_t complain, /* Walk through the pattern of a pack expansion, adding everything in local_specializations to a list. */ -struct el_data +class el_data { +public: hash_set internal; tree extra; tsubst_flags_t complain; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 372c442..a737e24 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1803,8 +1803,9 @@ field_accessor_p (tree fn, tree field_decl, bool const_p) /* Callback data for dfs_locate_field_accessor_pre. */ -struct locate_field_data +class locate_field_data { +public: locate_field_data (tree field_decl_, bool const_p_) : field_decl (field_decl_), const_p (const_p_) {} diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index cd24490..ceb6c64 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4380,8 +4380,9 @@ expand_or_defer_fn (tree fn) } } -struct nrv_data +class nrv_data { +public: nrv_data () : visited (37) {} tree var; diff --git a/gcc/df-problems.c b/gcc/df-problems.c index a9dfa62..62b2cf6 100644 --- a/gcc/df-problems.c +++ b/gcc/df-problems.c @@ -144,8 +144,9 @@ df_print_bb_index (basic_block bb, FILE *file) /* Private data used to compute the solution for this problem. These data structures are not accessible outside of this module. */ -struct df_rd_problem_data +class df_rd_problem_data { +public: /* The set of defs to regs invalidated by call. */ bitmap_head sparse_invalidated_by_call; /* The set of defs to regs invalidate by call for rd. */ diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 81e221e..ffaca0b 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -44,8 +44,9 @@ static HARD_REG_SET elim_reg_set; /* Initialize ur_in and ur_out as if all hard registers were partially available. */ -struct df_collection_rec +class df_collection_rec { +public: auto_vec def_vec; auto_vec use_vec; auto_vec eq_use_vec; diff --git a/gcc/df.h b/gcc/df.h index d76d31b..13358f9 100644 --- a/gcc/df.h +++ b/gcc/df.h @@ -524,8 +524,9 @@ struct df_reg_info used by owners of the problem. ----------------------------------------------------------------------------*/ -struct df_d +class df_d { +public: /* The set of problems to be solved is stored in two arrays. In PROBLEMS_IN_ORDER, the problems are stored in the order that they @@ -830,8 +831,9 @@ struct df_scan_bb_info the ref except sparse_kill which is indexed by regno. For the LR&RD problem, the kill set is not complete: It does not contain DEFs killed because the set register has died in the LR set. */ -struct df_rd_bb_info +class df_rd_bb_info { +public: /* Local sets to describe the basic blocks. */ bitmap_head kill; bitmap_head sparse_kill; @@ -846,8 +848,9 @@ struct df_rd_bb_info /* Multiple reaching definitions. All bitmaps are referenced by the register number. */ -struct df_md_bb_info +class df_md_bb_info { +public: /* Local sets to describe the basic blocks. */ bitmap_head gen; /* Partial/conditional definitions live at BB out. */ bitmap_head kill; /* Other definitions that are live at BB out. */ @@ -862,8 +865,9 @@ struct df_md_bb_info /* Live registers, a backwards dataflow problem. All bitmaps are referenced by the register number. */ -struct df_lr_bb_info +class df_lr_bb_info { +public: /* Local sets to describe the basic blocks. */ bitmap_head def; /* The set of registers set in this block - except artificial defs at the top. */ @@ -879,8 +883,9 @@ struct df_lr_bb_info register number. Anded results of the forwards and backward live info. Note that the forwards live information is not available separately. */ -struct df_live_bb_info +class df_live_bb_info { +public: /* Local sets to describe the basic blocks. */ bitmap_head kill; /* The set of registers unset in this block. Calls, for instance, unset registers. */ @@ -897,8 +902,9 @@ struct df_live_bb_info pseudo. Only pseudos that have a size of 2 * UNITS_PER_WORD are meaningfully tracked. */ -struct df_word_lr_bb_info +class df_word_lr_bb_info { +public: /* Local sets to describe the basic blocks. */ bitmap_head def; /* The set of registers set in this block - except artificial defs at the top. */ @@ -911,8 +917,9 @@ struct df_word_lr_bb_info /* Must-initialized registers. All bitmaps are referenced by the register number. */ -struct df_mir_bb_info +class df_mir_bb_info { +public: /* Local sets to describe the basic blocks. */ bitmap_head kill; /* The set of registers unset in this block. Calls, for instance, unset registers. */ @@ -1222,7 +1229,7 @@ df_single_use (const df_insn_info *info) /* web */ -class web_entry_base +struct web_entry_base { private: /* Reference to the parent in the union/find tree. */ diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c index 89074be..4d563dd 100644 --- a/gcc/diagnostic-show-locus.c +++ b/gcc/diagnostic-show-locus.c @@ -164,8 +164,9 @@ struct line_bounds splits the pertinent source lines into a list of disjoint line_span instances (e.g. lines 5-10, lines 15-20, line 23). */ -struct line_span +class line_span { +public: line_span (linenum_type first_line, linenum_type last_line) : m_first_line (first_line), m_last_line (last_line) { @@ -1409,8 +1410,9 @@ layout::print_annotation_line (linenum_type row, const line_bounds lbounds) A label within the given row of source. */ -struct line_label +class line_label { +public: line_label (int state_idx, int column, label_text text) : m_state_idx (state_idx), m_column (column), m_text (text), m_length (strlen (text.m_buffer)), @@ -1723,8 +1725,9 @@ layout::annotation_line_showed_range_p (linenum_type line, int start_column, /* A range of columns within a line. */ -struct column_range +class column_range { +public: column_range (int start_, int finish_) : start (start_), finish (finish_) { /* We must have either a range, or an insertion. */ @@ -1776,8 +1779,9 @@ get_printed_columns (const fixit_hint *hint) instances that affected the line, potentially consolidating hints into corrections to make the result easier for the user to read. */ -struct correction +class correction { +public: correction (column_range affected_columns, column_range printed_columns, const char *new_text, size_t new_text_len) @@ -1854,8 +1858,9 @@ correction::ensure_terminated () This is used by layout::print_trailing_fixits for planning how to print the fix-it hints affecting the line. */ -struct line_corrections +class line_corrections { +public: line_corrections (const char *filename, linenum_type row) : m_filename (filename), m_row (row) {} @@ -1881,8 +1886,9 @@ line_corrections::~line_corrections () /* A struct wrapping a particular source line, allowing run-time bounds-checking of accesses in a checked build. */ -struct source_line +class source_line { +public: source_line (const char *filename, int line); char_span as_span () { return char_span (chars, width); } diff --git a/gcc/dojump.h b/gcc/dojump.h index ad01929..f4dbc11 100644 --- a/gcc/dojump.h +++ b/gcc/dojump.h @@ -37,8 +37,9 @@ extern void do_pending_stack_adjust (void); /* Struct for saving/restoring of pending_stack_adjust/stack_pointer_delta values. */ -struct saved_pending_stack_adjust +class saved_pending_stack_adjust { +public: /* Saved value of pending_stack_adjust. */ poly_int64 x_pending_stack_adjust; diff --git a/gcc/dse.c b/gcc/dse.c index 6f6f768..a3cefbf 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -220,8 +220,9 @@ static bitmap scratch = NULL; struct insn_info_type; /* This structure holds information about a candidate store. */ -struct store_info +class store_info { +public: /* False means this is a clobber. */ bool is_set; @@ -309,8 +310,9 @@ static object_allocator rtx_store_info_pool ("rtx_store_info_pool"); /* This structure holds information about a load. These are only built for rtx bases. */ -struct read_info_type +class read_info_type { +public: /* The id of the mem group of the base address. */ int group_id; diff --git a/gcc/dump-context.h b/gcc/dump-context.h index b17b86a..bb856c6 100644 --- a/gcc/dump-context.h +++ b/gcc/dump-context.h @@ -166,8 +166,9 @@ public: private: /* Information on an optinfo_item that was generated during phase 2 of formatting. */ - struct stashed_item + class stashed_item { + public: stashed_item (const char **buffer_ptr_, optinfo_item *item_) : buffer_ptr (buffer_ptr_), item (item_) {} const char **buffer_ptr; diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h index 9bcaa25..8614483 100644 --- a/gcc/dumpfile.h +++ b/gcc/dumpfile.h @@ -367,8 +367,9 @@ class dump_user_location_t /* A class for identifying where in the compiler's own source (or a plugin) that a dump message is being emitted from. */ -struct dump_impl_location_t +class dump_impl_location_t { +public: dump_impl_location_t ( #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) const char *file = __builtin_FILE (), diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 2c4cc6c..0449c2b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3104,7 +3104,8 @@ die_node; /* Set to TRUE while dwarf2out_early_global_decl is running. */ static bool early_dwarf; static bool early_dwarf_finished; -struct set_early_dwarf { +class set_early_dwarf { +public: bool saved; set_early_dwarf () : saved(early_dwarf) { diff --git a/gcc/edit-context.c b/gcc/edit-context.c index 93d1066..4cd26c9 100644 --- a/gcc/edit-context.c +++ b/gcc/edit-context.c @@ -48,8 +48,9 @@ class line_event; /* A struct to hold the params of a print_diff call. */ -struct diff +class diff { +public: diff (pretty_printer *pp, bool show_filenames) : m_pp (pp), m_show_filenames (show_filenames) {} diff --git a/gcc/fibonacci_heap.c b/gcc/fibonacci_heap.c index aec6913..bddd047 100644 --- a/gcc/fibonacci_heap.c +++ b/gcc/fibonacci_heap.c @@ -219,8 +219,9 @@ test_union_of_equal_heaps () /* Dummy struct for testing. */ -struct heap_key +class heap_key { +public: heap_key (int k): key (k) { } diff --git a/gcc/flags.h b/gcc/flags.h index 0ea1812..0cc7df2 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -42,8 +42,9 @@ extern bool final_insns_dump_p; /* Other basic status info about current function. */ -struct target_flag_state +class target_flag_state { +public: /* Each falign-foo can generate up to two levels of alignment: -falign-foo=N:M[:N2:M2] */ align_flags x_align_loops; diff --git a/gcc/function.c b/gcc/function.c index 0bce4ec..b44c4d0 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -556,7 +556,8 @@ assign_stack_local (machine_mode mode, poly_int64 size, int align) result, all temporaries are preserved. A temporary is preserved by pretending it was allocated at the previous nesting level. */ -struct GTY(()) temp_slot { +class GTY(()) temp_slot { +public: /* Points to next temporary slot. */ struct temp_slot *next; /* Points to previous temporary slot. */ diff --git a/gcc/function.h b/gcc/function.h index bfe9919..c2596bf 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -183,16 +183,18 @@ struct GTY(()) function_subsections { /* Describe an empty area of space in the stack frame. These can be chained into a list; this is used to keep track of space wasted for alignment reasons. */ -struct GTY(()) frame_space +class GTY(()) frame_space { +public: struct frame_space *next; poly_int64 start; poly_int64 length; }; -struct GTY(()) stack_usage +class GTY(()) stack_usage { +public: /* # of bytes of static stack space allocated by the function. */ HOST_WIDE_INT static_stack_size; diff --git a/gcc/gcc.c b/gcc/gcc.c index 0c0a686..a4323eb 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -57,7 +57,7 @@ compilation is specified by a string called a "spec". */ getenv (); Hence we need to use "get" for the accessor method, not "getenv". */ -class env_manager +struct env_manager { public: void init (bool can_restore, bool debug); @@ -8579,7 +8579,7 @@ static int n_mdswitches; /* Check whether a particular argument was used. The first time we canonicalize the switches to keep only the ones we care about. */ -class used_arg_t +struct used_arg_t { public: int operator () (const char *p, int len); diff --git a/gcc/gcov.c b/gcc/gcov.c index b06a671..1d9d3b2 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -121,8 +121,9 @@ struct arc_info /* Describes which locations (lines and files) are associated with a basic block. */ -struct block_location_info +class block_location_info { +public: block_location_info (unsigned _source_file_idx): source_file_idx (_source_file_idx) {} @@ -134,8 +135,9 @@ struct block_location_info /* Describes a basic block. Contains lists of arcs to successor and predecessor blocks. */ -struct block_info +class block_info { +public: /* Constructor. */ block_info (); @@ -191,8 +193,9 @@ block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0), /* Describes a single line of source. Contains a chain of basic blocks with code on it. */ -struct line_info +class line_info { +public: /* Default constructor. */ line_info (); @@ -230,8 +233,9 @@ static int flag_demangled_names = 0; /* Describes a single function. Contains an array of basic blocks. */ -struct function_info +class function_info { +public: function_info (); ~function_info (); @@ -356,8 +360,9 @@ struct coverage_info /* Describes a file mentioned in the block graph. Contains an array of line info. */ -struct source_info +class source_info { +public: /* Default constructor. */ source_info (); diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 78816ba..604526d 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -133,8 +133,9 @@ static struct obstack *temp_obstack = &obstack2; `struct insn_def'. This is done to allow attribute definitions to occur anywhere in the file. */ -struct insn_def +class insn_def { +public: struct insn_def *next; /* Next insn in chain. */ rtx def; /* The DEFINE_... */ int insn_code; /* Instruction number. */ @@ -169,8 +170,9 @@ struct attr_value /* Structure for each attribute. */ -struct attr_desc +class attr_desc { +public: char *name; /* Name of attribute. */ const char *enum_name; /* Enum name for DEFINE_ENUM_NAME. */ struct attr_desc *next; /* Next attribute. */ @@ -184,8 +186,9 @@ struct attr_desc /* Structure for each DEFINE_DELAY. */ -struct delay_desc +class delay_desc { +public: rtx def; /* DEFINE_DELAY expression. */ struct delay_desc *next; /* Next DEFINE_DELAY. */ file_location loc; /* Where in the .md files it occurs. */ diff --git a/gcc/genextract.c b/gcc/genextract.c index b26f56a..66886f6 100644 --- a/gcc/genextract.c +++ b/gcc/genextract.c @@ -68,8 +68,9 @@ static struct code_ptr *peepholes; data that will be used to produce an extractions structure. */ -struct accum_extract +class accum_extract { +public: accum_extract () : oplocs (10), duplocs (10), dupnums (10), pathstr (20) {} auto_vec oplocs; diff --git a/gcc/genmatch.c b/gcc/genmatch.c index 109bd9e..7403ccb 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -347,8 +347,9 @@ comparison_code_p (enum tree_code code) /* Base class for all identifiers the parser knows. */ -struct id_base : nofree_ptr_hash +class id_base : public nofree_ptr_hash { +public: enum id_kind { CODE, FN, PREDICATE, USER, NULL_ID } kind; id_base (id_kind, const char *, int = -1); @@ -393,8 +394,9 @@ id_base::id_base (id_kind kind_, const char *id_, int nargs_) /* Identifier that maps to a tree code. */ -struct operator_id : public id_base +class operator_id : public id_base { +public: operator_id (enum tree_code code_, const char *id_, unsigned nargs_, const char *tcc_) : id_base (id_base::CODE, id_, nargs_), code (code_), tcc (tcc_) {} @@ -404,8 +406,9 @@ struct operator_id : public id_base /* Identifier that maps to a builtin or internal function code. */ -struct fn_id : public id_base +class fn_id : public id_base { +public: fn_id (enum built_in_function fn_, const char *id_) : id_base (id_base::FN, id_), fn (fn_) {} fn_id (enum internal_fn fn_, const char *id_) @@ -417,8 +420,9 @@ struct simplify; /* Identifier that maps to a user-defined predicate. */ -struct predicate_id : public id_base +class predicate_id : public id_base { +public: predicate_id (const char *id_) : id_base (id_base::PREDICATE, id_), matchers (vNULL) {} vec matchers; @@ -426,8 +430,9 @@ struct predicate_id : public id_base /* Identifier that maps to a operator defined by a 'for' directive. */ -struct user_id : public id_base +class user_id : public id_base { +public: user_id (const char *id_, bool is_oper_list_ = false) : id_base (id_base::USER, id_), substitutes (vNULL), used (false), is_oper_list (is_oper_list_) {} @@ -665,7 +670,8 @@ struct capture_info; /* The base class for operands. */ -struct operand { +class operand { +public: enum op_type { OP_PREDICATE, OP_EXPR, OP_CAPTURE, OP_C_EXPR, OP_IF, OP_WITH }; operand (enum op_type type_, location_t loc_) : type (type_), location (loc_) {} @@ -680,8 +686,9 @@ struct operand { /* A predicate operand. Predicates are leafs in the AST. */ -struct predicate : public operand +class predicate : public operand { +public: predicate (predicate_id *p_, location_t loc) : operand (OP_PREDICATE, loc), p (p_) {} predicate_id *p; @@ -690,8 +697,9 @@ struct predicate : public operand /* An operand that constitutes an expression. Expressions include function calls and user-defined predicate invocations. */ -struct expr : public operand +class expr : public operand { +public: expr (id_base *operation_, location_t loc, bool is_commutative_ = false) : operand (OP_EXPR, loc), operation (operation_), ops (vNULL), expr_type (NULL), is_commutative (is_commutative_), @@ -723,11 +731,13 @@ struct expr : public operand a leaf operand in the AST. This class is also used to represent the code to be generated for 'if' and 'with' expressions. */ -struct c_expr : public operand +class c_expr : public operand { +public: /* A mapping of an identifier and its replacement. Used to apply 'for' lowering. */ - struct id_tab { + class id_tab { + public: const char *id; const char *oper; id_tab (const char *id_, const char *oper_): id (id_), oper (oper_) {} @@ -753,8 +763,9 @@ struct c_expr : public operand /* A wrapper around another operand that captures its value. */ -struct capture : public operand +class capture : public operand { +public: capture (location_t loc, unsigned where_, operand *what_, bool value_) : operand (OP_CAPTURE, loc), where (where_), value_match (value_), what (what_) {} @@ -773,8 +784,9 @@ struct capture : public operand /* if expression. */ -struct if_expr : public operand +class if_expr : public operand { +public: if_expr (location_t loc) : operand (OP_IF, loc), cond (NULL), trueexpr (NULL), falseexpr (NULL) {} c_expr *cond; @@ -784,8 +796,9 @@ struct if_expr : public operand /* with expression. */ -struct with_expr : public operand +class with_expr : public operand { +public: with_expr (location_t loc) : operand (OP_WITH, loc), with (NULL), subexpr (NULL) {} c_expr *with; @@ -845,8 +858,9 @@ is_a_helper ::test (operand *op) duplicates all outer 'if' and 'for' expressions here so each simplify can exist in isolation. */ -struct simplify +class simplify { +public: enum simplify_kind { SIMPLIFY, MATCH }; simplify (simplify_kind kind_, unsigned id_, operand *match_, @@ -1598,8 +1612,9 @@ static unsigned current_id; /* Decision tree base class, used for DT_NODE. */ -struct dt_node +class dt_node { +public: enum dt_type { DT_NODE, DT_OPERAND, DT_TRUE, DT_MATCH, DT_SIMPLIFY }; enum dt_type type; @@ -1634,8 +1649,9 @@ struct dt_node /* Generic decision tree node used for DT_OPERAND, DT_MATCH and DT_TRUE. */ -struct dt_operand : public dt_node +class dt_operand : public dt_node { +public: operand *op; dt_operand *match_dop; unsigned pos; @@ -1660,8 +1676,9 @@ struct dt_operand : public dt_node /* Leaf node of the decision tree, used for DT_SIMPLIFY. */ -struct dt_simplify : public dt_node +class dt_simplify : public dt_node { +public: simplify *s; unsigned pattern_no; dt_operand **indexes; @@ -1697,8 +1714,9 @@ is_a_helper ::test (dt_node *n) /* A container for the actual decision tree. */ -struct decision_tree +class decision_tree { +public: dt_node *root; void insert (struct simplify *, unsigned); @@ -2070,8 +2088,9 @@ decision_tree::print (FILE *f) on the outermost match expression operands for cases we cannot handle. */ -struct capture_info +class capture_info { +public: capture_info (simplify *s, operand *, bool); void walk_match (operand *o, unsigned toplevel_arg, bool, bool); bool walk_result (operand *o, bool, operand *); diff --git a/gcc/genoutput.c b/gcc/genoutput.c index 37ee509..ab4c46a 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -143,8 +143,9 @@ static struct operand_data **odata_end = &null_operand.next; /* Record in this chain all information that we will output, associated with the code number of the insn. */ -struct data +class data { +public: struct data *next; const char *name; const char *template_code; @@ -179,8 +180,9 @@ static void process_template (struct data *, const char *); static void validate_insn_alternatives (struct data *); static void validate_insn_operands (struct data *); -struct constraint_data +class constraint_data { +public: struct constraint_data *next_this_letter; file_location loc; unsigned int namelen; diff --git a/gcc/genpreds.c b/gcc/genpreds.c index 19b7dcb..293930c 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -666,8 +666,9 @@ write_one_predicate_function (struct pred_data *p) verify that there are no duplicate names. */ /* All data from one constraint definition. */ -struct constraint_data +class constraint_data { +public: struct constraint_data *next_this_letter; struct constraint_data *next_textual; const char *name; diff --git a/gcc/genrecog.c b/gcc/genrecog.c index 90e2508..a3b8e68 100644 --- a/gcc/genrecog.c +++ b/gcc/genrecog.c @@ -818,11 +818,13 @@ validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code) to "T *prev, *next;" and a function "void set_parent (list_head *)" to set the parent list. */ template -struct list_head +class list_head { +public: /* A range of linked items. */ - struct range + class range { + public: range (T *); range (T *, T *); @@ -1008,8 +1010,9 @@ operator != (const acceptance_type &a, const acceptance_type &b) } /* Represents a parameter to a pattern routine. */ -struct parameter +class parameter { +public: /* The C type of parameter. */ enum type_enum { /* Represents an invalid parameter. */ @@ -1069,8 +1072,9 @@ operator != (const parameter ¶m1, const parameter ¶m2) an ad-hoc enum value on success and -1 on failure. The routine can be used by any subroutine type. The match can be parameterized by things like mode, code and UNSPEC number. */ -struct pattern_routine +class pattern_routine { +public: /* The state that implements the pattern. */ state *s; @@ -1096,8 +1100,9 @@ struct pattern_routine static vec patterns; /* Represents one use of a pattern routine. */ -struct pattern_use +class pattern_use { +public: /* The pattern routine to use. */ pattern_routine *routine; @@ -1107,8 +1112,9 @@ struct pattern_use }; /* Represents a test performed by a decision. */ -struct rtx_test +class rtx_test { +public: rtx_test (); /* The types of test that can be performed. Most of them take as input @@ -1427,8 +1433,9 @@ operator != (const rtx_test &a, const rtx_test &b) /* A simple set of transition labels. Most transitions have a singleton label, so try to make that case as efficient as possible. */ -struct int_set : public auto_vec +class int_set : public auto_vec { +public: typedef uint64_t *iterator; int_set (); @@ -1496,8 +1503,9 @@ struct decision; /* Represents a transition between states, dependent on the result of a test T. */ -struct transition +class transition { +public: transition (const int_set &, state *, bool); void set_parent (list_head *); @@ -1536,8 +1544,9 @@ struct transition to the transition's target state. If no suitable transition exists, the machine either falls through to the next decision or, if there are no more decisions to try, fails the match. */ -struct decision : list_head +class decision : public list_head { +public: decision (const rtx_test &); void set_parent (list_head *s); @@ -1556,8 +1565,9 @@ struct decision : list_head /* Represents one machine state. For each state the machine tries a list of decisions, in order, and acts on the first match. It fails without further backtracking if no decisions match. */ -struct state : list_head +class state : public list_head { +public: void set_parent (list_head *) {} }; @@ -1767,8 +1777,9 @@ const unsigned char TESTED_CODE = 1; const unsigned char TESTED_VECLEN = 2; /* Represents a set of conditions that are known to hold. */ -struct known_conditions +class known_conditions { +public: /* A mask of TESTED_ values for each position, indexed by the position's id field. */ auto_vec position_tests; @@ -2095,8 +2106,9 @@ find_operand_positions (state *s, vec &operand_pos) } /* Statistics about a matching routine. */ -struct stats +class stats { +public: stats (); /* The total number of decisions in the routine, excluding trivial @@ -2235,8 +2247,9 @@ optimize_subroutine_group (const char *type, state *root) struct merge_pattern_info; /* Represents a transition from one pattern to another. */ -struct merge_pattern_transition +class merge_pattern_transition { +public: merge_pattern_transition (merge_pattern_info *); /* The target pattern. */ @@ -2256,8 +2269,9 @@ merge_pattern_transition::merge_pattern_transition (merge_pattern_info *to_in) /* Represents a pattern that can might match several states. The pattern may replace parts of the test with a parameter value. It may also replace transition labels with parameters. */ -struct merge_pattern_info +class merge_pattern_info { +public: merge_pattern_info (unsigned int); /* If PARAM_TEST_P, the state's singleton test should be generalized @@ -2329,8 +2343,9 @@ merge_pattern_info::merge_pattern_info (unsigned int num_transitions) /* Describes one way of matching a particular state to a particular pattern. */ -struct merge_state_result +class merge_state_result { +public: merge_state_result (merge_pattern_info *, position *, merge_state_result *); /* A pattern that matches the state. */ @@ -2360,8 +2375,9 @@ merge_state_result::merge_state_result (merge_pattern_info *pattern_in, /* Information about a state, used while trying to match it against a pattern. */ -struct merge_state_info +class merge_state_info { +public: merge_state_info (state *); /* The state itself. */ @@ -3860,7 +3876,8 @@ merge_into_state (state *s1, state *s2) /* Pairs a pattern that needs to be matched with the rtx position at which the pattern should occur. */ -struct pattern_pos { +class pattern_pos { +public: pattern_pos () {} pattern_pos (rtx, position *); @@ -4384,8 +4401,9 @@ enum exit_state { /* Information used while writing out code. */ -struct output_state +class output_state { +public: /* The type of routine that we're generating. */ routine_type type; diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 0150346..07aa839 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -65,8 +65,9 @@ static htab_t condition_table; define_cond_exec and define_subst patterns, then return them one at a time. */ -struct queue_elem +class queue_elem { +public: rtx data; file_location loc; struct queue_elem *next; diff --git a/gcc/gensupport.h b/gcc/gensupport.h index 5c43203..10a5c7a 100644 --- a/gcc/gensupport.h +++ b/gcc/gensupport.h @@ -26,7 +26,8 @@ struct obstack; extern struct obstack *rtl_obstack; /* Information about an .md define_* rtx. */ -struct md_rtx_info { +class md_rtx_info { +public: /* The rtx itself. */ rtx def; diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c index 6fb5a3d..0968d97 100644 --- a/gcc/ggc-common.c +++ b/gcc/ggc-common.c @@ -818,8 +818,9 @@ init_ggc_heuristics (void) } /* GGC memory usage. */ -struct ggc_usage: public mem_usage +class ggc_usage: public mem_usage { +public: /* Default constructor. */ ggc_usage (): m_freed (0), m_collected (0), m_overhead (0) {} /* Constructor. */ diff --git a/gcc/ggc-tests.c b/gcc/ggc-tests.c index 752f446..1ea5e4c 100644 --- a/gcc/ggc-tests.c +++ b/gcc/ggc-tests.c @@ -176,8 +176,9 @@ test_union () /* Verify that destructors get run when instances are collected. */ -struct GTY(()) test_struct_with_dtor +class GTY(()) test_struct_with_dtor { +public: /* This struct has a destructor; it *ought* to be called by the ggc machinery when instances are collected. */ ~test_struct_with_dtor () { dtor_call_count++; } diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc index b188ce8..1324489 100644 --- a/gcc/gimple-loop-interchange.cc +++ b/gcc/gimple-loop-interchange.cc @@ -172,8 +172,9 @@ dump_induction (struct loop *loop, induction_p iv) /* Loop candidate for interchange. */ -struct loop_cand +class loop_cand { +public: loop_cand (struct loop *, struct loop *); ~loop_cand (); diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc index fe27300..468f586 100644 --- a/gcc/gimple-loop-versioning.cc +++ b/gcc/gimple-loop-versioning.cc @@ -179,8 +179,9 @@ struct address_term_info /* Information about an address calculation, and the range of constant offsets applied to it. */ -struct address_info +class address_info { +public: static const unsigned int MAX_TERMS = 8; /* One statement that calculates the address. If multiple statements @@ -210,8 +211,9 @@ struct address_info_hasher : nofree_ptr_hash }; /* Information about the versioning we'd like to apply to a loop. */ -struct loop_info +class loop_info { +public: bool worth_versioning_p () const; /* True if we've decided not to version this loop. The remaining diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h index ad7f730..ea0f66f 100644 --- a/gcc/gimple-match.h +++ b/gcc/gimple-match.h @@ -43,8 +43,9 @@ private: /* Represents the condition under which an operation should happen, and the value to use otherwise. The condition applies elementwise (as for VEC_COND_EXPR) if the values are vectors. */ -struct gimple_match_cond +class gimple_match_cond { +public: enum uncond { UNCOND }; /* Build an unconditional op. */ @@ -79,8 +80,9 @@ gimple_match_cond::any_else () const /* Represents an operation to be simplified, or the result of the simplification. */ -struct gimple_match_op +class gimple_match_op { +public: gimple_match_op (); gimple_match_op (const gimple_match_cond &, code_helper, tree, unsigned int); gimple_match_op (const gimple_match_cond &, diff --git a/gcc/gimple-ssa-backprop.c b/gcc/gimple-ssa-backprop.c index 30fb7cb..0aeac4e 100644 --- a/gcc/gimple-ssa-backprop.c +++ b/gcc/gimple-ssa-backprop.c @@ -107,8 +107,9 @@ along with GCC; see the file COPYING3. If not see namespace { /* Information about a group of uses of an SSA name. */ -struct usage_info +class usage_info { +public: usage_info () : flag_word (0) {} usage_info &operator &= (const usage_info &); usage_info operator & (const usage_info &) const; diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index a0934bc..6ba3d86 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -520,8 +520,9 @@ enum format_lengths /* Description of the result of conversion either of a single directive or the whole format string. */ -struct fmtresult +class fmtresult { +public: /* Construct a FMTRESULT object with all counters initialized to MIN. KNOWNRANGE is set when MIN is valid. */ fmtresult (unsigned HOST_WIDE_INT min = HOST_WIDE_INT_MAX) diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 5a93830..1f50e3a 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -1324,8 +1324,9 @@ namespace { and the other fields also reflect the memory load, or an SSA name, then VAL represents the SSA name and all the other fields are zero, */ -struct store_operand_info +class store_operand_info { +public: tree val; tree base_addr; poly_uint64 bitsize; @@ -1347,8 +1348,9 @@ store_operand_info::store_operand_info () to memory. These are created in the first phase and coalesced into merged_store_group objects in the second phase. */ -struct store_immediate_info +class store_immediate_info { +public: unsigned HOST_WIDE_INT bitsize; unsigned HOST_WIDE_INT bitpos; unsigned HOST_WIDE_INT bitregion_start; @@ -1413,8 +1415,9 @@ store_immediate_info::store_immediate_info (unsigned HOST_WIDE_INT bs, These are produced by the second phase (coalescing) and consumed in the third phase that outputs the widened stores. */ -struct merged_store_group +class merged_store_group { +public: unsigned HOST_WIDE_INT start; unsigned HOST_WIDE_INT width; unsigned HOST_WIDE_INT bitregion_start; @@ -2083,8 +2086,9 @@ merged_store_group::apply_stores () /* Structure describing the store chain. */ -struct imm_store_chain_info +class imm_store_chain_info { +public: /* Doubly-linked list that imposes an order on chain processing. PNXP (prev's next pointer) points to the head of a list, or to the next field in the previous chain in the list. @@ -3064,8 +3068,9 @@ get_location_for_stmts (vec &stmts) /* Used to decribe a store resulting from splitting a wide store in smaller regularly-sized stores in split_group. */ -struct split_store +class split_store { +public: unsigned HOST_WIDE_INT bytepos; unsigned HOST_WIDE_INT size; unsigned HOST_WIDE_INT align; diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index bfda44a..aa5a856 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -226,8 +226,9 @@ enum cand_kind CAND_PHI }; -struct slsr_cand_d +class slsr_cand_d { +public: /* The candidate statement S1. */ gimple *cand_stmt; @@ -329,8 +330,9 @@ typedef const struct cand_chain_d *const_cand_chain_t; of the cost of initializers. The absolute value of the increment is stored in the incr_info. */ -struct incr_info_d +class incr_info_d { +public: /* The increment that relates a candidate to its basis. */ widest_int incr; diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c index d804146..73726c1 100644 --- a/gcc/gimple-ssa-warn-alloca.c +++ b/gcc/gimple-ssa-warn-alloca.c @@ -118,7 +118,8 @@ enum alloca_type { }; // Type of an alloca call with its corresponding limit, if applicable. -struct alloca_type_and_limit { +class alloca_type_and_limit { +public: enum alloca_type type; // For ALLOCA_BOUND_MAYBE_LARGE and ALLOCA_BOUND_DEFINITELY_LARGE // types, this field indicates the assumed limit if known or diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index 0c571ef..64175f2 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -124,8 +124,9 @@ pass_wrestrict::execute (function *fun) /* Description of a memory reference by a built-in function. This is similar to ao_ref but made especially suitable for -Wrestrict and not for optimization. */ -struct builtin_memref +class builtin_memref { +public: /* The original pointer argument to the built-in function. */ tree ptr; /* The referenced subobject or NULL if not available, and the base diff --git a/gcc/godump.c b/gcc/godump.c index 617a9648..39cce5e 100644 --- a/gcc/godump.c +++ b/gcc/godump.c @@ -535,8 +535,9 @@ go_type_decl (tree decl, int local) /* A container for the data we pass around when generating information at the end of the compilation. */ -struct godump_container +class godump_container { +public: /* DECLs that we have already seen. */ hash_set decls_seen; diff --git a/gcc/hash-map-tests.c b/gcc/hash-map-tests.c index 5888f25..f3b216b 100644 --- a/gcc/hash-map-tests.c +++ b/gcc/hash-map-tests.c @@ -103,8 +103,9 @@ test_map_of_strings_to_int () ASSERT_EQ (1, string_map.elements ()); } -typedef struct hash_map_test_val_t +typedef class hash_map_test_val_t { +public: static int ndefault; static int ncopy; static int nassign; diff --git a/gcc/hash-map.h b/gcc/hash-map.h index f3f1f9a..ba20fe7 100644 --- a/gcc/hash-map.h +++ b/gcc/hash-map.h @@ -253,7 +253,8 @@ public: /* Can't use std::pair here, because GCC before 4.3 don't handle std::pair where template parameters are references well. See PR86739. */ - struct reference_pair { + class reference_pair { + public: const Key &first; Value &second; diff --git a/gcc/hash-set-tests.c b/gcc/hash-set-tests.c index c96fe53..ce59059 100644 --- a/gcc/hash-set-tests.c +++ b/gcc/hash-set-tests.c @@ -134,8 +134,9 @@ test_set_of_strings () ASSERT_EQ (2, t.elements ()); } -typedef struct hash_set_test_value_t +typedef class hash_set_test_value_t { +public: static int ndefault; static int ncopy; static int nassign; diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c index 016e61f..424eac7 100644 --- a/gcc/hsa-brig.c +++ b/gcc/hsa-brig.c @@ -195,8 +195,9 @@ hash_table *hsa_emitted_internal_decls; /* List of sbr instructions. */ static vec *switch_instructions; -struct function_linkage_pair +class function_linkage_pair { +public: function_linkage_pair (tree decl, unsigned int off) : function_decl (decl), offset (off) {} diff --git a/gcc/hsa-common.h b/gcc/hsa-common.h index 9c61786..121c4ea 100644 --- a/gcc/hsa-common.h +++ b/gcc/hsa-common.h @@ -55,8 +55,9 @@ class hsa_bb; /* Class representing an input argument, output argument (result) or a variable, that will eventually end up being a symbol directive. */ -struct hsa_symbol +class hsa_symbol { +public: /* Constructor. */ hsa_symbol (BrigType16_t type, BrigSegment8_t segment, BrigLinkage8_t linkage, bool global_scope_p = false, @@ -1213,8 +1214,9 @@ enum hsa_function_kind HSA_FUNCTION }; -struct hsa_function_summary +class hsa_function_summary { +public: /* Default constructor. */ hsa_function_summary (); diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index f52c49c..54d98a5 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -6213,8 +6213,9 @@ transformable_switch_to_sbr_p (gswitch *s) /* Structure hold connection between PHI nodes and immediate values hold by there nodes. */ -struct phi_definition +class phi_definition { +public: phi_definition (unsigned phi_i, unsigned label_i, tree imm): phi_index (phi_i), label_index (label_i), phi_value (imm) {} diff --git a/gcc/input.c b/gcc/input.c index 1e84d2e..baab42a 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -32,11 +32,13 @@ along with GCC; see the file COPYING3. If not see /* This is a cache used by get_next_line to store the content of a file to be searched for file lines. */ -struct fcache +class fcache { +public: /* These are information used to store a line boundary. */ - struct line_info + class line_info { + public: /* The line number. It starts from 1. */ size_t line_num; @@ -1691,8 +1693,9 @@ assert_loceq (const char *exp_filename, int exp_linenum, int exp_colnum, The following struct describes a particular case within our test matrix. */ -struct line_table_case +class line_table_case { +public: line_table_case (int default_range_bits, int base_location) : m_default_range_bits (default_range_bits), m_base_location (base_location) @@ -2085,8 +2088,9 @@ class cpp_reader_ptr /* A struct for writing lexer tests. */ -struct lexer_test +class lexer_test { +public: lexer_test (const line_table_case &case_, const char *content, lexer_test_options *options); ~lexer_test (); diff --git a/gcc/input.h b/gcc/input.h index 3c7cf36..3e03820 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -175,8 +175,9 @@ void diagnostics_file_cache_fini (void); void diagnostics_file_cache_forcibly_evict_file (const char *file_path); -struct GTY(()) string_concat +class GTY(()) string_concat { +public: string_concat (int num, location_t *locs); int m_num; diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index b6e781f..e62a9a0 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -130,7 +130,7 @@ template class ipcp_value; /* Describes a particular source for an IPA-CP value. */ template -class ipcp_value_source +struct ipcp_value_source { public: /* Aggregate offset of the source, negative if the source is scalar value of @@ -209,7 +209,7 @@ public: contains_variable flag should be disregarded. */ template -class ipcp_lattice +struct ipcp_lattice { public: /* The list of known values and types in this lattice. Note that values are @@ -236,7 +236,7 @@ public: /* Lattice of tree values with an offset to describe a part of an aggregate. */ -class ipcp_agg_lattice : public ipcp_lattice +struct ipcp_agg_lattice : public ipcp_lattice { public: /* Offset that is being described by this lattice. */ @@ -3385,8 +3385,9 @@ static call_summary *edge_clone_summaries = NULL; /* Edge clone summary. */ -struct edge_clone_summary +class edge_clone_summary { +public: /* Default constructor. */ edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {} diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 252d920..a5e3a63 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -2626,8 +2626,9 @@ possible_polymorphic_call_targets_1 (vec &nodes, polymorphic calls in the program, so we memoize all the previous queries and avoid duplicated work. */ -struct polymorphic_call_target_d +class polymorphic_call_target_d { +public: HOST_WIDE_INT otr_token; ipa_polymorphic_call_context context; odr_type type; @@ -2949,8 +2950,9 @@ struct decl_warn_count /* Information about type and decl warnings. */ -struct final_warning_record +class final_warning_record { +public: /* If needed grow type_warnings vector and initialize new decl_warn_count to have dyn_count set to profile_count::zero (). */ void grow_type_warnings (unsigned newlen); diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h index 0f08e84..7b07704 100644 --- a/gcc/ipa-fnsummary.h +++ b/gcc/ipa-fnsummary.h @@ -72,8 +72,9 @@ struct agg_position_info /* Representation of function body size and time depending on the call context. We keep simple array of record, every containing of predicate and time/size to account. */ -struct GTY(()) size_time_entry +class GTY(()) size_time_entry { +public: /* Predicate for code to be executed. */ predicate exec_predicate; /* Predicate for value to be constant and optimized out in a specialized copy. @@ -85,8 +86,9 @@ struct GTY(()) size_time_entry }; /* Function inlining information. */ -struct GTY(()) ipa_fn_summary +class GTY(()) ipa_fn_summary { +public: /* Keep all field empty so summary dumping works during its computation. This is useful for debugging. */ ipa_fn_summary () @@ -205,8 +207,9 @@ extern GTY(()) fast_function_summary *ipa_fn_summaries; /* Information kept about callgraph edges. */ -struct ipa_call_summary +class ipa_call_summary { +public: /* Keep all field empty so summary dumping works during its computation. This is useful for debugging. */ ipa_call_summary () diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h index f6eb677..18c8e1e 100644 --- a/gcc/ipa-inline.h +++ b/gcc/ipa-inline.h @@ -23,8 +23,9 @@ along with GCC; see the file COPYING3. If not see /* Data we cache about callgraph edges during inlining to avoid expensive re-computations during the greedy algorithm. */ -struct edge_growth_cache_entry +class edge_growth_cache_entry { +public: sreal time, nonspec_time; int size; ipa_hints hints; diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 7257a6d..7605911 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -144,8 +144,9 @@ struct GTY(()) ipa_agg_jump_function typedef struct ipa_agg_jump_function *ipa_agg_jump_function_p; /* Information about zero/non-zero bits. */ -struct GTY(()) ipa_bits +class GTY(()) ipa_bits { +public: /* The propagated value. */ widest_int value; /* Mask corresponding to the value. @@ -156,8 +157,9 @@ struct GTY(()) ipa_bits /* Info about value ranges. */ -struct GTY(()) ipa_vr +class GTY(()) ipa_vr { +public: /* The data fields below are valid only if known is true. */ bool known; enum value_range_kind type; @@ -319,8 +321,9 @@ struct GTY(()) ipa_param_descriptor and some other information for interprocedural passes that operate on parameters (such as ipa-cp). */ -struct GTY((for_user)) ipa_node_params +class GTY((for_user)) ipa_node_params { +public: /* Default constructor. */ ipa_node_params (); diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 5eaf825..44ae2c7 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -108,8 +108,9 @@ along with GCC; see the file COPYING3. If not see /* Per basic block info. */ -struct split_bb_info +class split_bb_info { +public: unsigned int size; sreal time; }; @@ -118,8 +119,9 @@ static vec bb_info_vec; /* Description of split point. */ -struct split_point +class split_point { +public: /* Size of the partitions. */ sreal header_time, split_time; unsigned int header_size, split_size; @@ -979,8 +981,9 @@ visit_bb (basic_block bb, basic_block return_bb, /* Stack entry for recursive DFS walk in find_split_point. */ -struct stack_entry +class stack_entry { +public: /* Basic block we are examining. */ basic_block bb; diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 1ea35f7..08848f0 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -597,8 +597,9 @@ extern int ira_copies_num; /* The following structure describes a stack slot used for spilled pseudo-registers. */ -struct ira_spilled_reg_stack_slot +class ira_spilled_reg_stack_slot { +public: /* pseudo-registers assigned to the stack slot. */ bitmap_head spilled_regs; /* RTL representation of the stack slot. */ @@ -774,7 +775,8 @@ minmax_set_iter_next (minmax_set_iterator *i) minmax_set_iter_cond (&(ITER), &(N)); \ minmax_set_iter_next (&(ITER))) -struct target_ira_int { +class target_ira_int { +public: ~target_ira_int (); void free_ira_costs (); diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index b880ead..4fc73d4 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -58,8 +58,9 @@ along with GCC; see the file COPYING3. If not see /* The data stored for the loop. */ -struct loop_data +class loop_data { +public: struct loop *outermost_exit; /* The outermost exit of the loop. */ bool has_call; /* True if the loop contains a call. */ /* Maximal register pressure inside loop for given register class diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c index 207b5e2..f078a68 100644 --- a/gcc/loop-iv.c +++ b/gcc/loop-iv.c @@ -85,8 +85,9 @@ enum iv_grd_result /* Information about a biv. */ -struct biv_entry +class biv_entry { +public: unsigned regno; /* The register of the biv. */ struct rtx_iv iv; /* Value of the biv. */ }; diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c index 051839a..e583bca 100644 --- a/gcc/lra-eliminations.c +++ b/gcc/lra-eliminations.c @@ -71,8 +71,9 @@ along with GCC; see the file COPYING3. If not see /* This structure is used to record information about hard register eliminations. */ -struct lra_elim_table +class lra_elim_table { +public: /* Hard register number to be eliminated. */ int from; /* Hard register number used as replacement. */ diff --git a/gcc/lra-int.h b/gcc/lra-int.h index d0a8fac..cc47c4d 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -64,8 +64,9 @@ struct lra_copy }; /* Common info about a register (pseudo or hard register). */ -struct lra_reg +class lra_reg { +public: /* Bitmap of UIDs of insns (including debug insns) referring the reg. */ bitmap_head insn_bitmap; @@ -210,8 +211,9 @@ struct lra_static_insn_data /* LRA internal info about an insn (LRA internal insn representation). */ -struct lra_insn_recog_data +class lra_insn_recog_data { +public: /* The insn code. */ int icode; /* The alternative should be used for the insn, LRA_UNKNOWN_ALT if diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index 55b2adc..975e523 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -384,8 +384,9 @@ mark_regno_dead (int regno, machine_mode mode) /* Structure describing local BB data used for pseudo live-analysis. */ -struct bb_data_pseudos +class bb_data_pseudos { +public: /* Basic block about which the below data are. */ basic_block bb; bitmap_head killed_pseudos; /* pseudos killed in the BB. */ diff --git a/gcc/lra-remat.c b/gcc/lra-remat.c index 1083811..51d3543 100644 --- a/gcc/lra-remat.c +++ b/gcc/lra-remat.c @@ -124,8 +124,9 @@ static cand_t *regno_cands; /* Data about basic blocks used for the rematerialization sub-pass. */ -struct remat_bb_data +class remat_bb_data { +public: /* Basic block about which the below data are. */ basic_block bb; /* Registers changed in the basic block: */ diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index c19b76a..5db94dc 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -97,8 +97,9 @@ static struct pseudo_slot *pseudo_slots; /* The structure describes a register or a stack slot which can be used for several spilled pseudos. */ -struct slot +class slot { +public: /* First pseudo with given stack slot. */ int regno; /* Hard reg into which the slot pseudos are spilled. The value is diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index f1593d6..d5dbeb7 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -735,8 +735,9 @@ struct output_block /* Data and descriptors used when reading from an LTO file. */ -struct data_in +class data_in { +public: /* The global decls and types. */ struct lto_file_decl_data *file_data; diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 871598c..f3796f5 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Martin Sebor + + PR c++/61339 + * lto-dump.c: Change class-key from class to struct and vice versa + to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. + 2019-07-04 Martin Liska PR lto/91078 diff --git a/gcc/lto/lto-dump.c b/gcc/lto/lto-dump.c index e9de33c..262f9f2 100644 --- a/gcc/lto/lto-dump.c +++ b/gcc/lto/lto-dump.c @@ -38,8 +38,9 @@ along with GCC; see the file COPYING3. If not see /* Stores details of symbols for dumping symbol list. */ -struct symbol_entry +class symbol_entry { +public: symtab_node *node; symbol_entry (symtab_node *node_): node (node_) {} @@ -70,8 +71,9 @@ struct symbol_entry /* Stores variable specific details of symbols for dumping symbol list. */ -struct variable_entry: public symbol_entry +class variable_entry: public symbol_entry { +public: variable_entry (varpool_node *node_): symbol_entry (node_) {} @@ -100,8 +102,9 @@ struct variable_entry: public symbol_entry /* Stores function specific details of symbols for dumping symbol list. */ -struct function_entry: public symbol_entry +class function_entry: public symbol_entry { +public: function_entry (cgraph_node *node_): symbol_entry (node_) {} diff --git a/gcc/mem-stats.h b/gcc/mem-stats.h index 7796059..9ceb9cc 100644 --- a/gcc/mem-stats.h +++ b/gcc/mem-stats.h @@ -31,8 +31,9 @@ class hash_map; #define LOCATION_LINE_WIDTH 48 /* Memory allocation location. */ -struct mem_location +class mem_location { +public: /* Default constructor. */ inline mem_location () {} @@ -123,8 +124,9 @@ struct mem_location }; /* Memory usage register to a memory location. */ -struct mem_usage +class mem_usage { +public: /* Default constructor. */ mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {} @@ -260,8 +262,9 @@ struct mem_usage /* Memory usage pair that connectes memory usage and number of allocated bytes. */ template -struct mem_usage_pair +class mem_usage_pair { +public: mem_usage_pair (T *usage_, size_t allocated_): usage (usage_), allocated (allocated_) {} diff --git a/gcc/omp-grid.c b/gcc/omp-grid.c index 1ff65aa..898d73f 100644 --- a/gcc/omp-grid.c +++ b/gcc/omp-grid.c @@ -83,8 +83,9 @@ omp_grid_lastprivate_predicate (struct omp_for_data *fd) /* Structure describing the basic properties of the loop we ara analyzing whether it can be gridified and when it is gridified. */ -struct grid_prop +class grid_prop { +public: /* True when we are doing tiling gridification, i.e. when there is a distinct distribute loop over groups and a loop construct over work-items. False when distribute and parallel for loops form a combined construct. */ diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 3fe466f..a855c5b 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3777,7 +3777,8 @@ omp_clause_aligned_alignment (tree clause) /* This structure is part of the interface between lower_rec_simd_input_clauses and lower_rec_input_clauses. */ -struct omplow_simd_context { +class omplow_simd_context { +public: omplow_simd_context () { memset (this, 0, sizeof (*this)); } tree idx; tree lane; diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h index b0f50a9..d998fca 100644 --- a/gcc/optabs-query.h +++ b/gcc/optabs-query.h @@ -144,8 +144,9 @@ get_vcond_eq_icode (machine_mode vmode, machine_mode cmode) enum extraction_pattern { EP_insv, EP_extv, EP_extzv }; /* Describes an instruction that inserts or extracts a bitfield. */ -struct extraction_insn +class extraction_insn { +public: /* The code of the instruction. */ enum insn_code icode; diff --git a/gcc/optabs.h b/gcc/optabs.h index 17b5dfb..ca7e063 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -41,7 +41,8 @@ enum expand_operand_type { }; /* Information about an operand for instruction expansion. */ -struct expand_operand { +class expand_operand { +public: /* The type of operand. */ ENUM_BITFIELD (expand_operand_type) type : 8; diff --git a/gcc/opts.c b/gcc/opts.c index b38bfb1..46a19a2 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1282,8 +1282,9 @@ wrap_help (const char *help, /* Data structure used to print list of valid option values. */ -struct option_help_tuple +class option_help_tuple { +public: option_help_tuple (int code, vec values): m_code (code), m_values (values) {} @@ -1801,8 +1802,9 @@ const struct sanitizer_opts_s coverage_sanitizer_opts[] = /* A struct for describing a run of chars within a string. */ -struct string_fragment +class string_fragment { +public: string_fragment (const char *start, size_t len) : m_start (start), m_len (len) {} diff --git a/gcc/poly-int.h b/gcc/poly-int.h index d68a652..635f1eb 100644 --- a/gcc/poly-int.h +++ b/gcc/poly-int.h @@ -335,7 +335,7 @@ struct poly_result /* A base POD class for polynomial integers. The polynomial has N coefficients of type C. */ template -class poly_int_pod +struct poly_int_pod { public: template diff --git a/gcc/predict.c b/gcc/predict.c index ad19d12..766f418 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -3236,8 +3236,9 @@ predict_paths_leading_to_edge (edge e, enum br_predictor pred, /* This is used to carry information about basic blocks. It is attached to the AUX field of the standard CFG block. */ -struct block_info +class block_info { +public: /* Estimated frequency of execution of basic_block. */ sreal frequency; @@ -3249,8 +3250,9 @@ struct block_info }; /* Similar information for edges. */ -struct edge_prob_info +class edge_prob_info { +public: /* In case edge is a loopback edge, the probability edge will be reached in case header is. Estimated number of iterations of the loop can be then computed as 1 / (1 - back_edge_prob). */ diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h index e4df659..2d03b3f 100644 --- a/gcc/pretty-print.h +++ b/gcc/pretty-print.h @@ -74,8 +74,9 @@ struct chunk_info /* The output buffer datatype. This is best seen as an abstract datatype whose fields should not be accessed directly by clients. */ -struct output_buffer +class output_buffer { +public: output_buffer (); ~output_buffer (); @@ -214,8 +215,9 @@ class format_postprocessor /* The data structure that contains the bare minimum required to do proper pretty-printing. Clients may derived from this structure and add additional fields they need. */ -struct pretty_printer +class pretty_printer { +public: /* Default construct a pretty printer with specified maximum line length cut off limit. */ explicit pretty_printer (int = 0); diff --git a/gcc/profile-count.h b/gcc/profile-count.h index cbab596..e584aab 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -676,7 +676,7 @@ public: class sreal; -class GTY(()) profile_count +struct GTY(()) profile_count { public: /* Use 62bit to hold basic block counters. Should be at least diff --git a/gcc/read-md.h b/gcc/read-md.h index 327f378..9cb7569 100644 --- a/gcc/read-md.h +++ b/gcc/read-md.h @@ -23,7 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "obstack.h" /* Records a position in the file. */ -struct file_location { +class file_location { +public: file_location () {} file_location (const char *, int, int); diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c index 3cf34ba..f41f54a 100644 --- a/gcc/read-rtl-function.c +++ b/gcc/read-rtl-function.c @@ -52,8 +52,9 @@ class fixup; at LOC, which will be turned into an actual CFG edge once the "insn-chain" is fully parsed. */ -struct deferred_edge +class deferred_edge { +public: deferred_edge (file_location loc, int src_bb_idx, int dest_bb_idx, int flags) : m_loc (loc), m_src_bb_idx (src_bb_idx), m_dest_bb_idx (dest_bb_idx), m_flags (flags) diff --git a/gcc/ree.c b/gcc/ree.c index 104f8db..c63e159 100644 --- a/gcc/ree.c +++ b/gcc/ree.c @@ -579,8 +579,9 @@ struct ATTRIBUTE_PACKED ext_modified }; /* Vectors used by combine_reaching_defs and its helpers. */ -struct ext_state +class ext_state { +public: /* In order to avoid constant alloc/free, we keep these 4 vectors live through the entire find_and_remove_re and just truncate them each time. */ diff --git a/gcc/reginfo.c b/gcc/reginfo.c index bec2d40..4832aff 100644 --- a/gcc/reginfo.c +++ b/gcc/reginfo.c @@ -50,8 +50,9 @@ int max_regno; /* Used to cache the results of simplifiable_subregs. SHAPE is the input parameter and SIMPLIFIABLE_REGS is the result. */ -struct simplifiable_subreg +class simplifiable_subreg { +public: simplifiable_subreg (const subreg_shape &); subreg_shape shape; diff --git a/gcc/regrename.c b/gcc/regrename.c index 5259d56..7dbbeb9 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -547,8 +547,9 @@ struct incoming_reg_info { A pointer to such a structure is stored in each basic block's aux field during regrename_analyze, except for blocks we know can't be optimized (such as entry and exit blocks). */ -struct bb_rename_info +class bb_rename_info { +public: /* The basic block corresponding to this structure. */ basic_block bb; /* Copies of the global information. */ diff --git a/gcc/regrename.h b/gcc/regrename.h index 37f5e39..e9f2823 100644 --- a/gcc/regrename.h +++ b/gcc/regrename.h @@ -22,8 +22,9 @@ along with GCC; see the file COPYING3. If not see /* We keep linked lists of DU_HEAD structures, each of which describes a chain of occurrences of a reg. */ -struct du_head +class du_head { +public: /* The next chain. */ struct du_head *next_chain; /* The first and last elements of this chain. */ diff --git a/gcc/reload.h b/gcc/reload.h index 813075b..edfeebf 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -278,8 +278,9 @@ extern int num_not_at_initial_offset; /* This structure describes instructions which are relevant for reload. Apart from all regular insns, this also includes CODE_LABELs, since they must be examined for register elimination. */ -struct insn_chain +class insn_chain { +public: /* Links to the neighbor instructions. */ struct insn_chain *next, *prev; diff --git a/gcc/rtl-iter.h b/gcc/rtl-iter.h index e48ae4f..ba5e692 100644 --- a/gcc/rtl-iter.h +++ b/gcc/rtl-iter.h @@ -56,8 +56,9 @@ class generic_subrtx_iterator typedef typename T::rtunion_type rtunion_type; public: - struct array_type + class array_type { + public: array_type (); ~array_type (); value_type stack[LOCAL_ELEMS]; diff --git a/gcc/rtl.h b/gcc/rtl.h index a4fde4e..ad2f3cd 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -145,8 +145,9 @@ struct addr_diff_vec_flags /* Structure used to describe the attributes of a MEM. These are hashed so MEMs that the same attributes share a data structure. This means they cannot be modified in place. */ -struct GTY(()) mem_attrs +class GTY(()) mem_attrs { +public: mem_attrs (); /* The expression that the MEM accesses, or null if not known. @@ -187,7 +188,8 @@ struct GTY(()) mem_attrs object in the low part of a 4-byte register, the OFFSET field will be -3 rather than 0. */ -struct GTY((for_user)) reg_attrs { +class GTY((for_user)) reg_attrs { +public: tree decl; /* decl corresponding to REG. */ poly_int64 offset; /* Offset from start of DECL. */ }; @@ -449,8 +451,9 @@ struct GTY((desc("0"), tag("0"), /* A node for constructing singly-linked lists of rtx. */ -class GTY(()) rtx_expr_list : public rtx_def +struct GTY(()) rtx_expr_list : public rtx_def { +private: /* No extra fields, but adds invariant: (GET_CODE (X) == EXPR_LIST). */ public: @@ -469,8 +472,9 @@ is_a_helper ::test (rtx rt) return rt->code == EXPR_LIST; } -class GTY(()) rtx_insn_list : public rtx_def +struct GTY(()) rtx_insn_list : public rtx_def { +private: /* No extra fields, but adds invariant: (GET_CODE (X) == INSN_LIST). This is an instance of: @@ -501,8 +505,9 @@ is_a_helper ::test (rtx rt) /* A node with invariant GET_CODE (X) == SEQUENCE i.e. a vector of rtx, typically (but not always) of rtx_insn *, used in the late passes. */ -class GTY(()) rtx_sequence : public rtx_def +struct GTY(()) rtx_sequence : public rtx_def { +private: /* No extra fields, but adds invariant: (GET_CODE (X) == SEQUENCE). */ public: @@ -533,7 +538,7 @@ is_a_helper ::test (const_rtx rt) return rt->code == SEQUENCE; } -class GTY(()) rtx_insn : public rtx_def +struct GTY(()) rtx_insn : public rtx_def { public: /* No extra fields, but adds the invariant: @@ -567,7 +572,7 @@ public: /* Subclasses of rtx_insn. */ -class GTY(()) rtx_debug_insn : public rtx_insn +struct GTY(()) rtx_debug_insn : public rtx_insn { /* No extra fields, but adds the invariant: DEBUG_INSN_P (X) aka (GET_CODE (X) == DEBUG_INSN) @@ -578,7 +583,7 @@ class GTY(()) rtx_debug_insn : public rtx_insn from rtl.def. */ }; -class GTY(()) rtx_nonjump_insn : public rtx_insn +struct GTY(()) rtx_nonjump_insn : public rtx_insn { /* No extra fields, but adds the invariant: NONJUMP_INSN_P (X) aka (GET_CODE (X) == INSN) @@ -589,7 +594,7 @@ class GTY(()) rtx_nonjump_insn : public rtx_insn from rtl.def. */ }; -class GTY(()) rtx_jump_insn : public rtx_insn +struct GTY(()) rtx_jump_insn : public rtx_insn { public: /* No extra fields, but adds the invariant: @@ -616,7 +621,7 @@ public: inline void set_jump_target (rtx_code_label *); }; -class GTY(()) rtx_call_insn : public rtx_insn +struct GTY(()) rtx_call_insn : public rtx_insn { /* No extra fields, but adds the invariant: CALL_P (X) aka (GET_CODE (X) == CALL_INSN) @@ -629,7 +634,7 @@ class GTY(()) rtx_call_insn : public rtx_insn from rtl.def. */ }; -class GTY(()) rtx_jump_table_data : public rtx_insn +struct GTY(()) rtx_jump_table_data : public rtx_insn { /* No extra fields, but adds the invariant: JUMP_TABLE_DATA_P (X) aka (GET_CODE (INSN) == JUMP_TABLE_DATA) @@ -640,8 +645,6 @@ class GTY(()) rtx_jump_table_data : public rtx_insn DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "uuBe0000", RTX_INSN) from rtl.def. */ -public: - /* This can be either: (a) a table of absolute jumps, in which case PATTERN (this) is an @@ -657,7 +660,7 @@ public: inline scalar_int_mode get_data_mode () const; }; -class GTY(()) rtx_barrier : public rtx_insn +struct GTY(()) rtx_barrier : public rtx_insn { /* No extra fields, but adds the invariant: BARRIER_P (X) aka (GET_CODE (X) == BARRIER) @@ -668,7 +671,7 @@ class GTY(()) rtx_barrier : public rtx_insn from rtl.def. */ }; -class GTY(()) rtx_code_label : public rtx_insn +struct GTY(()) rtx_code_label : public rtx_insn { /* No extra fields, but adds the invariant: LABEL_P (X) aka (GET_CODE (X) == CODE_LABEL) @@ -679,7 +682,7 @@ class GTY(()) rtx_code_label : public rtx_insn from rtl.def. */ }; -class GTY(()) rtx_note : public rtx_insn +struct GTY(()) rtx_note : public rtx_insn { /* No extra fields, but adds the invariant: NOTE_P(X) aka (GET_CODE (X) == NOTE) @@ -2096,7 +2099,8 @@ costs_add_n_insns (struct full_rtx_costs *c, int n) inner_mode == the mode of the SUBREG_REG offset == the SUBREG_BYTE outer_mode == the mode of the SUBREG itself. */ -struct subreg_shape { +class subreg_shape { +public: subreg_shape (machine_mode, poly_uint16, machine_mode); bool operator == (const subreg_shape &) const; bool operator != (const subreg_shape &) const; diff --git a/gcc/sanopt.c b/gcc/sanopt.c index 5cb98e1..bf9fdc9 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -207,8 +207,9 @@ struct sanopt_tree_couple_hash : typed_noop_remove /* This is used to carry various hash maps and variables used in sanopt_optimize_walker. */ -struct sanopt_ctx +class sanopt_ctx { +public: /* This map maps a pointer (the first argument of UBSAN_NULL) to a vector of UBSAN_NULL call statements that check this pointer. */ hash_map > null_check_map; diff --git a/gcc/sched-int.h b/gcc/sched-int.h index 3ca5e26..5fef221 100644 --- a/gcc/sched-int.h +++ b/gcc/sched-int.h @@ -454,8 +454,9 @@ struct deps_reg }; /* Describe state of dependencies used during sched_analyze phase. */ -struct deps_desc +class deps_desc { +public: /* The *_insns and *_mems are paired lists. Each pending memory operation will have a pointer to the MEM rtx on one list and a pointer to the containing insn on the other list in the same place in the list. */ diff --git a/gcc/sel-sched-ir.h b/gcc/sel-sched-ir.h index 5dd273f..2a24a92 100644 --- a/gcc/sel-sched-ir.h +++ b/gcc/sel-sched-ir.h @@ -713,8 +713,9 @@ struct transformed_insns /* Indexed by INSN_LUID, the collection of all data associated with a single instruction that is in the stream. */ -struct _sel_insn_data +class _sel_insn_data { +public: /* The expression that contains vinsn for this insn and some flow-sensitive data like priority. */ expr_def expr; diff --git a/gcc/selftest.h b/gcc/selftest.h index d278f0a..6152ef5 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -30,8 +30,9 @@ namespace selftest { /* A struct describing the source-location of a selftest, to make it easier to track down failing tests. */ -struct location +class location { +public: location (const char *file, int line, const char *function) : m_file (file), m_line (line), m_function (function) {} diff --git a/gcc/sese.h b/gcc/sese.h index 8931b28..0319da6 100644 --- a/gcc/sese.h +++ b/gcc/sese.h @@ -26,8 +26,9 @@ typedef struct ifsese_s *ifsese; /* A Single Entry, Single Exit region is a part of the CFG delimited by two edges. */ -struct sese_l +class sese_l { +public: sese_l (edge e, edge x) : entry (e), exit (x) {} operator bool () const { return entry && exit; } @@ -71,8 +72,9 @@ vec_find (const vec &v, const T &elem) } /* A helper structure for bookkeeping information about a scop in graphite. */ -typedef struct sese_info_t +typedef class sese_info_t { +public: /* The SESE region. */ sese_l region; diff --git a/gcc/stmt.c b/gcc/stmt.c index 8ed3bf5..040899e 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -68,8 +68,9 @@ along with GCC; see the file COPYING3. If not see */ -struct simple_case_node +class simple_case_node { +public: simple_case_node (tree low, tree high, tree code_label): m_low (low), m_high (high), m_code_label (code_label) {} diff --git a/gcc/target-globals.h b/gcc/target-globals.h index 5af846c..57cb42f 100644 --- a/gcc/target-globals.h +++ b/gcc/target-globals.h @@ -39,7 +39,8 @@ extern struct target_bb_reorder *this_target_bb_reorder; extern struct target_lower_subreg *this_target_lower_subreg; #endif -struct GTY(()) target_globals { +class GTY(()) target_globals { +public: ~target_globals (); struct target_flag_state *GTY((skip)) flag_state; diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index b8a62a6..ee7e010 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -695,8 +695,9 @@ aff_combination_find_elt (aff_tree *comb, tree val, unsigned *idx) /* Element of the cache that maps ssa name NAME to its expanded form as an affine expression EXPANSION. */ -struct name_expansion +class name_expansion { +public: aff_tree expansion; /* True if the expansion for the name is just being generated. */ diff --git a/gcc/tree-affine.h b/gcc/tree-affine.h index 257e8f6..23c6096 100644 --- a/gcc/tree-affine.h +++ b/gcc/tree-affine.h @@ -28,8 +28,9 @@ along with GCC; see the file COPYING3. If not see /* Element of an affine combination. */ -struct aff_comb_elt +class aff_comb_elt { +public: /* The value of the element. */ tree val; @@ -37,8 +38,9 @@ struct aff_comb_elt widest_int coef; }; -struct aff_tree +class aff_tree { +public: /* Type of the result of the combination. */ tree type; diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h index 69d5a82..d7cd98d 100644 --- a/gcc/tree-data-ref.h +++ b/gcc/tree-data-ref.h @@ -203,8 +203,9 @@ typedef struct data_reference *data_reference_p; including the data ref itself and the segment length for aliasing checks. This is used to merge alias checks. */ -struct dr_with_seg_len +class dr_with_seg_len { +public: dr_with_seg_len (data_reference_p d, tree len, unsigned HOST_WIDE_INT size, unsigned int a) : dr (d), seg_len (len), access_size (size), align (a) {} @@ -224,8 +225,9 @@ struct dr_with_seg_len /* This struct contains two dr_with_seg_len objects with aliasing data refs. Two comparisons are generated from them. */ -struct dr_with_seg_len_pair_t +class dr_with_seg_len_pair_t { +public: dr_with_seg_len_pair_t (const dr_with_seg_len& d1, const dr_with_seg_len& d2) : first (d1), second (d2) {} diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index d8c8249..eb35ebf 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -129,8 +129,9 @@ ssa_is_replaceable_p (gimple *stmt) rarely more than 6, and in the bootstrap of gcc, the maximum number of nodes encountered was 12. */ -struct elim_graph +class elim_graph { +public: elim_graph (var_map map); /* Size of the elimination vectors. */ diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index 8e83a71..dfb2146 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -243,8 +243,9 @@ along with GCC; see the file COPYING3. If not see /* Data references (or phi nodes that carry data reference values across loop iterations). */ -typedef struct dref_d +typedef class dref_d { +public: /* The reference itself. */ struct data_reference *ref; diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index b1c15dc..08c882e 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -370,8 +370,9 @@ find_var_scev_info (basic_block instantiated_below, tree var) analyzing a scalar evolution, instantiating a CHREC or resolving mixers. */ -struct instantiate_cache_type +class instantiate_cache_type { +public: htab_t map; vec entries; diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h index ddd28ec..c7c6020 100644 --- a/gcc/tree-ssa-alias.h +++ b/gcc/tree-ssa-alias.h @@ -68,8 +68,9 @@ struct GTY(()) pt_solution /* Simplified and cached information about a memory reference tree. Used by the alias-oracle internally and externally in alternate interfaces. */ -struct ao_ref +class ao_ref { +public: /* The original full memory reference tree or NULL_TREE if that is not available. */ tree ref; diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 51b9d9f..4dd7035 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -157,7 +157,8 @@ typedef enum VARYING } ccp_lattice_t; -struct ccp_prop_value_t { +class ccp_prop_value_t { +public: /* Lattice value. */ ccp_lattice_t lattice_val; diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index 2ea0a66..2ca0d02 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -674,8 +674,9 @@ ssa_conflicts_dump (FILE *file, ssa_conflicts *ptr) marked as being live. This delays clearing of these bitmaps until they are actually needed again. */ -struct live_track +class live_track { +public: bitmap_obstack obstack; /* A place to allocate our bitmaps. */ bitmap_head live_base_var; /* Indicates if a basevar is live. */ bitmap_head *live_base_partitions; /* Live partitions for each basevar. */ diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 2064c29..f8bcabc 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -113,8 +113,9 @@ struct mem_ref_loc /* Description of a memory reference. */ -struct im_mem_ref +class im_mem_ref { +public: unsigned id : 30; /* ID assigned to the memory reference (its index in memory_accesses.refs_list) */ unsigned ref_canonical : 1; /* Whether mem.ref was canonicalized. */ @@ -1756,8 +1757,9 @@ for_all_locs_in_loop (struct loop *loop, im_mem_ref *ref, FN fn) /* Rewrites location LOC by TMP_VAR. */ -struct rewrite_mem_ref_loc +class rewrite_mem_ref_loc { +public: rewrite_mem_ref_loc (tree tmp_var_) : tmp_var (tmp_var_) {} bool operator () (mem_ref_loc *loc); tree tmp_var; @@ -1781,8 +1783,9 @@ rewrite_mem_refs (struct loop *loop, im_mem_ref *ref, tree tmp_var) /* Stores the first reference location in LOCP. */ -struct first_mem_ref_loc_1 +class first_mem_ref_loc_1 { +public: first_mem_ref_loc_1 (mem_ref_loc **locp_) : locp (locp_) {} bool operator () (mem_ref_loc *loc); mem_ref_loc **locp; @@ -2017,8 +2020,9 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag, /* When REF is set on the location, set flag indicating the store. */ -struct sm_set_flag_if_changed +class sm_set_flag_if_changed { +public: sm_set_flag_if_changed (tree flag_, hash_set *bbs_) : flag (flag_), bbs (bbs_) {} bool operator () (mem_ref_loc *loc); @@ -2151,8 +2155,9 @@ hoist_memory_references (struct loop *loop, bitmap mem_refs, } } -struct ref_always_accessed +class ref_always_accessed { +public: ref_always_accessed (struct loop *loop_, bool stored_p_) : loop (loop_), stored_p (stored_p_) {} bool operator () (mem_ref_loc *loc); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index bbae83c..cb189ab 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -175,8 +175,9 @@ enum use_type }; /* Cost of a computation. */ -struct comp_cost +class comp_cost { +public: comp_cost (): cost (0), complexity (0), scratch (0) {} @@ -352,8 +353,9 @@ operator<= (comp_cost cost1, comp_cost cost2) struct iv_inv_expr_ent; /* The candidate - cost pair. */ -struct cost_pair +class cost_pair { +public: struct iv_cand *cand; /* The candidate. */ comp_cost cost; /* The cost. */ enum tree_code comp; /* For iv elimination, the comparison. */ @@ -442,8 +444,9 @@ struct iv_cand }; /* Hashtable entry for common candidate derived from iv uses. */ -struct iv_common_cand +class iv_common_cand { +public: tree base; tree step; /* IV uses from which this common candidate is derived. */ @@ -616,8 +619,9 @@ struct ivopts_data /* An assignment of iv candidates to uses. */ -struct iv_ca +class iv_ca { +public: /* The number of uses covered by the assignment. */ unsigned upto; diff --git a/gcc/tree-ssa-loop.h b/gcc/tree-ssa-loop.h index 2fc9e8c..24fad0f 100644 --- a/gcc/tree-ssa-loop.h +++ b/gcc/tree-ssa-loop.h @@ -36,8 +36,9 @@ struct affine_iv the structure can be evaluated at the end of the loop's preheader (and due to ssa form, also anywhere inside the body of the loop). */ -struct tree_niter_desc +class tree_niter_desc { +public: tree assumptions; /* The boolean expression. If this expression evaluates to false, then the other fields in this structure should not be used; there is no guarantee that they diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 231ac00..36da4c6a 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -428,8 +428,9 @@ get_or_alloc_expr_for_name (tree name) /* An unordered bitmap set. One bitmap tracks values, the other, expressions. */ -typedef struct bitmap_set +typedef class bitmap_set { +public: bitmap_head expressions; bitmap_head values; } *bitmap_set_t; diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 29688d2..f470f31 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -1393,8 +1393,9 @@ static bitmap changed; /* Strongly Connected Component visitation info. */ -struct scc_info +class scc_info { +public: scc_info (size_t size); ~scc_info (); diff --git a/gcc/tree-switch-conversion.h b/gcc/tree-switch-conversion.h index a9a959c..653007f 100644 --- a/gcc/tree-switch-conversion.h +++ b/gcc/tree-switch-conversion.h @@ -44,8 +44,9 @@ enum cluster_type |-jump_table_cluster (JUMP_TABLE) `-bit_test_cluster (BIT_TEST). */ -struct cluster +class cluster { +public: /* Constructor. */ cluster (tree case_label_expr, basic_block case_bb, profile_probability prob, profile_probability subtree_prob); @@ -117,8 +118,9 @@ cluster::cluster (tree case_label_expr, basic_block case_bb, /* Subclass of cluster representing a simple contiguous range from [low..high]. */ -struct simple_cluster: public cluster +class simple_cluster: public cluster { +public: /* Constructor. */ simple_cluster (tree low, tree high, tree case_label_expr, basic_block case_bb, profile_probability prob); @@ -196,8 +198,9 @@ simple_cluster::simple_cluster (tree low, tree high, tree case_label_expr, /* Abstract subclass of jump table and bit test cluster, handling a collection of simple_cluster instances. */ -struct group_cluster: public cluster +class group_cluster: public cluster { +public: /* Constructor. */ group_cluster (vec &clusters, unsigned start, unsigned end); @@ -233,8 +236,9 @@ struct group_cluster: public cluster The "emit" vfunc gernerates a nested switch statement which is later lowered to a jump table. */ -struct jump_table_cluster: public group_cluster +class jump_table_cluster: public group_cluster { +public: /* Constructor. */ jump_table_cluster (vec &clusters, unsigned start, unsigned end) : group_cluster (clusters, start, end) @@ -332,8 +336,9 @@ This transformation was contributed by Roger Sayle, see this e-mail: http://gcc.gnu.org/ml/gcc-patches/2003-01/msg01950.html */ -struct bit_test_cluster: public group_cluster +class bit_test_cluster: public group_cluster { +public: /* Constructor. */ bit_test_cluster (vec &clusters, unsigned start, unsigned end, bool handles_entire_switch) @@ -417,8 +422,9 @@ struct bit_test_cluster: public group_cluster /* Helper struct to find minimal clusters. */ -struct min_cluster_item +class min_cluster_item { +public: /* Constructor. */ min_cluster_item (unsigned count, unsigned start, unsigned non_jt_cases): m_count (count), m_start (start), m_non_jt_cases (non_jt_cases) @@ -436,8 +442,9 @@ struct min_cluster_item /* Helper struct to represent switch decision tree. */ -struct case_tree_node +class case_tree_node { +public: /* Empty Constructor. */ case_tree_node (); @@ -503,8 +510,9 @@ bool jump_table_cluster::is_enabled (void) is used to quickly identify all cases in this set without looking at label_to_block for every case label. */ -struct case_bit_test +class case_bit_test { +public: wide_int mask; basic_block target_bb; tree label; @@ -515,8 +523,9 @@ struct case_bit_test static int cmp (const void *p1, const void *p2); }; -struct switch_decision_tree +class switch_decision_tree { +public: /* Constructor. */ switch_decision_tree (gswitch *swtch): m_switch (swtch), m_phi_mapping (), m_case_bbs (), m_case_node_pool ("struct case_node pool"), @@ -681,8 +690,9 @@ This transformation was contributed by Martin Jambor, see this e-mail: http://gcc.gnu.org/ml/gcc-patches/2008-07/msg00011.html */ /* The main structure of the pass. */ -struct switch_conversion +class switch_conversion { +public: /* Constructor. */ switch_conversion (); diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index ff952d6..0157ba4 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -286,7 +286,8 @@ type_conversion_p (tree name, stmt_vec_info stmt_vinfo, bool check_sign, /* Holds information about an input operand after some sign changes and type promotions have been peeled away. */ -struct vect_unpromoted_value { +class vect_unpromoted_value { +public: vect_unpromoted_value (); void set_op (tree, vect_def_type, stmt_vec_info = NULL); diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 325ef58..868dc5c 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -188,8 +188,9 @@ dump_stmt_cost (FILE *f, void *data, int count, enum vect_cost_for_stmt kind, /* For mapping simduid to vectorization factor. */ -struct simduid_to_vf : free_ptr_hash +class simduid_to_vf : public free_ptr_hash { +public: unsigned int simduid; poly_uint64 vf; diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index f7432f0..6e76b7e 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -141,7 +141,8 @@ struct _slp_tree { /* SLP instance is a sequence of stmts in a loop that can be packed into SIMD stmts. */ -typedef struct _slp_instance { +typedef class _slp_instance { +public: /* The root of SLP tree. */ slp_tree root; @@ -181,7 +182,8 @@ typedef std::pair vec_object_pair; /* Records that vectorization is only possible if abs (EXPR) >= MIN_VALUE. UNSIGNED_P is true if we can assume that abs (EXPR) == EXPR. */ -struct vec_lower_bound { +class vec_lower_bound { +public: vec_lower_bound () {} vec_lower_bound (tree e, bool u, poly_uint64 m) : expr (e), unsigned_p (u), min_value (m) {} @@ -193,7 +195,8 @@ struct vec_lower_bound { /* Vectorizer state shared between different analyses like vector sizes of the same CFG region. */ -struct vec_info_shared { +class vec_info_shared { +public: vec_info_shared(); ~vec_info_shared(); @@ -213,7 +216,8 @@ struct vec_info_shared { }; /* Vectorizer state common between loop and basic-block vectorization. */ -struct vec_info { +class vec_info { +public: enum vec_kind { bb, loop }; vec_info (vec_kind, void *, vec_info_shared *); @@ -377,7 +381,8 @@ typedef auto_vec vec_loop_masks; /*-----------------------------------------------------------------*/ /* Info on vectorized loops. */ /*-----------------------------------------------------------------*/ -typedef struct _loop_vec_info : public vec_info { +typedef class _loop_vec_info : public vec_info { +public: _loop_vec_info (struct loop *, vec_info_shared *); ~_loop_vec_info (); @@ -650,8 +655,9 @@ loop_vec_info_for_loop (struct loop *loop) return (loop_vec_info) loop->aux; } -typedef struct _bb_vec_info : public vec_info +typedef class _bb_vec_info : public vec_info { +public: _bb_vec_info (gimple_stmt_iterator, gimple_stmt_iterator, vec_info_shared *); ~_bb_vec_info (); @@ -790,7 +796,8 @@ enum vect_memory_access_type { VMAT_GATHER_SCATTER }; -struct dr_vec_info { +class dr_vec_info { +public: /* The data reference itself. */ data_reference *dr; /* The statement that contains the data reference. */ @@ -807,7 +814,8 @@ struct dr_vec_info { typedef struct data_reference *dr_p; -struct _stmt_vec_info { +class _stmt_vec_info { +public: enum stmt_vec_info_type type; diff --git a/gcc/tree.c b/gcc/tree.c index 563af6f..7892c20 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -5107,8 +5107,9 @@ protected_set_expr_location (tree t, location_t loc) /* Data used when collecting DECLs and TYPEs for language data removal. */ -struct free_lang_data_d +class free_lang_data_d { +public: free_lang_data_d () : decls (100), types (100) {} /* Worklist to avoid excessive recursion. */ diff --git a/gcc/tree.h b/gcc/tree.h index 3dce602..992abd1 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5984,8 +5984,9 @@ desired_pro_or_demotion_p (const_tree to_type, const_tree from_type) /* Pointer type used to declare builtins before we have seen its real declaration. */ -struct builtin_structptr_type +class builtin_structptr_type { +public: tree& node; tree& base; const char *str; @@ -6069,8 +6070,9 @@ fndecl_built_in_p (const_tree node, built_in_function name) where it is not. */ -struct op_location_t +class op_location_t { +public: location_t m_operator_loc; location_t m_combined_loc; diff --git a/gcc/unique-ptr-tests.cc b/gcc/unique-ptr-tests.cc index 9e0f2a9..45c189b 100644 --- a/gcc/unique-ptr-tests.cc +++ b/gcc/unique-ptr-tests.cc @@ -31,8 +31,9 @@ namespace { /* A class for counting ctor and dtor invocations. */ -struct stats +class stats { +public: stats () : ctor_count (0), dtor_count (0) {} int ctor_count; @@ -59,8 +60,9 @@ private: /* A struct for testing unique_ptr. */ -struct has_default_ctor +class has_default_ctor { +public: has_default_ctor () : m_field (42) {} int m_field; }; diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index c2b4204..65df25d 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -929,8 +929,9 @@ static poly_int64 hard_frame_pointer_adjustment = -1; /* Data for adjust_mems callback. */ -struct adjust_mem_data +class adjust_mem_data { +public: bool store; machine_mode mem_mode; HOST_WIDE_INT stack_adjust; @@ -8061,8 +8062,9 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv, /* Structure for passing some other parameters to function vt_expand_loc_callback. */ -struct expand_loc_callback_data +class expand_loc_callback_data { +public: /* The variables and values active at this point. */ variable_table_type *vars; diff --git a/gcc/varasm.c b/gcc/varasm.c index 626a4c9..827a370 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2899,7 +2899,8 @@ assemble_real (REAL_VALUE_TYPE d, scalar_float_mode mode, unsigned int align, Store them both in the structure *VALUE. EXP must be reducible. */ -struct addr_const { +class addr_const { +public: rtx base; poly_int64 offset; }; @@ -3621,7 +3622,8 @@ tree_output_constant_def (tree exp) return decl; } -struct GTY((chain_next ("%h.next"), for_user)) constant_descriptor_rtx { +class GTY((chain_next ("%h.next"), for_user)) constant_descriptor_rtx { +public: struct constant_descriptor_rtx *next; rtx mem; rtx sym; diff --git a/gcc/vec.c b/gcc/vec.c index f474922..cbd2db0 100644 --- a/gcc/vec.c +++ b/gcc/vec.c @@ -49,8 +49,9 @@ along with GCC; see the file COPYING3. If not see vnull vNULL; /* Vector memory usage. */ -struct vec_usage: public mem_usage +class vec_usage: public mem_usage { +public: /* Default constructor. */ vec_usage (): m_items (0), m_items_peak (0), m_element_size (0) {} diff --git a/gcc/wide-int-bitmask.h b/gcc/wide-int-bitmask.h index 529756f..e95e463 100644 --- a/gcc/wide-int-bitmask.h +++ b/gcc/wide-int-bitmask.h @@ -20,8 +20,9 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_WIDE_INT_BITMASK_H #define GCC_WIDE_INT_BITMASK_H -struct wide_int_bitmask +class wide_int_bitmask { +public: inline wide_int_bitmask (); inline wide_int_bitmask (uint64_t l); inline wide_int_bitmask (uint64_t l, uint64_t h); diff --git a/gcc/wide-int.h b/gcc/wide-int.h index 25ea054..18e76b7 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -642,8 +642,9 @@ namespace wi { /* Contains the components of a decomposed integer for easy, direct access. */ - struct storage_ref + class storage_ref { + public: storage_ref () {} storage_ref (const HOST_WIDE_INT *, unsigned int, unsigned int); @@ -968,7 +969,7 @@ decompose (HOST_WIDE_INT *, unsigned int precision, wide_int, with the optimization that VAL is normally a pointer to another integer's storage, so that no array copy is needed. */ template -struct wide_int_ref_storage : public wi::storage_ref +class wide_int_ref_storage : public wi::storage_ref { private: /* Scratch space that can be used when decomposing the original integer. @@ -1357,7 +1358,7 @@ namespace wi bytes beyond the sizeof need to be allocated. Use set_precision to initialize the structure. */ template -class GTY((user)) trailing_wide_ints +struct GTY((user)) trailing_wide_ints { private: /* The shared precision of each number. */ @@ -1554,8 +1555,9 @@ namespace wi { /* Stores HWI-sized integer VAL, treating it as having signedness SGN and precision PRECISION. */ - struct hwi_with_prec + class hwi_with_prec { + public: hwi_with_prec () {} hwi_with_prec (HOST_WIDE_INT, unsigned int, signop); HOST_WIDE_INT val; -- cgit v1.1 From 18c0ed4b46990c504525aa4928aab45907c8256d Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Tue, 9 Jul 2019 17:30:34 +0000 Subject: rs6000-internal.h (create_TOC_reference): Delete. 2019-07-09 Michael Meissner * config/rs6000/rs6000-internal.h (create_TOC_reference): Delete. * config/rs6000/rs6000-logue.c (create_TOC_reference): Move function from rs6000-logue.c back to rs6000.c. * config/rs6000/rs6000.c (create_TOC_reference): Likewise. From-SVN: r273309 --- gcc/ChangeLog | 7 +++++++ gcc/config/rs6000/rs6000-internal.h | 1 - gcc/config/rs6000/rs6000-logue.c | 35 --------------------------------- gcc/config/rs6000/rs6000.c | 39 +++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 36 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1606b91..dc34222 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-09 Michael Meissner + + * config/rs6000/rs6000-internal.h (create_TOC_reference): Delete. + * config/rs6000/rs6000-logue.c (create_TOC_reference): Move + function from rs6000-logue.c back to rs6000.c. + * config/rs6000/rs6000.c (create_TOC_reference): Likewise. + 2019-07-09 Martin Sebor PR c++/61339 diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h index f69fa5d..c526967 100644 --- a/gcc/config/rs6000/rs6000-internal.h +++ b/gcc/config/rs6000/rs6000-internal.h @@ -92,7 +92,6 @@ extern void rs6000_emit_prologue_components (sbitmap components); extern void rs6000_emit_epilogue_components (sbitmap components); extern void rs6000_set_handled_components (sbitmap components); extern rs6000_stack_t * rs6000_stack_info (void); -extern rtx create_TOC_reference (rtx symbol, rtx largetoc_reg); extern rtx rs6000_got_sym (void); extern struct machine_function *rs6000_init_machine_status (void); extern bool save_reg_p (int reg); diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index 8454f96..acc11df 100644 --- a/gcc/config/rs6000/rs6000-logue.c +++ b/gcc/config/rs6000/rs6000-logue.c @@ -1406,41 +1406,6 @@ uses_TOC (void) } #endif -rtx -create_TOC_reference (rtx symbol, rtx largetoc_reg) -{ - rtx tocrel, tocreg, hi; - - if (TARGET_DEBUG_ADDR) - { - if (SYMBOL_REF_P (symbol)) - fprintf (stderr, "\ncreate_TOC_reference, (symbol_ref %s)\n", - XSTR (symbol, 0)); - else - { - fprintf (stderr, "\ncreate_TOC_reference, code %s:\n", - GET_RTX_NAME (GET_CODE (symbol))); - debug_rtx (symbol); - } - } - - if (!can_create_pseudo_p ()) - df_set_regs_ever_live (TOC_REGISTER, true); - - tocreg = gen_rtx_REG (Pmode, TOC_REGISTER); - tocrel = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, symbol, tocreg), UNSPEC_TOCREL); - if (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p ()) - return tocrel; - - hi = gen_rtx_HIGH (Pmode, copy_rtx (tocrel)); - if (largetoc_reg != NULL) - { - emit_move_insn (largetoc_reg, hi); - hi = largetoc_reg; - } - return gen_rtx_LO_SUM (Pmode, hi, tocrel); -} - /* Issue assembly directives that create a reference to the given DWARF FRAME_TABLE_LABEL from the current function section. */ void diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index bec3436..ccc9d76 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -7735,6 +7735,45 @@ constant_pool_expr_p (rtx op) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode)); } +/* Create a TOC reference for symbol_ref SYMBOL. If LARGETOC_REG is non-null, + use that as the register to put the HIGH value into if register allocation + is already done. */ + +rtx +create_TOC_reference (rtx symbol, rtx largetoc_reg) +{ + rtx tocrel, tocreg, hi; + + if (TARGET_DEBUG_ADDR) + { + if (SYMBOL_REF_P (symbol)) + fprintf (stderr, "\ncreate_TOC_reference, (symbol_ref %s)\n", + XSTR (symbol, 0)); + else + { + fprintf (stderr, "\ncreate_TOC_reference, code %s:\n", + GET_RTX_NAME (GET_CODE (symbol))); + debug_rtx (symbol); + } + } + + if (!can_create_pseudo_p ()) + df_set_regs_ever_live (TOC_REGISTER, true); + + tocreg = gen_rtx_REG (Pmode, TOC_REGISTER); + tocrel = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, symbol, tocreg), UNSPEC_TOCREL); + if (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p ()) + return tocrel; + + hi = gen_rtx_HIGH (Pmode, copy_rtx (tocrel)); + if (largetoc_reg != NULL) + { + emit_move_insn (largetoc_reg, hi); + hi = largetoc_reg; + } + return gen_rtx_LO_SUM (Pmode, hi, tocrel); +} + /* These are only used to pass through from print_operand/print_operand_address to rs6000_output_addr_const_extra over the intervening function output_addr_const which is not target code. */ -- cgit v1.1 From 99b1c316ec974a39bdd949f8559bb28861b69592 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 9 Jul 2019 18:32:49 +0000 Subject: PR c++/61339 - add mismatch between struct and class [-Wmismatched-tags] to non-bugs gcc/c/ChangeLog: PR c++/61339 * c-decl.c (xref_tag): Change class-key of PODs to struct and others to class. (field_decl_cmp): Same. * c-parser.c (c_parser_struct_or_union_specifier): Same. * c-tree.h: Same. * gimple-parser.c (c_parser_gimple_compound_statement): Same. gcc/c-family/ChangeLog: PR c++/61339 * c-opts.c (handle_deferred_opts): : Change class-key of PODs to struct and others to class. * c-pretty-print.h: Same. gcc/cp/ChangeLog: PR c++/61339 * cp-tree.h: Change class-key of PODs to struct and others to class. * search.c: Same. * semantics.c (finalize_nrv_r): Same. gcc/lto/ChangeLog: PR c++/61339 * lto-common.c (lto_splay_tree_new): : Change class-key of PODs to struct and others to class. (mentions_vars_p): Same. (register_resolution): Same. (lto_register_var_decl_in_symtab): Same. (lto_register_function_decl_in_symtab): Same. (cmp_tree): Same. (lto_read_decls): Same. gcc/ChangeLog: PR c++/61339 * auto-profile.c: Change class-key of PODs to struct and others to class. * basic-block.h: Same. * bitmap.c (bitmap_alloc): Same. * bitmap.h: Same. * builtins.c (expand_builtin_prefetch): Same. (expand_builtin_interclass_mathfn): Same. (expand_builtin_strlen): Same. (expand_builtin_mempcpy_args): Same. (expand_cmpstr): Same. (expand_builtin___clear_cache): Same. (expand_ifn_atomic_bit_test_and): Same. (expand_builtin_thread_pointer): Same. (expand_builtin_set_thread_pointer): Same. * caller-save.c (setup_save_areas): Same. (replace_reg_with_saved_mem): Same. (insert_restore): Same. (insert_save): Same. (add_used_regs): Same. * cfg.c (get_bb_copy): Same. (set_loop_copy): Same. * cfg.h: Same. * cfganal.h: Same. * cfgexpand.c (alloc_stack_frame_space): Same. (add_stack_var): Same. (add_stack_var_conflict): Same. (add_scope_conflicts_1): Same. (update_alias_info_with_stack_vars): Same. (expand_used_vars): Same. * cfghooks.c (redirect_edge_and_branch_force): Same. (delete_basic_block): Same. (split_edge): Same. (make_forwarder_block): Same. (force_nonfallthru): Same. (duplicate_block): Same. (lv_flush_pending_stmts): Same. * cfghooks.h: Same. * cfgloop.c (flow_loops_cfg_dump): Same. (flow_loop_nested_p): Same. (superloop_at_depth): Same. (get_loop_latch_edges): Same. (flow_loop_dump): Same. (flow_loops_dump): Same. (flow_loops_free): Same. (flow_loop_nodes_find): Same. (establish_preds): Same. (flow_loop_tree_node_add): Same. (flow_loop_tree_node_remove): Same. (flow_loops_find): Same. (find_subloop_latch_edge_by_profile): Same. (find_subloop_latch_edge_by_ivs): Same. (mfb_redirect_edges_in_set): Same. (form_subloop): Same. (merge_latch_edges): Same. (disambiguate_multiple_latches): Same. (disambiguate_loops_with_multiple_latches): Same. (flow_bb_inside_loop_p): Same. (glb_enum_p): Same. (get_loop_body_with_size): Same. (get_loop_body): Same. (fill_sons_in_loop): Same. (get_loop_body_in_dom_order): Same. (get_loop_body_in_custom_order): Same. (release_recorded_exits): Same. (get_loop_exit_edges): Same. (num_loop_branches): Same. (remove_bb_from_loops): Same. (find_common_loop): Same. (delete_loop): Same. (cancel_loop): Same. (verify_loop_structure): Same. (loop_preheader_edge): Same. (loop_exit_edge_p): Same. (single_exit): Same. (loop_exits_to_bb_p): Same. (loop_exits_from_bb_p): Same. (get_loop_location): Same. (record_niter_bound): Same. (get_estimated_loop_iterations_int): Same. (max_stmt_executions_int): Same. (likely_max_stmt_executions_int): Same. (get_estimated_loop_iterations): Same. (get_max_loop_iterations): Same. (get_max_loop_iterations_int): Same. (get_likely_max_loop_iterations): Same. * cfgloop.h (simple_loop_desc): Same. (get_loop): Same. (loop_depth): Same. (loop_outer): Same. (loop_iterator::next): Same. (loop_outermost): Same. * cfgloopanal.c (mark_irreducible_loops): Same. (num_loop_insns): Same. (average_num_loop_insns): Same. (expected_loop_iterations_unbounded): Same. (expected_loop_iterations): Same. (mark_loop_exit_edges): Same. (single_likely_exit): Same. * cfgloopmanip.c (fix_bb_placement): Same. (fix_bb_placements): Same. (remove_path): Same. (place_new_loop): Same. (add_loop): Same. (scale_loop_frequencies): Same. (scale_loop_profile): Same. (create_empty_if_region_on_edge): Same. (create_empty_loop_on_edge): Same. (loopify): Same. (unloop): Same. (fix_loop_placements): Same. (copy_loop_info): Same. (duplicate_loop): Same. (duplicate_subloops): Same. (loop_redirect_edge): Same. (can_duplicate_loop_p): Same. (duplicate_loop_to_header_edge): Same. (mfb_keep_just): Same. (has_preds_from_loop): Same. (create_preheader): Same. (create_preheaders): Same. (lv_adjust_loop_entry_edge): Same. (loop_version): Same. * cfgloopmanip.h: Same. * cgraph.h: Same. * cgraphbuild.c: Same. * combine.c (make_extraction): Same. * config/i386/i386-features.c: Same. * config/i386/i386-features.h: Same. * config/i386/i386.c (ix86_emit_outlined_ms2sysv_save): Same. (ix86_emit_outlined_ms2sysv_restore): Same. (ix86_noce_conversion_profitable_p): Same. (ix86_init_cost): Same. (ix86_simd_clone_usable): Same. * configure.ac: Same. * coretypes.h: Same. * data-streamer-in.c (string_for_index): Same. (streamer_read_indexed_string): Same. (streamer_read_string): Same. (bp_unpack_indexed_string): Same. (bp_unpack_string): Same. (streamer_read_uhwi): Same. (streamer_read_hwi): Same. (streamer_read_gcov_count): Same. (streamer_read_wide_int): Same. * data-streamer.h (streamer_write_bitpack): Same. (bp_unpack_value): Same. (streamer_write_char_stream): Same. (streamer_write_hwi_in_range): Same. (streamer_write_record_start): Same. * ddg.c (create_ddg_dep_from_intra_loop_link): Same. (add_cross_iteration_register_deps): Same. (build_intra_loop_deps): Same. * df-core.c (df_analyze): Same. (loop_post_order_compute): Same. (loop_inverted_post_order_compute): Same. * df-problems.c (df_rd_alloc): Same. (df_rd_simulate_one_insn): Same. (df_rd_local_compute): Same. (df_rd_init_solution): Same. (df_rd_confluence_n): Same. (df_rd_transfer_function): Same. (df_rd_free): Same. (df_rd_dump_defs_set): Same. (df_rd_top_dump): Same. (df_lr_alloc): Same. (df_lr_reset): Same. (df_lr_local_compute): Same. (df_lr_init): Same. (df_lr_confluence_n): Same. (df_lr_free): Same. (df_lr_top_dump): Same. (df_lr_verify_transfer_functions): Same. (df_live_alloc): Same. (df_live_reset): Same. (df_live_init): Same. (df_live_confluence_n): Same. (df_live_finalize): Same. (df_live_free): Same. (df_live_top_dump): Same. (df_live_verify_transfer_functions): Same. (df_mir_alloc): Same. (df_mir_reset): Same. (df_mir_init): Same. (df_mir_confluence_n): Same. (df_mir_free): Same. (df_mir_top_dump): Same. (df_word_lr_alloc): Same. (df_word_lr_reset): Same. (df_word_lr_init): Same. (df_word_lr_confluence_n): Same. (df_word_lr_free): Same. (df_word_lr_top_dump): Same. (df_md_alloc): Same. (df_md_simulate_one_insn): Same. (df_md_reset): Same. (df_md_init): Same. (df_md_free): Same. (df_md_top_dump): Same. * df-scan.c (df_insn_delete): Same. (df_insn_rescan): Same. (df_notes_rescan): Same. (df_sort_and_compress_mws): Same. (df_install_mws): Same. (df_refs_add_to_chains): Same. (df_ref_create_structure): Same. (df_ref_record): Same. (df_def_record_1): Same. (df_find_hard_reg_defs): Same. (df_uses_record): Same. (df_get_conditional_uses): Same. (df_get_call_refs): Same. (df_recompute_luids): Same. (df_get_entry_block_def_set): Same. (df_entry_block_defs_collect): Same. (df_get_exit_block_use_set): Same. (df_exit_block_uses_collect): Same. (df_mws_verify): Same. (df_bb_verify): Same. * df.h (df_scan_get_bb_info): Same. * doc/tm.texi: Same. * dse.c (record_store): Same. * dumpfile.h: Same. * emit-rtl.c (const_fixed_hasher::equal): Same. (set_mem_attributes_minus_bitpos): Same. (change_address): Same. (adjust_address_1): Same. (offset_address): Same. * emit-rtl.h: Same. * except.c (dw2_build_landing_pads): Same. (sjlj_emit_dispatch_table): Same. * explow.c (allocate_dynamic_stack_space): Same. (emit_stack_probe): Same. (probe_stack_range): Same. * expmed.c (store_bit_field_using_insv): Same. (store_bit_field_1): Same. (store_integral_bit_field): Same. (extract_bit_field_using_extv): Same. (extract_bit_field_1): Same. (emit_cstore): Same. * expr.c (emit_block_move_via_cpymem): Same. (expand_cmpstrn_or_cmpmem): Same. (set_storage_via_setmem): Same. (emit_single_push_insn_1): Same. (expand_assignment): Same. (store_constructor): Same. (expand_expr_real_2): Same. (expand_expr_real_1): Same. (try_casesi): Same. * flags.h: Same. * function.c (try_fit_stack_local): Same. (assign_stack_local_1): Same. (assign_stack_local): Same. (cut_slot_from_list): Same. (insert_slot_to_list): Same. (max_slot_level): Same. (move_slot_to_level): Same. (temp_address_hasher::equal): Same. (remove_unused_temp_slot_addresses): Same. (assign_temp): Same. (combine_temp_slots): Same. (update_temp_slot_address): Same. (preserve_temp_slots): Same. * function.h: Same. * fwprop.c: Same. * gcc-rich-location.h: Same. * gcov.c: Same. * genattrtab.c (check_attr_test): Same. (check_attr_value): Same. (convert_set_attr_alternative): Same. (convert_set_attr): Same. (check_defs): Same. (copy_boolean): Same. (get_attr_value): Same. (expand_delays): Same. (make_length_attrs): Same. (min_fn): Same. (make_alternative_compare): Same. (simplify_test_exp): Same. (tests_attr_p): Same. (get_attr_order): Same. (clear_struct_flag): Same. (gen_attr): Same. (compares_alternatives_p): Same. (gen_insn): Same. (gen_delay): Same. (find_attrs_to_cache): Same. (write_test_expr): Same. (walk_attr_value): Same. (write_attr_get): Same. (eliminate_known_true): Same. (write_insn_cases): Same. (write_attr_case): Same. (write_attr_valueq): Same. (write_attr_value): Same. (write_dummy_eligible_delay): Same. (next_comma_elt): Same. (find_attr): Same. (make_internal_attr): Same. (copy_rtx_unchanging): Same. (gen_insn_reserv): Same. (check_tune_attr): Same. (make_automaton_attrs): Same. (handle_arg): Same. * genextract.c (gen_insn): Same. (VEC_char_to_string): Same. * genmatch.c (print_operand): Same. (lower): Same. (parser::parse_operation): Same. (parser::parse_capture): Same. (parser::parse_c_expr): Same. (parser::parse_simplify): Same. (main): Same. * genoutput.c (output_operand_data): Same. (output_get_insn_name): Same. (compare_operands): Same. (place_operands): Same. (process_template): Same. (validate_insn_alternatives): Same. (validate_insn_operands): Same. (gen_expand): Same. (note_constraint): Same. * genpreds.c (write_one_predicate_function): Same. (add_constraint): Same. (process_define_register_constraint): Same. (write_lookup_constraint_1): Same. (write_lookup_constraint_array): Same. (write_insn_constraint_len): Same. (write_reg_class_for_constraint_1): Same. (write_constraint_satisfied_p_array): Same. * genrecog.c (optimize_subroutine_group): Same. * gensupport.c (process_define_predicate): Same. (queue_pattern): Same. (remove_from_queue): Same. (process_rtx): Same. (is_predicable): Same. (change_subst_attribute): Same. (subst_pattern_match): Same. (alter_constraints): Same. (alter_attrs_for_insn): Same. (shift_output_template): Same. (alter_output_for_subst_insn): Same. (process_one_cond_exec): Same. (subst_dup): Same. (process_define_cond_exec): Same. (mnemonic_htab_callback): Same. (gen_mnemonic_attr): Same. (read_md_rtx): Same. * ggc-page.c: Same. * gimple-loop-interchange.cc (dump_reduction): Same. (dump_induction): Same. (loop_cand::~loop_cand): Same. (free_data_refs_with_aux): Same. (tree_loop_interchange::interchange_loops): Same. (tree_loop_interchange::map_inductions_to_loop): Same. (tree_loop_interchange::move_code_to_inner_loop): Same. (compute_access_stride): Same. (compute_access_strides): Same. (proper_loop_form_for_interchange): Same. (tree_loop_interchange_compute_ddrs): Same. (prune_datarefs_not_in_loop): Same. (prepare_data_references): Same. (pass_linterchange::execute): Same. * gimple-loop-jam.c (bb_prevents_fusion_p): Same. (unroll_jam_possible_p): Same. (fuse_loops): Same. (adjust_unroll_factor): Same. (tree_loop_unroll_and_jam): Same. * gimple-loop-versioning.cc (loop_versioning::~loop_versioning): Same. (loop_versioning::expensive_stmt_p): Same. (loop_versioning::version_for_unity): Same. (loop_versioning::dump_inner_likelihood): Same. (loop_versioning::find_per_loop_multiplication): Same. (loop_versioning::analyze_term_using_scevs): Same. (loop_versioning::record_address_fragment): Same. (loop_versioning::analyze_expr): Same. (loop_versioning::analyze_blocks): Same. (loop_versioning::prune_conditions): Same. (loop_versioning::merge_loop_info): Same. (loop_versioning::add_loop_to_queue): Same. (loop_versioning::decide_whether_loop_is_versionable): Same. (loop_versioning::make_versioning_decisions): Same. (loop_versioning::implement_versioning_decisions): Same. * gimple-ssa-evrp-analyze.c (evrp_range_analyzer::record_ranges_from_phis): Same. * gimple-ssa-store-merging.c (split_store::split_store): Same. (count_multiple_uses): Same. (split_group): Same. (imm_store_chain_info::output_merged_store): Same. (pass_store_merging::process_store): Same. * gimple-ssa-strength-reduction.c (slsr_process_phi): Same. * gimple-ssa-warn-alloca.c (adjusted_warn_limit): Same. (is_max): Same. (alloca_call_type): Same. (pass_walloca::execute): Same. * gimple-streamer-in.c (input_phi): Same. (input_gimple_stmt): Same. * gimple-streamer.h: Same. * godump.c (go_force_record_alignment): Same. (go_format_type): Same. (go_output_type): Same. (go_output_fndecl): Same. (go_output_typedef): Same. (keyword_hash_init): Same. (find_dummy_types): Same. * graph.c (draw_cfg_nodes_no_loops): Same. (draw_cfg_nodes_for_loop): Same. * hard-reg-set.h (hard_reg_set_iter_next): Same. * hsa-brig.c: Same. * hsa-common.h (hsa_internal_fn_hasher::equal): Same. * hsa-dump.c (dump_hsa_cfun): Same. * hsa-gen.c (gen_function_def_parameters): Same. * hsa-regalloc.c (dump_hsa_cfun_regalloc): Same. * input.c (dump_line_table_statistics): Same. (test_lexer): Same. * input.h: Same. * internal-fn.c (get_multi_vector_move): Same. (expand_load_lanes_optab_fn): Same. (expand_GOMP_SIMT_ENTER_ALLOC): Same. (expand_GOMP_SIMT_EXIT): Same. (expand_GOMP_SIMT_LAST_LANE): Same. (expand_GOMP_SIMT_ORDERED_PRED): Same. (expand_GOMP_SIMT_VOTE_ANY): Same. (expand_GOMP_SIMT_XCHG_BFLY): Same. (expand_GOMP_SIMT_XCHG_IDX): Same. (expand_addsub_overflow): Same. (expand_neg_overflow): Same. (expand_mul_overflow): Same. (expand_call_mem_ref): Same. (expand_mask_load_optab_fn): Same. (expand_scatter_store_optab_fn): Same. (expand_gather_load_optab_fn): Same. * ipa-cp.c (ipa_get_parm_lattices): Same. (print_all_lattices): Same. (ignore_edge_p): Same. (build_toporder_info): Same. (free_toporder_info): Same. (push_node_to_stack): Same. (ipcp_lattice::set_contains_variable): Same. (set_agg_lats_to_bottom): Same. (ipcp_bits_lattice::meet_with): Same. (set_single_call_flag): Same. (initialize_node_lattices): Same. (ipa_get_jf_ancestor_result): Same. (ipcp_verify_propagated_values): Same. (propagate_scalar_across_jump_function): Same. (propagate_context_across_jump_function): Same. (propagate_bits_across_jump_function): Same. (ipa_vr_operation_and_type_effects): Same. (propagate_vr_across_jump_function): Same. (set_check_aggs_by_ref): Same. (set_chain_of_aglats_contains_variable): Same. (merge_aggregate_lattices): Same. (agg_pass_through_permissible_p): Same. (propagate_aggs_across_jump_function): Same. (call_passes_through_thunk_p): Same. (propagate_constants_across_call): Same. (devirtualization_time_bonus): Same. (good_cloning_opportunity_p): Same. (context_independent_aggregate_values): Same. (gather_context_independent_values): Same. (perform_estimation_of_a_value): Same. (estimate_local_effects): Same. (value_topo_info::add_val): Same. (add_all_node_vals_to_toposort): Same. (value_topo_info::propagate_effects): Same. (ipcp_propagate_stage): Same. (ipcp_discover_new_direct_edges): Same. (same_node_or_its_all_contexts_clone_p): Same. (cgraph_edge_brings_value_p): Same. (gather_edges_for_value): Same. (create_specialized_node): Same. (find_more_scalar_values_for_callers_subset): Same. (find_more_contexts_for_caller_subset): Same. (copy_plats_to_inter): Same. (intersect_aggregates_with_edge): Same. (find_aggregate_values_for_callers_subset): Same. (cgraph_edge_brings_all_agg_vals_for_node): Same. (decide_about_value): Same. (decide_whether_version_node): Same. (spread_undeadness): Same. (identify_dead_nodes): Same. (ipcp_store_vr_results): Same. * ipa-devirt.c (final_warning_record::grow_type_warnings): Same. * ipa-fnsummary.c (ipa_fn_summary::account_size_time): Same. (redirect_to_unreachable): Same. (edge_set_predicate): Same. (evaluate_conditions_for_known_args): Same. (evaluate_properties_for_edge): Same. (ipa_fn_summary_t::duplicate): Same. (ipa_call_summary_t::duplicate): Same. (dump_ipa_call_summary): Same. (ipa_dump_fn_summary): Same. (eliminated_by_inlining_prob): Same. (set_cond_stmt_execution_predicate): Same. (set_switch_stmt_execution_predicate): Same. (compute_bb_predicates): Same. (will_be_nonconstant_expr_predicate): Same. (phi_result_unknown_predicate): Same. (analyze_function_body): Same. (compute_fn_summary): Same. (estimate_edge_devirt_benefit): Same. (estimate_edge_size_and_time): Same. (estimate_calls_size_and_time): Same. (estimate_node_size_and_time): Same. (remap_edge_change_prob): Same. (remap_edge_summaries): Same. (ipa_merge_fn_summary_after_inlining): Same. (ipa_fn_summary_generate): Same. (inline_read_section): Same. (ipa_fn_summary_read): Same. (ipa_fn_summary_write): Same. * ipa-fnsummary.h: Same. * ipa-hsa.c (ipa_hsa_read_section): Same. * ipa-icf-gimple.c (func_checker::compare_loops): Same. * ipa-icf.c (sem_function::param_used_p): Same. * ipa-inline-analysis.c (do_estimate_edge_time): Same. * ipa-inline.c (edge_badness): Same. (inline_small_functions): Same. * ipa-polymorphic-call.c (ipa_polymorphic_call_context::stream_out): Same. * ipa-predicate.c (predicate::remap_after_duplication): Same. (predicate::remap_after_inlining): Same. (predicate::stream_out): Same. * ipa-predicate.h: Same. * ipa-profile.c (ipa_profile_read_summary): Same. * ipa-prop.c (ipa_get_param_decl_index_1): Same. (count_formal_params): Same. (ipa_dump_param): Same. (ipa_alloc_node_params): Same. (ipa_print_node_jump_functions_for_edge): Same. (ipa_print_node_jump_functions): Same. (ipa_load_from_parm_agg): Same. (get_ancestor_addr_info): Same. (ipa_compute_jump_functions_for_edge): Same. (ipa_analyze_virtual_call_uses): Same. (ipa_analyze_stmt_uses): Same. (ipa_analyze_params_uses_in_bb): Same. (update_jump_functions_after_inlining): Same. (try_decrement_rdesc_refcount): Same. (ipa_impossible_devirt_target): Same. (update_indirect_edges_after_inlining): Same. (combine_controlled_uses_counters): Same. (ipa_edge_args_sum_t::duplicate): Same. (ipa_write_jump_function): Same. (ipa_write_indirect_edge_info): Same. (ipa_write_node_info): Same. (ipa_read_edge_info): Same. (ipa_prop_read_section): Same. (read_replacements_section): Same. * ipa-prop.h (ipa_get_param_count): Same. (ipa_get_param): Same. (ipa_get_type): Same. (ipa_get_param_move_cost): Same. (ipa_set_param_used): Same. (ipa_get_controlled_uses): Same. (ipa_set_controlled_uses): Same. (ipa_get_cs_argument_count): Same. * ipa-pure-const.c (analyze_function): Same. (pure_const_read_summary): Same. * ipa-ref.h: Same. * ipa-reference.c (ipa_reference_read_optimization_summary): Same. * ipa-split.c (test_nonssa_use): Same. (dump_split_point): Same. (dominated_by_forbidden): Same. (split_part_set_ssa_name_p): Same. (find_split_points): Same. * ira-build.c (finish_loop_tree_nodes): Same. (low_pressure_loop_node_p): Same. * ira-color.c (ira_reuse_stack_slot): Same. * ira-int.h: Same. * ira.c (setup_reg_equiv): Same. (print_insn_chain): Same. (ira): Same. * loop-doloop.c (doloop_condition_get): Same. (add_test): Same. (record_reg_sets): Same. (doloop_optimize): Same. * loop-init.c (loop_optimizer_init): Same. (fix_loop_structure): Same. * loop-invariant.c (merge_identical_invariants): Same. (compute_always_reached): Same. (find_exits): Same. (may_assign_reg_p): Same. (find_invariants_bb): Same. (find_invariants_body): Same. (replace_uses): Same. (can_move_invariant_reg): Same. (free_inv_motion_data): Same. (move_single_loop_invariants): Same. (change_pressure): Same. (mark_ref_regs): Same. (calculate_loop_reg_pressure): Same. * loop-iv.c (biv_entry_hasher::equal): Same. (iv_extend_to_rtx_code): Same. (check_iv_ref_table_size): Same. (clear_iv_info): Same. (latch_dominating_def): Same. (iv_get_reaching_def): Same. (iv_constant): Same. (iv_subreg): Same. (iv_extend): Same. (iv_neg): Same. (iv_add): Same. (iv_mult): Same. (get_biv_step): Same. (record_iv): Same. (analyzed_for_bivness_p): Same. (record_biv): Same. (iv_analyze_biv): Same. (iv_analyze_expr): Same. (iv_analyze_def): Same. (iv_analyze_op): Same. (iv_analyze): Same. (iv_analyze_result): Same. (biv_p): Same. (eliminate_implied_conditions): Same. (simplify_using_initial_values): Same. (shorten_into_mode): Same. (canonicalize_iv_subregs): Same. (determine_max_iter): Same. (check_simple_exit): Same. (find_simple_exit): Same. (get_simple_loop_desc): Same. * loop-unroll.c (report_unroll): Same. (decide_unrolling): Same. (unroll_loops): Same. (loop_exit_at_end_p): Same. (decide_unroll_constant_iterations): Same. (unroll_loop_constant_iterations): Same. (compare_and_jump_seq): Same. (unroll_loop_runtime_iterations): Same. (decide_unroll_stupid): Same. (unroll_loop_stupid): Same. (referenced_in_one_insn_in_loop_p): Same. (reset_debug_uses_in_loop): Same. (analyze_iv_to_split_insn): Same. * lra-eliminations.c (lra_debug_elim_table): Same. (setup_can_eliminate): Same. (form_sum): Same. (lra_get_elimination_hard_regno): Same. (lra_eliminate_regs_1): Same. (eliminate_regs_in_insn): Same. (update_reg_eliminate): Same. (init_elimination): Same. (lra_eliminate): Same. * lra-int.h: Same. * lra-lives.c (initiate_live_solver): Same. * lra-remat.c (create_remat_bb_data): Same. * lra-spills.c (lra_spill): Same. * lra.c (lra_set_insn_recog_data): Same. (lra_set_used_insn_alternative_by_uid): Same. (init_reg_info): Same. (expand_reg_info): Same. * lto-cgraph.c (output_symtab): Same. (read_identifier): Same. (get_alias_symbol): Same. (input_node): Same. (input_varpool_node): Same. (input_ref): Same. (input_edge): Same. (input_cgraph_1): Same. (input_refs): Same. (input_symtab): Same. (input_offload_tables): Same. (output_cgraph_opt_summary): Same. (input_edge_opt_summary): Same. (input_cgraph_opt_section): Same. * lto-section-in.c (lto_free_raw_section_data): Same. (lto_create_simple_input_block): Same. (lto_free_function_in_decl_state_for_node): Same. * lto-streamer-in.c (lto_tag_check_set): Same. (lto_location_cache::revert_location_cache): Same. (lto_location_cache::input_location): Same. (lto_input_location): Same. (stream_input_location_now): Same. (lto_input_tree_ref): Same. (lto_input_eh_catch_list): Same. (input_eh_region): Same. (lto_init_eh): Same. (make_new_block): Same. (input_cfg): Same. (fixup_call_stmt_edges): Same. (input_struct_function_base): Same. (input_function): Same. (lto_read_body_or_constructor): Same. (lto_read_tree_1): Same. (lto_read_tree): Same. (lto_input_scc): Same. (lto_input_tree_1): Same. (lto_input_toplevel_asms): Same. (lto_input_mode_table): Same. (lto_reader_init): Same. (lto_data_in_create): Same. * lto-streamer-out.c (output_cfg): Same. * lto-streamer.h: Same. * modulo-sched.c (duplicate_insns_of_cycles): Same. (generate_prolog_epilog): Same. (mark_loop_unsched): Same. (dump_insn_location): Same. (loop_canon_p): Same. (sms_schedule): Same. * omp-expand.c (expand_omp_for_ordered_loops): Same. (expand_omp_for_generic): Same. (expand_omp_for_static_nochunk): Same. (expand_omp_for_static_chunk): Same. (expand_omp_simd): Same. (expand_omp_taskloop_for_inner): Same. (expand_oacc_for): Same. (expand_omp_atomic_pipeline): Same. (mark_loops_in_oacc_kernels_region): Same. * omp-offload.c (oacc_xform_loop): Same. * omp-simd-clone.c (simd_clone_adjust): Same. * optabs-query.c (get_traditional_extraction_insn): Same. * optabs.c (expand_vector_broadcast): Same. (expand_binop_directly): Same. (expand_twoval_unop): Same. (expand_twoval_binop): Same. (expand_unop_direct): Same. (emit_indirect_jump): Same. (emit_conditional_move): Same. (emit_conditional_neg_or_complement): Same. (emit_conditional_add): Same. (vector_compare_rtx): Same. (expand_vec_perm_1): Same. (expand_vec_perm_const): Same. (expand_vec_cond_expr): Same. (expand_vec_series_expr): Same. (maybe_emit_atomic_exchange): Same. (maybe_emit_sync_lock_test_and_set): Same. (expand_atomic_compare_and_swap): Same. (expand_atomic_load): Same. (expand_atomic_store): Same. (maybe_emit_op): Same. (valid_multiword_target_p): Same. (create_integer_operand): Same. (maybe_legitimize_operand_same_code): Same. (maybe_legitimize_operand): Same. (create_convert_operand_from_type): Same. (can_reuse_operands_p): Same. (maybe_legitimize_operands): Same. (maybe_gen_insn): Same. (maybe_expand_insn): Same. (maybe_expand_jump_insn): Same. (expand_insn): Same. * optabs.h (create_expand_operand): Same. (create_fixed_operand): Same. (create_output_operand): Same. (create_input_operand): Same. (create_convert_operand_to): Same. (create_convert_operand_from): Same. * optinfo.h: Same. * poly-int.h: Same. * predict.c (optimize_insn_for_speed_p): Same. (optimize_loop_for_size_p): Same. (optimize_loop_for_speed_p): Same. (optimize_loop_nest_for_speed_p): Same. (get_base_value): Same. (predicted_by_loop_heuristics_p): Same. (predict_extra_loop_exits): Same. (predict_loops): Same. (predict_paths_for_bb): Same. (predict_paths_leading_to): Same. (propagate_freq): Same. (pass_profile::execute): Same. * predict.h: Same. * profile-count.c (profile_count::differs_from_p): Same. (profile_probability::differs_lot_from_p): Same. * profile-count.h: Same. * profile.c (branch_prob): Same. * regrename.c (free_chain_data): Same. (mark_conflict): Same. (create_new_chain): Same. (merge_overlapping_regs): Same. (init_rename_info): Same. (merge_chains): Same. (regrename_analyze): Same. (regrename_do_replace): Same. (scan_rtx_reg): Same. (record_out_operands): Same. (build_def_use): Same. * regrename.h: Same. * reload.h: Same. * reload1.c (init_reload): Same. (maybe_fix_stack_asms): Same. (copy_reloads): Same. (count_pseudo): Same. (count_spilled_pseudo): Same. (find_reg): Same. (find_reload_regs): Same. (select_reload_regs): Same. (spill_hard_reg): Same. (fixup_eh_region_note): Same. (set_reload_reg): Same. (allocate_reload_reg): Same. (compute_reload_subreg_offset): Same. (reload_adjust_reg_for_icode): Same. (emit_input_reload_insns): Same. (emit_output_reload_insns): Same. (do_input_reload): Same. (inherit_piecemeal_p): Same. * rtl.h: Same. * sanopt.c (maybe_get_dominating_check): Same. (maybe_optimize_ubsan_ptr_ifn): Same. (can_remove_asan_check): Same. (maybe_optimize_asan_check_ifn): Same. (sanopt_optimize_walker): Same. * sched-deps.c (add_dependence_list): Same. (chain_to_prev_insn): Same. (add_insn_mem_dependence): Same. (create_insn_reg_set): Same. (maybe_extend_reg_info_p): Same. (sched_analyze_reg): Same. (sched_analyze_1): Same. (get_implicit_reg_pending_clobbers): Same. (chain_to_prev_insn_p): Same. (deps_analyze_insn): Same. (deps_start_bb): Same. (sched_free_deps): Same. (init_deps): Same. (init_deps_reg_last): Same. (free_deps): Same. * sched-ebb.c: Same. * sched-int.h: Same. * sched-rgn.c (add_branch_dependences): Same. (concat_insn_mem_list): Same. (deps_join): Same. (sched_rgn_compute_dependencies): Same. * sel-sched-ir.c (reset_target_context): Same. (copy_deps_context): Same. (init_id_from_df): Same. (has_dependence_p): Same. (change_loops_latches): Same. (bb_top_order_comparator): Same. (make_region_from_loop_preheader): Same. (sel_init_pipelining): Same. (get_loop_nest_for_rgn): Same. (make_regions_from_the_rest): Same. (sel_is_loop_preheader_p): Same. * sel-sched-ir.h (inner_loop_header_p): Same. (get_all_loop_exits): Same. * selftest.h: Same. * sese.c (sese_build_liveouts): Same. (sese_insert_phis_for_liveouts): Same. * sese.h (defined_in_sese_p): Same. * sreal.c (sreal::stream_out): Same. * sreal.h: Same. * streamer-hooks.h: Same. * target-globals.c (save_target_globals): Same. * target-globals.h: Same. * target.def: Same. * target.h: Same. * targhooks.c (default_has_ifunc_p): Same. (default_empty_mask_is_expensive): Same. (default_init_cost): Same. * targhooks.h: Same. * toplev.c: Same. * tree-affine.c (aff_combination_mult): Same. (aff_combination_expand): Same. (aff_combination_constant_multiple_p): Same. * tree-affine.h: Same. * tree-cfg.c (build_gimple_cfg): Same. (replace_loop_annotate_in_block): Same. (replace_uses_by): Same. (remove_bb): Same. (dump_cfg_stats): Same. (gimple_duplicate_sese_region): Same. (gimple_duplicate_sese_tail): Same. (move_block_to_fn): Same. (replace_block_vars_by_duplicates): Same. (move_sese_region_to_fn): Same. (print_loops_bb): Same. (print_loop): Same. (print_loops): Same. (debug): Same. (debug_loops): Same. * tree-cfg.h: Same. * tree-chrec.c (chrec_fold_plus_poly_poly): Same. (chrec_fold_multiply_poly_poly): Same. (chrec_evaluate): Same. (chrec_component_in_loop_num): Same. (reset_evolution_in_loop): Same. (is_multivariate_chrec): Same. (chrec_contains_symbols): Same. (nb_vars_in_chrec): Same. (chrec_convert_1): Same. (chrec_convert_aggressive): Same. * tree-chrec.h: Same. * tree-core.h: Same. * tree-data-ref.c (dump_data_dependence_relation): Same. (canonicalize_base_object_address): Same. (data_ref_compare_tree): Same. (prune_runtime_alias_test_list): Same. (get_segment_min_max): Same. (create_intersect_range_checks): Same. (conflict_fn_no_dependence): Same. (object_address_invariant_in_loop_p): Same. (analyze_ziv_subscript): Same. (analyze_siv_subscript_cst_affine): Same. (analyze_miv_subscript): Same. (analyze_overlapping_iterations): Same. (build_classic_dist_vector_1): Same. (add_other_self_distances): Same. (same_access_functions): Same. (build_classic_dir_vector): Same. (subscript_dependence_tester_1): Same. (subscript_dependence_tester): Same. (access_functions_are_affine_or_constant_p): Same. (get_references_in_stmt): Same. (loop_nest_has_data_refs): Same. (graphite_find_data_references_in_stmt): Same. (find_data_references_in_bb): Same. (get_base_for_alignment): Same. (find_loop_nest_1): Same. (find_loop_nest): Same. * tree-data-ref.h (dr_alignment): Same. (ddr_dependence_level): Same. * tree-if-conv.c (fold_build_cond_expr): Same. (add_to_predicate_list): Same. (add_to_dst_predicate_list): Same. (phi_convertible_by_degenerating_args): Same. (idx_within_array_bound): Same. (all_preds_critical_p): Same. (pred_blocks_visited_p): Same. (predicate_bbs): Same. (build_region): Same. (if_convertible_loop_p_1): Same. (is_cond_scalar_reduction): Same. (predicate_scalar_phi): Same. (remove_conditions_and_labels): Same. (combine_blocks): Same. (version_loop_for_if_conversion): Same. (versionable_outer_loop_p): Same. (ifcvt_local_dce): Same. (tree_if_conversion): Same. (pass_if_conversion::gate): Same. * tree-if-conv.h: Same. * tree-inline.c (maybe_move_debug_stmts_to_successors): Same. * tree-loop-distribution.c (bb_top_order_cmp): Same. (free_rdg): Same. (stmt_has_scalar_dependences_outside_loop): Same. (copy_loop_before): Same. (create_bb_after_loop): Same. (const_with_all_bytes_same): Same. (generate_memset_builtin): Same. (generate_memcpy_builtin): Same. (destroy_loop): Same. (build_rdg_partition_for_vertex): Same. (compute_access_range): Same. (data_ref_segment_size): Same. (latch_dominated_by_data_ref): Same. (compute_alias_check_pairs): Same. (fuse_memset_builtins): Same. (finalize_partitions): Same. (find_seed_stmts_for_distribution): Same. (prepare_perfect_loop_nest): Same. * tree-parloops.c (lambda_transform_legal_p): Same. (loop_parallel_p): Same. (reduc_stmt_res): Same. (add_field_for_name): Same. (create_call_for_reduction_1): Same. (replace_uses_in_bb_by): Same. (transform_to_exit_first_loop_alt): Same. (try_transform_to_exit_first_loop_alt): Same. (transform_to_exit_first_loop): Same. (num_phis): Same. (gen_parallel_loop): Same. (gather_scalar_reductions): Same. (get_omp_data_i_param): Same. (try_create_reduction_list): Same. (oacc_entry_exit_single_gang): Same. (parallelize_loops): Same. * tree-pass.h: Same. * tree-predcom.c (determine_offset): Same. (last_always_executed_block): Same. (split_data_refs_to_components): Same. (suitable_component_p): Same. (valid_initializer_p): Same. (find_looparound_phi): Same. (insert_looparound_copy): Same. (add_looparound_copies): Same. (determine_roots_comp): Same. (predcom_tmp_var): Same. (initialize_root_vars): Same. (initialize_root_vars_store_elim_1): Same. (initialize_root_vars_store_elim_2): Same. (finalize_eliminated_stores): Same. (initialize_root_vars_lm): Same. (remove_stmt): Same. (determine_unroll_factor): Same. (execute_pred_commoning_cbck): Same. (base_names_in_chain_on): Same. (combine_chains): Same. (pcom_stmt_dominates_stmt_p): Same. (try_combine_chains): Same. (prepare_initializers_chain_store_elim): Same. (prepare_initializers_chain): Same. (prepare_initializers): Same. (prepare_finalizers_chain): Same. (prepare_finalizers): Same. (insert_init_seqs): Same. * tree-scalar-evolution.c (loop_phi_node_p): Same. (compute_overall_effect_of_inner_loop): Same. (add_to_evolution_1): Same. (add_to_evolution): Same. (follow_ssa_edge_binary): Same. (follow_ssa_edge_expr): Same. (backedge_phi_arg_p): Same. (follow_ssa_edge_in_condition_phi_branch): Same. (follow_ssa_edge_in_condition_phi): Same. (follow_ssa_edge_inner_loop_phi): Same. (follow_ssa_edge): Same. (analyze_evolution_in_loop): Same. (analyze_initial_condition): Same. (interpret_loop_phi): Same. (interpret_condition_phi): Same. (interpret_rhs_expr): Same. (interpret_expr): Same. (interpret_gimple_assign): Same. (analyze_scalar_evolution_1): Same. (analyze_scalar_evolution): Same. (analyze_scalar_evolution_for_address_of): Same. (get_instantiated_value_entry): Same. (loop_closed_phi_def): Same. (instantiate_scev_name): Same. (instantiate_scev_poly): Same. (instantiate_scev_binary): Same. (instantiate_scev_convert): Same. (instantiate_scev_not): Same. (instantiate_scev_r): Same. (instantiate_scev): Same. (resolve_mixers): Same. (initialize_scalar_evolutions_analyzer): Same. (scev_reset_htab): Same. (scev_reset): Same. (derive_simple_iv_with_niters): Same. (simple_iv_with_niters): Same. (expression_expensive_p): Same. (final_value_replacement_loop): Same. * tree-scalar-evolution.h (block_before_loop): Same. * tree-ssa-address.h: Same. * tree-ssa-dce.c (find_obviously_necessary_stmts): Same. * tree-ssa-dom.c (edge_info::record_simple_equiv): Same. (record_edge_info): Same. * tree-ssa-live.c (var_map_base_fini): Same. (remove_unused_locals): Same. * tree-ssa-live.h: Same. * tree-ssa-loop-ch.c (should_duplicate_loop_header_p): Same. (pass_ch_vect::execute): Same. (pass_ch::process_loop_p): Same. * tree-ssa-loop-im.c (mem_ref_hasher::hash): Same. (movement_possibility): Same. (outermost_invariant_loop): Same. (stmt_cost): Same. (determine_max_movement): Same. (invariantness_dom_walker::before_dom_children): Same. (move_computations): Same. (may_move_till): Same. (force_move_till_op): Same. (force_move_till): Same. (memref_free): Same. (record_mem_ref_loc): Same. (set_ref_stored_in_loop): Same. (mark_ref_stored): Same. (sort_bbs_in_loop_postorder_cmp): Same. (sort_locs_in_loop_postorder_cmp): Same. (analyze_memory_references): Same. (mem_refs_may_alias_p): Same. (find_ref_loc_in_loop_cmp): Same. (rewrite_mem_ref_loc::operator): Same. (first_mem_ref_loc_1::operator): Same. (sm_set_flag_if_changed::operator): Same. (execute_sm_if_changed_flag_set): Same. (execute_sm): Same. (hoist_memory_references): Same. (ref_always_accessed::operator): Same. (refs_independent_p): Same. (record_dep_loop): Same. (ref_indep_loop_p_1): Same. (ref_indep_loop_p): Same. (can_sm_ref_p): Same. (find_refs_for_sm): Same. (loop_suitable_for_sm): Same. (store_motion_loop): Same. (store_motion): Same. (fill_always_executed_in): Same. * tree-ssa-loop-ivcanon.c (constant_after_peeling): Same. (estimated_unrolled_size): Same. (loop_edge_to_cancel): Same. (remove_exits_and_undefined_stmts): Same. (remove_redundant_iv_tests): Same. (unloop_loops): Same. (estimated_peeled_sequence_size): Same. (try_peel_loop): Same. (canonicalize_loop_induction_variables): Same. (canonicalize_induction_variables): Same. * tree-ssa-loop-ivopts.c (iv_inv_expr_hasher::equal): Same. (name_info): Same. (stmt_after_inc_pos): Same. (contains_abnormal_ssa_name_p): Same. (niter_for_exit): Same. (find_bivs): Same. (mark_bivs): Same. (find_givs_in_bb): Same. (find_induction_variables): Same. (find_interesting_uses_cond): Same. (outermost_invariant_loop_for_expr): Same. (idx_find_step): Same. (add_candidate_1): Same. (add_iv_candidate_derived_from_uses): Same. (alloc_use_cost_map): Same. (prepare_decl_rtl): Same. (generic_predict_doloop_p): Same. (computation_cost): Same. (determine_common_wider_type): Same. (get_computation_aff_1): Same. (get_use_type): Same. (determine_group_iv_cost_address): Same. (iv_period): Same. (difference_cannot_overflow_p): Same. (may_eliminate_iv): Same. (determine_set_costs): Same. (cheaper_cost_pair): Same. (compare_cost_pair): Same. (iv_ca_cand_for_group): Same. (iv_ca_recount_cost): Same. (iv_ca_set_remove_invs): Same. (iv_ca_set_no_cp): Same. (iv_ca_set_add_invs): Same. (iv_ca_set_cp): Same. (iv_ca_add_group): Same. (iv_ca_cost): Same. (iv_ca_compare_deps): Same. (iv_ca_delta_reverse): Same. (iv_ca_delta_commit): Same. (iv_ca_cand_used_p): Same. (iv_ca_delta_free): Same. (iv_ca_new): Same. (iv_ca_free): Same. (iv_ca_dump): Same. (iv_ca_extend): Same. (iv_ca_narrow): Same. (iv_ca_prune): Same. (cheaper_cost_with_cand): Same. (iv_ca_replace): Same. (try_add_cand_for): Same. (get_initial_solution): Same. (try_improve_iv_set): Same. (find_optimal_iv_set_1): Same. (create_new_iv): Same. (rewrite_use_compare): Same. (remove_unused_ivs): Same. (determine_scaling_factor): Same. * tree-ssa-loop-ivopts.h: Same. * tree-ssa-loop-manip.c (create_iv): Same. (compute_live_loop_exits): Same. (add_exit_phi): Same. (add_exit_phis): Same. (find_uses_to_rename_use): Same. (find_uses_to_rename_def): Same. (find_uses_to_rename_in_loop): Same. (rewrite_into_loop_closed_ssa): Same. (check_loop_closed_ssa_bb): Same. (split_loop_exit_edge): Same. (ip_end_pos): Same. (ip_normal_pos): Same. (copy_phi_node_args): Same. (gimple_duplicate_loop_to_header_edge): Same. (can_unroll_loop_p): Same. (determine_exit_conditions): Same. (scale_dominated_blocks_in_loop): Same. (niter_for_unrolled_loop): Same. (tree_transform_and_unroll_loop): Same. (rewrite_all_phi_nodes_with_iv): Same. * tree-ssa-loop-manip.h: Same. * tree-ssa-loop-niter.c (number_of_iterations_ne_max): Same. (number_of_iterations_ne): Same. (assert_no_overflow_lt): Same. (assert_loop_rolls_lt): Same. (number_of_iterations_lt): Same. (adjust_cond_for_loop_until_wrap): Same. (tree_simplify_using_condition): Same. (simplify_using_initial_conditions): Same. (simplify_using_outer_evolutions): Same. (loop_only_exit_p): Same. (ssa_defined_by_minus_one_stmt_p): Same. (number_of_iterations_popcount): Same. (number_of_iterations_exit): Same. (find_loop_niter): Same. (finite_loop_p): Same. (chain_of_csts_start): Same. (get_val_for): Same. (loop_niter_by_eval): Same. (derive_constant_upper_bound_ops): Same. (do_warn_aggressive_loop_optimizations): Same. (record_estimate): Same. (get_cst_init_from_scev): Same. (record_nonwrapping_iv): Same. (idx_infer_loop_bounds): Same. (infer_loop_bounds_from_ref): Same. (infer_loop_bounds_from_array): Same. (infer_loop_bounds_from_pointer_arith): Same. (infer_loop_bounds_from_signedness): Same. (bound_index): Same. (discover_iteration_bound_by_body_walk): Same. (maybe_lower_iteration_bound): Same. (estimate_numbers_of_iterations): Same. (estimated_loop_iterations): Same. (estimated_loop_iterations_int): Same. (max_loop_iterations): Same. (max_loop_iterations_int): Same. (likely_max_loop_iterations): Same. (likely_max_loop_iterations_int): Same. (estimated_stmt_executions_int): Same. (max_stmt_executions): Same. (likely_max_stmt_executions): Same. (estimated_stmt_executions): Same. (stmt_dominates_stmt_p): Same. (nowrap_type_p): Same. (loop_exits_before_overflow): Same. (scev_var_range_cant_overflow): Same. (scev_probably_wraps_p): Same. (free_numbers_of_iterations_estimates): Same. * tree-ssa-loop-niter.h: Same. * tree-ssa-loop-prefetch.c (release_mem_refs): Same. (idx_analyze_ref): Same. (analyze_ref): Same. (gather_memory_references_ref): Same. (mark_nontemporal_store): Same. (emit_mfence_after_loop): Same. (may_use_storent_in_loop_p): Same. (mark_nontemporal_stores): Same. (should_unroll_loop_p): Same. (volume_of_dist_vector): Same. (add_subscript_strides): Same. (self_reuse_distance): Same. (insn_to_prefetch_ratio_too_small_p): Same. * tree-ssa-loop-split.c (split_at_bb_p): Same. (patch_loop_exit): Same. (find_or_create_guard_phi): Same. (easy_exit_values): Same. (connect_loop_phis): Same. (connect_loops): Same. (compute_new_first_bound): Same. (split_loop): Same. (tree_ssa_split_loops): Same. * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Same. (is_maybe_undefined): Same. (tree_may_unswitch_on): Same. (simplify_using_entry_checks): Same. (tree_unswitch_single_loop): Same. (tree_unswitch_loop): Same. (tree_unswitch_outer_loop): Same. (empty_bb_without_guard_p): Same. (used_outside_loop_p): Same. (get_vop_from_header): Same. (hoist_guard): Same. * tree-ssa-loop.c (gate_oacc_kernels): Same. (get_lsm_tmp_name): Same. * tree-ssa-loop.h: Same. * tree-ssa-reassoc.c (add_repeat_to_ops_vec): Same. (build_and_add_sum): Same. (no_side_effect_bb): Same. (get_ops): Same. (linearize_expr): Same. (should_break_up_subtract): Same. (linearize_expr_tree): Same. * tree-ssa-scopedtables.c: Same. * tree-ssa-scopedtables.h: Same. * tree-ssa-structalias.c (condense_visit): Same. (label_visit): Same. (dump_pred_graph): Same. (perform_var_substitution): Same. (move_complex_constraints): Same. (remove_preds_and_fake_succs): Same. * tree-ssa-threadupdate.c (dbds_continue_enumeration_p): Same. (determine_bb_domination_status): Same. (duplicate_thread_path): Same. (thread_through_all_blocks): Same. * tree-ssa-threadupdate.h: Same. * tree-streamer-in.c (streamer_read_string_cst): Same. (input_identifier): Same. (unpack_ts_type_common_value_fields): Same. (unpack_ts_block_value_fields): Same. (unpack_ts_translation_unit_decl_value_fields): Same. (unpack_ts_omp_clause_value_fields): Same. (streamer_read_tree_bitfields): Same. (streamer_alloc_tree): Same. (lto_input_ts_common_tree_pointers): Same. (lto_input_ts_vector_tree_pointers): Same. (lto_input_ts_poly_tree_pointers): Same. (lto_input_ts_complex_tree_pointers): Same. (lto_input_ts_decl_minimal_tree_pointers): Same. (lto_input_ts_decl_common_tree_pointers): Same. (lto_input_ts_decl_non_common_tree_pointers): Same. (lto_input_ts_decl_with_vis_tree_pointers): Same. (lto_input_ts_field_decl_tree_pointers): Same. (lto_input_ts_function_decl_tree_pointers): Same. (lto_input_ts_type_common_tree_pointers): Same. (lto_input_ts_type_non_common_tree_pointers): Same. (lto_input_ts_list_tree_pointers): Same. (lto_input_ts_vec_tree_pointers): Same. (lto_input_ts_exp_tree_pointers): Same. (lto_input_ts_block_tree_pointers): Same. (lto_input_ts_binfo_tree_pointers): Same. (lto_input_ts_constructor_tree_pointers): Same. (lto_input_ts_omp_clause_tree_pointers): Same. (streamer_read_tree_body): Same. * tree-streamer.h: Same. * tree-switch-conversion.c (bit_test_cluster::is_beneficial): Same. * tree-vect-data-refs.c (vect_get_smallest_scalar_type): Same. (vect_analyze_possibly_independent_ddr): Same. (vect_analyze_data_ref_dependence): Same. (vect_compute_data_ref_alignment): Same. (vect_enhance_data_refs_alignment): Same. (vect_analyze_data_ref_access): Same. (vect_check_gather_scatter): Same. (vect_find_stmt_data_reference): Same. (vect_create_addr_base_for_vector_ref): Same. (vect_setup_realignment): Same. (vect_supportable_dr_alignment): Same. * tree-vect-loop-manip.c (rename_variables_in_bb): Same. (adjust_phi_and_debug_stmts): Same. (vect_set_loop_mask): Same. (add_preheader_seq): Same. (vect_maybe_permute_loop_masks): Same. (vect_set_loop_masks_directly): Same. (vect_set_loop_condition_masked): Same. (vect_set_loop_condition_unmasked): Same. (slpeel_duplicate_current_defs_from_edges): Same. (slpeel_add_loop_guard): Same. (slpeel_can_duplicate_loop_p): Same. (create_lcssa_for_virtual_phi): Same. (iv_phi_p): Same. (vect_update_ivs_after_vectorizer): Same. (vect_gen_vector_loop_niters_mult_vf): Same. (slpeel_update_phi_nodes_for_loops): Same. (slpeel_update_phi_nodes_for_guard1): Same. (find_guard_arg): Same. (slpeel_update_phi_nodes_for_guard2): Same. (slpeel_update_phi_nodes_for_lcssa): Same. (vect_do_peeling): Same. (vect_create_cond_for_alias_checks): Same. (vect_loop_versioning): Same. * tree-vect-loop.c (vect_determine_vf_for_stmt): Same. (vect_inner_phi_in_double_reduction_p): Same. (vect_analyze_scalar_cycles_1): Same. (vect_fixup_scalar_cycles_with_patterns): Same. (vect_get_loop_niters): Same. (bb_in_loop_p): Same. (vect_get_max_nscalars_per_iter): Same. (vect_verify_full_masking): Same. (vect_compute_single_scalar_iteration_cost): Same. (vect_analyze_loop_form_1): Same. (vect_analyze_loop_form): Same. (vect_active_double_reduction_p): Same. (vect_analyze_loop_operations): Same. (neutral_op_for_slp_reduction): Same. (vect_is_simple_reduction): Same. (vect_model_reduction_cost): Same. (get_initial_def_for_reduction): Same. (get_initial_defs_for_reduction): Same. (vect_create_epilog_for_reduction): Same. (vectorize_fold_left_reduction): Same. (vectorizable_reduction): Same. (vectorizable_induction): Same. (vectorizable_live_operation): Same. (loop_niters_no_overflow): Same. (vect_get_loop_mask): Same. (vect_transform_loop_stmt): Same. (vect_transform_loop): Same. * tree-vect-patterns.c (vect_reassociating_reduction_p): Same. (vect_determine_precisions): Same. (vect_pattern_recog_1): Same. * tree-vect-slp.c (vect_analyze_slp_instance): Same. * tree-vect-stmts.c (stmt_vectype): Same. (process_use): Same. (vect_init_vector_1): Same. (vect_truncate_gather_scatter_offset): Same. (get_group_load_store_type): Same. (vect_build_gather_load_calls): Same. (vect_get_strided_load_store_ops): Same. (vectorizable_simd_clone_call): Same. (vectorizable_store): Same. (permute_vec_elements): Same. (vectorizable_load): Same. (vect_transform_stmt): Same. (supportable_widening_operation): Same. * tree-vectorizer.c (vec_info::replace_stmt): Same. (vec_info::free_stmt_vec_info): Same. (vect_free_loop_info_assumptions): Same. (vect_loop_vectorized_call): Same. (set_uid_loop_bbs): Same. (vectorize_loops): Same. * tree-vectorizer.h (STMT_VINFO_BB_VINFO): Same. * tree.c (add_tree_to_fld_list): Same. (fld_type_variant_equal_p): Same. (fld_decl_context): Same. (fld_incomplete_type_of): Same. (free_lang_data_in_binfo): Same. (need_assembler_name_p): Same. (find_decls_types_r): Same. (get_eh_types_for_runtime): Same. (find_decls_types_in_eh_region): Same. (find_decls_types_in_node): Same. (assign_assembler_name_if_needed): Same. * value-prof.c (stream_out_histogram_value): Same. * value-prof.h: Same. * var-tracking.c (use_narrower_mode): Same. (prepare_call_arguments): Same. (vt_expand_loc_callback): Same. (resolve_expansions_pending_recursion): Same. (vt_expand_loc): Same. * varasm.c (const_hash_1): Same. (compare_constant): Same. (tree_output_constant_def): Same. (simplify_subtraction): Same. (get_pool_constant): Same. (output_constant_pool_2): Same. (output_constant_pool_1): Same. (mark_constants_in_pattern): Same. (mark_constant_pool): Same. (get_section_anchor): Same. * vr-values.c (compare_range_with_value): Same. (vr_values::extract_range_from_phi_node): Same. * vr-values.h: Same. * web.c (unionfind_union): Same. * wide-int.h: Same. From-SVN: r273311 --- gcc/ChangeLog | 1431 +++++++++++++++++++++++++++++++++++ gcc/auto-profile.c | 2 +- gcc/basic-block.h | 2 +- gcc/bitmap.c | 2 +- gcc/bitmap.h | 2 +- gcc/builtins.c | 18 +- gcc/c-family/ChangeLog | 7 + gcc/c-family/c-opts.c | 2 +- gcc/c-family/c-pretty-print.h | 2 +- gcc/c/ChangeLog | 10 + gcc/c/c-decl.c | 6 +- gcc/c/c-parser.c | 2 +- gcc/c/c-tree.h | 6 +- gcc/c/gimple-parser.c | 4 +- gcc/caller-save.c | 24 +- gcc/cfg.c | 6 +- gcc/cfg.h | 4 +- gcc/cfganal.h | 4 +- gcc/cfgexpand.c | 22 +- gcc/cfghooks.c | 18 +- gcc/cfghooks.h | 6 +- gcc/cfgloop.c | 134 ++-- gcc/cfgloop.h | 146 ++-- gcc/cfgloopanal.c | 20 +- gcc/cfgloopmanip.c | 90 +-- gcc/cfgloopmanip.h | 32 +- gcc/cgraph.h | 15 +- gcc/cgraphbuild.c | 2 +- gcc/combine.c | 2 +- gcc/config/i386/i386-features.c | 2 +- gcc/config/i386/i386-features.h | 2 +- gcc/config/i386/i386.c | 10 +- gcc/configure.ac | 3 +- gcc/coretypes.h | 46 +- gcc/cp/ChangeLog | 7 + gcc/cp/search.c | 2 +- gcc/cp/semantics.c | 4 +- gcc/data-streamer-in.c | 22 +- gcc/data-streamer.h | 30 +- gcc/ddg.c | 8 +- gcc/df-core.c | 10 +- gcc/df-problems.c | 156 ++-- gcc/df-scan.c | 60 +- gcc/df.h | 30 +- gcc/doc/tm.texi | 10 +- gcc/dse.c | 8 +- gcc/dumpfile.h | 2 +- gcc/emit-rtl.c | 10 +- gcc/emit-rtl.h | 10 +- gcc/except.c | 6 +- gcc/explow.c | 6 +- gcc/expmed.c | 14 +- gcc/expr.c | 22 +- gcc/flags.h | 4 +- gcc/function.c | 40 +- gcc/function.h | 4 +- gcc/fwprop.c | 4 +- gcc/gcc-rich-location.h | 2 +- gcc/gcov.c | 14 +- gcc/genattrtab.c | 136 ++-- gcc/genextract.c | 8 +- gcc/genmatch.c | 30 +- gcc/genoutput.c | 46 +- gcc/genpreds.c | 30 +- gcc/genrecog.c | 6 +- gcc/gensupport.c | 110 +-- gcc/ggc-page.c | 2 +- gcc/gimple-loop-interchange.cc | 62 +- gcc/gimple-loop-jam.c | 20 +- gcc/gimple-loop-versioning.cc | 64 +- gcc/gimple-ssa-evrp-analyze.c | 2 +- gcc/gimple-ssa-store-merging.c | 20 +- gcc/gimple-ssa-strength-reduction.c | 8 +- gcc/gimple-ssa-warn-alloca.c | 8 +- gcc/gimple-streamer-in.c | 8 +- gcc/gimple-streamer.h | 2 +- gcc/godump.c | 16 +- gcc/graph.c | 4 +- gcc/hard-reg-set.h | 4 +- gcc/hsa-brig.c | 5 +- gcc/hsa-common.h | 10 +- gcc/hsa-dump.c | 2 +- gcc/hsa-gen.c | 4 +- gcc/hsa-regalloc.c | 2 +- gcc/input.c | 8 +- gcc/input.h | 4 +- gcc/internal-fn.c | 34 +- gcc/ipa-cp.c | 172 ++--- gcc/ipa-devirt.c | 2 +- gcc/ipa-fnsummary.c | 114 +-- gcc/ipa-fnsummary.h | 2 +- gcc/ipa-hsa.c | 2 +- gcc/ipa-icf-gimple.c | 4 +- gcc/ipa-icf.c | 2 +- gcc/ipa-inline-analysis.c | 6 +- gcc/ipa-inline.c | 4 +- gcc/ipa-polymorphic-call.c | 4 +- gcc/ipa-predicate.c | 8 +- gcc/ipa-predicate.h | 8 +- gcc/ipa-profile.c | 2 +- gcc/ipa-prop.c | 104 +-- gcc/ipa-prop.h | 42 +- gcc/ipa-pure-const.c | 8 +- gcc/ipa-ref.h | 4 +- gcc/ipa-reference.c | 2 +- gcc/ipa-split.c | 14 +- gcc/ira-build.c | 8 +- gcc/ira-color.c | 4 +- gcc/ira-int.h | 8 +- gcc/ira.c | 22 +- gcc/loop-doloop.c | 10 +- gcc/loop-init.c | 6 +- gcc/loop-invariant.c | 42 +- gcc/loop-iv.c | 100 +-- gcc/loop-unroll.c | 62 +- gcc/lra-eliminations.c | 36 +- gcc/lra-int.h | 4 +- gcc/lra-lives.c | 4 +- gcc/lra-remat.c | 4 +- gcc/lra-spills.c | 4 +- gcc/lra.c | 8 +- gcc/lto-cgraph.c | 30 +- gcc/lto-section-in.c | 6 +- gcc/lto-streamer-in.c | 58 +- gcc/lto-streamer-out.c | 2 +- gcc/lto-streamer.h | 30 +- gcc/lto/ChangeLog | 12 + gcc/lto/lto-common.c | 14 +- gcc/modulo-sched.c | 14 +- gcc/omp-expand.c | 40 +- gcc/omp-offload.c | 4 +- gcc/omp-simd-clone.c | 2 +- gcc/optabs-query.c | 2 +- gcc/optabs.c | 78 +- gcc/optabs.h | 30 +- gcc/optinfo.h | 2 +- gcc/poly-int.h | 2 +- gcc/predict.c | 38 +- gcc/predict.h | 8 +- gcc/profile-count.c | 4 +- gcc/profile-count.h | 8 +- gcc/profile.c | 2 +- gcc/regrename.c | 70 +- gcc/regrename.h | 8 +- gcc/reload.h | 8 +- gcc/reload1.c | 76 +- gcc/rtl.h | 8 +- gcc/sanopt.c | 10 +- gcc/sched-deps.c | 44 +- gcc/sched-ebb.c | 2 +- gcc/sched-int.h | 18 +- gcc/sched-rgn.c | 12 +- gcc/sel-sched-ir.c | 28 +- gcc/sel-sched-ir.h | 16 +- gcc/selftest.h | 2 +- gcc/sese.c | 6 +- gcc/sese.h | 6 +- gcc/sreal.c | 2 +- gcc/sreal.h | 4 +- gcc/streamer-hooks.h | 8 +- gcc/target-globals.c | 14 +- gcc/target-globals.h | 16 +- gcc/target.def | 10 +- gcc/target.h | 10 +- gcc/targhooks.c | 6 +- gcc/targhooks.h | 8 +- gcc/toplev.c | 4 +- gcc/tree-affine.c | 8 +- gcc/tree-affine.h | 4 +- gcc/tree-cfg.c | 52 +- gcc/tree-cfg.h | 10 +- gcc/tree-chrec.c | 26 +- gcc/tree-chrec.h | 4 +- gcc/tree-core.h | 4 +- gcc/tree-data-ref.c | 56 +- gcc/tree-data-ref.h | 20 +- gcc/tree-if-conv.c | 50 +- gcc/tree-if-conv.h | 2 +- gcc/tree-inline.c | 6 +- gcc/tree-loop-distribution.c | 48 +- gcc/tree-parloops.c | 42 +- gcc/tree-pass.h | 2 +- gcc/tree-predcom.c | 64 +- gcc/tree-scalar-evolution.c | 102 +-- gcc/tree-scalar-evolution.h | 24 +- gcc/tree-ssa-address.h | 4 +- gcc/tree-ssa-dce.c | 2 +- gcc/tree-ssa-dom.c | 6 +- gcc/tree-ssa-live.c | 4 +- gcc/tree-ssa-live.h | 2 +- gcc/tree-ssa-loop-ch.c | 16 +- gcc/tree-ssa-loop-im.c | 126 +-- gcc/tree-ssa-loop-ivcanon.c | 36 +- gcc/tree-ssa-loop-ivopts.c | 208 ++--- gcc/tree-ssa-loop-ivopts.h | 8 +- gcc/tree-ssa-loop-manip.c | 58 +- gcc/tree-ssa-loop-manip.h | 36 +- gcc/tree-ssa-loop-niter.c | 146 ++-- gcc/tree-ssa-loop-niter.h | 52 +- gcc/tree-ssa-loop-prefetch.c | 36 +- gcc/tree-ssa-loop-split.c | 24 +- gcc/tree-ssa-loop-unswitch.c | 50 +- gcc/tree-ssa-loop.c | 6 +- gcc/tree-ssa-loop.h | 4 +- gcc/tree-ssa-reassoc.c | 16 +- gcc/tree-ssa-scopedtables.c | 4 +- gcc/tree-ssa-scopedtables.h | 2 +- gcc/tree-ssa-structalias.c | 16 +- gcc/tree-ssa-threadupdate.c | 8 +- gcc/tree-ssa-threadupdate.h | 2 +- gcc/tree-streamer-in.c | 98 +-- gcc/tree-streamer.h | 16 +- gcc/tree-switch-conversion.c | 6 +- gcc/tree-vect-data-refs.c | 36 +- gcc/tree-vect-loop-manip.c | 72 +- gcc/tree-vect-loop.c | 86 +-- gcc/tree-vect-patterns.c | 6 +- gcc/tree-vect-slp.c | 2 +- gcc/tree-vect-stmts.c | 40 +- gcc/tree-vectorizer.c | 16 +- gcc/tree-vectorizer.h | 52 +- gcc/tree.c | 30 +- gcc/value-prof.c | 2 +- gcc/value-prof.h | 2 +- gcc/var-tracking.c | 16 +- gcc/varasm.c | 34 +- gcc/vr-values.c | 4 +- gcc/vr-values.h | 2 +- gcc/web.c | 2 +- gcc/wide-int.h | 2 +- 230 files changed, 4109 insertions(+), 2643 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dc34222..3872b6d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -8,6 +8,1437 @@ 2019-07-09 Martin Sebor PR c++/61339 + * auto-profile.c: Change class-key of PODs to struct and others + to class. + * basic-block.h: Same. + * bitmap.c (bitmap_alloc): Same. + * bitmap.h: Same. + * builtins.c (expand_builtin_prefetch): Same. + (expand_builtin_interclass_mathfn): Same. + (expand_builtin_strlen): Same. + (expand_builtin_mempcpy_args): Same. + (expand_cmpstr): Same. + (expand_builtin___clear_cache): Same. + (expand_ifn_atomic_bit_test_and): Same. + (expand_builtin_thread_pointer): Same. + (expand_builtin_set_thread_pointer): Same. + * caller-save.c (setup_save_areas): Same. + (replace_reg_with_saved_mem): Same. + (insert_restore): Same. + (insert_save): Same. + (add_used_regs): Same. + * cfg.c (get_bb_copy): Same. + (set_loop_copy): Same. + * cfg.h: Same. + * cfganal.h: Same. + * cfgexpand.c (alloc_stack_frame_space): Same. + (add_stack_var): Same. + (add_stack_var_conflict): Same. + (add_scope_conflicts_1): Same. + (update_alias_info_with_stack_vars): Same. + (expand_used_vars): Same. + * cfghooks.c (redirect_edge_and_branch_force): Same. + (delete_basic_block): Same. + (split_edge): Same. + (make_forwarder_block): Same. + (force_nonfallthru): Same. + (duplicate_block): Same. + (lv_flush_pending_stmts): Same. + * cfghooks.h: Same. + * cfgloop.c (flow_loops_cfg_dump): Same. + (flow_loop_nested_p): Same. + (superloop_at_depth): Same. + (get_loop_latch_edges): Same. + (flow_loop_dump): Same. + (flow_loops_dump): Same. + (flow_loops_free): Same. + (flow_loop_nodes_find): Same. + (establish_preds): Same. + (flow_loop_tree_node_add): Same. + (flow_loop_tree_node_remove): Same. + (flow_loops_find): Same. + (find_subloop_latch_edge_by_profile): Same. + (find_subloop_latch_edge_by_ivs): Same. + (mfb_redirect_edges_in_set): Same. + (form_subloop): Same. + (merge_latch_edges): Same. + (disambiguate_multiple_latches): Same. + (disambiguate_loops_with_multiple_latches): Same. + (flow_bb_inside_loop_p): Same. + (glb_enum_p): Same. + (get_loop_body_with_size): Same. + (get_loop_body): Same. + (fill_sons_in_loop): Same. + (get_loop_body_in_dom_order): Same. + (get_loop_body_in_custom_order): Same. + (release_recorded_exits): Same. + (get_loop_exit_edges): Same. + (num_loop_branches): Same. + (remove_bb_from_loops): Same. + (find_common_loop): Same. + (delete_loop): Same. + (cancel_loop): Same. + (verify_loop_structure): Same. + (loop_preheader_edge): Same. + (loop_exit_edge_p): Same. + (single_exit): Same. + (loop_exits_to_bb_p): Same. + (loop_exits_from_bb_p): Same. + (get_loop_location): Same. + (record_niter_bound): Same. + (get_estimated_loop_iterations_int): Same. + (max_stmt_executions_int): Same. + (likely_max_stmt_executions_int): Same. + (get_estimated_loop_iterations): Same. + (get_max_loop_iterations): Same. + (get_max_loop_iterations_int): Same. + (get_likely_max_loop_iterations): Same. + * cfgloop.h (simple_loop_desc): Same. + (get_loop): Same. + (loop_depth): Same. + (loop_outer): Same. + (loop_iterator::next): Same. + (loop_outermost): Same. + * cfgloopanal.c (mark_irreducible_loops): Same. + (num_loop_insns): Same. + (average_num_loop_insns): Same. + (expected_loop_iterations_unbounded): Same. + (expected_loop_iterations): Same. + (mark_loop_exit_edges): Same. + (single_likely_exit): Same. + * cfgloopmanip.c (fix_bb_placement): Same. + (fix_bb_placements): Same. + (remove_path): Same. + (place_new_loop): Same. + (add_loop): Same. + (scale_loop_frequencies): Same. + (scale_loop_profile): Same. + (create_empty_if_region_on_edge): Same. + (create_empty_loop_on_edge): Same. + (loopify): Same. + (unloop): Same. + (fix_loop_placements): Same. + (copy_loop_info): Same. + (duplicate_loop): Same. + (duplicate_subloops): Same. + (loop_redirect_edge): Same. + (can_duplicate_loop_p): Same. + (duplicate_loop_to_header_edge): Same. + (mfb_keep_just): Same. + (has_preds_from_loop): Same. + (create_preheader): Same. + (create_preheaders): Same. + (lv_adjust_loop_entry_edge): Same. + (loop_version): Same. + * cfgloopmanip.h: Same. + * cgraph.h: Same. + * cgraphbuild.c: Same. + * combine.c (make_extraction): Same. + * config/i386/i386-features.c: Same. + * config/i386/i386-features.h: Same. + * config/i386/i386.c (ix86_emit_outlined_ms2sysv_save): Same. + (ix86_emit_outlined_ms2sysv_restore): Same. + (ix86_noce_conversion_profitable_p): Same. + (ix86_init_cost): Same. + (ix86_simd_clone_usable): Same. + * configure.ac: Same. + * coretypes.h: Same. + * data-streamer-in.c (string_for_index): Same. + (streamer_read_indexed_string): Same. + (streamer_read_string): Same. + (bp_unpack_indexed_string): Same. + (bp_unpack_string): Same. + (streamer_read_uhwi): Same. + (streamer_read_hwi): Same. + (streamer_read_gcov_count): Same. + (streamer_read_wide_int): Same. + * data-streamer.h (streamer_write_bitpack): Same. + (bp_unpack_value): Same. + (streamer_write_char_stream): Same. + (streamer_write_hwi_in_range): Same. + (streamer_write_record_start): Same. + * ddg.c (create_ddg_dep_from_intra_loop_link): Same. + (add_cross_iteration_register_deps): Same. + (build_intra_loop_deps): Same. + * df-core.c (df_analyze): Same. + (loop_post_order_compute): Same. + (loop_inverted_post_order_compute): Same. + * df-problems.c (df_rd_alloc): Same. + (df_rd_simulate_one_insn): Same. + (df_rd_local_compute): Same. + (df_rd_init_solution): Same. + (df_rd_confluence_n): Same. + (df_rd_transfer_function): Same. + (df_rd_free): Same. + (df_rd_dump_defs_set): Same. + (df_rd_top_dump): Same. + (df_lr_alloc): Same. + (df_lr_reset): Same. + (df_lr_local_compute): Same. + (df_lr_init): Same. + (df_lr_confluence_n): Same. + (df_lr_free): Same. + (df_lr_top_dump): Same. + (df_lr_verify_transfer_functions): Same. + (df_live_alloc): Same. + (df_live_reset): Same. + (df_live_init): Same. + (df_live_confluence_n): Same. + (df_live_finalize): Same. + (df_live_free): Same. + (df_live_top_dump): Same. + (df_live_verify_transfer_functions): Same. + (df_mir_alloc): Same. + (df_mir_reset): Same. + (df_mir_init): Same. + (df_mir_confluence_n): Same. + (df_mir_free): Same. + (df_mir_top_dump): Same. + (df_word_lr_alloc): Same. + (df_word_lr_reset): Same. + (df_word_lr_init): Same. + (df_word_lr_confluence_n): Same. + (df_word_lr_free): Same. + (df_word_lr_top_dump): Same. + (df_md_alloc): Same. + (df_md_simulate_one_insn): Same. + (df_md_reset): Same. + (df_md_init): Same. + (df_md_free): Same. + (df_md_top_dump): Same. + * df-scan.c (df_insn_delete): Same. + (df_insn_rescan): Same. + (df_notes_rescan): Same. + (df_sort_and_compress_mws): Same. + (df_install_mws): Same. + (df_refs_add_to_chains): Same. + (df_ref_create_structure): Same. + (df_ref_record): Same. + (df_def_record_1): Same. + (df_find_hard_reg_defs): Same. + (df_uses_record): Same. + (df_get_conditional_uses): Same. + (df_get_call_refs): Same. + (df_recompute_luids): Same. + (df_get_entry_block_def_set): Same. + (df_entry_block_defs_collect): Same. + (df_get_exit_block_use_set): Same. + (df_exit_block_uses_collect): Same. + (df_mws_verify): Same. + (df_bb_verify): Same. + * df.h (df_scan_get_bb_info): Same. + * doc/tm.texi: Same. + * dse.c (record_store): Same. + * dumpfile.h: Same. + * emit-rtl.c (const_fixed_hasher::equal): Same. + (set_mem_attributes_minus_bitpos): Same. + (change_address): Same. + (adjust_address_1): Same. + (offset_address): Same. + * emit-rtl.h: Same. + * except.c (dw2_build_landing_pads): Same. + (sjlj_emit_dispatch_table): Same. + * explow.c (allocate_dynamic_stack_space): Same. + (emit_stack_probe): Same. + (probe_stack_range): Same. + * expmed.c (store_bit_field_using_insv): Same. + (store_bit_field_1): Same. + (store_integral_bit_field): Same. + (extract_bit_field_using_extv): Same. + (extract_bit_field_1): Same. + (emit_cstore): Same. + * expr.c (emit_block_move_via_cpymem): Same. + (expand_cmpstrn_or_cmpmem): Same. + (set_storage_via_setmem): Same. + (emit_single_push_insn_1): Same. + (expand_assignment): Same. + (store_constructor): Same. + (expand_expr_real_2): Same. + (expand_expr_real_1): Same. + (try_casesi): Same. + * flags.h: Same. + * function.c (try_fit_stack_local): Same. + (assign_stack_local_1): Same. + (assign_stack_local): Same. + (cut_slot_from_list): Same. + (insert_slot_to_list): Same. + (max_slot_level): Same. + (move_slot_to_level): Same. + (temp_address_hasher::equal): Same. + (remove_unused_temp_slot_addresses): Same. + (assign_temp): Same. + (combine_temp_slots): Same. + (update_temp_slot_address): Same. + (preserve_temp_slots): Same. + * function.h: Same. + * fwprop.c: Same. + * gcc-rich-location.h: Same. + * gcov.c: Same. + * genattrtab.c (check_attr_test): Same. + (check_attr_value): Same. + (convert_set_attr_alternative): Same. + (convert_set_attr): Same. + (check_defs): Same. + (copy_boolean): Same. + (get_attr_value): Same. + (expand_delays): Same. + (make_length_attrs): Same. + (min_fn): Same. + (make_alternative_compare): Same. + (simplify_test_exp): Same. + (tests_attr_p): Same. + (get_attr_order): Same. + (clear_struct_flag): Same. + (gen_attr): Same. + (compares_alternatives_p): Same. + (gen_insn): Same. + (gen_delay): Same. + (find_attrs_to_cache): Same. + (write_test_expr): Same. + (walk_attr_value): Same. + (write_attr_get): Same. + (eliminate_known_true): Same. + (write_insn_cases): Same. + (write_attr_case): Same. + (write_attr_valueq): Same. + (write_attr_value): Same. + (write_dummy_eligible_delay): Same. + (next_comma_elt): Same. + (find_attr): Same. + (make_internal_attr): Same. + (copy_rtx_unchanging): Same. + (gen_insn_reserv): Same. + (check_tune_attr): Same. + (make_automaton_attrs): Same. + (handle_arg): Same. + * genextract.c (gen_insn): Same. + (VEC_char_to_string): Same. + * genmatch.c (print_operand): Same. + (lower): Same. + (parser::parse_operation): Same. + (parser::parse_capture): Same. + (parser::parse_c_expr): Same. + (parser::parse_simplify): Same. + (main): Same. + * genoutput.c (output_operand_data): Same. + (output_get_insn_name): Same. + (compare_operands): Same. + (place_operands): Same. + (process_template): Same. + (validate_insn_alternatives): Same. + (validate_insn_operands): Same. + (gen_expand): Same. + (note_constraint): Same. + * genpreds.c (write_one_predicate_function): Same. + (add_constraint): Same. + (process_define_register_constraint): Same. + (write_lookup_constraint_1): Same. + (write_lookup_constraint_array): Same. + (write_insn_constraint_len): Same. + (write_reg_class_for_constraint_1): Same. + (write_constraint_satisfied_p_array): Same. + * genrecog.c (optimize_subroutine_group): Same. + * gensupport.c (process_define_predicate): Same. + (queue_pattern): Same. + (remove_from_queue): Same. + (process_rtx): Same. + (is_predicable): Same. + (change_subst_attribute): Same. + (subst_pattern_match): Same. + (alter_constraints): Same. + (alter_attrs_for_insn): Same. + (shift_output_template): Same. + (alter_output_for_subst_insn): Same. + (process_one_cond_exec): Same. + (subst_dup): Same. + (process_define_cond_exec): Same. + (mnemonic_htab_callback): Same. + (gen_mnemonic_attr): Same. + (read_md_rtx): Same. + * ggc-page.c: Same. + * gimple-loop-interchange.cc (dump_reduction): Same. + (dump_induction): Same. + (loop_cand::~loop_cand): Same. + (free_data_refs_with_aux): Same. + (tree_loop_interchange::interchange_loops): Same. + (tree_loop_interchange::map_inductions_to_loop): Same. + (tree_loop_interchange::move_code_to_inner_loop): Same. + (compute_access_stride): Same. + (compute_access_strides): Same. + (proper_loop_form_for_interchange): Same. + (tree_loop_interchange_compute_ddrs): Same. + (prune_datarefs_not_in_loop): Same. + (prepare_data_references): Same. + (pass_linterchange::execute): Same. + * gimple-loop-jam.c (bb_prevents_fusion_p): Same. + (unroll_jam_possible_p): Same. + (fuse_loops): Same. + (adjust_unroll_factor): Same. + (tree_loop_unroll_and_jam): Same. + * gimple-loop-versioning.cc (loop_versioning::~loop_versioning): Same. + (loop_versioning::expensive_stmt_p): Same. + (loop_versioning::version_for_unity): Same. + (loop_versioning::dump_inner_likelihood): Same. + (loop_versioning::find_per_loop_multiplication): Same. + (loop_versioning::analyze_term_using_scevs): Same. + (loop_versioning::record_address_fragment): Same. + (loop_versioning::analyze_expr): Same. + (loop_versioning::analyze_blocks): Same. + (loop_versioning::prune_conditions): Same. + (loop_versioning::merge_loop_info): Same. + (loop_versioning::add_loop_to_queue): Same. + (loop_versioning::decide_whether_loop_is_versionable): Same. + (loop_versioning::make_versioning_decisions): Same. + (loop_versioning::implement_versioning_decisions): Same. + * gimple-ssa-evrp-analyze.c + (evrp_range_analyzer::record_ranges_from_phis): Same. + * gimple-ssa-store-merging.c (split_store::split_store): Same. + (count_multiple_uses): Same. + (split_group): Same. + (imm_store_chain_info::output_merged_store): Same. + (pass_store_merging::process_store): Same. + * gimple-ssa-strength-reduction.c (slsr_process_phi): Same. + * gimple-ssa-warn-alloca.c (adjusted_warn_limit): Same. + (is_max): Same. + (alloca_call_type): Same. + (pass_walloca::execute): Same. + * gimple-streamer-in.c (input_phi): Same. + (input_gimple_stmt): Same. + * gimple-streamer.h: Same. + * godump.c (go_force_record_alignment): Same. + (go_format_type): Same. + (go_output_type): Same. + (go_output_fndecl): Same. + (go_output_typedef): Same. + (keyword_hash_init): Same. + (find_dummy_types): Same. + * graph.c (draw_cfg_nodes_no_loops): Same. + (draw_cfg_nodes_for_loop): Same. + * hard-reg-set.h (hard_reg_set_iter_next): Same. + * hsa-brig.c: Same. + * hsa-common.h (hsa_internal_fn_hasher::equal): Same. + * hsa-dump.c (dump_hsa_cfun): Same. + * hsa-gen.c (gen_function_def_parameters): Same. + * hsa-regalloc.c (dump_hsa_cfun_regalloc): Same. + * input.c (dump_line_table_statistics): Same. + (test_lexer): Same. + * input.h: Same. + * internal-fn.c (get_multi_vector_move): Same. + (expand_load_lanes_optab_fn): Same. + (expand_GOMP_SIMT_ENTER_ALLOC): Same. + (expand_GOMP_SIMT_EXIT): Same. + (expand_GOMP_SIMT_LAST_LANE): Same. + (expand_GOMP_SIMT_ORDERED_PRED): Same. + (expand_GOMP_SIMT_VOTE_ANY): Same. + (expand_GOMP_SIMT_XCHG_BFLY): Same. + (expand_GOMP_SIMT_XCHG_IDX): Same. + (expand_addsub_overflow): Same. + (expand_neg_overflow): Same. + (expand_mul_overflow): Same. + (expand_call_mem_ref): Same. + (expand_mask_load_optab_fn): Same. + (expand_scatter_store_optab_fn): Same. + (expand_gather_load_optab_fn): Same. + * ipa-cp.c (ipa_get_parm_lattices): Same. + (print_all_lattices): Same. + (ignore_edge_p): Same. + (build_toporder_info): Same. + (free_toporder_info): Same. + (push_node_to_stack): Same. + (ipcp_lattice::set_contains_variable): Same. + (set_agg_lats_to_bottom): Same. + (ipcp_bits_lattice::meet_with): Same. + (set_single_call_flag): Same. + (initialize_node_lattices): Same. + (ipa_get_jf_ancestor_result): Same. + (ipcp_verify_propagated_values): Same. + (propagate_scalar_across_jump_function): Same. + (propagate_context_across_jump_function): Same. + (propagate_bits_across_jump_function): Same. + (ipa_vr_operation_and_type_effects): Same. + (propagate_vr_across_jump_function): Same. + (set_check_aggs_by_ref): Same. + (set_chain_of_aglats_contains_variable): Same. + (merge_aggregate_lattices): Same. + (agg_pass_through_permissible_p): Same. + (propagate_aggs_across_jump_function): Same. + (call_passes_through_thunk_p): Same. + (propagate_constants_across_call): Same. + (devirtualization_time_bonus): Same. + (good_cloning_opportunity_p): Same. + (context_independent_aggregate_values): Same. + (gather_context_independent_values): Same. + (perform_estimation_of_a_value): Same. + (estimate_local_effects): Same. + (value_topo_info::add_val): Same. + (add_all_node_vals_to_toposort): Same. + (value_topo_info::propagate_effects): Same. + (ipcp_propagate_stage): Same. + (ipcp_discover_new_direct_edges): Same. + (same_node_or_its_all_contexts_clone_p): Same. + (cgraph_edge_brings_value_p): Same. + (gather_edges_for_value): Same. + (create_specialized_node): Same. + (find_more_scalar_values_for_callers_subset): Same. + (find_more_contexts_for_caller_subset): Same. + (copy_plats_to_inter): Same. + (intersect_aggregates_with_edge): Same. + (find_aggregate_values_for_callers_subset): Same. + (cgraph_edge_brings_all_agg_vals_for_node): Same. + (decide_about_value): Same. + (decide_whether_version_node): Same. + (spread_undeadness): Same. + (identify_dead_nodes): Same. + (ipcp_store_vr_results): Same. + * ipa-devirt.c (final_warning_record::grow_type_warnings): Same. + * ipa-fnsummary.c (ipa_fn_summary::account_size_time): Same. + (redirect_to_unreachable): Same. + (edge_set_predicate): Same. + (evaluate_conditions_for_known_args): Same. + (evaluate_properties_for_edge): Same. + (ipa_fn_summary_t::duplicate): Same. + (ipa_call_summary_t::duplicate): Same. + (dump_ipa_call_summary): Same. + (ipa_dump_fn_summary): Same. + (eliminated_by_inlining_prob): Same. + (set_cond_stmt_execution_predicate): Same. + (set_switch_stmt_execution_predicate): Same. + (compute_bb_predicates): Same. + (will_be_nonconstant_expr_predicate): Same. + (phi_result_unknown_predicate): Same. + (analyze_function_body): Same. + (compute_fn_summary): Same. + (estimate_edge_devirt_benefit): Same. + (estimate_edge_size_and_time): Same. + (estimate_calls_size_and_time): Same. + (estimate_node_size_and_time): Same. + (remap_edge_change_prob): Same. + (remap_edge_summaries): Same. + (ipa_merge_fn_summary_after_inlining): Same. + (ipa_fn_summary_generate): Same. + (inline_read_section): Same. + (ipa_fn_summary_read): Same. + (ipa_fn_summary_write): Same. + * ipa-fnsummary.h: Same. + * ipa-hsa.c (ipa_hsa_read_section): Same. + * ipa-icf-gimple.c (func_checker::compare_loops): Same. + * ipa-icf.c (sem_function::param_used_p): Same. + * ipa-inline-analysis.c (do_estimate_edge_time): Same. + * ipa-inline.c (edge_badness): Same. + (inline_small_functions): Same. + * ipa-polymorphic-call.c + (ipa_polymorphic_call_context::stream_out): Same. + * ipa-predicate.c (predicate::remap_after_duplication): Same. + (predicate::remap_after_inlining): Same. + (predicate::stream_out): Same. + * ipa-predicate.h: Same. + * ipa-profile.c (ipa_profile_read_summary): Same. + * ipa-prop.c (ipa_get_param_decl_index_1): Same. + (count_formal_params): Same. + (ipa_dump_param): Same. + (ipa_alloc_node_params): Same. + (ipa_print_node_jump_functions_for_edge): Same. + (ipa_print_node_jump_functions): Same. + (ipa_load_from_parm_agg): Same. + (get_ancestor_addr_info): Same. + (ipa_compute_jump_functions_for_edge): Same. + (ipa_analyze_virtual_call_uses): Same. + (ipa_analyze_stmt_uses): Same. + (ipa_analyze_params_uses_in_bb): Same. + (update_jump_functions_after_inlining): Same. + (try_decrement_rdesc_refcount): Same. + (ipa_impossible_devirt_target): Same. + (update_indirect_edges_after_inlining): Same. + (combine_controlled_uses_counters): Same. + (ipa_edge_args_sum_t::duplicate): Same. + (ipa_write_jump_function): Same. + (ipa_write_indirect_edge_info): Same. + (ipa_write_node_info): Same. + (ipa_read_edge_info): Same. + (ipa_prop_read_section): Same. + (read_replacements_section): Same. + * ipa-prop.h (ipa_get_param_count): Same. + (ipa_get_param): Same. + (ipa_get_type): Same. + (ipa_get_param_move_cost): Same. + (ipa_set_param_used): Same. + (ipa_get_controlled_uses): Same. + (ipa_set_controlled_uses): Same. + (ipa_get_cs_argument_count): Same. + * ipa-pure-const.c (analyze_function): Same. + (pure_const_read_summary): Same. + * ipa-ref.h: Same. + * ipa-reference.c (ipa_reference_read_optimization_summary): Same. + * ipa-split.c (test_nonssa_use): Same. + (dump_split_point): Same. + (dominated_by_forbidden): Same. + (split_part_set_ssa_name_p): Same. + (find_split_points): Same. + * ira-build.c (finish_loop_tree_nodes): Same. + (low_pressure_loop_node_p): Same. + * ira-color.c (ira_reuse_stack_slot): Same. + * ira-int.h: Same. + * ira.c (setup_reg_equiv): Same. + (print_insn_chain): Same. + (ira): Same. + * loop-doloop.c (doloop_condition_get): Same. + (add_test): Same. + (record_reg_sets): Same. + (doloop_optimize): Same. + * loop-init.c (loop_optimizer_init): Same. + (fix_loop_structure): Same. + * loop-invariant.c (merge_identical_invariants): Same. + (compute_always_reached): Same. + (find_exits): Same. + (may_assign_reg_p): Same. + (find_invariants_bb): Same. + (find_invariants_body): Same. + (replace_uses): Same. + (can_move_invariant_reg): Same. + (free_inv_motion_data): Same. + (move_single_loop_invariants): Same. + (change_pressure): Same. + (mark_ref_regs): Same. + (calculate_loop_reg_pressure): Same. + * loop-iv.c (biv_entry_hasher::equal): Same. + (iv_extend_to_rtx_code): Same. + (check_iv_ref_table_size): Same. + (clear_iv_info): Same. + (latch_dominating_def): Same. + (iv_get_reaching_def): Same. + (iv_constant): Same. + (iv_subreg): Same. + (iv_extend): Same. + (iv_neg): Same. + (iv_add): Same. + (iv_mult): Same. + (get_biv_step): Same. + (record_iv): Same. + (analyzed_for_bivness_p): Same. + (record_biv): Same. + (iv_analyze_biv): Same. + (iv_analyze_expr): Same. + (iv_analyze_def): Same. + (iv_analyze_op): Same. + (iv_analyze): Same. + (iv_analyze_result): Same. + (biv_p): Same. + (eliminate_implied_conditions): Same. + (simplify_using_initial_values): Same. + (shorten_into_mode): Same. + (canonicalize_iv_subregs): Same. + (determine_max_iter): Same. + (check_simple_exit): Same. + (find_simple_exit): Same. + (get_simple_loop_desc): Same. + * loop-unroll.c (report_unroll): Same. + (decide_unrolling): Same. + (unroll_loops): Same. + (loop_exit_at_end_p): Same. + (decide_unroll_constant_iterations): Same. + (unroll_loop_constant_iterations): Same. + (compare_and_jump_seq): Same. + (unroll_loop_runtime_iterations): Same. + (decide_unroll_stupid): Same. + (unroll_loop_stupid): Same. + (referenced_in_one_insn_in_loop_p): Same. + (reset_debug_uses_in_loop): Same. + (analyze_iv_to_split_insn): Same. + * lra-eliminations.c (lra_debug_elim_table): Same. + (setup_can_eliminate): Same. + (form_sum): Same. + (lra_get_elimination_hard_regno): Same. + (lra_eliminate_regs_1): Same. + (eliminate_regs_in_insn): Same. + (update_reg_eliminate): Same. + (init_elimination): Same. + (lra_eliminate): Same. + * lra-int.h: Same. + * lra-lives.c (initiate_live_solver): Same. + * lra-remat.c (create_remat_bb_data): Same. + * lra-spills.c (lra_spill): Same. + * lra.c (lra_set_insn_recog_data): Same. + (lra_set_used_insn_alternative_by_uid): Same. + (init_reg_info): Same. + (expand_reg_info): Same. + * lto-cgraph.c (output_symtab): Same. + (read_identifier): Same. + (get_alias_symbol): Same. + (input_node): Same. + (input_varpool_node): Same. + (input_ref): Same. + (input_edge): Same. + (input_cgraph_1): Same. + (input_refs): Same. + (input_symtab): Same. + (input_offload_tables): Same. + (output_cgraph_opt_summary): Same. + (input_edge_opt_summary): Same. + (input_cgraph_opt_section): Same. + * lto-section-in.c (lto_free_raw_section_data): Same. + (lto_create_simple_input_block): Same. + (lto_free_function_in_decl_state_for_node): Same. + * lto-streamer-in.c (lto_tag_check_set): Same. + (lto_location_cache::revert_location_cache): Same. + (lto_location_cache::input_location): Same. + (lto_input_location): Same. + (stream_input_location_now): Same. + (lto_input_tree_ref): Same. + (lto_input_eh_catch_list): Same. + (input_eh_region): Same. + (lto_init_eh): Same. + (make_new_block): Same. + (input_cfg): Same. + (fixup_call_stmt_edges): Same. + (input_struct_function_base): Same. + (input_function): Same. + (lto_read_body_or_constructor): Same. + (lto_read_tree_1): Same. + (lto_read_tree): Same. + (lto_input_scc): Same. + (lto_input_tree_1): Same. + (lto_input_toplevel_asms): Same. + (lto_input_mode_table): Same. + (lto_reader_init): Same. + (lto_data_in_create): Same. + * lto-streamer-out.c (output_cfg): Same. + * lto-streamer.h: Same. + * modulo-sched.c (duplicate_insns_of_cycles): Same. + (generate_prolog_epilog): Same. + (mark_loop_unsched): Same. + (dump_insn_location): Same. + (loop_canon_p): Same. + (sms_schedule): Same. + * omp-expand.c (expand_omp_for_ordered_loops): Same. + (expand_omp_for_generic): Same. + (expand_omp_for_static_nochunk): Same. + (expand_omp_for_static_chunk): Same. + (expand_omp_simd): Same. + (expand_omp_taskloop_for_inner): Same. + (expand_oacc_for): Same. + (expand_omp_atomic_pipeline): Same. + (mark_loops_in_oacc_kernels_region): Same. + * omp-offload.c (oacc_xform_loop): Same. + * omp-simd-clone.c (simd_clone_adjust): Same. + * optabs-query.c (get_traditional_extraction_insn): Same. + * optabs.c (expand_vector_broadcast): Same. + (expand_binop_directly): Same. + (expand_twoval_unop): Same. + (expand_twoval_binop): Same. + (expand_unop_direct): Same. + (emit_indirect_jump): Same. + (emit_conditional_move): Same. + (emit_conditional_neg_or_complement): Same. + (emit_conditional_add): Same. + (vector_compare_rtx): Same. + (expand_vec_perm_1): Same. + (expand_vec_perm_const): Same. + (expand_vec_cond_expr): Same. + (expand_vec_series_expr): Same. + (maybe_emit_atomic_exchange): Same. + (maybe_emit_sync_lock_test_and_set): Same. + (expand_atomic_compare_and_swap): Same. + (expand_atomic_load): Same. + (expand_atomic_store): Same. + (maybe_emit_op): Same. + (valid_multiword_target_p): Same. + (create_integer_operand): Same. + (maybe_legitimize_operand_same_code): Same. + (maybe_legitimize_operand): Same. + (create_convert_operand_from_type): Same. + (can_reuse_operands_p): Same. + (maybe_legitimize_operands): Same. + (maybe_gen_insn): Same. + (maybe_expand_insn): Same. + (maybe_expand_jump_insn): Same. + (expand_insn): Same. + * optabs.h (create_expand_operand): Same. + (create_fixed_operand): Same. + (create_output_operand): Same. + (create_input_operand): Same. + (create_convert_operand_to): Same. + (create_convert_operand_from): Same. + * optinfo.h: Same. + * poly-int.h: Same. + * predict.c (optimize_insn_for_speed_p): Same. + (optimize_loop_for_size_p): Same. + (optimize_loop_for_speed_p): Same. + (optimize_loop_nest_for_speed_p): Same. + (get_base_value): Same. + (predicted_by_loop_heuristics_p): Same. + (predict_extra_loop_exits): Same. + (predict_loops): Same. + (predict_paths_for_bb): Same. + (predict_paths_leading_to): Same. + (propagate_freq): Same. + (pass_profile::execute): Same. + * predict.h: Same. + * profile-count.c (profile_count::differs_from_p): Same. + (profile_probability::differs_lot_from_p): Same. + * profile-count.h: Same. + * profile.c (branch_prob): Same. + * regrename.c (free_chain_data): Same. + (mark_conflict): Same. + (create_new_chain): Same. + (merge_overlapping_regs): Same. + (init_rename_info): Same. + (merge_chains): Same. + (regrename_analyze): Same. + (regrename_do_replace): Same. + (scan_rtx_reg): Same. + (record_out_operands): Same. + (build_def_use): Same. + * regrename.h: Same. + * reload.h: Same. + * reload1.c (init_reload): Same. + (maybe_fix_stack_asms): Same. + (copy_reloads): Same. + (count_pseudo): Same. + (count_spilled_pseudo): Same. + (find_reg): Same. + (find_reload_regs): Same. + (select_reload_regs): Same. + (spill_hard_reg): Same. + (fixup_eh_region_note): Same. + (set_reload_reg): Same. + (allocate_reload_reg): Same. + (compute_reload_subreg_offset): Same. + (reload_adjust_reg_for_icode): Same. + (emit_input_reload_insns): Same. + (emit_output_reload_insns): Same. + (do_input_reload): Same. + (inherit_piecemeal_p): Same. + * rtl.h: Same. + * sanopt.c (maybe_get_dominating_check): Same. + (maybe_optimize_ubsan_ptr_ifn): Same. + (can_remove_asan_check): Same. + (maybe_optimize_asan_check_ifn): Same. + (sanopt_optimize_walker): Same. + * sched-deps.c (add_dependence_list): Same. + (chain_to_prev_insn): Same. + (add_insn_mem_dependence): Same. + (create_insn_reg_set): Same. + (maybe_extend_reg_info_p): Same. + (sched_analyze_reg): Same. + (sched_analyze_1): Same. + (get_implicit_reg_pending_clobbers): Same. + (chain_to_prev_insn_p): Same. + (deps_analyze_insn): Same. + (deps_start_bb): Same. + (sched_free_deps): Same. + (init_deps): Same. + (init_deps_reg_last): Same. + (free_deps): Same. + * sched-ebb.c: Same. + * sched-int.h: Same. + * sched-rgn.c (add_branch_dependences): Same. + (concat_insn_mem_list): Same. + (deps_join): Same. + (sched_rgn_compute_dependencies): Same. + * sel-sched-ir.c (reset_target_context): Same. + (copy_deps_context): Same. + (init_id_from_df): Same. + (has_dependence_p): Same. + (change_loops_latches): Same. + (bb_top_order_comparator): Same. + (make_region_from_loop_preheader): Same. + (sel_init_pipelining): Same. + (get_loop_nest_for_rgn): Same. + (make_regions_from_the_rest): Same. + (sel_is_loop_preheader_p): Same. + * sel-sched-ir.h (inner_loop_header_p): Same. + (get_all_loop_exits): Same. + * selftest.h: Same. + * sese.c (sese_build_liveouts): Same. + (sese_insert_phis_for_liveouts): Same. + * sese.h (defined_in_sese_p): Same. + * sreal.c (sreal::stream_out): Same. + * sreal.h: Same. + * streamer-hooks.h: Same. + * target-globals.c (save_target_globals): Same. + * target-globals.h: Same. + * target.def: Same. + * target.h: Same. + * targhooks.c (default_has_ifunc_p): Same. + (default_empty_mask_is_expensive): Same. + (default_init_cost): Same. + * targhooks.h: Same. + * toplev.c: Same. + * tree-affine.c (aff_combination_mult): Same. + (aff_combination_expand): Same. + (aff_combination_constant_multiple_p): Same. + * tree-affine.h: Same. + * tree-cfg.c (build_gimple_cfg): Same. + (replace_loop_annotate_in_block): Same. + (replace_uses_by): Same. + (remove_bb): Same. + (dump_cfg_stats): Same. + (gimple_duplicate_sese_region): Same. + (gimple_duplicate_sese_tail): Same. + (move_block_to_fn): Same. + (replace_block_vars_by_duplicates): Same. + (move_sese_region_to_fn): Same. + (print_loops_bb): Same. + (print_loop): Same. + (print_loops): Same. + (debug): Same. + (debug_loops): Same. + * tree-cfg.h: Same. + * tree-chrec.c (chrec_fold_plus_poly_poly): Same. + (chrec_fold_multiply_poly_poly): Same. + (chrec_evaluate): Same. + (chrec_component_in_loop_num): Same. + (reset_evolution_in_loop): Same. + (is_multivariate_chrec): Same. + (chrec_contains_symbols): Same. + (nb_vars_in_chrec): Same. + (chrec_convert_1): Same. + (chrec_convert_aggressive): Same. + * tree-chrec.h: Same. + * tree-core.h: Same. + * tree-data-ref.c (dump_data_dependence_relation): Same. + (canonicalize_base_object_address): Same. + (data_ref_compare_tree): Same. + (prune_runtime_alias_test_list): Same. + (get_segment_min_max): Same. + (create_intersect_range_checks): Same. + (conflict_fn_no_dependence): Same. + (object_address_invariant_in_loop_p): Same. + (analyze_ziv_subscript): Same. + (analyze_siv_subscript_cst_affine): Same. + (analyze_miv_subscript): Same. + (analyze_overlapping_iterations): Same. + (build_classic_dist_vector_1): Same. + (add_other_self_distances): Same. + (same_access_functions): Same. + (build_classic_dir_vector): Same. + (subscript_dependence_tester_1): Same. + (subscript_dependence_tester): Same. + (access_functions_are_affine_or_constant_p): Same. + (get_references_in_stmt): Same. + (loop_nest_has_data_refs): Same. + (graphite_find_data_references_in_stmt): Same. + (find_data_references_in_bb): Same. + (get_base_for_alignment): Same. + (find_loop_nest_1): Same. + (find_loop_nest): Same. + * tree-data-ref.h (dr_alignment): Same. + (ddr_dependence_level): Same. + * tree-if-conv.c (fold_build_cond_expr): Same. + (add_to_predicate_list): Same. + (add_to_dst_predicate_list): Same. + (phi_convertible_by_degenerating_args): Same. + (idx_within_array_bound): Same. + (all_preds_critical_p): Same. + (pred_blocks_visited_p): Same. + (predicate_bbs): Same. + (build_region): Same. + (if_convertible_loop_p_1): Same. + (is_cond_scalar_reduction): Same. + (predicate_scalar_phi): Same. + (remove_conditions_and_labels): Same. + (combine_blocks): Same. + (version_loop_for_if_conversion): Same. + (versionable_outer_loop_p): Same. + (ifcvt_local_dce): Same. + (tree_if_conversion): Same. + (pass_if_conversion::gate): Same. + * tree-if-conv.h: Same. + * tree-inline.c (maybe_move_debug_stmts_to_successors): Same. + * tree-loop-distribution.c (bb_top_order_cmp): Same. + (free_rdg): Same. + (stmt_has_scalar_dependences_outside_loop): Same. + (copy_loop_before): Same. + (create_bb_after_loop): Same. + (const_with_all_bytes_same): Same. + (generate_memset_builtin): Same. + (generate_memcpy_builtin): Same. + (destroy_loop): Same. + (build_rdg_partition_for_vertex): Same. + (compute_access_range): Same. + (data_ref_segment_size): Same. + (latch_dominated_by_data_ref): Same. + (compute_alias_check_pairs): Same. + (fuse_memset_builtins): Same. + (finalize_partitions): Same. + (find_seed_stmts_for_distribution): Same. + (prepare_perfect_loop_nest): Same. + * tree-parloops.c (lambda_transform_legal_p): Same. + (loop_parallel_p): Same. + (reduc_stmt_res): Same. + (add_field_for_name): Same. + (create_call_for_reduction_1): Same. + (replace_uses_in_bb_by): Same. + (transform_to_exit_first_loop_alt): Same. + (try_transform_to_exit_first_loop_alt): Same. + (transform_to_exit_first_loop): Same. + (num_phis): Same. + (gen_parallel_loop): Same. + (gather_scalar_reductions): Same. + (get_omp_data_i_param): Same. + (try_create_reduction_list): Same. + (oacc_entry_exit_single_gang): Same. + (parallelize_loops): Same. + * tree-pass.h: Same. + * tree-predcom.c (determine_offset): Same. + (last_always_executed_block): Same. + (split_data_refs_to_components): Same. + (suitable_component_p): Same. + (valid_initializer_p): Same. + (find_looparound_phi): Same. + (insert_looparound_copy): Same. + (add_looparound_copies): Same. + (determine_roots_comp): Same. + (predcom_tmp_var): Same. + (initialize_root_vars): Same. + (initialize_root_vars_store_elim_1): Same. + (initialize_root_vars_store_elim_2): Same. + (finalize_eliminated_stores): Same. + (initialize_root_vars_lm): Same. + (remove_stmt): Same. + (determine_unroll_factor): Same. + (execute_pred_commoning_cbck): Same. + (base_names_in_chain_on): Same. + (combine_chains): Same. + (pcom_stmt_dominates_stmt_p): Same. + (try_combine_chains): Same. + (prepare_initializers_chain_store_elim): Same. + (prepare_initializers_chain): Same. + (prepare_initializers): Same. + (prepare_finalizers_chain): Same. + (prepare_finalizers): Same. + (insert_init_seqs): Same. + * tree-scalar-evolution.c (loop_phi_node_p): Same. + (compute_overall_effect_of_inner_loop): Same. + (add_to_evolution_1): Same. + (add_to_evolution): Same. + (follow_ssa_edge_binary): Same. + (follow_ssa_edge_expr): Same. + (backedge_phi_arg_p): Same. + (follow_ssa_edge_in_condition_phi_branch): Same. + (follow_ssa_edge_in_condition_phi): Same. + (follow_ssa_edge_inner_loop_phi): Same. + (follow_ssa_edge): Same. + (analyze_evolution_in_loop): Same. + (analyze_initial_condition): Same. + (interpret_loop_phi): Same. + (interpret_condition_phi): Same. + (interpret_rhs_expr): Same. + (interpret_expr): Same. + (interpret_gimple_assign): Same. + (analyze_scalar_evolution_1): Same. + (analyze_scalar_evolution): Same. + (analyze_scalar_evolution_for_address_of): Same. + (get_instantiated_value_entry): Same. + (loop_closed_phi_def): Same. + (instantiate_scev_name): Same. + (instantiate_scev_poly): Same. + (instantiate_scev_binary): Same. + (instantiate_scev_convert): Same. + (instantiate_scev_not): Same. + (instantiate_scev_r): Same. + (instantiate_scev): Same. + (resolve_mixers): Same. + (initialize_scalar_evolutions_analyzer): Same. + (scev_reset_htab): Same. + (scev_reset): Same. + (derive_simple_iv_with_niters): Same. + (simple_iv_with_niters): Same. + (expression_expensive_p): Same. + (final_value_replacement_loop): Same. + * tree-scalar-evolution.h (block_before_loop): Same. + * tree-ssa-address.h: Same. + * tree-ssa-dce.c (find_obviously_necessary_stmts): Same. + * tree-ssa-dom.c (edge_info::record_simple_equiv): Same. + (record_edge_info): Same. + * tree-ssa-live.c (var_map_base_fini): Same. + (remove_unused_locals): Same. + * tree-ssa-live.h: Same. + * tree-ssa-loop-ch.c (should_duplicate_loop_header_p): Same. + (pass_ch_vect::execute): Same. + (pass_ch::process_loop_p): Same. + * tree-ssa-loop-im.c (mem_ref_hasher::hash): Same. + (movement_possibility): Same. + (outermost_invariant_loop): Same. + (stmt_cost): Same. + (determine_max_movement): Same. + (invariantness_dom_walker::before_dom_children): Same. + (move_computations): Same. + (may_move_till): Same. + (force_move_till_op): Same. + (force_move_till): Same. + (memref_free): Same. + (record_mem_ref_loc): Same. + (set_ref_stored_in_loop): Same. + (mark_ref_stored): Same. + (sort_bbs_in_loop_postorder_cmp): Same. + (sort_locs_in_loop_postorder_cmp): Same. + (analyze_memory_references): Same. + (mem_refs_may_alias_p): Same. + (find_ref_loc_in_loop_cmp): Same. + (rewrite_mem_ref_loc::operator): Same. + (first_mem_ref_loc_1::operator): Same. + (sm_set_flag_if_changed::operator): Same. + (execute_sm_if_changed_flag_set): Same. + (execute_sm): Same. + (hoist_memory_references): Same. + (ref_always_accessed::operator): Same. + (refs_independent_p): Same. + (record_dep_loop): Same. + (ref_indep_loop_p_1): Same. + (ref_indep_loop_p): Same. + (can_sm_ref_p): Same. + (find_refs_for_sm): Same. + (loop_suitable_for_sm): Same. + (store_motion_loop): Same. + (store_motion): Same. + (fill_always_executed_in): Same. + * tree-ssa-loop-ivcanon.c (constant_after_peeling): Same. + (estimated_unrolled_size): Same. + (loop_edge_to_cancel): Same. + (remove_exits_and_undefined_stmts): Same. + (remove_redundant_iv_tests): Same. + (unloop_loops): Same. + (estimated_peeled_sequence_size): Same. + (try_peel_loop): Same. + (canonicalize_loop_induction_variables): Same. + (canonicalize_induction_variables): Same. + * tree-ssa-loop-ivopts.c (iv_inv_expr_hasher::equal): Same. + (name_info): Same. + (stmt_after_inc_pos): Same. + (contains_abnormal_ssa_name_p): Same. + (niter_for_exit): Same. + (find_bivs): Same. + (mark_bivs): Same. + (find_givs_in_bb): Same. + (find_induction_variables): Same. + (find_interesting_uses_cond): Same. + (outermost_invariant_loop_for_expr): Same. + (idx_find_step): Same. + (add_candidate_1): Same. + (add_iv_candidate_derived_from_uses): Same. + (alloc_use_cost_map): Same. + (prepare_decl_rtl): Same. + (generic_predict_doloop_p): Same. + (computation_cost): Same. + (determine_common_wider_type): Same. + (get_computation_aff_1): Same. + (get_use_type): Same. + (determine_group_iv_cost_address): Same. + (iv_period): Same. + (difference_cannot_overflow_p): Same. + (may_eliminate_iv): Same. + (determine_set_costs): Same. + (cheaper_cost_pair): Same. + (compare_cost_pair): Same. + (iv_ca_cand_for_group): Same. + (iv_ca_recount_cost): Same. + (iv_ca_set_remove_invs): Same. + (iv_ca_set_no_cp): Same. + (iv_ca_set_add_invs): Same. + (iv_ca_set_cp): Same. + (iv_ca_add_group): Same. + (iv_ca_cost): Same. + (iv_ca_compare_deps): Same. + (iv_ca_delta_reverse): Same. + (iv_ca_delta_commit): Same. + (iv_ca_cand_used_p): Same. + (iv_ca_delta_free): Same. + (iv_ca_new): Same. + (iv_ca_free): Same. + (iv_ca_dump): Same. + (iv_ca_extend): Same. + (iv_ca_narrow): Same. + (iv_ca_prune): Same. + (cheaper_cost_with_cand): Same. + (iv_ca_replace): Same. + (try_add_cand_for): Same. + (get_initial_solution): Same. + (try_improve_iv_set): Same. + (find_optimal_iv_set_1): Same. + (create_new_iv): Same. + (rewrite_use_compare): Same. + (remove_unused_ivs): Same. + (determine_scaling_factor): Same. + * tree-ssa-loop-ivopts.h: Same. + * tree-ssa-loop-manip.c (create_iv): Same. + (compute_live_loop_exits): Same. + (add_exit_phi): Same. + (add_exit_phis): Same. + (find_uses_to_rename_use): Same. + (find_uses_to_rename_def): Same. + (find_uses_to_rename_in_loop): Same. + (rewrite_into_loop_closed_ssa): Same. + (check_loop_closed_ssa_bb): Same. + (split_loop_exit_edge): Same. + (ip_end_pos): Same. + (ip_normal_pos): Same. + (copy_phi_node_args): Same. + (gimple_duplicate_loop_to_header_edge): Same. + (can_unroll_loop_p): Same. + (determine_exit_conditions): Same. + (scale_dominated_blocks_in_loop): Same. + (niter_for_unrolled_loop): Same. + (tree_transform_and_unroll_loop): Same. + (rewrite_all_phi_nodes_with_iv): Same. + * tree-ssa-loop-manip.h: Same. + * tree-ssa-loop-niter.c (number_of_iterations_ne_max): Same. + (number_of_iterations_ne): Same. + (assert_no_overflow_lt): Same. + (assert_loop_rolls_lt): Same. + (number_of_iterations_lt): Same. + (adjust_cond_for_loop_until_wrap): Same. + (tree_simplify_using_condition): Same. + (simplify_using_initial_conditions): Same. + (simplify_using_outer_evolutions): Same. + (loop_only_exit_p): Same. + (ssa_defined_by_minus_one_stmt_p): Same. + (number_of_iterations_popcount): Same. + (number_of_iterations_exit): Same. + (find_loop_niter): Same. + (finite_loop_p): Same. + (chain_of_csts_start): Same. + (get_val_for): Same. + (loop_niter_by_eval): Same. + (derive_constant_upper_bound_ops): Same. + (do_warn_aggressive_loop_optimizations): Same. + (record_estimate): Same. + (get_cst_init_from_scev): Same. + (record_nonwrapping_iv): Same. + (idx_infer_loop_bounds): Same. + (infer_loop_bounds_from_ref): Same. + (infer_loop_bounds_from_array): Same. + (infer_loop_bounds_from_pointer_arith): Same. + (infer_loop_bounds_from_signedness): Same. + (bound_index): Same. + (discover_iteration_bound_by_body_walk): Same. + (maybe_lower_iteration_bound): Same. + (estimate_numbers_of_iterations): Same. + (estimated_loop_iterations): Same. + (estimated_loop_iterations_int): Same. + (max_loop_iterations): Same. + (max_loop_iterations_int): Same. + (likely_max_loop_iterations): Same. + (likely_max_loop_iterations_int): Same. + (estimated_stmt_executions_int): Same. + (max_stmt_executions): Same. + (likely_max_stmt_executions): Same. + (estimated_stmt_executions): Same. + (stmt_dominates_stmt_p): Same. + (nowrap_type_p): Same. + (loop_exits_before_overflow): Same. + (scev_var_range_cant_overflow): Same. + (scev_probably_wraps_p): Same. + (free_numbers_of_iterations_estimates): Same. + * tree-ssa-loop-niter.h: Same. + * tree-ssa-loop-prefetch.c (release_mem_refs): Same. + (idx_analyze_ref): Same. + (analyze_ref): Same. + (gather_memory_references_ref): Same. + (mark_nontemporal_store): Same. + (emit_mfence_after_loop): Same. + (may_use_storent_in_loop_p): Same. + (mark_nontemporal_stores): Same. + (should_unroll_loop_p): Same. + (volume_of_dist_vector): Same. + (add_subscript_strides): Same. + (self_reuse_distance): Same. + (insn_to_prefetch_ratio_too_small_p): Same. + * tree-ssa-loop-split.c (split_at_bb_p): Same. + (patch_loop_exit): Same. + (find_or_create_guard_phi): Same. + (easy_exit_values): Same. + (connect_loop_phis): Same. + (connect_loops): Same. + (compute_new_first_bound): Same. + (split_loop): Same. + (tree_ssa_split_loops): Same. + * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Same. + (is_maybe_undefined): Same. + (tree_may_unswitch_on): Same. + (simplify_using_entry_checks): Same. + (tree_unswitch_single_loop): Same. + (tree_unswitch_loop): Same. + (tree_unswitch_outer_loop): Same. + (empty_bb_without_guard_p): Same. + (used_outside_loop_p): Same. + (get_vop_from_header): Same. + (hoist_guard): Same. + * tree-ssa-loop.c (gate_oacc_kernels): Same. + (get_lsm_tmp_name): Same. + * tree-ssa-loop.h: Same. + * tree-ssa-reassoc.c (add_repeat_to_ops_vec): Same. + (build_and_add_sum): Same. + (no_side_effect_bb): Same. + (get_ops): Same. + (linearize_expr): Same. + (should_break_up_subtract): Same. + (linearize_expr_tree): Same. + * tree-ssa-scopedtables.c: Same. + * tree-ssa-scopedtables.h: Same. + * tree-ssa-structalias.c (condense_visit): Same. + (label_visit): Same. + (dump_pred_graph): Same. + (perform_var_substitution): Same. + (move_complex_constraints): Same. + (remove_preds_and_fake_succs): Same. + * tree-ssa-threadupdate.c (dbds_continue_enumeration_p): Same. + (determine_bb_domination_status): Same. + (duplicate_thread_path): Same. + (thread_through_all_blocks): Same. + * tree-ssa-threadupdate.h: Same. + * tree-streamer-in.c (streamer_read_string_cst): Same. + (input_identifier): Same. + (unpack_ts_type_common_value_fields): Same. + (unpack_ts_block_value_fields): Same. + (unpack_ts_translation_unit_decl_value_fields): Same. + (unpack_ts_omp_clause_value_fields): Same. + (streamer_read_tree_bitfields): Same. + (streamer_alloc_tree): Same. + (lto_input_ts_common_tree_pointers): Same. + (lto_input_ts_vector_tree_pointers): Same. + (lto_input_ts_poly_tree_pointers): Same. + (lto_input_ts_complex_tree_pointers): Same. + (lto_input_ts_decl_minimal_tree_pointers): Same. + (lto_input_ts_decl_common_tree_pointers): Same. + (lto_input_ts_decl_non_common_tree_pointers): Same. + (lto_input_ts_decl_with_vis_tree_pointers): Same. + (lto_input_ts_field_decl_tree_pointers): Same. + (lto_input_ts_function_decl_tree_pointers): Same. + (lto_input_ts_type_common_tree_pointers): Same. + (lto_input_ts_type_non_common_tree_pointers): Same. + (lto_input_ts_list_tree_pointers): Same. + (lto_input_ts_vec_tree_pointers): Same. + (lto_input_ts_exp_tree_pointers): Same. + (lto_input_ts_block_tree_pointers): Same. + (lto_input_ts_binfo_tree_pointers): Same. + (lto_input_ts_constructor_tree_pointers): Same. + (lto_input_ts_omp_clause_tree_pointers): Same. + (streamer_read_tree_body): Same. + * tree-streamer.h: Same. + * tree-switch-conversion.c (bit_test_cluster::is_beneficial): Same. + * tree-vect-data-refs.c (vect_get_smallest_scalar_type): Same. + (vect_analyze_possibly_independent_ddr): Same. + (vect_analyze_data_ref_dependence): Same. + (vect_compute_data_ref_alignment): Same. + (vect_enhance_data_refs_alignment): Same. + (vect_analyze_data_ref_access): Same. + (vect_check_gather_scatter): Same. + (vect_find_stmt_data_reference): Same. + (vect_create_addr_base_for_vector_ref): Same. + (vect_setup_realignment): Same. + (vect_supportable_dr_alignment): Same. + * tree-vect-loop-manip.c (rename_variables_in_bb): Same. + (adjust_phi_and_debug_stmts): Same. + (vect_set_loop_mask): Same. + (add_preheader_seq): Same. + (vect_maybe_permute_loop_masks): Same. + (vect_set_loop_masks_directly): Same. + (vect_set_loop_condition_masked): Same. + (vect_set_loop_condition_unmasked): Same. + (slpeel_duplicate_current_defs_from_edges): Same. + (slpeel_add_loop_guard): Same. + (slpeel_can_duplicate_loop_p): Same. + (create_lcssa_for_virtual_phi): Same. + (iv_phi_p): Same. + (vect_update_ivs_after_vectorizer): Same. + (vect_gen_vector_loop_niters_mult_vf): Same. + (slpeel_update_phi_nodes_for_loops): Same. + (slpeel_update_phi_nodes_for_guard1): Same. + (find_guard_arg): Same. + (slpeel_update_phi_nodes_for_guard2): Same. + (slpeel_update_phi_nodes_for_lcssa): Same. + (vect_do_peeling): Same. + (vect_create_cond_for_alias_checks): Same. + (vect_loop_versioning): Same. + * tree-vect-loop.c (vect_determine_vf_for_stmt): Same. + (vect_inner_phi_in_double_reduction_p): Same. + (vect_analyze_scalar_cycles_1): Same. + (vect_fixup_scalar_cycles_with_patterns): Same. + (vect_get_loop_niters): Same. + (bb_in_loop_p): Same. + (vect_get_max_nscalars_per_iter): Same. + (vect_verify_full_masking): Same. + (vect_compute_single_scalar_iteration_cost): Same. + (vect_analyze_loop_form_1): Same. + (vect_analyze_loop_form): Same. + (vect_active_double_reduction_p): Same. + (vect_analyze_loop_operations): Same. + (neutral_op_for_slp_reduction): Same. + (vect_is_simple_reduction): Same. + (vect_model_reduction_cost): Same. + (get_initial_def_for_reduction): Same. + (get_initial_defs_for_reduction): Same. + (vect_create_epilog_for_reduction): Same. + (vectorize_fold_left_reduction): Same. + (vectorizable_reduction): Same. + (vectorizable_induction): Same. + (vectorizable_live_operation): Same. + (loop_niters_no_overflow): Same. + (vect_get_loop_mask): Same. + (vect_transform_loop_stmt): Same. + (vect_transform_loop): Same. + * tree-vect-patterns.c (vect_reassociating_reduction_p): Same. + (vect_determine_precisions): Same. + (vect_pattern_recog_1): Same. + * tree-vect-slp.c (vect_analyze_slp_instance): Same. + * tree-vect-stmts.c (stmt_vectype): Same. + (process_use): Same. + (vect_init_vector_1): Same. + (vect_truncate_gather_scatter_offset): Same. + (get_group_load_store_type): Same. + (vect_build_gather_load_calls): Same. + (vect_get_strided_load_store_ops): Same. + (vectorizable_simd_clone_call): Same. + (vectorizable_store): Same. + (permute_vec_elements): Same. + (vectorizable_load): Same. + (vect_transform_stmt): Same. + (supportable_widening_operation): Same. + * tree-vectorizer.c (vec_info::replace_stmt): Same. + (vec_info::free_stmt_vec_info): Same. + (vect_free_loop_info_assumptions): Same. + (vect_loop_vectorized_call): Same. + (set_uid_loop_bbs): Same. + (vectorize_loops): Same. + * tree-vectorizer.h (STMT_VINFO_BB_VINFO): Same. + * tree.c (add_tree_to_fld_list): Same. + (fld_type_variant_equal_p): Same. + (fld_decl_context): Same. + (fld_incomplete_type_of): Same. + (free_lang_data_in_binfo): Same. + (need_assembler_name_p): Same. + (find_decls_types_r): Same. + (get_eh_types_for_runtime): Same. + (find_decls_types_in_eh_region): Same. + (find_decls_types_in_node): Same. + (assign_assembler_name_if_needed): Same. + * value-prof.c (stream_out_histogram_value): Same. + * value-prof.h: Same. + * var-tracking.c (use_narrower_mode): Same. + (prepare_call_arguments): Same. + (vt_expand_loc_callback): Same. + (resolve_expansions_pending_recursion): Same. + (vt_expand_loc): Same. + * varasm.c (const_hash_1): Same. + (compare_constant): Same. + (tree_output_constant_def): Same. + (simplify_subtraction): Same. + (get_pool_constant): Same. + (output_constant_pool_2): Same. + (output_constant_pool_1): Same. + (mark_constants_in_pattern): Same. + (mark_constant_pool): Same. + (get_section_anchor): Same. + * vr-values.c (compare_range_with_value): Same. + (vr_values::extract_range_from_phi_node): Same. + * vr-values.h: Same. + * web.c (unionfind_union): Same. + * wide-int.h: Same. + +2019-07-09 Martin Sebor + + PR c++/61339 * align.h: Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. * alloc-pool.h: Same. diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c index 59100a0..ee1a83a 100644 --- a/gcc/auto-profile.c +++ b/gcc/auto-profile.c @@ -104,7 +104,7 @@ namespace autofdo /* Intermediate edge info used when propagating AutoFDO profile information. We can't edge->count() directly since it's computed from edge's probability while probability is yet not decided during propagation. */ -#define AFDO_EINFO(e) ((struct edge_info *) e->aux) +#define AFDO_EINFO(e) ((class edge_info *) e->aux) class edge_info { public: diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 964f2bd..5e0fbc0 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -123,7 +123,7 @@ struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_d PTR GTY ((skip (""))) aux; /* Innermost loop containing the block. */ - struct loop *loop_father; + class loop *loop_father; /* The dominance and postdominance information node. */ struct et_node * GTY ((skip (""))) dom[2]; diff --git a/gcc/bitmap.c b/gcc/bitmap.c index 894aefa..c99d646 100644 --- a/gcc/bitmap.c +++ b/gcc/bitmap.c @@ -775,7 +775,7 @@ bitmap_alloc (bitmap_obstack *bit_obstack MEM_STAT_DECL) bit_obstack = &bitmap_default_obstack; map = bit_obstack->heads; if (map) - bit_obstack->heads = (struct bitmap_head *) map->first; + bit_obstack->heads = (class bitmap_head *) map->first; else map = XOBNEW (&bit_obstack->obstack, bitmap_head); bitmap_initialize (map, bit_obstack PASS_MEM_STAT); diff --git a/gcc/bitmap.h b/gcc/bitmap.h index 0e3ffc8..b0ca7b9 100644 --- a/gcc/bitmap.h +++ b/gcc/bitmap.h @@ -290,7 +290,7 @@ typedef unsigned long BITMAP_WORD; /* Obstack for allocating bitmaps and elements from. */ struct bitmap_obstack { struct bitmap_element *elements; - struct bitmap_head *heads; + bitmap_head *heads; struct obstack obstack; }; diff --git a/gcc/builtins.c b/gcc/builtins.c index e2ba356..e5a9261 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1400,7 +1400,7 @@ expand_builtin_prefetch (tree exp) if (targetm.have_prefetch ()) { - struct expand_operand ops[3]; + class expand_operand ops[3]; create_address_operand (&ops[0], op0); create_integer_operand (&ops[1], INTVAL (op1)); @@ -2445,7 +2445,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target) if (icode != CODE_FOR_nothing) { - struct expand_operand ops[1]; + class expand_operand ops[1]; rtx_insn *last = get_last_insn (); tree orig_arg = arg; @@ -2946,7 +2946,7 @@ expand_builtin_strlen (tree exp, rtx target, if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) return NULL_RTX; - struct expand_operand ops[4]; + class expand_operand ops[4]; rtx pat; tree len; tree src = CALL_EXPR_ARG (exp, 0); @@ -3923,7 +3923,7 @@ expand_builtin_mempcpy_args (tree dest, tree src, tree len, static rtx expand_movstr (tree dest, tree src, rtx target, memop_ret retmode) { - struct expand_operand ops[3]; + class expand_operand ops[3]; rtx dest_mem; rtx src_mem; @@ -4633,7 +4633,7 @@ expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx, if (target && (!REG_P (target) || HARD_REGISTER_P (target))) target = NULL_RTX; - struct expand_operand ops[4]; + class expand_operand ops[4]; create_output_operand (&ops[0], target, insn_mode); create_fixed_operand (&ops[1], arg1_rtx); create_fixed_operand (&ops[2], arg2_rtx); @@ -5606,7 +5606,7 @@ expand_builtin___clear_cache (tree exp) if (targetm.have_clear_cache ()) { - struct expand_operand ops[2]; + class expand_operand ops[2]; begin = CALL_EXPR_ARG (exp, 0); begin_rtx = expand_expr (begin, NULL_RTX, Pmode, EXPAND_NORMAL); @@ -6566,7 +6566,7 @@ expand_ifn_atomic_bit_test_and (gcall *call) machine_mode mode = TYPE_MODE (TREE_TYPE (flag)); enum rtx_code code; optab optab; - struct expand_operand ops[5]; + class expand_operand ops[5]; gcc_assert (flag_inline_atomics); @@ -6874,7 +6874,7 @@ expand_builtin_thread_pointer (tree exp, rtx target) icode = direct_optab_handler (get_thread_pointer_optab, Pmode); if (icode != CODE_FOR_nothing) { - struct expand_operand op; + class expand_operand op; /* If the target is not sutitable then create a new target. */ if (target == NULL_RTX || !REG_P (target) @@ -6897,7 +6897,7 @@ expand_builtin_set_thread_pointer (tree exp) icode = direct_optab_handler (set_thread_pointer_optab, Pmode); if (icode != CODE_FOR_nothing) { - struct expand_operand op; + class expand_operand op; rtx val = expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, Pmode, EXPAND_NORMAL); create_input_operand (&op, val, Pmode); diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 4d8f967..bbad47f 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,6 +1,13 @@ 2019-07-09 Martin Sebor PR c++/61339 + * c-opts.c (handle_deferred_opts): : Change class-key of PODs to struct + and others to class. + * c-pretty-print.h: Same. + +2019-07-09 Martin Sebor + + PR c++/61339 * c-format.c (check_argument_type): Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 188da43..e97bbdf5 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -1287,7 +1287,7 @@ handle_deferred_opts (void) if (!deps_seen) return; - struct mkdeps *deps = cpp_get_deps (parse_in); + mkdeps *deps = cpp_get_deps (parse_in); for (size_t i = 0; i < deferred_count; i++) { diff --git a/gcc/c-family/c-pretty-print.h b/gcc/c-family/c-pretty-print.h index 8c516c3..8d69620 100644 --- a/gcc/c-family/c-pretty-print.h +++ b/gcc/c-family/c-pretty-print.h @@ -36,7 +36,7 @@ enum pp_c_pretty_print_flags /* The data type used to bundle information necessary for pretty-printing a C or C++ entity. */ -struct c_pretty_printer; +class c_pretty_printer; /* The type of a C pretty-printer 'member' function. */ typedef void (*c_pretty_print_fn) (c_pretty_printer *, tree); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index d2645a8..29836ff 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,6 +1,16 @@ 2019-07-09 Martin Sebor PR c++/61339 + * c-decl.c (xref_tag): Change class-key of PODs to struct and others + to class. + (field_decl_cmp): Same. + * c-parser.c (c_parser_struct_or_union_specifier): Same. + * c-tree.h: Same. + * gimple-parser.c (c_parser_gimple_compound_statement): Same. + +2019-07-09 Martin Sebor + + PR c++/61339 * c-decl.c: Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. * gimple-parser.c: Same. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 35e15ba..d75648a 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -592,7 +592,7 @@ public: /* Information for the struct or union currently being parsed, or NULL if not parsing a struct or union. */ -static struct c_struct_parse_info *struct_parse_info; +static class c_struct_parse_info *struct_parse_info; /* Forward declarations. */ static tree lookup_name_in_scope (tree, struct c_scope *); @@ -7768,7 +7768,7 @@ xref_tag (enum tree_code code, tree name) tree start_struct (location_t loc, enum tree_code code, tree name, - struct c_struct_parse_info **enclosing_struct_parse_info) + class c_struct_parse_info **enclosing_struct_parse_info) { /* If there is already a tag defined at this scope (as a forward reference), just return it. */ @@ -8183,7 +8183,7 @@ field_decl_cmp (const void *x_p, const void *y_p) tree finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, - struct c_struct_parse_info *enclosing_struct_parse_info) + class c_struct_parse_info *enclosing_struct_parse_info) { tree x; bool toplevel = file_scope == current_scope; diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 9850872..3fa7e68 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -3145,7 +3145,7 @@ c_parser_struct_or_union_specifier (c_parser *parser) { /* Parse a struct or union definition. Start the scope of the tag before parsing components. */ - struct c_struct_parse_info *struct_info; + class c_struct_parse_info *struct_info; tree type = start_struct (struct_loc, code, ident, &struct_info); tree postfix_attrs; /* We chain the components in reverse order, then put them in diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 346f46a..dae2979 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -525,7 +525,7 @@ extern void gen_aux_info_record (tree, int, int, int); /* in c-decl.c */ struct c_spot_bindings; -struct c_struct_parse_info; +class c_struct_parse_info; extern struct obstack parser_obstack; extern tree c_break_label; extern tree c_cont_label; @@ -562,7 +562,7 @@ extern void finish_decl (tree, location_t, tree, tree, tree); extern tree finish_enum (tree, tree, tree); extern void finish_function (void); extern tree finish_struct (location_t, tree, tree, tree, - struct c_struct_parse_info *); + class c_struct_parse_info *); extern struct c_arg_info *build_arg_info (void); extern struct c_arg_info *get_parm_info (bool, tree); extern tree grokfield (location_t, struct c_declarator *, @@ -586,7 +586,7 @@ extern bool start_function (struct c_declspecs *, struct c_declarator *, tree); extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool, tree); extern tree start_struct (location_t, enum tree_code, tree, - struct c_struct_parse_info **); + class c_struct_parse_info **); extern void store_parm_decls (void); extern void store_parm_decls_from (struct c_arg_info *); extern void temp_store_parm_decls (tree, tree); diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index e388d93..9a65394 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -585,7 +585,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) profile_probability::always ()); /* We leave the proper setting to fixup. */ - struct loop *loop_father = loops_for_fn (cfun)->tree_root; + class loop *loop_father = loops_for_fn (cfun)->tree_root; /* If the new block is a loop header, allocate a loop struct. Fixup will take care of proper placement within the loop tree. */ @@ -598,7 +598,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) } else { - struct loop *loop = alloc_loop (); + class loop *loop = alloc_loop (); loop->num = is_loop_header_of; loop->header = bb; vec_safe_grow_cleared (loops_for_fn (cfun)->larray, diff --git a/gcc/caller-save.c b/gcc/caller-save.c index 9ff470c..7c1de89 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -88,11 +88,11 @@ static void mark_set_regs (rtx, const_rtx, void *); static void mark_referenced_regs (rtx *, refmarker_fn *mark, void *mark_arg); static refmarker_fn mark_reg_as_referenced; static refmarker_fn replace_reg_with_saved_mem; -static int insert_save (struct insn_chain *, int, HARD_REG_SET *, +static int insert_save (class insn_chain *, int, HARD_REG_SET *, machine_mode *); -static int insert_restore (struct insn_chain *, int, int, int, +static int insert_restore (class insn_chain *, int, int, int, machine_mode *); -static struct insn_chain *insert_one_insn (struct insn_chain *, int, int, +static class insn_chain *insert_one_insn (class insn_chain *, int, int, rtx); static void add_stored_regs (rtx, const_rtx, void *); @@ -419,7 +419,7 @@ setup_save_areas (void) HARD_REG_SET hard_regs_used; struct saved_hard_reg *saved_reg; rtx_insn *insn; - struct insn_chain *chain, *next; + class insn_chain *chain, *next; unsigned int regno; HARD_REG_SET hard_regs_to_save, used_regs, this_insn_sets; reg_set_iterator rsi; @@ -744,7 +744,7 @@ setup_save_areas (void) void save_call_clobbered_regs (void) { - struct insn_chain *chain, *next, *last = NULL; + class insn_chain *chain, *next, *last = NULL; machine_mode save_mode [FIRST_PSEUDO_REGISTER]; /* Computed in mark_set_regs, holds all registers set by the current @@ -1174,14 +1174,14 @@ replace_reg_with_saved_mem (rtx *loc, Return the extra number of registers saved. */ static int -insert_restore (struct insn_chain *chain, int before_p, int regno, +insert_restore (class insn_chain *chain, int before_p, int regno, int maxrestore, machine_mode *save_mode) { int i, k; rtx pat = NULL_RTX; int code; unsigned int numregs = 0; - struct insn_chain *new_chain; + class insn_chain *new_chain; rtx mem; /* A common failure mode if register status is not correct in the @@ -1253,7 +1253,7 @@ insert_restore (struct insn_chain *chain, int before_p, int regno, /* Like insert_restore above, but save registers instead. */ static int -insert_save (struct insn_chain *chain, int regno, +insert_save (class insn_chain *chain, int regno, HARD_REG_SET *to_save, machine_mode *save_mode) { int i; @@ -1261,7 +1261,7 @@ insert_save (struct insn_chain *chain, int regno, rtx pat = NULL_RTX; int code; unsigned int numregs = 0; - struct insn_chain *new_chain; + class insn_chain *new_chain; rtx mem; /* A common failure mode if register status is not correct in the @@ -1351,11 +1351,11 @@ add_used_regs (rtx *loc, void *data) } /* Emit a new caller-save insn and set the code. */ -static struct insn_chain * -insert_one_insn (struct insn_chain *chain, int before_p, int code, rtx pat) +static class insn_chain * +insert_one_insn (class insn_chain *chain, int before_p, int code, rtx pat) { rtx_insn *insn = chain->insn; - struct insn_chain *new_chain; + class insn_chain *new_chain; /* If INSN references CC0, put our insns in front of the insn that sets CC0. This is always safe, since the only way we could be passed an diff --git a/gcc/cfg.c b/gcc/cfg.c index 983115e..4757bab 100644 --- a/gcc/cfg.c +++ b/gcc/cfg.c @@ -1145,7 +1145,7 @@ get_bb_copy (basic_block bb) initialized so passes not needing this don't need to care. */ void -set_loop_copy (struct loop *loop, struct loop *copy) +set_loop_copy (class loop *loop, class loop *copy) { if (!copy) copy_original_table_clear (loop_copy, loop->num); @@ -1155,8 +1155,8 @@ set_loop_copy (struct loop *loop, struct loop *copy) /* Get the copy of LOOP. */ -struct loop * -get_loop_copy (struct loop *loop) +class loop * +get_loop_copy (class loop *loop) { struct htab_bb_copy_original_entry *entry; struct htab_bb_copy_original_entry key; diff --git a/gcc/cfg.h b/gcc/cfg.h index b6f95bd..12cd760 100644 --- a/gcc/cfg.h +++ b/gcc/cfg.h @@ -122,8 +122,8 @@ extern void set_bb_original (basic_block, basic_block); extern basic_block get_bb_original (basic_block); extern void set_bb_copy (basic_block, basic_block); extern basic_block get_bb_copy (basic_block); -void set_loop_copy (struct loop *, struct loop *); -struct loop *get_loop_copy (struct loop *); +void set_loop_copy (class loop *, class loop *); +class loop *get_loop_copy (class loop *); /* Generic RAII class to allocate a bit from storage of integer type T. The allocated bit is accessible as mask with the single bit set diff --git a/gcc/cfganal.h b/gcc/cfganal.h index ba889e2..c928fea 100644 --- a/gcc/cfganal.h +++ b/gcc/cfganal.h @@ -72,8 +72,8 @@ extern int rev_post_order_and_mark_dfs_back_seme (struct function *, edge, extern int dfs_enumerate_from (basic_block, int, bool (*)(const_basic_block, const void *), basic_block *, int, const void *); -extern void compute_dominance_frontiers (struct bitmap_head *); -extern bitmap compute_idf (bitmap, struct bitmap_head *); +extern void compute_dominance_frontiers (class bitmap_head *); +extern bitmap compute_idf (bitmap, class bitmap_head *); extern void bitmap_intersection_of_succs (sbitmap, sbitmap *, basic_block); extern void bitmap_intersection_of_preds (sbitmap, sbitmap *, basic_block); extern void bitmap_union_of_succs (sbitmap, sbitmap *, basic_block); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 0128fca..d0c1d31 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -332,7 +332,7 @@ public: #define EOC ((size_t)-1) /* We have an array of such objects while deciding allocation. */ -static struct stack_var *stack_vars; +static class stack_var *stack_vars; static size_t stack_vars_alloc; static size_t stack_vars_num; static hash_map *decl_to_stack_part; @@ -426,7 +426,7 @@ alloc_stack_frame_space (poly_int64 size, unsigned HOST_WIDE_INT align) static void add_stack_var (tree decl, bool really_expand) { - struct stack_var *v; + class stack_var *v; if (stack_vars_num >= stack_vars_alloc) { @@ -435,7 +435,7 @@ add_stack_var (tree decl, bool really_expand) else stack_vars_alloc = 32; stack_vars - = XRESIZEVEC (struct stack_var, stack_vars, stack_vars_alloc); + = XRESIZEVEC (class stack_var, stack_vars, stack_vars_alloc); } if (!decl_to_stack_part) decl_to_stack_part = new hash_map; @@ -474,8 +474,8 @@ add_stack_var (tree decl, bool really_expand) static void add_stack_var_conflict (size_t x, size_t y) { - struct stack_var *a = &stack_vars[x]; - struct stack_var *b = &stack_vars[y]; + class stack_var *a = &stack_vars[x]; + class stack_var *b = &stack_vars[y]; if (x == y) return; if (!a->conflicts) @@ -491,8 +491,8 @@ add_stack_var_conflict (size_t x, size_t y) static bool stack_var_conflict_p (size_t x, size_t y) { - struct stack_var *a = &stack_vars[x]; - struct stack_var *b = &stack_vars[y]; + class stack_var *a = &stack_vars[x]; + class stack_var *b = &stack_vars[y]; if (x == y) return false; /* Partitions containing an SSA name result from gimple registers @@ -607,7 +607,7 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict) unsigned i; EXECUTE_IF_SET_IN_BITMAP (work, 0, i, bi) { - struct stack_var *a = &stack_vars[i]; + class stack_var *a = &stack_vars[i]; if (!a->conflicts) a->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack); bitmap_ior_into (a->conflicts, work); @@ -853,7 +853,7 @@ update_alias_info_with_stack_vars (void) static void union_stack_vars (size_t a, size_t b) { - struct stack_var *vb = &stack_vars[b]; + class stack_var *vb = &stack_vars[b]; bitmap_iterator bi; unsigned u; @@ -1045,7 +1045,7 @@ public: with that location. */ static void -expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) +expand_stack_vars (bool (*pred) (size_t), class stack_vars_data *data) { size_t si, i, j, n = stack_vars_num; poly_uint64 large_size = 0, large_alloc = 0; @@ -2232,7 +2232,7 @@ expand_used_vars (void) /* Assign rtl to each variable based on these partitions. */ if (stack_vars_num > 0) { - struct stack_vars_data data; + class stack_vars_data data; data.asan_base = NULL_RTX; data.asan_alignb = 0; diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c index 76183ec..7c00fc3 100644 --- a/gcc/cfghooks.c +++ b/gcc/cfghooks.c @@ -496,7 +496,7 @@ redirect_edge_and_branch_force (edge e, basic_block dest) { if (ret != NULL) { - struct loop *loop + class loop *loop = find_common_loop (single_pred (ret)->loop_father, single_succ (ret)->loop_father); add_bb_to_loop (ret, loop); @@ -604,7 +604,7 @@ delete_basic_block (basic_block bb) if (current_loops != NULL) { - struct loop *loop = bb->loop_father; + class loop *loop = bb->loop_father; /* If we remove the header or the latch of a loop, mark the loop for removal. */ @@ -640,7 +640,7 @@ split_edge (edge e) profile_count count = e->count (); edge f; bool irr = (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0; - struct loop *loop; + class loop *loop; basic_block src = e->src, dest = e->dest; if (!cfg_hooks->split_edge) @@ -870,7 +870,7 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge), edge e, fallthru; edge_iterator ei; basic_block dummy, jump; - struct loop *loop, *ploop, *cloop; + class loop *loop, *ploop, *cloop; if (!cfg_hooks->make_forwarder_block) internal_error ("%s does not support make_forwarder_block", @@ -1035,7 +1035,7 @@ force_nonfallthru (edge e) { basic_block pred = single_pred (ret); basic_block succ = single_succ (ret); - struct loop *loop + class loop *loop = find_common_loop (pred->loop_father, succ->loop_father); rescan_loop_exit (e, false, true); add_bb_to_loop (ret, loop); @@ -1118,8 +1118,8 @@ duplicate_block (basic_block bb, edge e, basic_block after, copy_bb_data *id) of BB if the loop is not being copied. */ if (current_loops != NULL) { - struct loop *cloop = bb->loop_father; - struct loop *copy = get_loop_copy (cloop); + class loop *cloop = bb->loop_father; + class loop *copy = get_loop_copy (cloop); /* If we copied the loop header block but not the loop we have created a loop with multiple entries. Ditch the loop, add the new block to the outer loop and arrange for a fixup. */ @@ -1228,7 +1228,7 @@ lv_flush_pending_stmts (edge e) a need to call the tree_duplicate_loop_to_header_edge rather than duplicate_loop_to_header_edge when we are in tree mode. */ bool -cfg_hook_duplicate_loop_to_header_edge (struct loop *loop, edge e, +cfg_hook_duplicate_loop_to_header_edge (class loop *loop, edge e, unsigned int ndupl, sbitmap wont_exit, edge orig, vec *to_remove, @@ -1336,7 +1336,7 @@ end: void copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs, edge *edges, unsigned num_edges, edge *new_edges, - struct loop *base, basic_block after, bool update_dominance) + class loop *base, basic_block after, bool update_dominance) { unsigned i, j; basic_block bb, new_bb, dom_bb; diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h index 9ed0c36..627eff9 100644 --- a/gcc/cfghooks.h +++ b/gcc/cfghooks.h @@ -166,7 +166,7 @@ struct cfg_hooks /* A hook for duplicating loop in CFG, currently this is used in loop versioning. */ - bool (*cfg_hook_duplicate_loop_to_header_edge) (struct loop *, edge, + bool (*cfg_hook_duplicate_loop_to_header_edge) (class loop *, edge, unsigned, sbitmap, edge, vec *, int); @@ -250,7 +250,7 @@ extern bool block_ends_with_condjump_p (const_basic_block bb); extern int flow_call_edges_add (sbitmap); extern void execute_on_growing_pred (edge); extern void execute_on_shrinking_pred (edge); -extern bool cfg_hook_duplicate_loop_to_header_edge (struct loop *loop, edge, +extern bool cfg_hook_duplicate_loop_to_header_edge (class loop *loop, edge, unsigned int ndupl, sbitmap wont_exit, edge orig, @@ -266,7 +266,7 @@ extern void lv_add_condition_to_bb (basic_block, basic_block, basic_block, extern bool can_copy_bbs_p (basic_block *, unsigned); extern void copy_bbs (basic_block *, unsigned, basic_block *, - edge *, unsigned, edge *, struct loop *, + edge *, unsigned, edge *, class loop *, basic_block, bool); void profile_record_check_consistency (profile_record *); diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index f64326b..4ad1f65 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -59,7 +59,7 @@ flow_loops_cfg_dump (FILE *file) /* Return nonzero if the nodes of LOOP are a subset of OUTER. */ bool -flow_loop_nested_p (const struct loop *outer, const struct loop *loop) +flow_loop_nested_p (const class loop *outer, const class loop *loop) { unsigned odepth = loop_depth (outer); @@ -70,8 +70,8 @@ flow_loop_nested_p (const struct loop *outer, const struct loop *loop) /* Returns the loop such that LOOP is nested DEPTH (indexed from zero) loops within LOOP. */ -struct loop * -superloop_at_depth (struct loop *loop, unsigned depth) +class loop * +superloop_at_depth (class loop *loop, unsigned depth) { unsigned ldepth = loop_depth (loop); @@ -86,7 +86,7 @@ superloop_at_depth (struct loop *loop, unsigned depth) /* Returns the list of the latch edges of LOOP. */ static vec -get_loop_latch_edges (const struct loop *loop) +get_loop_latch_edges (const class loop *loop) { edge_iterator ei; edge e; @@ -105,8 +105,8 @@ get_loop_latch_edges (const struct loop *loop) using auxiliary dump callback function LOOP_DUMP_AUX if non null. */ void -flow_loop_dump (const struct loop *loop, FILE *file, - void (*loop_dump_aux) (const struct loop *, FILE *, int), +flow_loop_dump (const class loop *loop, FILE *file, + void (*loop_dump_aux) (const class loop *, FILE *, int), int verbose) { basic_block *bbs; @@ -160,9 +160,9 @@ flow_loop_dump (const struct loop *loop, FILE *file, using auxiliary dump callback function LOOP_DUMP_AUX if non null. */ void -flow_loops_dump (FILE *file, void (*loop_dump_aux) (const struct loop *, FILE *, int), int verbose) +flow_loops_dump (FILE *file, void (*loop_dump_aux) (const class loop *, FILE *, int), int verbose) { - struct loop *loop; + class loop *loop; if (!current_loops || ! file) return; @@ -181,7 +181,7 @@ flow_loops_dump (FILE *file, void (*loop_dump_aux) (const struct loop *, FILE *, /* Free data allocated for LOOP. */ void -flow_loop_free (struct loop *loop) +flow_loop_free (class loop *loop) { struct loop_exit *exit, *next; @@ -229,7 +229,7 @@ flow_loops_free (struct loops *loops) Return the number of nodes within the loop. */ int -flow_loop_nodes_find (basic_block header, struct loop *loop) +flow_loop_nodes_find (basic_block header, class loop *loop) { vec stack = vNULL; int num_nodes = 1; @@ -278,7 +278,7 @@ flow_loop_nodes_find (basic_block header, struct loop *loop) superloop is FATHER. */ static void -establish_preds (struct loop *loop, struct loop *father) +establish_preds (class loop *loop, class loop *father) { loop_p ploop; unsigned depth = loop_depth (father) + 1; @@ -302,8 +302,8 @@ establish_preds (struct loop *loop, struct loop *father) of FATHERs siblings. */ void -flow_loop_tree_node_add (struct loop *father, struct loop *loop, - struct loop *after) +flow_loop_tree_node_add (class loop *father, class loop *loop, + class loop *after) { if (after) { @@ -322,9 +322,9 @@ flow_loop_tree_node_add (struct loop *father, struct loop *loop, /* Remove LOOP from the loop hierarchy tree. */ void -flow_loop_tree_node_remove (struct loop *loop) +flow_loop_tree_node_remove (class loop *loop) { - struct loop *prev, *father; + class loop *prev, *father; father = loop_outer (loop); @@ -343,10 +343,10 @@ flow_loop_tree_node_remove (struct loop *loop) /* Allocates and returns new loop structure. */ -struct loop * +class loop * alloc_loop (void) { - struct loop *loop = ggc_cleared_alloc (); + class loop *loop = ggc_cleared_alloc (); loop->exits = ggc_cleared_alloc (); loop->exits->next = loop->exits->prev = loop->exits; @@ -365,7 +365,7 @@ void init_loops_structure (struct function *fn, struct loops *loops, unsigned num_loops) { - struct loop *root; + class loop *root; memset (loops, 0, sizeof *loops); vec_alloc (loops->larray, num_loops); @@ -460,7 +460,7 @@ flow_loops_find (struct loops *loops) basic_block header = BASIC_BLOCK_FOR_FN (cfun, rc_order[b]); if (bb_loop_header_p (header)) { - struct loop *loop; + class loop *loop; /* The current active loop tree has valid loop-fathers for header blocks. */ @@ -503,7 +503,7 @@ flow_loops_find (struct loops *loops) and assign basic-block ownership. */ for (i = 0; i < larray.length (); ++i) { - struct loop *loop = larray[i]; + class loop *loop = larray[i]; basic_block header = loop->header; edge_iterator ei; edge e; @@ -539,8 +539,8 @@ static int *sort_sibling_loops_cmp_rpo; static int sort_sibling_loops_cmp (const void *la_, const void *lb_) { - const struct loop *la = *(const struct loop * const *)la_; - const struct loop *lb = *(const struct loop * const *)lb_; + const class loop *la = *(const class loop * const *)la_; + const class loop *lb = *(const class loop * const *)lb_; return (sort_sibling_loops_cmp_rpo[la->header->index] - sort_sibling_loops_cmp_rpo[lb->header->index]); } @@ -643,7 +643,7 @@ find_subloop_latch_edge_by_profile (vec latches) another edge. */ static edge -find_subloop_latch_edge_by_ivs (struct loop *loop ATTRIBUTE_UNUSED, vec latches) +find_subloop_latch_edge_by_ivs (class loop *loop ATTRIBUTE_UNUSED, vec latches) { edge e, latch = latches[0]; unsigned i; @@ -695,7 +695,7 @@ find_subloop_latch_edge_by_ivs (struct loop *loop ATTRIBUTE_UNUSED, vec la returns NULL. */ static edge -find_subloop_latch_edge (struct loop *loop) +find_subloop_latch_edge (class loop *loop) { vec latches = get_loop_latch_edges (loop); edge latch = NULL; @@ -729,11 +729,11 @@ mfb_redirect_edges_in_set (edge e) /* Creates a subloop of LOOP with latch edge LATCH. */ static void -form_subloop (struct loop *loop, edge latch) +form_subloop (class loop *loop, edge latch) { edge_iterator ei; edge e, new_entry; - struct loop *new_loop; + class loop *new_loop; mfb_reis_set = new hash_set; FOR_EACH_EDGE (e, ei, loop->header->preds) @@ -759,7 +759,7 @@ form_subloop (struct loop *loop, edge latch) a new latch of LOOP. */ static void -merge_latch_edges (struct loop *loop) +merge_latch_edges (class loop *loop) { vec latches = get_loop_latch_edges (loop); edge latch, e; @@ -792,7 +792,7 @@ merge_latch_edges (struct loop *loop) loops with single latch edge. */ static void -disambiguate_multiple_latches (struct loop *loop) +disambiguate_multiple_latches (class loop *loop) { edge e; @@ -836,7 +836,7 @@ disambiguate_multiple_latches (struct loop *loop) void disambiguate_loops_with_multiple_latches (void) { - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, 0) { @@ -847,9 +847,9 @@ disambiguate_loops_with_multiple_latches (void) /* Return nonzero if basic block BB belongs to LOOP. */ bool -flow_bb_inside_loop_p (const struct loop *loop, const_basic_block bb) +flow_bb_inside_loop_p (const class loop *loop, const_basic_block bb) { - struct loop *source_loop; + class loop *source_loop; if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun) || bb == EXIT_BLOCK_PTR_FOR_FN (cfun)) @@ -863,7 +863,7 @@ flow_bb_inside_loop_p (const struct loop *loop, const_basic_block bb) static bool glb_enum_p (const_basic_block bb, const void *glb_loop) { - const struct loop *const loop = (const struct loop *) glb_loop; + const class loop *const loop = (const class loop *) glb_loop; return (bb != loop->header && dominated_by_p (CDI_DOMINATORS, bb, loop->header)); } @@ -876,7 +876,7 @@ glb_enum_p (const_basic_block bb, const void *glb_loop) returned. */ unsigned -get_loop_body_with_size (const struct loop *loop, basic_block *body, +get_loop_body_with_size (const class loop *loop, basic_block *body, unsigned max_size) { return dfs_enumerate_from (loop->header, 1, glb_enum_p, @@ -888,7 +888,7 @@ get_loop_body_with_size (const struct loop *loop, basic_block *body, header != latch, latch is the 1-st block. */ basic_block * -get_loop_body (const struct loop *loop) +get_loop_body (const class loop *loop) { basic_block *body, bb; unsigned tv = 0; @@ -918,7 +918,7 @@ get_loop_body (const struct loop *loop) array TOVISIT from index *TV. */ static void -fill_sons_in_loop (const struct loop *loop, basic_block bb, +fill_sons_in_loop (const class loop *loop, basic_block bb, basic_block *tovisit, int *tv) { basic_block son, postpone = NULL; @@ -948,7 +948,7 @@ fill_sons_in_loop (const struct loop *loop, basic_block bb, the latch, then only blocks dominated by s are be after it. */ basic_block * -get_loop_body_in_dom_order (const struct loop *loop) +get_loop_body_in_dom_order (const class loop *loop) { basic_block *tovisit; int tv; @@ -970,7 +970,7 @@ get_loop_body_in_dom_order (const struct loop *loop) /* Gets body of a LOOP sorted via provided BB_COMPARATOR. */ basic_block * -get_loop_body_in_custom_order (const struct loop *loop, +get_loop_body_in_custom_order (const class loop *loop, int (*bb_comparator) (const void *, const void *)) { basic_block *bbs = get_loop_body (loop); @@ -983,7 +983,7 @@ get_loop_body_in_custom_order (const struct loop *loop, /* Get body of a LOOP in breadth first sort order. */ basic_block * -get_loop_body_in_bfs_order (const struct loop *loop) +get_loop_body_in_bfs_order (const class loop *loop) { basic_block *blocks; basic_block bb; @@ -1069,7 +1069,7 @@ void rescan_loop_exit (edge e, bool new_edge, bool removed) { struct loop_exit *exits = NULL, *exit; - struct loop *aloop, *cloop; + class loop *aloop, *cloop; if (!loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS)) return; @@ -1190,7 +1190,7 @@ release_recorded_exits (function *fn) /* Returns the list of the exit edges of a LOOP. */ vec -get_loop_exit_edges (const struct loop *loop) +get_loop_exit_edges (const class loop *loop) { vec edges = vNULL; edge e; @@ -1226,7 +1226,7 @@ get_loop_exit_edges (const struct loop *loop) /* Counts the number of conditional branches inside LOOP. */ unsigned -num_loop_branches (const struct loop *loop) +num_loop_branches (const class loop *loop) { unsigned i, n; basic_block * body; @@ -1245,7 +1245,7 @@ num_loop_branches (const struct loop *loop) /* Adds basic block BB to LOOP. */ void -add_bb_to_loop (basic_block bb, struct loop *loop) +add_bb_to_loop (basic_block bb, class loop *loop) { unsigned i; loop_p ploop; @@ -1273,7 +1273,7 @@ void remove_bb_from_loops (basic_block bb) { unsigned i; - struct loop *loop = bb->loop_father; + class loop *loop = bb->loop_father; loop_p ploop; edge_iterator ei; edge e; @@ -1295,8 +1295,8 @@ remove_bb_from_loops (basic_block bb) } /* Finds nearest common ancestor in loop tree for given loops. */ -struct loop * -find_common_loop (struct loop *loop_s, struct loop *loop_d) +class loop * +find_common_loop (class loop *loop_s, class loop *loop_d) { unsigned sdepth, ddepth; @@ -1322,7 +1322,7 @@ find_common_loop (struct loop *loop_s, struct loop *loop_d) /* Removes LOOP from structures and frees its data. */ void -delete_loop (struct loop *loop) +delete_loop (class loop *loop) { /* Remove the loop from structure. */ flow_loop_tree_node_remove (loop); @@ -1337,11 +1337,11 @@ delete_loop (struct loop *loop) /* Cancels the LOOP; it must be innermost one. */ static void -cancel_loop (struct loop *loop) +cancel_loop (class loop *loop) { basic_block *bbs; unsigned i; - struct loop *outer = loop_outer (loop); + class loop *outer = loop_outer (loop); gcc_assert (!loop->inner); @@ -1356,7 +1356,7 @@ cancel_loop (struct loop *loop) /* Cancels LOOP and all its subloops. */ void -cancel_loop_tree (struct loop *loop) +cancel_loop_tree (class loop *loop) { while (loop->inner) cancel_loop_tree (loop->inner); @@ -1385,7 +1385,7 @@ verify_loop_structure (void) { unsigned *sizes, i, j; basic_block bb, *bbs; - struct loop *loop; + class loop *loop; int err = 0; edge e; unsigned num = number_of_loops (cfun); @@ -1727,14 +1727,14 @@ verify_loop_structure (void) /* Returns latch edge of LOOP. */ edge -loop_latch_edge (const struct loop *loop) +loop_latch_edge (const class loop *loop) { return find_edge (loop->latch, loop->header); } /* Returns preheader edge of LOOP. */ edge -loop_preheader_edge (const struct loop *loop) +loop_preheader_edge (const class loop *loop) { edge e; edge_iterator ei; @@ -1758,7 +1758,7 @@ loop_preheader_edge (const struct loop *loop) /* Returns true if E is an exit of LOOP. */ bool -loop_exit_edge_p (const struct loop *loop, const_edge e) +loop_exit_edge_p (const class loop *loop, const_edge e) { return (flow_bb_inside_loop_p (loop, e->src) && !flow_bb_inside_loop_p (loop, e->dest)); @@ -1769,7 +1769,7 @@ loop_exit_edge_p (const struct loop *loop, const_edge e) is returned always. */ edge -single_exit (const struct loop *loop) +single_exit (const class loop *loop) { struct loop_exit *exit = loop->exits->next; @@ -1785,7 +1785,7 @@ single_exit (const struct loop *loop) /* Returns true when BB has an incoming edge exiting LOOP. */ bool -loop_exits_to_bb_p (struct loop *loop, basic_block bb) +loop_exits_to_bb_p (class loop *loop, basic_block bb) { edge e; edge_iterator ei; @@ -1800,7 +1800,7 @@ loop_exits_to_bb_p (struct loop *loop, basic_block bb) /* Returns true when BB has an outgoing edge exiting LOOP. */ bool -loop_exits_from_bb_p (struct loop *loop, basic_block bb) +loop_exits_from_bb_p (class loop *loop, basic_block bb) { edge e; edge_iterator ei; @@ -1815,10 +1815,10 @@ loop_exits_from_bb_p (struct loop *loop, basic_block bb) /* Return location corresponding to the loop control condition if possible. */ dump_user_location_t -get_loop_location (struct loop *loop) +get_loop_location (class loop *loop) { rtx_insn *insn = NULL; - struct niter_desc *desc = NULL; + class niter_desc *desc = NULL; edge exit; /* For a for or while loop, we would like to return the location @@ -1869,7 +1869,7 @@ get_loop_location (struct loop *loop) I_BOUND times. */ void -record_niter_bound (struct loop *loop, const widest_int &i_bound, +record_niter_bound (class loop *loop, const widest_int &i_bound, bool realistic, bool upper) { /* Update the bounds only when there is no previous estimation, or when the @@ -1920,7 +1920,7 @@ record_niter_bound (struct loop *loop, const widest_int &i_bound, on the number of iterations of LOOP could not be derived, returns -1. */ HOST_WIDE_INT -get_estimated_loop_iterations_int (struct loop *loop) +get_estimated_loop_iterations_int (class loop *loop) { widest_int nit; HOST_WIDE_INT hwi_nit; @@ -1940,7 +1940,7 @@ get_estimated_loop_iterations_int (struct loop *loop) the number of execution of the latch by one. */ HOST_WIDE_INT -max_stmt_executions_int (struct loop *loop) +max_stmt_executions_int (class loop *loop) { HOST_WIDE_INT nit = get_max_loop_iterations_int (loop); HOST_WIDE_INT snit; @@ -1959,7 +1959,7 @@ max_stmt_executions_int (struct loop *loop) the number of execution of the latch by one. */ HOST_WIDE_INT -likely_max_stmt_executions_int (struct loop *loop) +likely_max_stmt_executions_int (class loop *loop) { HOST_WIDE_INT nit = get_likely_max_loop_iterations_int (loop); HOST_WIDE_INT snit; @@ -1978,7 +1978,7 @@ likely_max_stmt_executions_int (struct loop *loop) returns true. */ bool -get_estimated_loop_iterations (struct loop *loop, widest_int *nit) +get_estimated_loop_iterations (class loop *loop, widest_int *nit) { /* Even if the bound is not recorded, possibly we can derrive one from profile. */ @@ -2002,7 +2002,7 @@ get_estimated_loop_iterations (struct loop *loop, widest_int *nit) false, otherwise returns true. */ bool -get_max_loop_iterations (const struct loop *loop, widest_int *nit) +get_max_loop_iterations (const class loop *loop, widest_int *nit) { if (!loop->any_upper_bound) return false; @@ -2016,7 +2016,7 @@ get_max_loop_iterations (const struct loop *loop, widest_int *nit) on the number of iterations of LOOP could not be derived, returns -1. */ HOST_WIDE_INT -get_max_loop_iterations_int (const struct loop *loop) +get_max_loop_iterations_int (const class loop *loop) { widest_int nit; HOST_WIDE_INT hwi_nit; @@ -2036,7 +2036,7 @@ get_max_loop_iterations_int (const struct loop *loop) false, otherwise returns true. */ bool -get_likely_max_loop_iterations (struct loop *loop, widest_int *nit) +get_likely_max_loop_iterations (class loop *loop, widest_int *nit) { if (!loop->any_likely_upper_bound) return false; @@ -2050,7 +2050,7 @@ get_likely_max_loop_iterations (struct loop *loop, widest_int *nit) on the number of iterations of LOOP could not be derived, returns -1. */ HOST_WIDE_INT -get_likely_max_loop_iterations_int (struct loop *loop) +get_likely_max_loop_iterations_int (class loop *loop) { widest_int nit; HOST_WIDE_INT hwi_nit; diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 9414070..0b0154f 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -66,7 +66,7 @@ public: bool is_exit; /* The next bound in the list. */ - struct nb_iter_bound *next; + class nb_iter_bound *next; }; /* Description of the loop exit. */ @@ -92,7 +92,7 @@ struct loop_exit_hasher : ggc_ptr_hash static void remove (loop_exit *); }; -typedef struct loop *loop_p; +typedef class loop *loop_p; /* An integer estimation of the number of iterations. Estimate_state describes what is the state of the estimation. */ @@ -142,10 +142,10 @@ public: vec *superloops; /* The first inner (child) loop or NULL if innermost loop. */ - struct loop *inner; + class loop *inner; /* Link to the next (sibling) loop. */ - struct loop *next; + class loop *next; /* Auxiliary info specific to a pass. */ PTR GTY ((skip (""))) aux; @@ -252,7 +252,7 @@ public: int orig_loop_num; /* Upper bound on number of iterations of a loop. */ - struct nb_iter_bound *bounds; + class nb_iter_bound *bounds; /* Non-overflow control ivs of a loop. */ struct control_iv *control_ivs; @@ -261,7 +261,7 @@ public: struct loop_exit *exits; /* Number of iteration analysis data for RTL. */ - struct niter_desc *simple_loop_desc; + class niter_desc *simple_loop_desc; /* For sanity checking during loop fixup we record here the former loop header for loops marked for removal. Note that this prevents @@ -277,21 +277,21 @@ public: /* Set C to the LOOP constraint. */ static inline void -loop_constraint_set (struct loop *loop, unsigned c) +loop_constraint_set (class loop *loop, unsigned c) { loop->constraints |= c; } /* Clear C from the LOOP constraint. */ static inline void -loop_constraint_clear (struct loop *loop, unsigned c) +loop_constraint_clear (class loop *loop, unsigned c) { loop->constraints &= ~c; } /* Check if C is set in the LOOP constraint. */ static inline bool -loop_constraint_set_p (struct loop *loop, unsigned c) +loop_constraint_set_p (class loop *loop, unsigned c) { return (loop->constraints & c) == c; } @@ -327,7 +327,7 @@ struct GTY (()) loops { hash_table *GTY(()) exits; /* Pointer to root of loop hierarchy tree. */ - struct loop *tree_root; + class loop *tree_root; }; /* Loop recognition. */ @@ -337,12 +337,12 @@ extern struct loops *flow_loops_find (struct loops *); extern void disambiguate_loops_with_multiple_latches (void); extern void flow_loops_free (struct loops *); extern void flow_loops_dump (FILE *, - void (*)(const struct loop *, FILE *, int), int); -extern void flow_loop_dump (const struct loop *, FILE *, - void (*)(const struct loop *, FILE *, int), int); -struct loop *alloc_loop (void); -extern void flow_loop_free (struct loop *); -int flow_loop_nodes_find (basic_block, struct loop *); + void (*)(const class loop *, FILE *, int), int); +extern void flow_loop_dump (const class loop *, FILE *, + void (*)(const class loop *, FILE *, int), int); +class loop *alloc_loop (void); +extern void flow_loop_free (class loop *); +int flow_loop_nodes_find (basic_block, class loop *); unsigned fix_loop_structure (bitmap changed_bbs); bool mark_irreducible_loops (void); void release_recorded_exits (function *); @@ -351,54 +351,54 @@ void rescan_loop_exit (edge, bool, bool); void sort_sibling_loops (function *); /* Loop data structure manipulation/querying. */ -extern void flow_loop_tree_node_add (struct loop *, struct loop *, - struct loop * = NULL); -extern void flow_loop_tree_node_remove (struct loop *); -extern bool flow_loop_nested_p (const struct loop *, const struct loop *); -extern bool flow_bb_inside_loop_p (const struct loop *, const_basic_block); -extern struct loop * find_common_loop (struct loop *, struct loop *); -struct loop *superloop_at_depth (struct loop *, unsigned); +extern void flow_loop_tree_node_add (class loop *, class loop *, + class loop * = NULL); +extern void flow_loop_tree_node_remove (class loop *); +extern bool flow_loop_nested_p (const class loop *, const class loop *); +extern bool flow_bb_inside_loop_p (const class loop *, const_basic_block); +extern class loop * find_common_loop (class loop *, class loop *); +class loop *superloop_at_depth (class loop *, unsigned); struct eni_weights; -extern int num_loop_insns (const struct loop *); -extern int average_num_loop_insns (const struct loop *); -extern unsigned get_loop_level (const struct loop *); -extern bool loop_exit_edge_p (const struct loop *, const_edge); -extern bool loop_exits_to_bb_p (struct loop *, basic_block); -extern bool loop_exits_from_bb_p (struct loop *, basic_block); +extern int num_loop_insns (const class loop *); +extern int average_num_loop_insns (const class loop *); +extern unsigned get_loop_level (const class loop *); +extern bool loop_exit_edge_p (const class loop *, const_edge); +extern bool loop_exits_to_bb_p (class loop *, basic_block); +extern bool loop_exits_from_bb_p (class loop *, basic_block); extern void mark_loop_exit_edges (void); -extern dump_user_location_t get_loop_location (struct loop *loop); +extern dump_user_location_t get_loop_location (class loop *loop); /* Loops & cfg manipulation. */ -extern basic_block *get_loop_body (const struct loop *); -extern unsigned get_loop_body_with_size (const struct loop *, basic_block *, +extern basic_block *get_loop_body (const class loop *); +extern unsigned get_loop_body_with_size (const class loop *, basic_block *, unsigned); -extern basic_block *get_loop_body_in_dom_order (const struct loop *); -extern basic_block *get_loop_body_in_bfs_order (const struct loop *); -extern basic_block *get_loop_body_in_custom_order (const struct loop *, +extern basic_block *get_loop_body_in_dom_order (const class loop *); +extern basic_block *get_loop_body_in_bfs_order (const class loop *); +extern basic_block *get_loop_body_in_custom_order (const class loop *, int (*) (const void *, const void *)); -extern vec get_loop_exit_edges (const struct loop *); -extern edge single_exit (const struct loop *); -extern edge single_likely_exit (struct loop *loop); -extern unsigned num_loop_branches (const struct loop *); +extern vec get_loop_exit_edges (const class loop *); +extern edge single_exit (const class loop *); +extern edge single_likely_exit (class loop *loop); +extern unsigned num_loop_branches (const class loop *); -extern edge loop_preheader_edge (const struct loop *); -extern edge loop_latch_edge (const struct loop *); +extern edge loop_preheader_edge (const class loop *); +extern edge loop_latch_edge (const class loop *); -extern void add_bb_to_loop (basic_block, struct loop *); +extern void add_bb_to_loop (basic_block, class loop *); extern void remove_bb_from_loops (basic_block); -extern void cancel_loop_tree (struct loop *); -extern void delete_loop (struct loop *); +extern void cancel_loop_tree (class loop *); +extern void delete_loop (class loop *); extern void verify_loop_structure (void); /* Loop analysis. */ -extern bool just_once_each_iteration_p (const struct loop *, const_basic_block); -gcov_type expected_loop_iterations_unbounded (const struct loop *, +extern bool just_once_each_iteration_p (const class loop *, const_basic_block); +gcov_type expected_loop_iterations_unbounded (const class loop *, bool *read_profile_p = NULL, bool by_profile_only = false); -extern unsigned expected_loop_iterations (struct loop *); +extern unsigned expected_loop_iterations (class loop *); extern rtx doloop_condition_get (rtx_insn *); void mark_loop_for_removal (loop_p); @@ -490,21 +490,21 @@ public: rtx niter_expr; }; -extern void iv_analysis_loop_init (struct loop *); -extern bool iv_analyze (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *); -extern bool iv_analyze_result (rtx_insn *, rtx, struct rtx_iv *); +extern void iv_analysis_loop_init (class loop *); +extern bool iv_analyze (rtx_insn *, scalar_int_mode, rtx, class rtx_iv *); +extern bool iv_analyze_result (rtx_insn *, rtx, class rtx_iv *); extern bool iv_analyze_expr (rtx_insn *, scalar_int_mode, rtx, - struct rtx_iv *); -extern rtx get_iv_value (struct rtx_iv *, rtx); + class rtx_iv *); +extern rtx get_iv_value (class rtx_iv *, rtx); extern bool biv_p (rtx_insn *, scalar_int_mode, rtx); -extern void find_simple_exit (struct loop *, struct niter_desc *); +extern void find_simple_exit (class loop *, class niter_desc *); extern void iv_analysis_done (void); -extern struct niter_desc *get_simple_loop_desc (struct loop *loop); -extern void free_simple_loop_desc (struct loop *loop); +extern class niter_desc *get_simple_loop_desc (class loop *loop); +extern void free_simple_loop_desc (class loop *loop); -static inline struct niter_desc * -simple_loop_desc (struct loop *loop) +static inline class niter_desc * +simple_loop_desc (class loop *loop) { return loop->simple_loop_desc; } @@ -513,7 +513,7 @@ simple_loop_desc (struct loop *loop) /* Returns the loop with index NUM from FNs loop tree. */ -static inline struct loop * +static inline class loop * get_loop (struct function *fn, unsigned num) { return (*loops_for_fn (fn)->larray)[num]; @@ -522,7 +522,7 @@ get_loop (struct function *fn, unsigned num) /* Returns the number of superloops of LOOP. */ static inline unsigned -loop_depth (const struct loop *loop) +loop_depth (const class loop *loop) { return vec_safe_length (loop->superloops); } @@ -530,8 +530,8 @@ loop_depth (const struct loop *loop) /* Returns the immediate superloop of LOOP, or NULL if LOOP is the outermost loop. */ -static inline struct loop * -loop_outer (const struct loop *loop) +static inline class loop * +loop_outer (const class loop *loop) { unsigned n = vec_safe_length (loop->superloops); @@ -544,7 +544,7 @@ loop_outer (const struct loop *loop) /* Returns true if LOOP has at least one exit edge. */ static inline bool -loop_has_exit_edges (const struct loop *loop) +loop_has_exit_edges (const class loop *loop) { return loop->exits->next->e != NULL; } @@ -692,7 +692,7 @@ loop_iterator::next () inline loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags) { - struct loop *aloop; + class loop *aloop; unsigned i; int mn; @@ -843,11 +843,11 @@ enum extern void doloop_optimize_loops (void); extern void move_loop_invariants (void); -extern vec get_loop_hot_path (const struct loop *loop); +extern vec get_loop_hot_path (const class loop *loop); /* Returns the outermost loop of the loop nest that contains LOOP.*/ -static inline struct loop * -loop_outermost (struct loop *loop) +static inline class loop * +loop_outermost (class loop *loop) { unsigned n = vec_safe_length (loop->superloops); @@ -857,13 +857,13 @@ loop_outermost (struct loop *loop) return (*loop->superloops)[1]; } -extern void record_niter_bound (struct loop *, const widest_int &, bool, bool); -extern HOST_WIDE_INT get_estimated_loop_iterations_int (struct loop *); -extern HOST_WIDE_INT get_max_loop_iterations_int (const struct loop *); -extern HOST_WIDE_INT get_likely_max_loop_iterations_int (struct loop *); -extern bool get_estimated_loop_iterations (struct loop *loop, widest_int *nit); -extern bool get_max_loop_iterations (const struct loop *loop, widest_int *nit); -extern bool get_likely_max_loop_iterations (struct loop *loop, widest_int *nit); +extern void record_niter_bound (class loop *, const widest_int &, bool, bool); +extern HOST_WIDE_INT get_estimated_loop_iterations_int (class loop *); +extern HOST_WIDE_INT get_max_loop_iterations_int (const class loop *); +extern HOST_WIDE_INT get_likely_max_loop_iterations_int (class loop *); +extern bool get_estimated_loop_iterations (class loop *loop, widest_int *nit); +extern bool get_max_loop_iterations (const class loop *loop, widest_int *nit); +extern bool get_likely_max_loop_iterations (class loop *loop, widest_int *nit); extern int bb_loop_depth (const_basic_block); /* Converts VAL to widest_int. */ diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index 6dbe96f..10037f0 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -41,7 +41,7 @@ struct target_cfgloop *this_target_cfgloop = &default_target_cfgloop; /* Checks whether BB is executed exactly once in each LOOP iteration. */ bool -just_once_each_iteration_p (const struct loop *loop, const_basic_block bb) +just_once_each_iteration_p (const class loop *loop, const_basic_block bb) { /* It must be executed at least once each iteration. */ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb)) @@ -81,7 +81,7 @@ mark_irreducible_loops (void) unsigned depth; struct graph *g; int num = number_of_loops (cfun); - struct loop *cloop; + class loop *cloop; bool irred_loop_found = false; int i; @@ -173,7 +173,7 @@ mark_irreducible_loops (void) /* Counts number of insns inside LOOP. */ int -num_loop_insns (const struct loop *loop) +num_loop_insns (const class loop *loop) { basic_block *bbs, bb; unsigned i, ninsns = 0; @@ -197,7 +197,7 @@ num_loop_insns (const struct loop *loop) /* Counts number of insns executed on average per iteration LOOP. */ int -average_num_loop_insns (const struct loop *loop) +average_num_loop_insns (const class loop *loop) { basic_block *bbs, bb; unsigned i, binsns; @@ -238,7 +238,7 @@ average_num_loop_insns (const struct loop *loop) return -1 in those scenarios. */ gcov_type -expected_loop_iterations_unbounded (const struct loop *loop, +expected_loop_iterations_unbounded (const class loop *loop, bool *read_profile_p, bool by_profile_only) { @@ -310,7 +310,7 @@ expected_loop_iterations_unbounded (const struct loop *loop, by REG_BR_PROB_BASE. */ unsigned -expected_loop_iterations (struct loop *loop) +expected_loop_iterations (class loop *loop) { gcov_type expected = expected_loop_iterations_unbounded (loop); return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected); @@ -319,9 +319,9 @@ expected_loop_iterations (struct loop *loop) /* Returns the maximum level of nesting of subloops of LOOP. */ unsigned -get_loop_level (const struct loop *loop) +get_loop_level (const class loop *loop) { - const struct loop *ploop; + const class loop *ploop; unsigned mx = 0, l; for (ploop = loop->inner; ploop; ploop = ploop->next) @@ -463,7 +463,7 @@ mark_loop_exit_edges (void) to noreturn call. */ edge -single_likely_exit (struct loop *loop) +single_likely_exit (class loop *loop) { edge found = single_exit (loop); vec exits; @@ -500,7 +500,7 @@ single_likely_exit (struct loop *loop) header != latch, latch is the 1-st block. */ vec -get_loop_hot_path (const struct loop *loop) +get_loop_hot_path (const class loop *loop) { basic_block bb = loop->header; vec path = vNULL; diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index b5f6a47..727e951 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -32,13 +32,13 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-loop-manip.h" #include "dumpfile.h" -static void copy_loops_to (struct loop **, int, - struct loop *); +static void copy_loops_to (class loop **, int, + class loop *); static void loop_redirect_edge (edge, basic_block); static void remove_bbs (basic_block *, int); static bool rpe_enum_p (const_basic_block, const void *); static int find_path (edge, basic_block **); -static void fix_loop_placements (struct loop *, bool *); +static void fix_loop_placements (class loop *, bool *); static bool fix_bb_placement (basic_block); static void fix_bb_placements (basic_block, bool *, bitmap); @@ -89,7 +89,7 @@ fix_bb_placement (basic_block bb) { edge e; edge_iterator ei; - struct loop *loop = current_loops->tree_root, *act; + class loop *loop = current_loops->tree_root, *act; FOR_EACH_EDGE (e, ei, bb->succs) { @@ -122,12 +122,12 @@ fix_bb_placement (basic_block bb) invalidate the information about irreducible regions. */ static bool -fix_loop_placement (struct loop *loop, bool *irred_invalidated) +fix_loop_placement (class loop *loop, bool *irred_invalidated) { unsigned i; edge e; vec exits = get_loop_exit_edges (loop); - struct loop *father = current_loops->tree_root, *act; + class loop *father = current_loops->tree_root, *act; bool ret = false; FOR_EACH_VEC_ELT (exits, i, e) @@ -182,7 +182,7 @@ fix_bb_placements (basic_block from, bitmap loop_closed_ssa_invalidated) { basic_block *queue, *qtop, *qbeg, *qend; - struct loop *base_loop, *target_loop; + class loop *base_loop, *target_loop; edge e; /* We pass through blocks back-reachable from FROM, testing whether some @@ -255,7 +255,7 @@ fix_bb_placements (basic_block from, FOR_EACH_EDGE (e, ei, from->preds) { basic_block pred = e->src; - struct loop *nca; + class loop *nca; if (e->flags & EDGE_IRREDUCIBLE_LOOP) *irred_invalidated = true; @@ -307,7 +307,7 @@ remove_path (edge e, bool *irred_invalidated, int i, nrem, n_bord_bbs; bool local_irred_invalidated = false; edge_iterator ei; - struct loop *l, *f; + class loop *l, *f; if (! irred_invalidated) irred_invalidated = &local_irred_invalidated; @@ -427,7 +427,7 @@ remove_path (edge e, bool *irred_invalidated, /* Creates place for a new LOOP in loops structure of FN. */ void -place_new_loop (struct function *fn, struct loop *loop) +place_new_loop (struct function *fn, class loop *loop) { loop->num = number_of_loops (fn); vec_safe_push (loops_for_fn (fn)->larray, loop); @@ -438,11 +438,11 @@ place_new_loop (struct function *fn, struct loop *loop) outer. */ void -add_loop (struct loop *loop, struct loop *outer) +add_loop (class loop *loop, class loop *outer) { basic_block *bbs; int i, n; - struct loop *subloop; + class loop *subloop; edge e; edge_iterator ei; @@ -490,7 +490,7 @@ add_loop (struct loop *loop, struct loop *outer) /* Scale profile of loop by P. */ void -scale_loop_frequencies (struct loop *loop, profile_probability p) +scale_loop_frequencies (class loop *loop, profile_probability p) { basic_block *bbs; @@ -508,7 +508,7 @@ scale_loop_frequencies (struct loop *loop, profile_probability p) they need to be scaled synchronously. */ void -scale_loop_profile (struct loop *loop, profile_probability p, +scale_loop_profile (class loop *loop, profile_probability p, gcov_type iteration_bound) { edge e, preheader_e; @@ -618,7 +618,7 @@ scale_loop_profile (struct loop *loop, profile_probability p, /* Recompute dominance information for basic blocks outside LOOP. */ static void -update_dominators_in_loop (struct loop *loop) +update_dominators_in_loop (class loop *loop) { vec dom_bbs = vNULL; basic_block *body; @@ -763,17 +763,17 @@ create_empty_if_region_on_edge (edge entry_edge, tree condition) should be used only when the UPPER_BOUND expression is a loop invariant. */ -struct loop * +class loop * create_empty_loop_on_edge (edge entry_edge, tree initial_value, tree stride, tree upper_bound, tree iv, tree *iv_before, tree *iv_after, - struct loop *outer) + class loop *outer) { basic_block loop_header, loop_latch, succ_bb, pred_bb; - struct loop *loop; + class loop *loop; gimple_stmt_iterator gsi; gimple_seq stmts; gcond *cond_expr; @@ -857,7 +857,7 @@ create_empty_loop_on_edge (edge entry_edge, Returns the newly created loop. Frequencies and counts in the new loop are scaled by FALSE_SCALE and in the old one by TRUE_SCALE. */ -struct loop * +class loop * loopify (edge latch_edge, edge header_edge, basic_block switch_bb, edge true_edge, edge false_edge, bool redirect_all_edges, profile_probability true_scale, @@ -865,8 +865,8 @@ loopify (edge latch_edge, edge header_edge, { basic_block succ_bb = latch_edge->dest; basic_block pred_bb = header_edge->src; - struct loop *loop = alloc_loop (); - struct loop *outer = loop_outer (succ_bb->loop_father); + class loop *loop = alloc_loop (); + class loop *outer = loop_outer (succ_bb->loop_father); profile_count cnt; loop->header = header_edge->dest; @@ -923,11 +923,11 @@ loopify (edge latch_edge, edge header_edge, basic blocks that had non-trivial update on their loop_father.*/ void -unloop (struct loop *loop, bool *irred_invalidated, +unloop (class loop *loop, bool *irred_invalidated, bitmap loop_closed_ssa_invalidated) { basic_block *body; - struct loop *ploop; + class loop *ploop; unsigned i, n; basic_block latch = loop->latch; bool dummy = false; @@ -978,9 +978,9 @@ unloop (struct loop *loop, bool *irred_invalidated, invalidate the information about irreducible regions. */ static void -fix_loop_placements (struct loop *loop, bool *irred_invalidated) +fix_loop_placements (class loop *loop, bool *irred_invalidated) { - struct loop *outer; + class loop *outer; while (loop_outer (loop)) { @@ -1003,7 +1003,7 @@ fix_loop_placements (struct loop *loop, bool *irred_invalidated) the loop into its duplicate. */ void -copy_loop_info (struct loop *loop, struct loop *target) +copy_loop_info (class loop *loop, class loop *target) { gcc_checking_assert (!target->any_upper_bound && !target->any_estimate); target->any_upper_bound = loop->any_upper_bound; @@ -1031,10 +1031,10 @@ copy_loop_info (struct loop *loop, struct loop *target) created loop into loops structure. If AFTER is non-null the new loop is added at AFTER->next, otherwise in front of TARGETs sibling list. */ -struct loop * -duplicate_loop (struct loop *loop, struct loop *target, struct loop *after) +class loop * +duplicate_loop (class loop *loop, class loop *target, class loop *after) { - struct loop *cloop; + class loop *cloop; cloop = alloc_loop (); place_new_loop (cfun, cloop); @@ -1053,9 +1053,9 @@ duplicate_loop (struct loop *loop, struct loop *target, struct loop *after) newly created loops into loop tree at the end of TARGETs sibling list in the original order. */ void -duplicate_subloops (struct loop *loop, struct loop *target) +duplicate_subloops (class loop *loop, class loop *target) { - struct loop *aloop, *cloop, *tail; + class loop *aloop, *cloop, *tail; for (tail = target->inner; tail && tail->next; tail = tail->next) ; @@ -1072,9 +1072,9 @@ duplicate_subloops (struct loop *loop, struct loop *target) into TARGET loop, placing newly created loops into loop tree adding them to TARGETs sibling list at the end in order. */ static void -copy_loops_to (struct loop **copied_loops, int n, struct loop *target) +copy_loops_to (class loop **copied_loops, int n, class loop *target) { - struct loop *aloop, *tail; + class loop *aloop, *tail; int i; for (tail = target->inner; tail && tail->next; tail = tail->next) @@ -1100,7 +1100,7 @@ loop_redirect_edge (edge e, basic_block dest) /* Check whether LOOP's body can be duplicated. */ bool -can_duplicate_loop_p (const struct loop *loop) +can_duplicate_loop_p (const class loop *loop) { int ret; basic_block *bbs = get_loop_body (loop); @@ -1124,13 +1124,13 @@ can_duplicate_loop_p (const struct loop *loop) impossible. */ bool -duplicate_loop_to_header_edge (struct loop *loop, edge e, +duplicate_loop_to_header_edge (class loop *loop, edge e, unsigned int ndupl, sbitmap wont_exit, edge orig, vec *to_remove, int flags) { - struct loop *target, *aloop; - struct loop **orig_loops; + class loop *target, *aloop; + class loop **orig_loops; unsigned n_orig_loops; basic_block header = loop->header, latch = loop->latch; basic_block *new_bbs, *bbs, *first_active; @@ -1276,7 +1276,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, n_orig_loops = 0; for (aloop = loop->inner; aloop; aloop = aloop->next) n_orig_loops++; - orig_loops = XNEWVEC (struct loop *, n_orig_loops); + orig_loops = XNEWVEC (class loop *, n_orig_loops); for (aloop = loop->inner, i = 0; aloop; aloop = aloop->next, i++) orig_loops[i] = aloop; @@ -1453,7 +1453,7 @@ mfb_keep_just (edge e) /* True when a candidate preheader BLOCK has predecessors from LOOP. */ static bool -has_preds_from_loop (basic_block block, struct loop *loop) +has_preds_from_loop (basic_block block, class loop *loop) { edge e; edge_iterator ei; @@ -1473,7 +1473,7 @@ has_preds_from_loop (basic_block block, struct loop *loop) The function also updates dominators. */ basic_block -create_preheader (struct loop *loop, int flags) +create_preheader (class loop *loop, int flags) { edge e; basic_block dummy; @@ -1573,7 +1573,7 @@ create_preheader (struct loop *loop, int flags) void create_preheaders (int flags) { - struct loop *loop; + class loop *loop; if (!current_loops) return; @@ -1588,7 +1588,7 @@ create_preheaders (int flags) void force_single_succ_latches (void) { - struct loop *loop; + class loop *loop; edge e; FOR_EACH_LOOP (loop, 0) @@ -1677,8 +1677,8 @@ lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head, If PLACE_AFTER is true, we place the new loop after LOOP in the instruction stream, otherwise it is placed before LOOP. */ -struct loop * -loop_version (struct loop *loop, +class loop * +loop_version (class loop *loop, void *cond_expr, basic_block *condition_bb, profile_probability then_prob, profile_probability else_prob, profile_probability then_scale, profile_probability else_scale, @@ -1687,7 +1687,7 @@ loop_version (struct loop *loop, basic_block first_head, second_head; edge entry, latch_edge, true_edge, false_edge; int irred_flag; - struct loop *nloop; + class loop *nloop; basic_block cond_bb; /* Record entry and latch edges for the loop */ diff --git a/gcc/cfgloopmanip.h b/gcc/cfgloopmanip.h index d57aead..d14f490 100644 --- a/gcc/cfgloopmanip.h +++ b/gcc/cfgloopmanip.h @@ -35,30 +35,30 @@ enum extern edge mfb_kj_edge; extern bool remove_path (edge, bool * = NULL, bitmap = NULL); -extern void place_new_loop (struct function *, struct loop *); -extern void add_loop (struct loop *, struct loop *); -extern void scale_loop_frequencies (struct loop *, profile_probability); -extern void scale_loop_profile (struct loop *, profile_probability, gcov_type); +extern void place_new_loop (struct function *, class loop *); +extern void add_loop (class loop *, class loop *); +extern void scale_loop_frequencies (class loop *, profile_probability); +extern void scale_loop_profile (class loop *, profile_probability, gcov_type); extern edge create_empty_if_region_on_edge (edge, tree); -extern struct loop *create_empty_loop_on_edge (edge, tree, tree, tree, tree, - tree *, tree *, struct loop *); -extern struct loop *loopify (edge, edge, +extern class loop *create_empty_loop_on_edge (edge, tree, tree, tree, tree, + tree *, tree *, class loop *); +extern class loop *loopify (edge, edge, basic_block, edge, edge, bool, profile_probability, profile_probability); -extern void unloop (struct loop *, bool *, bitmap); -extern void copy_loop_info (struct loop *loop, struct loop *target); -extern struct loop * duplicate_loop (struct loop *, struct loop *, - struct loop * = NULL); -extern void duplicate_subloops (struct loop *, struct loop *); -extern bool can_duplicate_loop_p (const struct loop *loop); -extern bool duplicate_loop_to_header_edge (struct loop *, edge, +extern void unloop (class loop *, bool *, bitmap); +extern void copy_loop_info (class loop *loop, class loop *target); +extern class loop * duplicate_loop (class loop *, class loop *, + class loop * = NULL); +extern void duplicate_subloops (class loop *, class loop *); +extern bool can_duplicate_loop_p (const class loop *loop); +extern bool duplicate_loop_to_header_edge (class loop *, edge, unsigned, sbitmap, edge, vec *, int); extern bool mfb_keep_just (edge); -basic_block create_preheader (struct loop *, int); +basic_block create_preheader (class loop *, int); extern void create_preheaders (int); extern void force_single_succ_latches (void); -struct loop * loop_version (struct loop *, void *, +class loop * loop_version (class loop *, void *, basic_block *, profile_probability, profile_probability, profile_probability, profile_probability, bool); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index e5fd6dd..fa5224f 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -912,9 +912,8 @@ struct cgraph_edge_hasher : ggc_ptr_hash /* The cgraph data structure. Each function decl has assigned cgraph_node listing callees and callers. */ -class GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node +struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node { -public: friend class symbol_table; /* Remove the node from cgraph and all inline clones inlined into it. @@ -1506,7 +1505,7 @@ struct cgraph_node_set_def typedef cgraph_node_set_def *cgraph_node_set; typedef struct varpool_node_set_def *varpool_node_set; -class varpool_node; +struct varpool_node; /* A varpool node set is a collection of varpool nodes. A varpool node can appear in multiple sets. */ @@ -1620,7 +1619,7 @@ public: /* LTO streaming. */ void stream_out (struct output_block *) const; - void stream_in (struct lto_input_block *, struct data_in *data_in); + void stream_in (class lto_input_block *, class data_in *data_in); private: bool combine_speculation_with (tree, HOST_WIDE_INT, bool, tree); @@ -1679,7 +1678,7 @@ class GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"), for_user)) cgraph_edge { public: - friend class cgraph_node; + friend struct cgraph_node; friend class symbol_table; /* Remove the edge in the cgraph. */ @@ -2078,9 +2077,9 @@ struct asmname_hasher : ggc_ptr_hash class GTY((tag ("SYMTAB"))) symbol_table { public: - friend class symtab_node; - friend class cgraph_node; - friend class cgraph_edge; + friend struct symtab_node; + friend struct cgraph_node; + friend struct cgraph_edge; symbol_table (): cgraph_max_uid (1), cgraph_max_summary_id (0), edges_max_uid (1), edges_max_summary_id (0) diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 97c0105..2e7d0b5 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see struct record_reference_ctx { bool only_vars; - class varpool_node *varpool_node; + struct varpool_node *varpool_node; }; /* Walk tree and record all calls and references to functions/variables. diff --git a/gcc/combine.c b/gcc/combine.c index 1be922d..f7b1ebc 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7829,7 +7829,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos, For memory, assume that the desired extraction_mode and pos_mode are the same as for a register operation, since at present we don't have named patterns for aligned memory structures. */ - struct extraction_insn insn; + class extraction_insn insn; unsigned int inner_size; if (GET_MODE_BITSIZE (inner_mode).is_constant (&inner_size) && get_best_reg_extraction_insn (&insn, pattern, inner_size, mode)) diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c index 2eac8f7..6ccd42a 100644 --- a/gcc/config/i386/i386-features.c +++ b/gcc/config/i386/i386-features.c @@ -152,7 +152,7 @@ const xlogue_layout xlogue_layout::s_instances[XLOGUE_SET_COUNT] = { /* Return an appropriate const instance of xlogue_layout based upon values in cfun->machine and crtl. */ -const struct xlogue_layout & +const class xlogue_layout & xlogue_layout::get_instance () { enum xlogue_stub_sets stub_set; diff --git a/gcc/config/i386/i386-features.h b/gcc/config/i386/i386-features.h index 3581222..f2c742f 100644 --- a/gcc/config/i386/i386-features.h +++ b/gcc/config/i386/i386-features.h @@ -84,7 +84,7 @@ public: return STUB_INDEX_OFFSET + m_stack_align_off_in; } - static const struct xlogue_layout &get_instance (); + static const class xlogue_layout &get_instance (); static unsigned count_stub_managed_regs (); static bool is_stub_managed_reg (unsigned regno, unsigned count); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 49f49c5..e278d9c 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -7689,7 +7689,7 @@ ix86_emit_outlined_ms2sysv_save (const struct ix86_frame &frame) rtx_insn *insn; rtx sym, addr; rtx rax = gen_rtx_REG (word_mode, AX_REG); - const struct xlogue_layout &xlogue = xlogue_layout::get_instance (); + const class xlogue_layout &xlogue = xlogue_layout::get_instance (); /* AL should only be live with sysv_abi. */ gcc_assert (!ix86_eax_live_at_start_p ()); @@ -8492,7 +8492,7 @@ ix86_emit_outlined_ms2sysv_restore (const struct ix86_frame &frame, rtx sym, tmp; rtx rsi = gen_rtx_REG (word_mode, SI_REG); rtx r10 = NULL_RTX; - const struct xlogue_layout &xlogue = xlogue_layout::get_instance (); + const class xlogue_layout &xlogue = xlogue_layout::get_instance (); HOST_WIDE_INT stub_ptr_offset = xlogue.get_stub_ptr_offset (); HOST_WIDE_INT rsi_offset = frame.stack_realign_offset + stub_ptr_offset; rtx rsi_frame_load = NULL_RTX; @@ -21503,7 +21503,7 @@ ix86_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info) /* Implement targetm.vectorize.init_cost. */ static void * -ix86_init_cost (struct loop *) +ix86_init_cost (class loop *) { unsigned *cost = XNEWVEC (unsigned, 3); cost[vect_prologue] = cost[vect_body] = cost[vect_epilogue] = 0; @@ -21514,7 +21514,7 @@ ix86_init_cost (struct loop *) static unsigned ix86_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind, - struct _stmt_vec_info *stmt_info, int misalign, + class _stmt_vec_info *stmt_info, int misalign, enum vect_cost_model_location where) { unsigned *cost = (unsigned *) data; @@ -21942,7 +21942,7 @@ ix86_simd_clone_usable (struct cgraph_node *node) (value 32 is used) as a heuristic. */ static unsigned -ix86_loop_unroll_adjust (unsigned nunroll, struct loop *loop) +ix86_loop_unroll_adjust (unsigned nunroll, class loop *loop) { basic_block *bbs; rtx_insn *insn; diff --git a/gcc/configure.ac b/gcc/configure.ac index 137d5b4..c620dd2 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -482,7 +482,8 @@ AC_ARG_ENABLE(build-format-warnings, AS_IF([test $enable_build_format_warnings = no], [wf_opt=-Wno-format],[wf_opt=]) ACX_PROG_CXX_WARNING_OPTS( - m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings ], + m4_quote(m4_do([-W -Wall -Wclass-is-pod -Wmismatched-tags ], + [-Wno-narrowing -Wstruct-not-pod -Wwrite-strings ], [-Wcast-qual -Wno-error=format-diag $wf_opt])), [loose_warn]) ACX_PROG_CC_WARNING_OPTS( diff --git a/gcc/coretypes.h b/gcc/coretypes.h index 2f6b859..eac2f39 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -47,9 +47,9 @@ typedef int64_t gcov_type; typedef uint64_t gcov_type_unsigned; struct bitmap_obstack; -struct bitmap_head; -typedef struct bitmap_head *bitmap; -typedef const struct bitmap_head *const_bitmap; +class bitmap_head; +typedef class bitmap_head *bitmap; +typedef const class bitmap_head *const_bitmap; struct simple_bitmap_def; typedef struct simple_bitmap_def *sbitmap; typedef const struct simple_bitmap_def *const_sbitmap; @@ -65,7 +65,7 @@ template class opt_mode; typedef opt_mode opt_scalar_mode; typedef opt_mode opt_scalar_int_mode; typedef opt_mode opt_scalar_float_mode; -template class pod_mode; +template struct pod_mode; typedef pod_mode scalar_mode_pod; typedef pod_mode scalar_int_mode_pod; typedef pod_mode fixed_size_mode_pod; @@ -73,19 +73,19 @@ typedef pod_mode fixed_size_mode_pod; /* Subclasses of rtx_def, using indentation to show the class hierarchy, along with the relevant invariant. Where possible, keep this list in the same order as in rtl.def. */ -class rtx_def; - class rtx_expr_list; /* GET_CODE (X) == EXPR_LIST */ - class rtx_insn_list; /* GET_CODE (X) == INSN_LIST */ - class rtx_sequence; /* GET_CODE (X) == SEQUENCE */ - class rtx_insn; - class rtx_debug_insn; /* DEBUG_INSN_P (X) */ - class rtx_nonjump_insn; /* NONJUMP_INSN_P (X) */ - class rtx_jump_insn; /* JUMP_P (X) */ - class rtx_call_insn; /* CALL_P (X) */ - class rtx_jump_table_data; /* JUMP_TABLE_DATA_P (X) */ - class rtx_barrier; /* BARRIER_P (X) */ - class rtx_code_label; /* LABEL_P (X) */ - class rtx_note; /* NOTE_P (X) */ +struct rtx_def; + struct rtx_expr_list; /* GET_CODE (X) == EXPR_LIST */ + struct rtx_insn_list; /* GET_CODE (X) == INSN_LIST */ + struct rtx_sequence; /* GET_CODE (X) == SEQUENCE */ + struct rtx_insn; + struct rtx_debug_insn; /* DEBUG_INSN_P (X) */ + struct rtx_nonjump_insn; /* NONJUMP_INSN_P (X) */ + struct rtx_jump_insn; /* JUMP_P (X) */ + struct rtx_call_insn; /* CALL_P (X) */ + struct rtx_jump_table_data; /* JUMP_TABLE_DATA_P (X) */ + struct rtx_barrier; /* BARRIER_P (X) */ + struct rtx_code_label; /* LABEL_P (X) */ + struct rtx_note; /* NOTE_P (X) */ struct rtvec_def; typedef struct rtvec_def *rtvec; @@ -138,9 +138,9 @@ struct gomp_teams; /* Subclasses of symtab_node, using indentation to show the class hierarchy. */ -class symtab_node; +struct symtab_node; struct cgraph_node; - class varpool_node; + struct varpool_node; union section; typedef union section section; @@ -151,7 +151,7 @@ struct cl_option; struct cl_decoded_option; struct cl_option_handlers; struct diagnostic_context; -struct pretty_printer; +class pretty_printer; /* Address space number for named address space support. */ typedef unsigned char addr_space_t; @@ -298,9 +298,9 @@ enum warn_strict_overflow_code set yet). */ typedef int alias_set_type; -struct edge_def; -typedef struct edge_def *edge; -typedef const struct edge_def *const_edge; +class edge_def; +typedef class edge_def *edge; +typedef const class edge_def *const_edge; struct basic_block_def; typedef struct basic_block_def *basic_block; typedef const struct basic_block_def *const_basic_block; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2dd3893..7609b20 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,6 +1,13 @@ 2019-07-09 Martin Sebor PR c++/61339 + * cp-tree.h: Change class-key of PODs to struct and others to class. + * search.c: Same. + * semantics.c (finalize_nrv_r): Same. + +2019-07-09 Martin Sebor + + PR c++/61339 * constexpr.c (cxx_eval_call_expression): Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. diff --git a/gcc/cp/search.c b/gcc/cp/search.c index a737e24..b441af8 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1275,7 +1275,7 @@ tree lookup_member_fuzzy (tree xbasetype, tree name, bool want_type_p) { tree type = NULL_TREE, basetype_path = NULL_TREE; - struct lookup_field_fuzzy_info lffi (want_type_p); + class lookup_field_fuzzy_info lffi (want_type_p); /* rval_binfo is the binfo associated with the found member, note, this can be set with useful information, even when rval is not diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ceb6c64..aadfaff 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4395,7 +4395,7 @@ public: static tree finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) { - struct nrv_data *dp = (struct nrv_data *)data; + class nrv_data *dp = (class nrv_data *)data; tree_node **slot; /* No need to walk into types. There wouldn't be any need to walk into @@ -4453,7 +4453,7 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) void finalize_nrv (tree *tp, tree var, tree result) { - struct nrv_data data; + class nrv_data data; /* Copy name from VAR to RESULT. */ DECL_NAME (result) = DECL_NAME (var); diff --git a/gcc/data-streamer-in.c b/gcc/data-streamer-in.c index 9c79e1d..11ad084 100644 --- a/gcc/data-streamer-in.c +++ b/gcc/data-streamer-in.c @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3. If not see IB. Write the length to RLEN. */ static const char * -string_for_index (struct data_in *data_in, unsigned int loc, unsigned int *rlen) +string_for_index (class data_in *data_in, unsigned int loc, unsigned int *rlen) { unsigned int len; const char *result; @@ -62,8 +62,8 @@ string_for_index (struct data_in *data_in, unsigned int loc, unsigned int *rlen) IB. Write the length to RLEN. */ const char * -streamer_read_indexed_string (struct data_in *data_in, - struct lto_input_block *ib, unsigned int *rlen) +streamer_read_indexed_string (class data_in *data_in, + class lto_input_block *ib, unsigned int *rlen) { return string_for_index (data_in, streamer_read_uhwi (ib), rlen); } @@ -72,7 +72,7 @@ streamer_read_indexed_string (struct data_in *data_in, /* Read a NULL terminated string from the string table in DATA_IN. */ const char * -streamer_read_string (struct data_in *data_in, struct lto_input_block *ib) +streamer_read_string (class data_in *data_in, class lto_input_block *ib) { unsigned int len; const char *ptr; @@ -91,7 +91,7 @@ streamer_read_string (struct data_in *data_in, struct lto_input_block *ib) Write the length to RLEN. */ const char * -bp_unpack_indexed_string (struct data_in *data_in, +bp_unpack_indexed_string (class data_in *data_in, struct bitpack_d *bp, unsigned int *rlen) { return string_for_index (data_in, bp_unpack_var_len_unsigned (bp), rlen); @@ -101,7 +101,7 @@ bp_unpack_indexed_string (struct data_in *data_in, /* Read a NULL terminated string from the string table in DATA_IN. */ const char * -bp_unpack_string (struct data_in *data_in, struct bitpack_d *bp) +bp_unpack_string (class data_in *data_in, struct bitpack_d *bp) { unsigned int len; const char *ptr; @@ -119,7 +119,7 @@ bp_unpack_string (struct data_in *data_in, struct bitpack_d *bp) /* Read an unsigned HOST_WIDE_INT number from IB. */ unsigned HOST_WIDE_INT -streamer_read_uhwi (struct lto_input_block *ib) +streamer_read_uhwi (class lto_input_block *ib) { unsigned HOST_WIDE_INT result; int shift; @@ -154,7 +154,7 @@ streamer_read_uhwi (struct lto_input_block *ib) /* Read a HOST_WIDE_INT number from IB. */ HOST_WIDE_INT -streamer_read_hwi (struct lto_input_block *ib) +streamer_read_hwi (class lto_input_block *ib) { HOST_WIDE_INT result = 0; int shift = 0; @@ -178,7 +178,7 @@ streamer_read_hwi (struct lto_input_block *ib) /* Read gcov_type value from IB. */ gcov_type -streamer_read_gcov_count (struct lto_input_block *ib) +streamer_read_gcov_count (class lto_input_block *ib) { gcov_type ret = streamer_read_hwi (ib); return ret; @@ -188,7 +188,7 @@ streamer_read_gcov_count (struct lto_input_block *ib) input block IB. */ wide_int -streamer_read_wide_int (struct lto_input_block *ib) +streamer_read_wide_int (class lto_input_block *ib) { HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; int i; @@ -203,7 +203,7 @@ streamer_read_wide_int (struct lto_input_block *ib) input block IB. */ widest_int -streamer_read_widest_int (struct lto_input_block *ib) +streamer_read_widest_int (class lto_input_block *ib) { HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; int i; diff --git a/gcc/data-streamer.h b/gcc/data-streamer.h index cb3efc1..c8bfd9a 100644 --- a/gcc/data-streamer.h +++ b/gcc/data-streamer.h @@ -73,18 +73,18 @@ void streamer_write_wide_int (struct output_block *, const wide_int &); void streamer_write_widest_int (struct output_block *, const widest_int &); /* In data-streamer-in.c */ -const char *streamer_read_string (struct data_in *, struct lto_input_block *); -const char *streamer_read_indexed_string (struct data_in *, - struct lto_input_block *, +const char *streamer_read_string (class data_in *, class lto_input_block *); +const char *streamer_read_indexed_string (class data_in *, + class lto_input_block *, unsigned int *); -const char *bp_unpack_indexed_string (struct data_in *, struct bitpack_d *, +const char *bp_unpack_indexed_string (class data_in *, struct bitpack_d *, unsigned int *); -const char *bp_unpack_string (struct data_in *, struct bitpack_d *); -unsigned HOST_WIDE_INT streamer_read_uhwi (struct lto_input_block *); -HOST_WIDE_INT streamer_read_hwi (struct lto_input_block *); -gcov_type streamer_read_gcov_count (struct lto_input_block *); -wide_int streamer_read_wide_int (struct lto_input_block *); -widest_int streamer_read_widest_int (struct lto_input_block *); +const char *bp_unpack_string (class data_in *, struct bitpack_d *); +unsigned HOST_WIDE_INT streamer_read_uhwi (class lto_input_block *); +HOST_WIDE_INT streamer_read_hwi (class lto_input_block *); +gcov_type streamer_read_gcov_count (class lto_input_block *); +wide_int streamer_read_wide_int (class lto_input_block *); +widest_int streamer_read_widest_int (class lto_input_block *); /* Returns a new bit-packing context for bit-packing into S. */ static inline struct bitpack_d @@ -149,7 +149,7 @@ streamer_write_bitpack (struct bitpack_d *bp) /* Returns a new bit-packing context for bit-unpacking from IB. */ static inline struct bitpack_d -streamer_read_bitpack (struct lto_input_block *ib) +streamer_read_bitpack (class lto_input_block *ib) { struct bitpack_d bp; bp.word = streamer_read_uhwi (ib); @@ -174,7 +174,7 @@ bp_unpack_value (struct bitpack_d *bp, unsigned nbits) if (pos + nbits > BITS_PER_BITPACK_WORD) { bp->word = val - = streamer_read_uhwi ((struct lto_input_block *)bp->stream); + = streamer_read_uhwi ((class lto_input_block *)bp->stream); bp->pos = nbits; return val & mask; } @@ -218,7 +218,7 @@ streamer_write_char_stream (struct lto_output_stream *obs, char c) /* Read byte from the input block. */ static inline unsigned char -streamer_read_uchar (struct lto_input_block *ib) +streamer_read_uchar (class lto_input_block *ib) { if (ib->p >= ib->len) lto_section_overrun (ib); @@ -248,7 +248,7 @@ streamer_write_hwi_in_range (struct lto_output_stream *obs, to be compile time constant. PURPOSE is used for error reporting. */ static inline HOST_WIDE_INT -streamer_read_hwi_in_range (struct lto_input_block *ib, +streamer_read_hwi_in_range (class lto_input_block *ib, const char *purpose, HOST_WIDE_INT min, HOST_WIDE_INT max) @@ -337,7 +337,7 @@ streamer_write_record_start (struct output_block *ob, enum LTO_tags tag) /* Return the next tag in the input block IB. */ static inline enum LTO_tags -streamer_read_record_start (struct lto_input_block *ib) +streamer_read_record_start (class lto_input_block *ib) { return streamer_read_enum (ib, LTO_tags, LTO_NUM_TAGS); } diff --git a/gcc/ddg.c b/gcc/ddg.c index 82554ed..28b2be9 100644 --- a/gcc/ddg.c +++ b/gcc/ddg.c @@ -215,7 +215,7 @@ create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node, { int regno = REGNO (SET_DEST (set)); df_ref first_def; - struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb); + class df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb); first_def = df_bb_regno_first_def_find (g->bb, regno); gcc_assert (first_def); @@ -288,7 +288,7 @@ add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def) if (flag_checking && DF_REF_ID (last_def) != DF_REF_ID (first_def)) { - struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb); + class df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb); gcc_assert (!bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def))); } @@ -369,7 +369,7 @@ static void build_inter_loop_deps (ddg_ptr g) { unsigned rd_num; - struct df_rd_bb_info *rd_bb_info; + class df_rd_bb_info *rd_bb_info; bitmap_iterator bi; rd_bb_info = DF_RD_BB_INFO (g->bb); @@ -475,7 +475,7 @@ build_intra_loop_deps (ddg_ptr g) { int i; /* Hold the dependency analysis state during dependency calculations. */ - struct deps_desc tmp_deps; + class deps_desc tmp_deps; rtx_insn *head, *tail; /* Build the dependence information, using the sched_analyze function. */ diff --git a/gcc/df-core.c b/gcc/df-core.c index 7299bfd..44848aa 100644 --- a/gcc/df-core.c +++ b/gcc/df-core.c @@ -407,7 +407,7 @@ bitmap_obstack df_bitmap_obstack; Functions to create, destroy and manipulate an instance of df. ----------------------------------------------------------------------------*/ -struct df_d *df; +class df_d *df; /* Add PROBLEM (and any dependent problems) to the DF instance. */ @@ -684,7 +684,7 @@ static unsigned int rest_of_handle_df_initialize (void) { gcc_assert (!df); - df = XCNEW (struct df_d); + df = XCNEW (class df_d); df->changeable_flags = 0; bitmap_obstack_initialize (&df_bitmap_obstack); @@ -1293,7 +1293,7 @@ df_analyze (void) Returns the number of blocks which is always loop->num_nodes. */ static int -loop_post_order_compute (int *post_order, struct loop *loop) +loop_post_order_compute (int *post_order, class loop *loop) { edge_iterator *stack; int sp; @@ -1354,7 +1354,7 @@ loop_post_order_compute (int *post_order, struct loop *loop) by LOOP. Returns the number of blocks which is always loop->num_nodes. */ static void -loop_inverted_post_order_compute (vec *post_order, struct loop *loop) +loop_inverted_post_order_compute (vec *post_order, class loop *loop) { basic_block bb; edge_iterator *stack; @@ -1419,7 +1419,7 @@ loop_inverted_post_order_compute (vec *post_order, struct loop *loop) /* Analyze dataflow info for the basic blocks contained in LOOP. */ void -df_analyze_loop (struct loop *loop) +df_analyze_loop (class loop *loop) { free (df->postorder); diff --git a/gcc/df-problems.c b/gcc/df-problems.c index 62b2cf6..d32c688 100644 --- a/gcc/df-problems.c +++ b/gcc/df-problems.c @@ -162,7 +162,7 @@ static void df_rd_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void *vbb_info) { - struct df_rd_bb_info *bb_info = (struct df_rd_bb_info *) vbb_info; + class df_rd_bb_info *bb_info = (class df_rd_bb_info *) vbb_info; if (bb_info) { bitmap_clear (&bb_info->kill); @@ -182,17 +182,17 @@ df_rd_alloc (bitmap all_blocks) { unsigned int bb_index; bitmap_iterator bi; - struct df_rd_problem_data *problem_data; + class df_rd_problem_data *problem_data; if (df_rd->problem_data) { - problem_data = (struct df_rd_problem_data *) df_rd->problem_data; + problem_data = (class df_rd_problem_data *) df_rd->problem_data; bitmap_clear (&problem_data->sparse_invalidated_by_call); bitmap_clear (&problem_data->dense_invalidated_by_call); } else { - problem_data = XNEW (struct df_rd_problem_data); + problem_data = XNEW (class df_rd_problem_data); df_rd->problem_data = problem_data; bitmap_obstack_initialize (&problem_data->rd_bitmaps); @@ -209,7 +209,7 @@ df_rd_alloc (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); /* When bitmaps are already initialized, just clear them. */ if (bb_info->kill.obstack) @@ -283,7 +283,7 @@ df_rd_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx_insn *insn, of kill sets. */ static void -df_rd_bb_local_compute_process_def (struct df_rd_bb_info *bb_info, +df_rd_bb_local_compute_process_def (class df_rd_bb_info *bb_info, df_ref def, int top_flag) { @@ -340,7 +340,7 @@ static void df_rd_bb_local_compute (unsigned int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); rtx_insn *insn; bitmap_clear (&seen_in_block); @@ -390,8 +390,8 @@ df_rd_local_compute (bitmap all_blocks) unsigned int bb_index; bitmap_iterator bi; unsigned int regno; - struct df_rd_problem_data *problem_data - = (struct df_rd_problem_data *) df_rd->problem_data; + class df_rd_problem_data *problem_data + = (class df_rd_problem_data *) df_rd->problem_data; bitmap sparse_invalidated = &problem_data->sparse_invalidated_by_call; bitmap dense_invalidated = &problem_data->dense_invalidated_by_call; @@ -435,7 +435,7 @@ df_rd_init_solution (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); bitmap_copy (&bb_info->out, &bb_info->gen); bitmap_clear (&bb_info->in); @@ -456,8 +456,8 @@ df_rd_confluence_n (edge e) if (e->flags & EDGE_EH) { - struct df_rd_problem_data *problem_data - = (struct df_rd_problem_data *) df_rd->problem_data; + class df_rd_problem_data *problem_data + = (class df_rd_problem_data *) df_rd->problem_data; bitmap sparse_invalidated = &problem_data->sparse_invalidated_by_call; bitmap dense_invalidated = &problem_data->dense_invalidated_by_call; bitmap_iterator bi; @@ -485,7 +485,7 @@ df_rd_confluence_n (edge e) static bool df_rd_transfer_function (int bb_index) { - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); unsigned int regno; bitmap_iterator bi; bitmap in = &bb_info->in; @@ -499,12 +499,12 @@ df_rd_transfer_function (int bb_index) changed = bitmap_ior_and_compl (out, gen, in, kill); else { - struct df_rd_problem_data *problem_data; + class df_rd_problem_data *problem_data; bitmap_head tmp; /* Note that TMP is _not_ a temporary bitmap if we end up replacing OUT with TMP. Therefore, allocate TMP in the RD bitmaps obstack. */ - problem_data = (struct df_rd_problem_data *) df_rd->problem_data; + problem_data = (class df_rd_problem_data *) df_rd->problem_data; bitmap_initialize (&tmp, &problem_data->rd_bitmaps); bitmap_and_compl (&tmp, in, kill); @@ -528,7 +528,7 @@ df_rd_transfer_function (int bb_index) basic block, and mask out DEFs of registers that are not live. Computing the mask looks costly, but the benefit of the pruning outweighs the cost. */ - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); bitmap regs_live_out = &df_lr_get_bb_info (bb_index)->out; bitmap live_defs = BITMAP_ALLOC (&df_bitmap_obstack); unsigned int regno; @@ -550,8 +550,8 @@ df_rd_transfer_function (int bb_index) static void df_rd_free (void) { - struct df_rd_problem_data *problem_data - = (struct df_rd_problem_data *) df_rd->problem_data; + class df_rd_problem_data *problem_data + = (class df_rd_problem_data *) df_rd->problem_data; if (problem_data) { @@ -571,8 +571,8 @@ df_rd_free (void) static void df_rd_start_dump (FILE *file) { - struct df_rd_problem_data *problem_data - = (struct df_rd_problem_data *) df_rd->problem_data; + class df_rd_problem_data *problem_data + = (class df_rd_problem_data *) df_rd->problem_data; unsigned int m = DF_REG_SIZE (df); unsigned int regno; @@ -644,7 +644,7 @@ df_rd_dump_defs_set (bitmap defs_set, const char *prefix, FILE *file) static void df_rd_top_dump (basic_block bb, FILE *file) { - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb->index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb->index); if (!bb_info) return; @@ -659,7 +659,7 @@ df_rd_top_dump (basic_block bb, FILE *file) static void df_rd_bottom_dump (basic_block bb, FILE *file) { - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb->index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb->index); if (!bb_info) return; @@ -692,7 +692,7 @@ static const struct df_problem problem_RD = NULL, /* Incremental solution verify start. */ NULL, /* Incremental solution verify end. */ NULL, /* Dependent problem. */ - sizeof (struct df_rd_bb_info),/* Size of entry of block_info array. */ + sizeof (class df_rd_bb_info),/* Size of entry of block_info array. */ TV_DF_RD, /* Timing variable. */ true /* Reset blocks on dropping out of blocks_to_analyze. */ }; @@ -734,7 +734,7 @@ static void df_lr_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void *vbb_info) { - struct df_lr_bb_info *bb_info = (struct df_lr_bb_info *) vbb_info; + class df_lr_bb_info *bb_info = (class df_lr_bb_info *) vbb_info; if (bb_info) { bitmap_clear (&bb_info->use); @@ -770,7 +770,7 @@ df_lr_alloc (bitmap all_blocks ATTRIBUTE_UNUSED) EXECUTE_IF_SET_IN_BITMAP (df_lr->out_of_date_transfer_functions, 0, bb_index, bi) { - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); /* When bitmaps are already initialized, just clear them. */ if (bb_info->use.obstack) @@ -801,7 +801,7 @@ df_lr_reset (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); gcc_assert (bb_info); bitmap_clear (&bb_info->in); bitmap_clear (&bb_info->out); @@ -815,7 +815,7 @@ static void df_lr_bb_local_compute (unsigned int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); rtx_insn *insn; df_ref def, use; @@ -930,7 +930,7 @@ df_lr_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED) { /* The exit block is special for this problem and its bits are computed from thin air. */ - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (EXIT_BLOCK); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (EXIT_BLOCK); bitmap_copy (&bb_info->use, df->exit_block_uses); } else @@ -951,7 +951,7 @@ df_lr_init (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); bitmap_copy (&bb_info->in, &bb_info->use); bitmap_clear (&bb_info->out); } @@ -997,7 +997,7 @@ df_lr_confluence_n (edge e) static bool df_lr_transfer_function (int bb_index) { - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index); bitmap in = &bb_info->in; bitmap out = &bb_info->out; bitmap use = &bb_info->use; @@ -1069,7 +1069,7 @@ df_lr_free (void) static void df_lr_top_dump (basic_block bb, FILE *file) { - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb->index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb->index); struct df_lr_problem_data *problem_data; if (!bb_info) return; @@ -1097,7 +1097,7 @@ df_lr_top_dump (basic_block bb, FILE *file) static void df_lr_bottom_dump (basic_block bb, FILE *file) { - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb->index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb->index); struct df_lr_problem_data *problem_data; if (!bb_info) return; @@ -1214,7 +1214,7 @@ static const struct df_problem problem_LR = df_lr_verify_solution_start,/* Incremental solution verify start. */ df_lr_verify_solution_end, /* Incremental solution verify end. */ NULL, /* Dependent problem. */ - sizeof (struct df_lr_bb_info),/* Size of entry of block_info array. */ + sizeof (class df_lr_bb_info),/* Size of entry of block_info array. */ TV_DF_LR, /* Timing variable. */ false /* Reset blocks on dropping out of blocks_to_analyze. */ }; @@ -1254,7 +1254,7 @@ df_lr_verify_transfer_functions (void) FOR_ALL_BB_FN (bb, cfun) { - struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb->index); + class df_lr_bb_info *bb_info = df_lr_get_bb_info (bb->index); bitmap_set_bit (&all_blocks, bb->index); if (bb_info) @@ -1340,7 +1340,7 @@ static void df_live_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void *vbb_info) { - struct df_live_bb_info *bb_info = (struct df_live_bb_info *) vbb_info; + class df_live_bb_info *bb_info = (class df_live_bb_info *) vbb_info; if (bb_info) { bitmap_clear (&bb_info->gen); @@ -1378,7 +1378,7 @@ df_live_alloc (bitmap all_blocks ATTRIBUTE_UNUSED) EXECUTE_IF_SET_IN_BITMAP (df_live->out_of_date_transfer_functions, 0, bb_index, bi) { - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); /* When bitmaps are already initialized, just clear them. */ if (bb_info->kill.obstack) @@ -1408,7 +1408,7 @@ df_live_reset (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); gcc_assert (bb_info); bitmap_clear (&bb_info->in); bitmap_clear (&bb_info->out); @@ -1422,7 +1422,7 @@ static void df_live_bb_local_compute (unsigned int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); rtx_insn *insn; df_ref def; int luid = 0; @@ -1498,8 +1498,8 @@ df_live_init (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); - struct df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (bb_index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); + class df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (bb_index); /* No register may reach a location where it is not used. Thus we trim the rr result to the places where it is used. */ @@ -1528,8 +1528,8 @@ df_live_confluence_n (edge e) static bool df_live_transfer_function (int bb_index) { - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); - struct df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (bb_index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb_index); + class df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (bb_index); bitmap in = &bb_info->in; bitmap out = &bb_info->out; bitmap gen = &bb_info->gen; @@ -1560,8 +1560,8 @@ df_live_finalize (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (bb_index); - struct df_live_bb_info *bb_live_info = df_live_get_bb_info (bb_index); + class df_lr_bb_info *bb_lr_info = df_lr_get_bb_info (bb_index); + class df_live_bb_info *bb_live_info = df_live_get_bb_info (bb_index); /* No register may reach a location where it is not used. Thus we trim the rr result to the places where it is used. */ @@ -1601,7 +1601,7 @@ df_live_free (void) static void df_live_top_dump (basic_block bb, FILE *file) { - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb->index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb->index); struct df_live_problem_data *problem_data; if (!bb_info) @@ -1630,7 +1630,7 @@ df_live_top_dump (basic_block bb, FILE *file) static void df_live_bottom_dump (basic_block bb, FILE *file) { - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb->index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb->index); struct df_live_problem_data *problem_data; if (!bb_info) @@ -1742,7 +1742,7 @@ static const struct df_problem problem_LIVE = df_live_verify_solution_start,/* Incremental solution verify start. */ df_live_verify_solution_end, /* Incremental solution verify end. */ &problem_LR, /* Dependent problem. */ - sizeof (struct df_live_bb_info),/* Size of entry of block_info array. */ + sizeof (class df_live_bb_info),/* Size of entry of block_info array. */ TV_DF_LIVE, /* Timing variable. */ false /* Reset blocks on dropping out of blocks_to_analyze. */ }; @@ -1797,7 +1797,7 @@ df_live_verify_transfer_functions (void) FOR_ALL_BB_FN (bb, cfun) { - struct df_live_bb_info *bb_info = df_live_get_bb_info (bb->index); + class df_live_bb_info *bb_info = df_live_get_bb_info (bb->index); bitmap_set_bit (&all_blocks, bb->index); if (bb_info) @@ -1859,7 +1859,7 @@ static void df_mir_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void *vbb_info) { - struct df_mir_bb_info *bb_info = (struct df_mir_bb_info *) vbb_info; + class df_mir_bb_info *bb_info = (class df_mir_bb_info *) vbb_info; if (bb_info) { bitmap_clear (&bb_info->gen); @@ -1896,7 +1896,7 @@ df_mir_alloc (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); + class df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); /* When bitmaps are already initialized, just clear them. */ if (bb_info->kill.obstack) @@ -1929,7 +1929,7 @@ df_mir_reset (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); + class df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); gcc_assert (bb_info); @@ -1947,7 +1947,7 @@ static void df_mir_bb_local_compute (unsigned int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); + class df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); rtx_insn *insn; int luid = 0; @@ -2011,7 +2011,7 @@ df_mir_init (bitmap all_blocks) static void df_mir_confluence_0 (basic_block bb) { - struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index); + class df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index); bitmap_clear (&bb_info->in); } @@ -2039,7 +2039,7 @@ df_mir_confluence_n (edge e) static bool df_mir_transfer_function (int bb_index) { - struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); + class df_mir_bb_info *bb_info = df_mir_get_bb_info (bb_index); bitmap in = &bb_info->in; bitmap out = &bb_info->out; bitmap gen = &bb_info->gen; @@ -2074,7 +2074,7 @@ df_mir_free (void) static void df_mir_top_dump (basic_block bb, FILE *file) { - struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index); + class df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index); if (!bb_info) return; @@ -2092,7 +2092,7 @@ df_mir_top_dump (basic_block bb, FILE *file) static void df_mir_bottom_dump (basic_block bb, FILE *file) { - struct df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index); + class df_mir_bb_info *bb_info = df_mir_get_bb_info (bb->index); if (!bb_info) return; @@ -2193,7 +2193,7 @@ static const struct df_problem problem_MIR = df_mir_verify_solution_start, /* Incremental solution verify start. */ df_mir_verify_solution_end, /* Incremental solution verify end. */ NULL, /* Dependent problem. */ - sizeof (struct df_mir_bb_info),/* Size of entry of block_info array. */ + sizeof (class df_mir_bb_info),/* Size of entry of block_info array. */ TV_DF_MIR, /* Timing variable. */ false /* Reset blocks on dropping out of blocks_to_analyze. */ }; @@ -2456,7 +2456,7 @@ static void df_chain_create_bb (unsigned int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); + class df_rd_bb_info *bb_info = df_rd_get_bb_info (bb_index); rtx_insn *insn; bitmap_head cpy; @@ -2711,7 +2711,7 @@ static void df_word_lr_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void *vbb_info) { - struct df_word_lr_bb_info *bb_info = (struct df_word_lr_bb_info *) vbb_info; + class df_word_lr_bb_info *bb_info = (class df_word_lr_bb_info *) vbb_info; if (bb_info) { bitmap_clear (&bb_info->use); @@ -2754,7 +2754,7 @@ df_word_lr_alloc (bitmap all_blocks ATTRIBUTE_UNUSED) EXECUTE_IF_SET_IN_BITMAP (df_word_lr->out_of_date_transfer_functions, 0, bb_index, bi) { - struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); + class df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); /* When bitmaps are already initialized, just clear them. */ if (bb_info->use.obstack) @@ -2785,7 +2785,7 @@ df_word_lr_reset (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); + class df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); gcc_assert (bb_info); bitmap_clear (&bb_info->in); bitmap_clear (&bb_info->out); @@ -2851,7 +2851,7 @@ static void df_word_lr_bb_local_compute (unsigned int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); + class df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); rtx_insn *insn; df_ref def, use; @@ -2918,7 +2918,7 @@ df_word_lr_init (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); + class df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); bitmap_copy (&bb_info->in, &bb_info->use); bitmap_clear (&bb_info->out); } @@ -2942,7 +2942,7 @@ df_word_lr_confluence_n (edge e) static bool df_word_lr_transfer_function (int bb_index) { - struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); + class df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index); bitmap in = &bb_info->in; bitmap out = &bb_info->out; bitmap use = &bb_info->use; @@ -2979,7 +2979,7 @@ df_word_lr_free (void) static void df_word_lr_top_dump (basic_block bb, FILE *file) { - struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb->index); + class df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb->index); if (!bb_info) return; @@ -2997,7 +2997,7 @@ df_word_lr_top_dump (basic_block bb, FILE *file) static void df_word_lr_bottom_dump (basic_block bb, FILE *file) { - struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb->index); + class df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb->index); if (!bb_info) return; @@ -3032,7 +3032,7 @@ static const struct df_problem problem_WORD_LR = NULL, /* Incremental solution verify start. */ NULL, /* Incremental solution verify end. */ NULL, /* Dependent problem. */ - sizeof (struct df_word_lr_bb_info),/* Size of entry of block_info array. */ + sizeof (class df_word_lr_bb_info),/* Size of entry of block_info array. */ TV_DF_WORD_LR, /* Timing variable. */ false /* Reset blocks on dropping out of blocks_to_analyze. */ }; @@ -4348,7 +4348,7 @@ static void df_md_free_bb_info (basic_block bb ATTRIBUTE_UNUSED, void *vbb_info) { - struct df_md_bb_info *bb_info = (struct df_md_bb_info *) vbb_info; + class df_md_bb_info *bb_info = (class df_md_bb_info *) vbb_info; if (bb_info) { bitmap_clear (&bb_info->kill); @@ -4383,7 +4383,7 @@ df_md_alloc (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); /* When bitmaps are already initialized, just clear them. */ if (bb_info->init.obstack) { @@ -4452,7 +4452,7 @@ df_md_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx_insn *insn, } static void -df_md_bb_local_compute_process_def (struct df_md_bb_info *bb_info, +df_md_bb_local_compute_process_def (class df_md_bb_info *bb_info, df_ref def, int top_flag) { @@ -4493,7 +4493,7 @@ static void df_md_bb_local_compute (unsigned int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); rtx_insn *insn; /* Artificials are only hard regs. */ @@ -4571,7 +4571,7 @@ df_md_reset (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); gcc_assert (bb_info); bitmap_clear (&bb_info->in); bitmap_clear (&bb_info->out); @@ -4582,7 +4582,7 @@ static bool df_md_transfer_function (int bb_index) { basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); bitmap in = &bb_info->in; bitmap out = &bb_info->out; bitmap gen = &bb_info->gen; @@ -4610,7 +4610,7 @@ df_md_init (bitmap all_blocks) EXECUTE_IF_SET_IN_BITMAP (all_blocks, 0, bb_index, bi) { - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb_index); bitmap_copy (&bb_info->in, &bb_info->init); df_md_transfer_function (bb_index); @@ -4620,7 +4620,7 @@ df_md_init (bitmap all_blocks) static void df_md_confluence_0 (basic_block bb) { - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb->index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb->index); bitmap_copy (&bb_info->in, &bb_info->init); } @@ -4667,7 +4667,7 @@ df_md_free (void) static void df_md_top_dump (basic_block bb, FILE *file) { - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb->index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb->index); if (!bb_info) return; @@ -4686,7 +4686,7 @@ df_md_top_dump (basic_block bb, FILE *file) static void df_md_bottom_dump (basic_block bb, FILE *file) { - struct df_md_bb_info *bb_info = df_md_get_bb_info (bb->index); + class df_md_bb_info *bb_info = df_md_get_bb_info (bb->index); if (!bb_info) return; @@ -4718,7 +4718,7 @@ static const struct df_problem problem_MD = NULL, /* Incremental solution verify start. */ NULL, /* Incremental solution verify end. */ NULL, /* Dependent problem. */ - sizeof (struct df_md_bb_info),/* Size of entry of block_info array. */ + sizeof (class df_md_bb_info),/* Size of entry of block_info array. */ TV_DF_MD, /* Timing variable. */ false /* Reset blocks on dropping out of blocks_to_analyze. */ }; diff --git a/gcc/df-scan.c b/gcc/df-scan.c index ffaca0b..03294a8 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -53,25 +53,25 @@ public: auto_vec mw_vec; }; -static void df_ref_record (enum df_ref_class, struct df_collection_rec *, +static void df_ref_record (enum df_ref_class, class df_collection_rec *, rtx, rtx *, basic_block, struct df_insn_info *, enum df_ref_type, int ref_flags); -static void df_def_record_1 (struct df_collection_rec *, rtx *, +static void df_def_record_1 (class df_collection_rec *, rtx *, basic_block, struct df_insn_info *, int ref_flags); -static void df_defs_record (struct df_collection_rec *, rtx, +static void df_defs_record (class df_collection_rec *, rtx, basic_block, struct df_insn_info *, int ref_flags); -static void df_uses_record (struct df_collection_rec *, +static void df_uses_record (class df_collection_rec *, rtx *, enum df_ref_type, basic_block, struct df_insn_info *, int ref_flags); static void df_install_ref_incremental (df_ref); -static void df_insn_refs_collect (struct df_collection_rec*, +static void df_insn_refs_collect (class df_collection_rec*, basic_block, struct df_insn_info *); -static void df_canonize_collection_rec (struct df_collection_rec *); +static void df_canonize_collection_rec (class df_collection_rec *); static void df_get_regular_block_artificial_uses (bitmap); static void df_get_eh_block_artificial_uses (bitmap); @@ -84,13 +84,13 @@ static void df_grow_ref_info (struct df_ref_info *, unsigned int); static void df_ref_chain_delete_du_chain (df_ref); static void df_ref_chain_delete (df_ref); -static void df_refs_add_to_chains (struct df_collection_rec *, +static void df_refs_add_to_chains (class df_collection_rec *, basic_block, rtx_insn *, unsigned int); -static bool df_insn_refs_verify (struct df_collection_rec *, basic_block, +static bool df_insn_refs_verify (class df_collection_rec *, basic_block, rtx_insn *, bool); -static void df_entry_block_defs_collect (struct df_collection_rec *, bitmap); -static void df_exit_block_uses_collect (struct df_collection_rec *, bitmap); +static void df_entry_block_defs_collect (class df_collection_rec *, bitmap); +static void df_exit_block_uses_collect (class df_collection_rec *, bitmap); static void df_install_ref (df_ref, struct df_reg_info *, struct df_ref_info *, bool); @@ -983,7 +983,7 @@ df_insn_delete (rtx_insn *insn) /* Free all of the refs and the mw_hardregs in COLLECTION_REC. */ static void -df_free_collection_rec (struct df_collection_rec *collection_rec) +df_free_collection_rec (class df_collection_rec *collection_rec) { unsigned int ix; struct df_scan_problem_data *problem_data @@ -1014,7 +1014,7 @@ df_insn_rescan (rtx_insn *insn) unsigned int uid = INSN_UID (insn); struct df_insn_info *insn_info = NULL; basic_block bb = BLOCK_FOR_INSN (insn); - struct df_collection_rec collection_rec; + class df_collection_rec collection_rec; if ((!df) || (!INSN_P (insn))) return false; @@ -1976,7 +1976,7 @@ df_notes_rescan (rtx_insn *insn) { basic_block bb = BLOCK_FOR_INSN (insn); rtx note; - struct df_collection_rec collection_rec; + class df_collection_rec collection_rec; unsigned int i; df_mw_hardreg_chain_delete_eq_uses (insn_info); @@ -2269,7 +2269,7 @@ df_sort_and_compress_mws (vec *mw_vec) /* Sort and remove duplicates from the COLLECTION_REC. */ static void -df_canonize_collection_rec (struct df_collection_rec *collection_rec) +df_canonize_collection_rec (class df_collection_rec *collection_rec) { df_sort_and_compress_refs (&collection_rec->def_vec); df_sort_and_compress_refs (&collection_rec->use_vec); @@ -2405,7 +2405,7 @@ df_install_mws (const vec *old_vec) chains and update other necessary information. */ static void -df_refs_add_to_chains (struct df_collection_rec *collection_rec, +df_refs_add_to_chains (class df_collection_rec *collection_rec, basic_block bb, rtx_insn *insn, unsigned int flags) { if (insn) @@ -2467,7 +2467,7 @@ df_refs_add_to_chains (struct df_collection_rec *collection_rec, static df_ref df_ref_create_structure (enum df_ref_class cl, - struct df_collection_rec *collection_rec, + class df_collection_rec *collection_rec, rtx reg, rtx *loc, basic_block bb, struct df_insn_info *info, enum df_ref_type ref_type, @@ -2553,7 +2553,7 @@ df_ref_create_structure (enum df_ref_class cl, static void df_ref_record (enum df_ref_class cl, - struct df_collection_rec *collection_rec, + class df_collection_rec *collection_rec, rtx reg, rtx *loc, basic_block bb, struct df_insn_info *insn_info, enum df_ref_type ref_type, @@ -2625,7 +2625,7 @@ df_ref_record (enum df_ref_class cl, Any change here has to be matched in df_find_hard_reg_defs_1. */ static void -df_def_record_1 (struct df_collection_rec *collection_rec, +df_def_record_1 (class df_collection_rec *collection_rec, rtx *loc, basic_block bb, struct df_insn_info *insn_info, int flags) { @@ -2690,7 +2690,7 @@ df_def_record_1 (struct df_collection_rec *collection_rec, here has to be matched in df_find_hard_reg_defs. */ static void -df_defs_record (struct df_collection_rec *collection_rec, +df_defs_record (class df_collection_rec *collection_rec, rtx x, basic_block bb, struct df_insn_info *insn_info, int flags) { @@ -2796,7 +2796,7 @@ df_find_hard_reg_defs (rtx x, HARD_REG_SET *defs) /* Process all the registers used in the rtx at address LOC. */ static void -df_uses_record (struct df_collection_rec *collection_rec, +df_uses_record (class df_collection_rec *collection_rec, rtx *loc, enum df_ref_type ref_type, basic_block bb, struct df_insn_info *insn_info, int flags) @@ -3055,7 +3055,7 @@ df_uses_record (struct df_collection_rec *collection_rec, /* For all DF_REF_CONDITIONAL defs, add a corresponding uses. */ static void -df_get_conditional_uses (struct df_collection_rec *collection_rec) +df_get_conditional_uses (class df_collection_rec *collection_rec) { unsigned int ix; df_ref ref; @@ -3079,7 +3079,7 @@ df_get_conditional_uses (struct df_collection_rec *collection_rec) /* Get call's extra defs and uses (track caller-saved registers). */ static void -df_get_call_refs (struct df_collection_rec *collection_rec, +df_get_call_refs (class df_collection_rec *collection_rec, basic_block bb, struct df_insn_info *insn_info, int flags) @@ -3162,7 +3162,7 @@ df_get_call_refs (struct df_collection_rec *collection_rec, and reg chains. */ static void -df_insn_refs_collect (struct df_collection_rec *collection_rec, +df_insn_refs_collect (class df_collection_rec *collection_rec, basic_block bb, struct df_insn_info *insn_info) { rtx note; @@ -3258,7 +3258,7 @@ df_recompute_luids (basic_block bb) to COLLECTION_REC. */ static void -df_bb_refs_collect (struct df_collection_rec *collection_rec, basic_block bb) +df_bb_refs_collect (class df_collection_rec *collection_rec, basic_block bb) { collection_rec->def_vec.truncate (0); collection_rec->use_vec.truncate (0); @@ -3558,7 +3558,7 @@ df_get_entry_block_def_set (bitmap entry_block_defs) reference to include. */ static void -df_entry_block_defs_collect (struct df_collection_rec *collection_rec, +df_entry_block_defs_collect (class df_collection_rec *collection_rec, bitmap entry_block_defs) { unsigned int i; @@ -3580,7 +3580,7 @@ df_entry_block_defs_collect (struct df_collection_rec *collection_rec, static void df_record_entry_block_defs (bitmap entry_block_defs) { - struct df_collection_rec collection_rec; + class df_collection_rec collection_rec; df_entry_block_defs_collect (&collection_rec, entry_block_defs); /* Process bb_refs chain */ @@ -3715,7 +3715,7 @@ df_get_exit_block_use_set (bitmap exit_block_uses) It uses df->exit_block_uses to determine register to include. */ static void -df_exit_block_uses_collect (struct df_collection_rec *collection_rec, bitmap exit_block_uses) +df_exit_block_uses_collect (class df_collection_rec *collection_rec, bitmap exit_block_uses) { unsigned int i; bitmap_iterator bi; @@ -3744,7 +3744,7 @@ df_exit_block_uses_collect (struct df_collection_rec *collection_rec, bitmap exi static void df_record_exit_block_uses (bitmap exit_block_uses) { - struct df_collection_rec collection_rec; + class df_collection_rec collection_rec; df_exit_block_uses_collect (&collection_rec, exit_block_uses); /* Process bb_refs chain */ @@ -4052,7 +4052,7 @@ df_mws_verify (const vec *new_rec, If ABORT_IF_FAIL is set, this function never returns false. */ static bool -df_insn_refs_verify (struct df_collection_rec *collection_rec, +df_insn_refs_verify (class df_collection_rec *collection_rec, basic_block bb, rtx_insn *insn, bool abort_if_fail) @@ -4093,7 +4093,7 @@ df_bb_verify (basic_block bb) { rtx_insn *insn; struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index); - struct df_collection_rec collection_rec; + class df_collection_rec collection_rec; gcc_assert (bb_info); diff --git a/gcc/df.h b/gcc/df.h index 13358f9..2e3b825 100644 --- a/gcc/df.h +++ b/gcc/df.h @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" struct dataflow; -struct df_d; +class df_d; struct df_problem; struct df_link; struct df_insn_info; @@ -935,7 +935,7 @@ public: /* This is used for debugging and for the dumpers to find the latest instance so that the df info can be added to the dumps. This should not be used by regular code. */ -extern struct df_d *df; +extern class df_d *df; #define df_scan (df->problems_by_index[DF_SCAN]) #define df_rd (df->problems_by_index[DF_RD]) #define df_lr (df->problems_by_index[DF_LR]) @@ -968,7 +968,7 @@ extern void df_remove_problem (struct dataflow *); extern void df_finish_pass (bool); extern void df_analyze_problem (struct dataflow *, bitmap, int *, int); extern void df_analyze (); -extern void df_analyze_loop (struct loop *); +extern void df_analyze_loop (class loop *); extern int df_get_n_blocks (enum df_flow_dir); extern int *df_get_postorder (enum df_flow_dir); extern void df_simple_dataflow (enum df_flow_dir, df_init_function, @@ -1103,56 +1103,56 @@ df_scan_get_bb_info (unsigned int index) return NULL; } -static inline struct df_rd_bb_info * +static inline class df_rd_bb_info * df_rd_get_bb_info (unsigned int index) { if (index < df_rd->block_info_size) - return &((struct df_rd_bb_info *) df_rd->block_info)[index]; + return &((class df_rd_bb_info *) df_rd->block_info)[index]; else return NULL; } -static inline struct df_lr_bb_info * +static inline class df_lr_bb_info * df_lr_get_bb_info (unsigned int index) { if (index < df_lr->block_info_size) - return &((struct df_lr_bb_info *) df_lr->block_info)[index]; + return &((class df_lr_bb_info *) df_lr->block_info)[index]; else return NULL; } -static inline struct df_md_bb_info * +static inline class df_md_bb_info * df_md_get_bb_info (unsigned int index) { if (index < df_md->block_info_size) - return &((struct df_md_bb_info *) df_md->block_info)[index]; + return &((class df_md_bb_info *) df_md->block_info)[index]; else return NULL; } -static inline struct df_live_bb_info * +static inline class df_live_bb_info * df_live_get_bb_info (unsigned int index) { if (index < df_live->block_info_size) - return &((struct df_live_bb_info *) df_live->block_info)[index]; + return &((class df_live_bb_info *) df_live->block_info)[index]; else return NULL; } -static inline struct df_word_lr_bb_info * +static inline class df_word_lr_bb_info * df_word_lr_get_bb_info (unsigned int index) { if (index < df_word_lr->block_info_size) - return &((struct df_word_lr_bb_info *) df_word_lr->block_info)[index]; + return &((class df_word_lr_bb_info *) df_word_lr->block_info)[index]; else return NULL; } -static inline struct df_mir_bb_info * +static inline class df_mir_bb_info * df_mir_get_bb_info (unsigned int index) { if (index < df_mir->block_info_size) - return &((struct df_mir_bb_info *) df_mir->block_info)[index]; + return &((class df_mir_bb_info *) df_mir->block_info)[index]; else return NULL; } diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 14c1ea6..8e5b01c 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4301,7 +4301,7 @@ with machine mode @var{mode}. The default version of this hook returns true for both @code{ptr_mode} and @code{Pmode}. @end deftypefn -@deftypefn {Target Hook} bool TARGET_REF_MAY_ALIAS_ERRNO (struct ao_ref *@var{ref}) +@deftypefn {Target Hook} bool TARGET_REF_MAY_ALIAS_ERRNO (ao_ref *@var{ref}) Define this to return nonzero if the memory reference @var{ref} may alias with the system C library errno location. The default version of this hook assumes the system C library errno location is either a declaration of type int or accessed by dereferencing a pointer to int. @end deftypefn @@ -6052,11 +6052,11 @@ type @code{internal_fn}) should be considered expensive when the mask is all zeros. GCC can then try to branch around the instruction instead. @end deftypefn -@deftypefn {Target Hook} {void *} TARGET_VECTORIZE_INIT_COST (struct loop *@var{loop_info}) +@deftypefn {Target Hook} {void *} TARGET_VECTORIZE_INIT_COST (class loop *@var{loop_info}) This hook should initialize target-specific data structures in preparation for modeling the costs of vectorizing a loop or basic block. The default allocates three unsigned integers for accumulating costs for the prologue, body, and epilogue of the loop or basic block. If @var{loop_info} is non-NULL, it identifies the loop being vectorized; otherwise a single block is being vectorized. @end deftypefn -@deftypefn {Target Hook} unsigned TARGET_VECTORIZE_ADD_STMT_COST (void *@var{data}, int @var{count}, enum vect_cost_for_stmt @var{kind}, struct _stmt_vec_info *@var{stmt_info}, int @var{misalign}, enum vect_cost_model_location @var{where}) +@deftypefn {Target Hook} unsigned TARGET_VECTORIZE_ADD_STMT_COST (void *@var{data}, int @var{count}, enum vect_cost_for_stmt @var{kind}, class _stmt_vec_info *@var{stmt_info}, int @var{misalign}, enum vect_cost_model_location @var{where}) This hook should update the target-specific @var{data} in response to adding @var{count} copies of the given @var{kind} of statement to a loop or basic block. The default adds the builtin vectorizer cost for the copies of the statement to the accumulator specified by @var{where}, (the prologue, body, or epilogue) and returns the amount added. The return value should be viewed as a tentative cost that may later be revised. @end deftypefn @@ -11610,7 +11610,7 @@ function version at run-time for a given set of function versions. body must be generated. @end deftypefn -@deftypefn {Target Hook} bool TARGET_PREDICT_DOLOOP_P (struct loop *@var{loop}) +@deftypefn {Target Hook} bool TARGET_PREDICT_DOLOOP_P (class loop *@var{loop}) Return true if we can predict it is possible to use a low-overhead loop for a particular loop. The parameter @var{loop} is a pointer to the loop. This target hook is required only when the target supports low-overhead @@ -11815,7 +11815,7 @@ This function prepares to emit a conditional comparison within a sequence @var{bit_code} is @code{AND} or @code{IOR}, which is the op on the compares. @end deftypefn -@deftypefn {Target Hook} unsigned TARGET_LOOP_UNROLL_ADJUST (unsigned @var{nunroll}, struct loop *@var{loop}) +@deftypefn {Target Hook} unsigned TARGET_LOOP_UNROLL_ADJUST (unsigned @var{nunroll}, class loop *@var{loop}) This target hook returns a new value for the number of times @var{loop} should be unrolled. The parameter @var{nunroll} is the number of times the loop is to be unrolled. The parameter @var{loop} is a pointer to diff --git a/gcc/dse.c b/gcc/dse.c index a3cefbf..a1c7e3b 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -278,7 +278,7 @@ public: } positions_needed; /* The next store info for this insn. */ - struct store_info *next; + class store_info *next; /* The right hand side of the store. This is used if there is a subsequent reload of the mems address somewhere later in the @@ -326,9 +326,9 @@ public: rtx mem; /* The next read_info for this insn. */ - struct read_info_type *next; + class read_info_type *next; }; -typedef struct read_info_type *read_info_t; +typedef class read_info_type *read_info_t; static object_allocator read_info_type_pool ("read_info_pool"); @@ -1509,7 +1509,7 @@ record_store (rtx body, bb_info_t bb_info) while (ptr) { insn_info_t next = ptr->next_local_store; - struct store_info *s_info = ptr->store_rec; + class store_info *s_info = ptr->store_rec; bool del = true; /* Skip the clobbers. We delete the active insn if this insn diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h index 8614483..ad8bcb2 100644 --- a/gcc/dumpfile.h +++ b/gcc/dumpfile.h @@ -648,7 +648,7 @@ extern void dump_combine_total_stats (FILE *); /* In cfghooks.c */ extern void dump_bb (FILE *, basic_block, int, dump_flags_t); -struct opt_pass; +class opt_pass; namespace gcc { diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index f60f2e2..a667cda 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -351,7 +351,7 @@ const_fixed_hasher::equal (rtx x, rtx y) /* Return true if the given memory attributes are equal. */ bool -mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q) +mem_attrs_eq_p (const class mem_attrs *p, const class mem_attrs *q) { if (p == q) return true; @@ -1924,7 +1924,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, { poly_int64 apply_bitpos = 0; tree type; - struct mem_attrs attrs, *defattrs, *refattrs; + class mem_attrs attrs, *defattrs, *refattrs; addr_space_t as; /* It can happen that type_for_mode was given a mode for which there @@ -2334,7 +2334,7 @@ change_address (rtx memref, machine_mode mode, rtx addr) { rtx new_rtx = change_address_1 (memref, mode, addr, 1, false); machine_mode mmode = GET_MODE (new_rtx); - struct mem_attrs *defattrs; + class mem_attrs *defattrs; mem_attrs attrs (*get_mem_attrs (memref)); defattrs = mode_mem_attrs[(int) mmode]; @@ -2378,7 +2378,7 @@ adjust_address_1 (rtx memref, machine_mode mode, poly_int64 offset, rtx addr = XEXP (memref, 0); rtx new_rtx; scalar_int_mode address_mode; - struct mem_attrs attrs (*get_mem_attrs (memref)), *defattrs; + class mem_attrs attrs (*get_mem_attrs (memref)), *defattrs; unsigned HOST_WIDE_INT max_align; #ifdef POINTERS_EXTEND_UNSIGNED scalar_int_mode pointer_mode @@ -2524,7 +2524,7 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) { rtx new_rtx, addr = XEXP (memref, 0); machine_mode address_mode; - struct mem_attrs *defattrs; + class mem_attrs *defattrs; mem_attrs attrs (*get_mem_attrs (memref)); address_mode = get_address_mode (memref); diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h index 7b1cecd..7643bf9 100644 --- a/gcc/emit-rtl.h +++ b/gcc/emit-rtl.h @@ -20,8 +20,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_EMIT_RTL_H #define GCC_EMIT_RTL_H -struct temp_slot; -typedef struct temp_slot *temp_slot_p; +class temp_slot; +typedef class temp_slot *temp_slot_p; /* Information mainlined about RTL representation of incoming arguments. */ struct GTY(()) incoming_args { @@ -110,7 +110,7 @@ struct GTY(()) rtl_data { vec *x_stack_slot_list; /* List of empty areas in the stack frame. */ - struct frame_space *frame_space_list; + class frame_space *frame_space_list; /* Place after which to insert the tail_recursion_label if we need one. */ rtx_note *x_stack_check_probe_note; @@ -136,7 +136,7 @@ struct GTY(()) rtl_data { vec *x_used_temp_slots; /* List of available temp slots. */ - struct temp_slot *x_avail_temp_slots; + class temp_slot *x_avail_temp_slots; /* Current nesting level for temporaries. */ int x_temp_slot_level; @@ -319,7 +319,7 @@ extern GTY(()) struct rtl_data x_rtl; #define crtl (&x_rtl) /* Return whether two MEM_ATTRs are equal. */ -bool mem_attrs_eq_p (const struct mem_attrs *, const struct mem_attrs *); +bool mem_attrs_eq_p (const class mem_attrs *, const class mem_attrs *); /* Set the alias set of MEM to SET. */ extern void set_mem_alias_set (rtx, alias_set_type); diff --git a/gcc/except.c b/gcc/except.c index b1f04ee..1e6f8af 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1015,7 +1015,7 @@ dw2_build_landing_pads (void) make_single_succ_edge (bb, bb->next_bb, e_flags); if (current_loops) { - struct loop *loop = bb->next_bb->loop_father; + class loop *loop = bb->next_bb->loop_father; /* If we created a pre-header block, add the new block to the outer loop, otherwise to the loop itself. */ if (bb->next_bb == loop->header) @@ -1389,7 +1389,7 @@ sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch) make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU); if (current_loops) { - struct loop *loop = bb->next_bb->loop_father; + class loop *loop = bb->next_bb->loop_father; /* If we created a pre-header block, add the new block to the outer loop, otherwise to the loop itself. */ if (bb->next_bb == loop->header) @@ -1427,7 +1427,7 @@ sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch) make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU); if (current_loops) { - struct loop *loop = bb->next_bb->loop_father; + class loop *loop = bb->next_bb->loop_father; /* If we created a pre-header block, add the new block to the outer loop, otherwise to the loop itself. */ if (bb->next_bb == loop->header) diff --git a/gcc/explow.c b/gcc/explow.c index aea7118..7eb854b 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -1489,7 +1489,7 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align, stack pointer, such as acquiring the space by calling malloc(). */ if (targetm.have_allocate_stack ()) { - struct expand_operand ops[2]; + class expand_operand ops[2]; /* We don't have to check against the predicate for operand 0 since TARGET is known to be a pseudo of the proper mode, which must be valid for the operand. */ @@ -1620,7 +1620,7 @@ emit_stack_probe (rtx address) { if (targetm.have_probe_stack_address ()) { - struct expand_operand ops[1]; + class expand_operand ops[1]; insn_code icode = targetm.code_for_probe_stack_address; create_address_operand (ops, address); maybe_legitimize_operands (icode, 0, 1, ops); @@ -1680,7 +1680,7 @@ probe_stack_range (HOST_WIDE_INT first, rtx size) /* Next see if we have an insn to check the stack. */ else if (targetm.have_check_stack ()) { - struct expand_operand ops[1]; + class expand_operand ops[1]; rtx addr = memory_address (Pmode, gen_rtx_fmt_ee (STACK_GROW_OP, Pmode, stack_pointer_rtx, diff --git a/gcc/expmed.c b/gcc/expmed.c index d7f8e9a..c582f3a 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -599,7 +599,7 @@ store_bit_field_using_insv (const extraction_insn *insv, rtx op0, unsigned HOST_WIDE_INT bitnum, rtx value, scalar_int_mode value_mode) { - struct expand_operand ops[4]; + class expand_operand ops[4]; rtx value1; rtx xop0 = op0; rtx_insn *last = get_last_insn (); @@ -759,7 +759,7 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, && known_eq (bitsize, GET_MODE_BITSIZE (innermode)) && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos)) { - struct expand_operand ops[3]; + class expand_operand ops[3]; enum insn_code icode = optab_handler (vec_set_optab, outermode); create_fixed_operand (&ops[0], op0); @@ -870,7 +870,7 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, && known_eq (bitsize, GET_MODE_BITSIZE (fieldmode)) && optab_handler (movstrict_optab, fieldmode) != CODE_FOR_nothing) { - struct expand_operand ops[2]; + class expand_operand ops[2]; enum insn_code icode = optab_handler (movstrict_optab, fieldmode); rtx arg0 = op0; unsigned HOST_WIDE_INT subreg_off; @@ -1499,7 +1499,7 @@ extract_bit_field_using_extv (const extraction_insn *extv, rtx op0, int unsignedp, rtx target, machine_mode mode, machine_mode tmode) { - struct expand_operand ops[4]; + class expand_operand ops[4]; rtx spec_target = target; rtx spec_target_subreg = 0; scalar_int_mode ext_mode = extv->field_mode; @@ -1655,7 +1655,7 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, != CODE_FOR_nothing) && multiple_p (bitnum, GET_MODE_BITSIZE (tmode), &pos)) { - struct expand_operand ops[3]; + class expand_operand ops[3]; machine_mode outermode = new_mode; machine_mode innermode = tmode; enum insn_code icode @@ -1722,7 +1722,7 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, && known_eq (bitsize, GET_MODE_BITSIZE (innermode)) && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos)) { - struct expand_operand ops[3]; + class expand_operand ops[3]; create_output_operand (&ops[0], target, innermode); ops[0].target = 1; @@ -5428,7 +5428,7 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code, int unsignedp, rtx x, rtx y, int normalizep, machine_mode target_mode) { - struct expand_operand ops[4]; + class expand_operand ops[4]; rtx op0, comparison, subtarget; rtx_insn *last; scalar_int_mode result_mode = targetm.cstore_mode (icode); diff --git a/gcc/expr.c b/gcc/expr.c index c922aaa..ff1f224 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1769,7 +1769,7 @@ emit_block_move_via_cpymem (rtx x, rtx y, rtx size, unsigned int align, || max_size <= (GET_MODE_MASK (mode) >> 1) || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) { - struct expand_operand ops[9]; + class expand_operand ops[9]; unsigned int nops; /* ??? When called via emit_block_move_for_call, it'd be @@ -1932,7 +1932,7 @@ expand_cmpstrn_or_cmpmem (insn_code icode, rtx target, rtx arg1_rtx, if (target && (!REG_P (target) || HARD_REGISTER_P (target))) target = NULL_RTX; - struct expand_operand ops[5]; + class expand_operand ops[5]; create_output_operand (&ops[0], target, insn_mode); create_fixed_operand (&ops[1], arg1_rtx); create_fixed_operand (&ops[2], arg2_rtx); @@ -3137,7 +3137,7 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, || max_size <= (GET_MODE_MASK (mode) >> 1) || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) { - struct expand_operand ops[9]; + class expand_operand ops[9]; unsigned int nops; nops = insn_data[(int) code].n_generator_args; @@ -4181,7 +4181,7 @@ emit_single_push_insn_1 (machine_mode mode, rtx x, tree type) icode = optab_handler (push_optab, mode); if (icode != CODE_FOR_nothing) { - struct expand_operand ops[1]; + class expand_operand ops[1]; create_input_operand (&ops[0], x, mode); if (maybe_expand_insn (icode, 1, ops)) @@ -5027,7 +5027,7 @@ expand_assignment (tree to, tree from, bool nontemporal) if (icode != CODE_FOR_nothing) { - struct expand_operand ops[2]; + class expand_operand ops[2]; create_fixed_operand (&ops[0], mem); create_input_operand (&ops[1], reg, mode); @@ -5456,7 +5456,7 @@ expand_assignment (tree to, tree from, bool nontemporal) bool emit_storent_insn (rtx to, rtx from) { - struct expand_operand ops[2]; + class expand_operand ops[2]; machine_mode mode = GET_MODE (to); enum insn_code code = optab_handler (storent_optab, mode); @@ -6759,7 +6759,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size, != CODE_FOR_nothing) && (elt = uniform_vector_p (exp))) { - struct expand_operand ops[2]; + class expand_operand ops[2]; create_output_operand (&ops[0], target, mode); create_input_operand (&ops[1], expand_normal (elt), eltmode); expand_insn (icode, 2, ops); @@ -9554,7 +9554,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, && mode == TYPE_MODE (TREE_TYPE (treeop0)) && SCALAR_INT_MODE_P (mode)) { - struct expand_operand eops[4]; + class expand_operand eops[4]; machine_mode imode = TYPE_MODE (TREE_TYPE (treeop0)); expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL); @@ -10292,7 +10292,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, && ((icode = optab_handler (movmisalign_optab, mode)) != CODE_FOR_nothing)) { - struct expand_operand ops[2]; + class expand_operand ops[2]; /* We've already validated the memory, and we're creating a new pseudo destination. The predicates really can't fail, @@ -10374,7 +10374,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, if ((icode = optab_handler (movmisalign_optab, mode)) != CODE_FOR_nothing) { - struct expand_operand ops[2]; + class expand_operand ops[2]; /* We've already validated the memory, and we're creating a new pseudo destination. The predicates really can't fail, @@ -12180,7 +12180,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range, rtx table_label, rtx default_label, rtx fallback_label, profile_probability default_probability) { - struct expand_operand ops[5]; + class expand_operand ops[5]; scalar_int_mode index_mode = SImode; rtx op1, op2, index; diff --git a/gcc/flags.h b/gcc/flags.h index 0cc7df2..0b9cd12 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -56,9 +56,9 @@ public: enum excess_precision x_flag_excess_precision; }; -extern struct target_flag_state default_target_flag_state; +extern class target_flag_state default_target_flag_state; #if SWITCHABLE_TARGET -extern struct target_flag_state *this_target_flag_state; +extern class target_flag_state *this_target_flag_state; #else #define this_target_flag_state (&default_target_flag_state) #endif diff --git a/gcc/function.c b/gcc/function.c index b44c4d0..373c1f2 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -133,7 +133,7 @@ vec *types_used_by_cur_var_decl; /* Forward declarations. */ -static struct temp_slot *find_temp_slot_from_address (rtx); +static class temp_slot *find_temp_slot_from_address (rtx); static void pad_to_arg_alignment (struct args_size *, int, struct args_size *); static void pad_below (struct args_size *, machine_mode, tree); static void reorder_blocks_1 (rtx_insn *, tree, vec *); @@ -345,7 +345,7 @@ try_fit_stack_local (poly_int64 start, poly_int64 length, static void add_frame_space (poly_int64 start, poly_int64 end) { - struct frame_space *space = ggc_alloc (); + class frame_space *space = ggc_alloc (); space->next = crtl->frame_space_list; crtl->frame_space_list = space; space->start = start; @@ -441,11 +441,11 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size, { if (kind & ASLK_RECORD_PAD) { - struct frame_space **psp; + class frame_space **psp; for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next) { - struct frame_space *space = *psp; + class frame_space *space = *psp; if (!try_fit_stack_local (space->start, space->length, size, alignment, &slot_offset)) continue; @@ -559,9 +559,9 @@ assign_stack_local (machine_mode mode, poly_int64 size, int align) class GTY(()) temp_slot { public: /* Points to next temporary slot. */ - struct temp_slot *next; + class temp_slot *next; /* Points to previous temporary slot. */ - struct temp_slot *prev; + class temp_slot *prev; /* The rtx to used to reference the slot. */ rtx slot; /* The size, in units, of the slot. */ @@ -589,7 +589,7 @@ public: struct GTY((for_user)) temp_slot_address_entry { hashval_t hash; rtx address; - struct temp_slot *temp_slot; + class temp_slot *temp_slot; }; struct temp_address_hasher : ggc_ptr_hash @@ -606,7 +606,7 @@ static size_t n_temp_slots_in_use; /* Removes temporary slot TEMP from LIST. */ static void -cut_slot_from_list (struct temp_slot *temp, struct temp_slot **list) +cut_slot_from_list (class temp_slot *temp, class temp_slot **list) { if (temp->next) temp->next->prev = temp->prev; @@ -621,7 +621,7 @@ cut_slot_from_list (struct temp_slot *temp, struct temp_slot **list) /* Inserts temporary slot TEMP to LIST. */ static void -insert_slot_to_list (struct temp_slot *temp, struct temp_slot **list) +insert_slot_to_list (class temp_slot *temp, class temp_slot **list) { temp->next = *list; if (*list) @@ -632,7 +632,7 @@ insert_slot_to_list (struct temp_slot *temp, struct temp_slot **list) /* Returns the list of used temp slots at LEVEL. */ -static struct temp_slot ** +static class temp_slot ** temp_slots_at_level (int level) { if (level >= (int) vec_safe_length (used_temp_slots)) @@ -655,7 +655,7 @@ max_slot_level (void) /* Moves temporary slot TEMP to LEVEL. */ static void -move_slot_to_level (struct temp_slot *temp, int level) +move_slot_to_level (class temp_slot *temp, int level) { cut_slot_from_list (temp, temp_slots_at_level (temp->level)); insert_slot_to_list (temp, temp_slots_at_level (level)); @@ -665,7 +665,7 @@ move_slot_to_level (struct temp_slot *temp, int level) /* Make temporary slot TEMP available. */ static void -make_slot_available (struct temp_slot *temp) +make_slot_available (class temp_slot *temp) { cut_slot_from_list (temp, temp_slots_at_level (temp->level)); insert_slot_to_list (temp, &avail_temp_slots); @@ -701,7 +701,7 @@ temp_address_hasher::equal (temp_slot_address_entry *t1, /* Add ADDRESS as an alias of TEMP_SLOT to the addess -> temp slot mapping. */ static void -insert_temp_slot_address (rtx address, struct temp_slot *temp_slot) +insert_temp_slot_address (rtx address, class temp_slot *temp_slot) { struct temp_slot_address_entry *t = ggc_alloc (); t->address = address; @@ -735,10 +735,10 @@ remove_unused_temp_slot_addresses (void) /* Find the temp slot corresponding to the object at address X. */ -static struct temp_slot * +static class temp_slot * find_temp_slot_from_address (rtx x) { - struct temp_slot *p; + class temp_slot *p; struct temp_slot_address_entry tmp, *t; /* First try the easy way: @@ -787,7 +787,7 @@ rtx assign_stack_temp_for_type (machine_mode mode, poly_int64 size, tree type) { unsigned int align; - struct temp_slot *p, *best_p = 0, *selected = NULL, **pp; + class temp_slot *p, *best_p = 0, *selected = NULL, **pp; rtx slot; gcc_assert (known_size_p (size)); @@ -1031,7 +1031,7 @@ assign_temp (tree type_or_decl, int memory_required, static void combine_temp_slots (void) { - struct temp_slot *p, *q, *next, *next_q; + class temp_slot *p, *q, *next, *next_q; int num_slots; /* We can't combine slots, because the information about which slot @@ -1095,7 +1095,7 @@ combine_temp_slots (void) void update_temp_slot_address (rtx old_rtx, rtx new_rtx) { - struct temp_slot *p; + class temp_slot *p; if (rtx_equal_p (old_rtx, new_rtx)) return; @@ -1149,7 +1149,7 @@ update_temp_slot_address (rtx old_rtx, rtx new_rtx) void preserve_temp_slots (rtx x) { - struct temp_slot *p = 0, *next; + class temp_slot *p = 0, *next; if (x == 0) return; @@ -1189,7 +1189,7 @@ preserve_temp_slots (rtx x) void free_temp_slots (void) { - struct temp_slot *p, *next; + class temp_slot *p, *next; bool some_available = false; for (p = *temp_slots_at_level (temp_slot_level); p; p = next) diff --git a/gcc/function.h b/gcc/function.h index c2596bf..43ac5dff 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -186,7 +186,7 @@ struct GTY(()) function_subsections { class GTY(()) frame_space { public: - struct frame_space *next; + class frame_space *next; poly_int64 start; poly_int64 length; @@ -243,7 +243,7 @@ struct GTY(()) function { char *pass_startwith; /* The stack usage of this function. */ - struct stack_usage *su; + class stack_usage *su; /* Value histograms attached to particular statements. */ htab_t GTY((skip)) value_histograms; diff --git a/gcc/fwprop.c b/gcc/fwprop.c index e6f3752..137864c 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -224,8 +224,8 @@ edge single_def_use_dom_walker::before_dom_children (basic_block bb) { int bb_index = bb->index; - struct df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index); - struct df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index); + class df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index); + class df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index); rtx_insn *insn; bitmap_copy (local_md, &md_bb_info->in); diff --git a/gcc/gcc-rich-location.h b/gcc/gcc-rich-location.h index de92e3b..3bee2e8 100644 --- a/gcc/gcc-rich-location.h +++ b/gcc/gcc-rich-location.h @@ -181,7 +181,7 @@ class maybe_range_label_for_tree_type_mismatch : public range_label tree m_other_expr; }; -struct op_location_t; +class op_location_t; /* A subclass of rich_location for showing problems with binary operations. diff --git a/gcc/gcov.c b/gcc/gcov.c index 1d9d3b2..c65b715 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -76,17 +76,17 @@ using namespace std; /* This is the size of the buffer used to read in source file lines. */ -struct function_info; -struct block_info; -struct source_info; +class function_info; +class block_info; +class source_info; /* Describes an arc between two basic blocks. */ struct arc_info { /* source and destination blocks. */ - struct block_info *src; - struct block_info *dst; + class block_info *src; + class block_info *dst; /* transition counts. */ gcov_type count; @@ -178,7 +178,7 @@ public: /* Temporary chain for solving graph, and for chaining blocks on one line. */ - struct block_info *chain; + class block_info *chain; }; @@ -297,7 +297,7 @@ public: vector lines; /* Next function. */ - struct function_info *next; + class function_info *next; /* Get demangled name of a function. The demangled name is converted when it is used for the first time. */ diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 604526d..cdf0b5c 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -136,7 +136,7 @@ static struct obstack *temp_obstack = &obstack2; class insn_def { public: - struct insn_def *next; /* Next insn in chain. */ + class insn_def *next; /* Next insn in chain. */ rtx def; /* The DEFINE_... */ int insn_code; /* Instruction number. */ int insn_index; /* Expression number in file, for errors. */ @@ -152,7 +152,7 @@ public: struct insn_ent { struct insn_ent *next; /* Next in chain. */ - struct insn_def *def; /* Instruction definition. */ + class insn_def *def; /* Instruction definition. */ }; /* Each value of an attribute (either constant or computed) is assigned a @@ -175,7 +175,7 @@ class attr_desc public: char *name; /* Name of attribute. */ const char *enum_name; /* Enum name for DEFINE_ENUM_NAME. */ - struct attr_desc *next; /* Next attribute. */ + class attr_desc *next; /* Next attribute. */ struct attr_value *first_value; /* First value of this attribute. */ struct attr_value *default_val; /* Default value for this attribute. */ file_location loc; /* Where in the .md files it occurs. */ @@ -190,7 +190,7 @@ class delay_desc { public: rtx def; /* DEFINE_DELAY expression. */ - struct delay_desc *next; /* Next DEFINE_DELAY. */ + class delay_desc *next; /* Next DEFINE_DELAY. */ file_location loc; /* Where in the .md files it occurs. */ int num; /* Number of DEFINE_DELAY, starting at 1. */ }; @@ -199,7 +199,7 @@ struct attr_value_list { struct attr_value *av; struct insn_ent *ie; - struct attr_desc *attr; + class attr_desc *attr; struct attr_value_list *next; }; @@ -207,9 +207,9 @@ struct attr_value_list /* This one is indexed by the first character of the attribute name. */ #define MAX_ATTRS_INDEX 256 -static struct attr_desc *attrs[MAX_ATTRS_INDEX]; -static struct insn_def *defs; -static struct delay_desc *delays; +static class attr_desc *attrs[MAX_ATTRS_INDEX]; +static class insn_def *defs; +static class delay_desc *delays; struct attr_value_list **insn_code_values; /* Other variables. */ @@ -260,7 +260,7 @@ static char *attr_string (const char *, int); static char *attr_printf (unsigned int, const char *, ...) ATTRIBUTE_PRINTF_2; static rtx make_numeric_value (int); -static struct attr_desc *find_attr (const char **, int); +static class attr_desc *find_attr (const char **, int); static rtx mk_attr_alt (alternative_mask); static char *next_comma_elt (const char **); static rtx insert_right_side (enum rtx_code, rtx, rtx, int, int); @@ -278,15 +278,15 @@ static rtx copy_rtx_unchanging (rtx); static bool attr_alt_subset_p (rtx, rtx); static bool attr_alt_subset_of_compl_p (rtx, rtx); static void clear_struct_flag (rtx); -static void write_attr_valueq (FILE *, struct attr_desc *, const char *); -static struct attr_value *find_most_used (struct attr_desc *); -static void write_attr_set (FILE *, struct attr_desc *, int, rtx, +static void write_attr_valueq (FILE *, class attr_desc *, const char *); +static struct attr_value *find_most_used (class attr_desc *); +static void write_attr_set (FILE *, class attr_desc *, int, rtx, const char *, const char *, rtx, int, int, unsigned int); -static void write_attr_case (FILE *, struct attr_desc *, +static void write_attr_case (FILE *, class attr_desc *, struct attr_value *, int, const char *, const char *, int, rtx); -static void write_attr_value (FILE *, struct attr_desc *, rtx); +static void write_attr_value (FILE *, class attr_desc *, rtx); static void write_upcase (FILE *, const char *); static void write_indent (FILE *, int); static rtx identity_fn (rtx); @@ -847,7 +847,7 @@ check_attr_test (file_location loc, rtx exp, attr_desc *attr) Return a perhaps modified replacement expression for the value. */ static rtx -check_attr_value (file_location loc, rtx exp, struct attr_desc *attr) +check_attr_value (file_location loc, rtx exp, class attr_desc *attr) { struct attr_value *av; const char *p; @@ -957,7 +957,7 @@ check_attr_value (file_location loc, rtx exp, struct attr_desc *attr) case ATTR: { - struct attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0); + class attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0); if (attr2 == NULL) error_at (loc, "unknown attribute `%s' in ATTR", XSTR (exp, 0)); @@ -991,7 +991,7 @@ check_attr_value (file_location loc, rtx exp, struct attr_desc *attr) It becomes a COND with each test being (eq_attr "alternative" "n") */ static rtx -convert_set_attr_alternative (rtx exp, struct insn_def *id) +convert_set_attr_alternative (rtx exp, class insn_def *id) { int num_alt = id->num_alternatives; rtx condexp; @@ -1027,7 +1027,7 @@ convert_set_attr_alternative (rtx exp, struct insn_def *id) list of values is given, convert to SET_ATTR_ALTERNATIVE first. */ static rtx -convert_set_attr (rtx exp, struct insn_def *id) +convert_set_attr (rtx exp, class insn_def *id) { rtx newexp; const char *name_ptr; @@ -1061,8 +1061,8 @@ convert_set_attr (rtx exp, struct insn_def *id) static void check_defs (void) { - struct insn_def *id; - struct attr_desc *attr; + class insn_def *id; + class attr_desc *attr; int i; rtx value; @@ -1119,7 +1119,7 @@ check_defs (void) value. LOC is the location to use for error reporting. */ static rtx -make_canonical (file_location loc, struct attr_desc *attr, rtx exp) +make_canonical (file_location loc, class attr_desc *attr, rtx exp) { int i; rtx newexp; @@ -1226,7 +1226,7 @@ copy_boolean (rtx exp) alternatives. LOC is the location to use for error reporting. */ static struct attr_value * -get_attr_value (file_location loc, rtx value, struct attr_desc *attr, +get_attr_value (file_location loc, rtx value, class attr_desc *attr, int insn_code) { struct attr_value *av; @@ -1276,7 +1276,7 @@ get_attr_value (file_location loc, rtx value, struct attr_desc *attr, static void expand_delays (void) { - struct delay_desc *delay; + class delay_desc *delay; rtx condexp; rtx newexp; int i; @@ -1362,11 +1362,11 @@ expand_delays (void) the attribute. */ static void -fill_attr (struct attr_desc *attr) +fill_attr (class attr_desc *attr) { struct attr_value *av; struct insn_ent *ie; - struct insn_def *id; + class insn_def *id; int i; rtx value; @@ -1491,7 +1491,7 @@ make_length_attrs (void) static rtx (*const address_fn[]) (rtx) = {max_fn, min_fn, one_fn, identity_fn}; size_t i; - struct attr_desc *length_attr, *new_attr; + class attr_desc *length_attr, *new_attr; struct attr_value *av, *new_av; struct insn_ent *ie, *new_ie; @@ -1565,7 +1565,7 @@ min_fn (rtx exp) static void write_length_unit_log (FILE *outf) { - struct attr_desc *length_attr = find_attr (&length_str, 0); + class attr_desc *length_attr = find_attr (&length_str, 0); struct attr_value *av; struct insn_ent *ie; unsigned int length_unit_log, length_or; @@ -1924,7 +1924,7 @@ make_alternative_compare (alternative_mask mask) corresponding to INSN_CODE and INSN_INDEX. */ static rtx -evaluate_eq_attr (rtx exp, struct attr_desc *attr, rtx value, +evaluate_eq_attr (rtx exp, class attr_desc *attr, rtx value, int insn_code, int insn_index) { rtx orexp, andexp; @@ -2417,7 +2417,7 @@ static rtx simplify_test_exp (rtx exp, int insn_code, int insn_index) { rtx left, right; - struct attr_desc *attr; + class attr_desc *attr; struct attr_value *av; struct insn_ent *ie; struct attr_value_list *iv; @@ -2758,7 +2758,7 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index) otherwise return 0. */ static int -tests_attr_p (rtx p, struct attr_desc *attr) +tests_attr_p (rtx p, class attr_desc *attr) { const char *fmt; int i, ie, j, je; @@ -2799,18 +2799,18 @@ tests_attr_p (rtx p, struct attr_desc *attr) attr_desc pointers), and return the size of that array. */ static int -get_attr_order (struct attr_desc ***ret) +get_attr_order (class attr_desc ***ret) { int i, j; int num = 0; - struct attr_desc *attr; - struct attr_desc **all, **sorted; + class attr_desc *attr; + class attr_desc **all, **sorted; char *handled; for (i = 0; i < MAX_ATTRS_INDEX; i++) for (attr = attrs[i]; attr; attr = attr->next) num++; - all = XNEWVEC (struct attr_desc *, num); - sorted = XNEWVEC (struct attr_desc *, num); + all = XNEWVEC (class attr_desc *, num); + sorted = XNEWVEC (class attr_desc *, num); handled = XCNEWVEC (char, num); num = 0; for (i = 0; i < MAX_ATTRS_INDEX; i++) @@ -2858,7 +2858,7 @@ get_attr_order (struct attr_desc ***ret) if (DEBUG) for (j = 0; j < num; j++) { - struct attr_desc *attr2; + class attr_desc *attr2; struct attr_value *av; attr = sorted[j]; @@ -2889,14 +2889,14 @@ get_attr_order (struct attr_desc ***ret) static void optimize_attrs (int num_insn_codes) { - struct attr_desc *attr; + class attr_desc *attr; struct attr_value *av; struct insn_ent *ie; rtx newexp; int i; struct attr_value_list *ivbuf; struct attr_value_list *iv; - struct attr_desc **topsort; + class attr_desc **topsort; int topnum; /* For each insn code, make a list of all the insn_ent's for it, @@ -3044,7 +3044,7 @@ clear_struct_flag (rtx x) /* Add attribute value NAME to the beginning of ATTR's list. */ static void -add_attr_value (struct attr_desc *attr, const char *name) +add_attr_value (class attr_desc *attr, const char *name) { struct attr_value *av; @@ -3064,7 +3064,7 @@ gen_attr (md_rtx_info *info) { struct enum_type *et; struct enum_value *ev; - struct attr_desc *attr; + class attr_desc *attr; const char *name_ptr; char *p; rtx def = info->def; @@ -3195,10 +3195,10 @@ compares_alternatives_p (rtx exp) static void gen_insn (md_rtx_info *info) { - struct insn_def *id; + class insn_def *id; rtx def = info->def; - id = oballoc (struct insn_def); + id = oballoc (class insn_def); id->next = defs; defs = id; id->def = def; @@ -3243,7 +3243,7 @@ gen_insn (md_rtx_info *info) static void gen_delay (md_rtx_info *info) { - struct delay_desc *delay; + class delay_desc *delay; int i; rtx def = info->def; @@ -3262,7 +3262,7 @@ gen_delay (md_rtx_info *info) have_annul_false = 1; } - delay = oballoc (struct delay_desc); + delay = oballoc (class delay_desc); delay->def = def; delay->num = ++num_delays; delay->next = delays; @@ -3289,7 +3289,7 @@ find_attrs_to_cache (rtx exp, bool create) { int i; const char *name; - struct attr_desc *attr; + class attr_desc *attr; if (exp == NULL) return; @@ -3369,7 +3369,7 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags, { int comparison_operator = 0; RTX_CODE code; - struct attr_desc *attr; + class attr_desc *attr; if (emit_parens) fprintf (outf, "("); @@ -4042,7 +4042,7 @@ walk_attr_value (rtx exp) /* Write out a function to obtain the attribute for a given INSN. */ static void -write_attr_get (FILE *outf, struct attr_desc *attr) +write_attr_get (FILE *outf, class attr_desc *attr) { struct attr_value *av, *common_av; int i, j; @@ -4099,7 +4099,7 @@ write_attr_get (FILE *outf, struct attr_desc *attr) if ((attrs_seen_more_than_once & (1U << i)) != 0) { const char *name = cached_attrs[i]; - struct attr_desc *cached_attr; + class attr_desc *cached_attr; if (i != j) cached_attrs[j] = name; cached_attr = find_attr (&name, 0); @@ -4163,7 +4163,7 @@ eliminate_known_true (rtx known_true, rtx exp, int insn_code, int insn_index) and ";"). */ static void -write_attr_set (FILE *outf, struct attr_desc *attr, int indent, rtx value, +write_attr_set (FILE *outf, class attr_desc *attr, int indent, rtx value, const char *prefix, const char *suffix, rtx known_true, int insn_code, int insn_index, unsigned int attrs_cached) { @@ -4291,7 +4291,7 @@ write_insn_cases (FILE *outf, struct insn_ent *ie, int indent) /* Write out the computation for one attribute value. */ static void -write_attr_case (FILE *outf, struct attr_desc *attr, struct attr_value *av, +write_attr_case (FILE *outf, class attr_desc *attr, struct attr_value *av, int write_case_lines, const char *prefix, const char *suffix, int indent, rtx known_true) { @@ -4355,7 +4355,7 @@ write_attr_case (FILE *outf, struct attr_desc *attr, struct attr_value *av, /* Utilities to write in various forms. */ static void -write_attr_valueq (FILE *outf, struct attr_desc *attr, const char *s) +write_attr_valueq (FILE *outf, class attr_desc *attr, const char *s) { if (attr->is_numeric) { @@ -4375,7 +4375,7 @@ write_attr_valueq (FILE *outf, struct attr_desc *attr, const char *s) } static void -write_attr_value (FILE *outf, struct attr_desc *attr, rtx value) +write_attr_value (FILE *outf, class attr_desc *attr, rtx value) { int op; @@ -4395,7 +4395,7 @@ write_attr_value (FILE *outf, struct attr_desc *attr, rtx value) case ATTR: { - struct attr_desc *attr2 = find_attr (&XSTR (value, 0), 0); + class attr_desc *attr2 = find_attr (&XSTR (value, 0), 0); if (attr->enum_name) fprintf (outf, "(enum %s)", attr->enum_name); else if (!attr->is_numeric) @@ -4503,11 +4503,11 @@ write_dummy_eligible_delay (FILE *outf, const char *kind) static void write_eligible_delay (FILE *outf, const char *kind) { - struct delay_desc *delay; + class delay_desc *delay; int max_slots; char str[50]; const char *pstr; - struct attr_desc *attr; + class attr_desc *attr; struct attr_value *av, *common_av; int i; @@ -4639,14 +4639,14 @@ next_comma_elt (const char **pstr) return attr_string (start, *pstr - start); } -/* Return a `struct attr_desc' pointer for a given named attribute. If CREATE +/* Return a `class attr_desc' pointer for a given named attribute. If CREATE is nonzero, build a new attribute, if one does not exist. *NAME_P is replaced by a pointer to a canonical copy of the string. */ -static struct attr_desc * +static class attr_desc * find_attr (const char **name_p, int create) { - struct attr_desc *attr; + class attr_desc *attr; int index; const char *name = *name_p; @@ -4671,7 +4671,7 @@ find_attr (const char **name_p, int create) if (! create) return NULL; - attr = oballoc (struct attr_desc); + attr = oballoc (class attr_desc); attr->name = DEF_ATTR_STRING (name); attr->enum_name = 0; attr->first_value = attr->default_val = NULL; @@ -4689,7 +4689,7 @@ find_attr (const char **name_p, int create) static void make_internal_attr (const char *name, rtx value, int special) { - struct attr_desc *attr; + class attr_desc *attr; attr = find_attr (&name, 1); gcc_assert (!attr->default_val); @@ -4704,7 +4704,7 @@ make_internal_attr (const char *name, rtx value, int special) /* Find the most used value of an attribute. */ static struct attr_value * -find_most_used (struct attr_desc *attr) +find_most_used (class attr_desc *attr) { struct attr_value *av; struct attr_value *most_used; @@ -4759,7 +4759,7 @@ copy_rtx_unchanging (rtx orig) static void write_const_num_delay_slots (FILE *outf) { - struct attr_desc *attr = find_attr (&num_delay_slots_str, 0); + class attr_desc *attr = find_attr (&num_delay_slots_str, 0); struct attr_value *av; if (attr) @@ -4815,7 +4815,7 @@ gen_insn_reserv (md_rtx_info *info) struct insn_reserv *decl = oballoc (struct insn_reserv); rtx def = info->def; - struct attr_desc attr = { }; + class attr_desc attr = { }; attr.name = DEF_ATTR_STRING (XSTR (def, 0)); attr.loc = info->loc; @@ -4932,10 +4932,10 @@ check_tune_attr (const char *name, rtx exp) /* Try to find a const attribute (usually cpu or tune) that is used in all define_insn_reservation conditions. */ -static struct attr_desc * +static class attr_desc * find_tune_attr (rtx exp) { - struct attr_desc *attr; + class attr_desc *attr; switch (GET_CODE (exp)) { @@ -4979,7 +4979,7 @@ make_automaton_attrs (void) int i; struct insn_reserv *decl; rtx code_exp, lats_exp, byps_exp; - struct attr_desc *tune_attr; + class attr_desc *tune_attr; if (n_insn_reservs == 0) return; @@ -5245,8 +5245,8 @@ handle_arg (const char *arg) int main (int argc, const char **argv) { - struct attr_desc *attr; - struct insn_def *id; + class attr_desc *attr; + class insn_def *id; int i; progname = "genattrtab"; diff --git a/gcc/genextract.c b/gcc/genextract.c index 66886f6..5dff683 100644 --- a/gcc/genextract.c +++ b/gcc/genextract.c @@ -80,7 +80,7 @@ public: }; /* Forward declarations. */ -static void walk_rtx (md_rtx_info *, rtx, struct accum_extract *); +static void walk_rtx (md_rtx_info *, rtx, class accum_extract *); #define UPPER_OFFSET ('A' - ('z' - 'a' + 1)) @@ -89,7 +89,7 @@ static void walk_rtx (md_rtx_info *, rtx, struct accum_extract *); in ACC. */ static void push_pathstr_operand (int operand, bool is_vector, - struct accum_extract *acc) + class accum_extract *acc) { if (is_vector && 'a' + operand > 'z') acc->pathstr.safe_push (operand + UPPER_OFFSET); @@ -106,7 +106,7 @@ gen_insn (md_rtx_info *info) unsigned int op_count, dup_count, j; struct extraction *p; struct code_ptr *link; - struct accum_extract acc; + class accum_extract acc; /* Walk the insn's pattern, remembering at all times the path down to the walking point. */ @@ -224,7 +224,7 @@ VEC_char_to_string (vec v) } static void -walk_rtx (md_rtx_info *info, rtx x, struct accum_extract *acc) +walk_rtx (md_rtx_info *info, rtx x, class accum_extract *acc) { RTX_CODE code; int i, len; diff --git a/gcc/genmatch.c b/gcc/genmatch.c index 7403ccb..2e7bf27 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -50,7 +50,7 @@ unsigned verbose; /* libccp helpers. */ -static struct line_maps *line_table; +static class line_maps *line_table; /* The rich_location class within libcpp requires a way to expand location_t instances, and relies on the client code @@ -416,7 +416,7 @@ public: unsigned int fn; }; -struct simplify; +class simplify; /* Identifier that maps to a user-defined predicate. */ @@ -665,8 +665,8 @@ typedef hash_map cid_map_t; /* The AST produced by parsing of the pattern definitions. */ -struct dt_operand; -struct capture_info; +class dt_operand; +class capture_info; /* The base class for operands. */ @@ -880,7 +880,7 @@ public: produced when the pattern applies in the leafs. For a (match ...) the leafs are either empty if it is a simple predicate or the single expression specifying the matched operands. */ - struct operand *result; + class operand *result; /* Collected 'for' expression operators that have to be replaced in the lowering phase. */ vec > for_vec; @@ -933,7 +933,7 @@ print_operand (operand *o, FILE *f = stderr, bool flattened = false) } DEBUG_FUNCTION void -print_matches (struct simplify *s, FILE *f = stderr) +print_matches (class simplify *s, FILE *f = stderr) { fprintf (f, "for expression: "); print_operand (s->match, f); @@ -1583,7 +1583,7 @@ lower (vec& simplifiers, bool gimple) matching code. It represents the 'match' expression of all simplifies and has those as its leafs. */ -struct dt_simplify; +class dt_simplify; /* A hash-map collecting semantically equivalent leafs in the decision tree for splitting out to separate functions. */ @@ -1719,7 +1719,7 @@ class decision_tree public: dt_node *root; - void insert (struct simplify *, unsigned); + void insert (class simplify *, unsigned); void gen (FILE *f, bool gimple); void print (FILE *f = stderr); @@ -2025,7 +2025,7 @@ at_assert_elm: /* Insert S into the decision tree. */ void -decision_tree::insert (struct simplify *s, unsigned pattern_no) +decision_tree::insert (class simplify *s, unsigned pattern_no) { current_id = s->id; dt_operand **indexes = XCNEWVEC (dt_operand *, s->capture_max + 1); @@ -4190,7 +4190,7 @@ parser::parse_operation () /* Parse a capture. capture = '@' */ -struct operand * +class operand * parser::parse_capture (operand *op, bool require_existing) { location_t src_loc = eat_token (CPP_ATSIGN)->src_loc; @@ -4227,7 +4227,7 @@ parser::parse_capture (operand *op, bool require_existing) /* Parse an expression expr = '(' [capture][flag][type] ... ')' */ -struct operand * +class operand * parser::parse_expr () { const cpp_token *token = peek (); @@ -4395,11 +4395,11 @@ parser::parse_c_expr (cpp_ttype start) a standalone capture. op = predicate | expr | c_expr | capture */ -struct operand * +class operand * parser::parse_op () { const cpp_token *token = peek (); - struct operand *op = NULL; + class operand *op = NULL; if (token->type == CPP_OPEN_PAREN) { eat_token (CPP_OPEN_PAREN); @@ -4618,7 +4618,7 @@ parser::parse_simplify (simplify::simplify_kind kind, const cpp_token *loc = peek (); parsing_match_operand = true; - struct operand *match = parse_op (); + class operand *match = parse_op (); finish_match_operand (match); parsing_match_operand = false; if (match->type == operand::OP_CAPTURE && !matcher) @@ -5090,7 +5090,7 @@ main (int argc, char **argv) } } - line_table = XCNEW (struct line_maps); + line_table = XCNEW (class line_maps); linemap_init (line_table, 0); line_table->reallocator = xrealloc; line_table->round_alloc_size = round_alloc_size; diff --git a/gcc/genoutput.c b/gcc/genoutput.c index ab4c46a..03fa482 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -146,7 +146,7 @@ static struct operand_data **odata_end = &null_operand.next; class data { public: - struct data *next; + class data *next; const char *name; const char *template_code; file_location loc; @@ -161,29 +161,29 @@ public: }; /* This variable points to the first link in the insn chain. */ -static struct data *idata; +static class data *idata; /* This variable points to the end of the insn chain. This is where everything relevant from the machien description is appended to. */ -static struct data **idata_end; +static class data **idata_end; static void output_prologue (void); static void output_operand_data (void); static void output_insn_data (void); static void output_get_insn_name (void); -static void scan_operands (struct data *, rtx, int, int); +static void scan_operands (class data *, rtx, int, int); static int compare_operands (struct operand_data *, struct operand_data *); -static void place_operands (struct data *); -static void process_template (struct data *, const char *); -static void validate_insn_alternatives (struct data *); -static void validate_insn_operands (struct data *); +static void place_operands (class data *); +static void process_template (class data *, const char *); +static void validate_insn_alternatives (class data *); +static void validate_insn_operands (class data *); class constraint_data { public: - struct constraint_data *next_this_letter; + class constraint_data *next_this_letter; file_location loc; unsigned int namelen; char name[1]; @@ -193,7 +193,7 @@ public: are handled outside the define*_constraint mechanism. */ static const char indep_constraints[] = ",=+%*?!^$#&g"; -static struct constraint_data * +static class constraint_data * constraints_by_letter_table[1 << CHAR_BIT]; static int mdep_constraint_len (const char *, file_location, int); @@ -277,12 +277,12 @@ output_operand_data (void) static void output_insn_data (void) { - struct data *d; + class data *d; int name_offset = 0; int next_name_offset; const char * last_name = 0; const char * next_name = 0; - struct data *n; + class data *n; for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++) if (n->name) @@ -423,7 +423,7 @@ output_get_insn_name (void) THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */ static void -scan_operands (struct data *d, rtx part, int this_address_p, +scan_operands (class data *d, rtx part, int this_address_p, int this_strict_low) { int i, j; @@ -565,7 +565,7 @@ compare_operands (struct operand_data *d0, struct operand_data *d1) find a subsequence that is the same, or allocate a new one at the end. */ static void -place_operands (struct data *d) +place_operands (class data *d) { struct operand_data *od, *od2; int i; @@ -619,7 +619,7 @@ place_operands (struct data *d) templates, or C code to generate the assembler code template. */ static void -process_template (struct data *d, const char *template_code) +process_template (class data *d, const char *template_code) { const char *cp; int i; @@ -742,7 +742,7 @@ process_template (struct data *d, const char *template_code) /* Check insn D for consistency in number of constraint alternatives. */ static void -validate_insn_alternatives (struct data *d) +validate_insn_alternatives (class data *d) { int n = 0, start; @@ -825,7 +825,7 @@ validate_insn_alternatives (struct data *d) /* Verify that there are no gaps in operand numbers for INSNs. */ static void -validate_insn_operands (struct data *d) +validate_insn_operands (class data *d) { int i; @@ -835,7 +835,7 @@ validate_insn_operands (struct data *d) } static void -validate_optab_operands (struct data *d) +validate_optab_operands (class data *d) { if (!d->name || d->name[0] == '\0' || d->name[0] == '*') return; @@ -980,7 +980,7 @@ gen_expand (md_rtx_info *info) static void init_insn_for_nothing (void) { - idata = XCNEW (struct data); + idata = XCNEW (class data); new (idata) data (); idata->name = "*placeholder_for_nothing"; idata->loc = file_location ("", 0, 0); @@ -1088,7 +1088,7 @@ note_constraint (md_rtx_info *info) { rtx exp = info->def; const char *name = XSTR (exp, 0); - struct constraint_data **iter, **slot, *new_cdata; + class constraint_data **iter, **slot, *new_cdata; if (strcmp (name, "TARGET_MEM_CONSTRAINT") == 0) name = general_mem; @@ -1138,8 +1138,8 @@ note_constraint (md_rtx_info *info) return; } } - new_cdata = XNEWVAR (struct constraint_data, - sizeof (struct constraint_data) + namelen); + new_cdata = XNEWVAR (class constraint_data, + sizeof (class constraint_data) + namelen); new (new_cdata) constraint_data (); strcpy (CONST_CAST (char *, new_cdata->name), name); new_cdata->namelen = namelen; @@ -1155,7 +1155,7 @@ note_constraint (md_rtx_info *info) static int mdep_constraint_len (const char *s, file_location loc, int opno) { - struct constraint_data *p; + class constraint_data *p; p = constraints_by_letter_table[(unsigned int)s[0]]; diff --git a/gcc/genpreds.c b/gcc/genpreds.c index 293930c..556c4bd 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -669,8 +669,8 @@ write_one_predicate_function (struct pred_data *p) class constraint_data { public: - struct constraint_data *next_this_letter; - struct constraint_data *next_textual; + class constraint_data *next_this_letter; + class constraint_data *next_textual; const char *name; const char *c_name; /* same as .name unless mangling is necessary */ file_location loc; /* location of definition */ @@ -690,13 +690,13 @@ public: /* Overview of all constraints beginning with a given letter. */ -static struct constraint_data * +static class constraint_data * constraints_by_letter_table[1<next_textual) @@ -775,7 +775,7 @@ add_constraint (const char *name, const char *regclass, rtx exp, bool is_memory, bool is_special_memory, bool is_address, file_location loc) { - struct constraint_data *c, **iter, **slot; + class constraint_data *c, **iter, **slot; const char *p; bool need_mangled_name = false; bool is_const_int; @@ -909,7 +909,7 @@ add_constraint (const char *name, const char *regclass, } - c = XOBNEW (rtl_obstack, struct constraint_data); + c = XOBNEW (rtl_obstack, class constraint_data); c->name = name; c->c_name = need_mangled_name ? mangle (name) : name; c->loc = loc; @@ -980,7 +980,7 @@ process_define_register_constraint (md_rtx_info *info) static void choose_enum_order (void) { - struct constraint_data *c; + class constraint_data *c; enum_order = XNEWVEC (const constraint_data *, num_constraints); unsigned int next = 0; @@ -1077,7 +1077,7 @@ write_lookup_constraint_1 (void) for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++) { - struct constraint_data *c = constraints_by_letter_table[i]; + class constraint_data *c = constraints_by_letter_table[i]; if (!c) continue; @@ -1117,7 +1117,7 @@ write_lookup_constraint_array (void) { if (i != 0) printf (",\n "); - struct constraint_data *c = constraints_by_letter_table[i]; + class constraint_data *c = constraints_by_letter_table[i]; if (!c) printf ("CONSTRAINT__UNKNOWN"); else if (c->namelen == 1) @@ -1143,7 +1143,7 @@ write_insn_constraint_len (void) for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++) { - struct constraint_data *c = constraints_by_letter_table[i]; + class constraint_data *c = constraints_by_letter_table[i]; if (!c || c->namelen == 1) @@ -1152,7 +1152,7 @@ write_insn_constraint_len (void) /* Constraints with multiple characters should have the same length. */ { - struct constraint_data *c2 = c->next_this_letter; + class constraint_data *c2 = c->next_this_letter; size_t len = c->namelen; while (c2) { @@ -1178,7 +1178,7 @@ write_insn_constraint_len (void) static void write_reg_class_for_constraint_1 (void) { - struct constraint_data *c; + class constraint_data *c; puts ("enum reg_class\n" "reg_class_for_constraint_1 (enum constraint_num c)\n" @@ -1201,7 +1201,7 @@ write_reg_class_for_constraint_1 (void) static void write_tm_constrs_h (void) { - struct constraint_data *c; + class constraint_data *c; printf ("\ /* Generated automatically by the program '%s'\n\ @@ -1288,7 +1288,7 @@ write_constraint_satisfied_p_array (void) static void write_insn_const_int_ok_for_constraint (void) { - struct constraint_data *c; + class constraint_data *c; puts ("bool\n" "insn_const_int_ok_for_constraint (HOST_WIDE_INT ival, " diff --git a/gcc/genrecog.c b/gcc/genrecog.c index a3b8e68..f20089e 100644 --- a/gcc/genrecog.c +++ b/gcc/genrecog.c @@ -950,7 +950,7 @@ list_head ::singleton () const return first == last ? first : 0; } -struct state; +class state; /* Describes a possible successful return from a routine. */ struct acceptance_type @@ -1499,7 +1499,7 @@ operator != (const int_set &a, const int_set &b) return !operator == (a, b); } -struct decision; +class decision; /* Represents a transition between states, dependent on the result of a test T. */ @@ -2244,7 +2244,7 @@ optimize_subroutine_group (const char *type, state *root) st.longest_backtrack, st.longest_backtrack_code); } -struct merge_pattern_info; +class merge_pattern_info; /* Represents a transition from one pattern to another. */ class merge_pattern_transition diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 07aa839..0ad9995 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -70,55 +70,55 @@ class queue_elem public: rtx data; file_location loc; - struct queue_elem *next; + class queue_elem *next; /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT or DEFINE_INSN_AND_REWRITE, SPLIT points to the generated DEFINE_SPLIT. */ - struct queue_elem *split; + class queue_elem *split; }; #define MNEMONIC_ATTR_NAME "mnemonic" #define MNEMONIC_HTAB_SIZE 1024 -static struct queue_elem *define_attr_queue; -static struct queue_elem **define_attr_tail = &define_attr_queue; -static struct queue_elem *define_pred_queue; -static struct queue_elem **define_pred_tail = &define_pred_queue; -static struct queue_elem *define_insn_queue; -static struct queue_elem **define_insn_tail = &define_insn_queue; -static struct queue_elem *define_cond_exec_queue; -static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue; -static struct queue_elem *define_subst_queue; -static struct queue_elem **define_subst_tail = &define_subst_queue; -static struct queue_elem *other_queue; -static struct queue_elem **other_tail = &other_queue; -static struct queue_elem *define_subst_attr_queue; -static struct queue_elem **define_subst_attr_tail = &define_subst_attr_queue; +static class queue_elem *define_attr_queue; +static class queue_elem **define_attr_tail = &define_attr_queue; +static class queue_elem *define_pred_queue; +static class queue_elem **define_pred_tail = &define_pred_queue; +static class queue_elem *define_insn_queue; +static class queue_elem **define_insn_tail = &define_insn_queue; +static class queue_elem *define_cond_exec_queue; +static class queue_elem **define_cond_exec_tail = &define_cond_exec_queue; +static class queue_elem *define_subst_queue; +static class queue_elem **define_subst_tail = &define_subst_queue; +static class queue_elem *other_queue; +static class queue_elem **other_tail = &other_queue; +static class queue_elem *define_subst_attr_queue; +static class queue_elem **define_subst_attr_tail = &define_subst_attr_queue; /* Mapping from DEFINE_* rtxes to their location in the source file. */ static hash_map *rtx_locs; static void remove_constraints (rtx); -static int is_predicable (struct queue_elem *); +static int is_predicable (class queue_elem *); static void identify_predicable_attribute (void); static int n_alternatives (const char *); static void collect_insn_data (rtx, int *, int *); -static const char *alter_test_for_insn (struct queue_elem *, - struct queue_elem *); +static const char *alter_test_for_insn (class queue_elem *, + class queue_elem *); static char *shift_output_template (char *, const char *, int); -static const char *alter_output_for_insn (struct queue_elem *, - struct queue_elem *, +static const char *alter_output_for_insn (class queue_elem *, + class queue_elem *, int, int); -static void process_one_cond_exec (struct queue_elem *); +static void process_one_cond_exec (class queue_elem *); static void process_define_cond_exec (void); static void init_predicate_table (void); static void record_insn_name (int, const char *); -static bool has_subst_attribute (struct queue_elem *, struct queue_elem *); +static bool has_subst_attribute (class queue_elem *, class queue_elem *); static const char * alter_output_for_subst_insn (rtx, int); -static void alter_attrs_for_subst_insn (struct queue_elem *, int); -static void process_substs_on_one_elem (struct queue_elem *, - struct queue_elem *); +static void alter_attrs_for_subst_insn (class queue_elem *, int); +static void process_substs_on_one_elem (class queue_elem *, + class queue_elem *); static rtx subst_dup (rtx, int, int); static void process_define_subst (void); @@ -400,11 +400,11 @@ process_define_predicate (rtx desc, file_location loc) /* Queue PATTERN on LIST_TAIL. Return the address of the new queue element. */ -static struct queue_elem * -queue_pattern (rtx pattern, struct queue_elem ***list_tail, +static class queue_elem * +queue_pattern (rtx pattern, class queue_elem ***list_tail, file_location loc) { - struct queue_elem *e = XNEW (struct queue_elem); + class queue_elem *e = XNEW (class queue_elem); e->data = pattern; e->loc = loc; e->next = NULL; @@ -416,9 +416,9 @@ queue_pattern (rtx pattern, struct queue_elem ***list_tail, /* Remove element ELEM from QUEUE. */ static void -remove_from_queue (struct queue_elem *elem, struct queue_elem **queue) +remove_from_queue (class queue_elem *elem, class queue_elem **queue) { - struct queue_elem *prev, *e; + class queue_elem *prev, *e; prev = NULL; for (e = *queue; e ; e = e->next) { @@ -440,7 +440,7 @@ remove_from_queue (struct queue_elem *elem, struct queue_elem **queue) static void add_define_attr (const char *name) { - struct queue_elem *e = XNEW (struct queue_elem); + class queue_elem *e = XNEW (class queue_elem); rtx t1 = rtx_alloc (DEFINE_ATTR); XSTR (t1, 0) = name; XSTR (t1, 1) = "no,yes"; @@ -591,8 +591,8 @@ process_rtx (rtx desc, file_location loc) rtx split; rtvec attr; int i; - struct queue_elem *insn_elem; - struct queue_elem *split_elem; + class queue_elem *insn_elem; + class queue_elem *split_elem; int split_code = (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE ? 5 : 6); /* Create a split with values from the insn_and_split. */ @@ -646,7 +646,7 @@ process_rtx (rtx desc, file_location loc) a DEFINE_INSN. */ static int -is_predicable (struct queue_elem *elem) +is_predicable (class queue_elem *elem) { rtvec vec = XVEC (elem->data, 4); const char *value; @@ -716,8 +716,8 @@ is_predicable (struct queue_elem *elem) /* Find attribute SUBST in ELEM and assign NEW_VALUE to it. */ static void -change_subst_attribute (struct queue_elem *elem, - struct queue_elem *subst_elem, +change_subst_attribute (class queue_elem *elem, + class queue_elem *subst_elem, const char *new_value) { rtvec attrs_vec = XVEC (elem->data, 4); @@ -746,7 +746,7 @@ change_subst_attribute (struct queue_elem *elem, words, we suppose the default value of the attribute to be 'no' since it is always generated automatically in read-rtl.c. */ static bool -has_subst_attribute (struct queue_elem *elem, struct queue_elem *subst_elem) +has_subst_attribute (class queue_elem *elem, class queue_elem *subst_elem) { rtvec attrs_vec = XVEC (elem->data, 4); const char *value, *subst_name = XSTR (subst_elem->data, 0); @@ -979,7 +979,7 @@ subst_pattern_match (rtx x, rtx pt, file_location loc) static void identify_predicable_attribute (void) { - struct queue_elem *elem; + class queue_elem *elem; char *p_true, *p_false; const char *value; @@ -1327,8 +1327,8 @@ alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter) } static const char * -alter_test_for_insn (struct queue_elem *ce_elem, - struct queue_elem *insn_elem) +alter_test_for_insn (class queue_elem *ce_elem, + class queue_elem *insn_elem) { return rtx_reader_ptr->join_c_conditions (XSTR (ce_elem->data, 1), XSTR (insn_elem->data, 2)); @@ -1439,7 +1439,7 @@ alter_attrs_for_insn (rtx insn) if (!global_changes_made) { - struct queue_elem *elem; + class queue_elem *elem; global_changes_made = true; add_define_attr ("ce_enabled"); @@ -1480,7 +1480,7 @@ alter_attrs_for_insn (rtx insn) ELEM is a queue element, containing our rtl-template, N_DUP - multiplication factor. */ static void -alter_attrs_for_subst_insn (struct queue_elem * elem, int n_dup) +alter_attrs_for_subst_insn (class queue_elem * elem, int n_dup) { rtvec vec = XVEC (elem->data, 4); int num_elem; @@ -1543,8 +1543,8 @@ shift_output_template (char *dest, const char *src, int disp) } static const char * -alter_output_for_insn (struct queue_elem *ce_elem, - struct queue_elem *insn_elem, +alter_output_for_insn (class queue_elem *ce_elem, + class queue_elem *insn_elem, int alt, int max_op) { const char *ce_out, *insn_out; @@ -1732,9 +1732,9 @@ alter_output_for_subst_insn (rtx insn, int alt) /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */ static void -process_one_cond_exec (struct queue_elem *ce_elem) +process_one_cond_exec (class queue_elem *ce_elem) { - struct queue_elem *insn_elem; + class queue_elem *insn_elem; for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next) { int alternatives, max_operand; @@ -1838,10 +1838,10 @@ process_one_cond_exec (struct queue_elem *ce_elem) was applied, ELEM would be deleted. */ static void -process_substs_on_one_elem (struct queue_elem *elem, - struct queue_elem *queue) +process_substs_on_one_elem (class queue_elem *elem, + class queue_elem *queue) { - struct queue_elem *subst_elem; + class queue_elem *subst_elem; int i, j, patterns_match; for (subst_elem = define_subst_queue; @@ -2248,7 +2248,7 @@ subst_dup (rtx pattern, int n_alt, int n_subst_alt) static void process_define_cond_exec (void) { - struct queue_elem *elem; + class queue_elem *elem; identify_predicable_attribute (); if (have_error) @@ -2264,7 +2264,7 @@ process_define_cond_exec (void) static void process_define_subst (void) { - struct queue_elem *elem, *elem_attr; + class queue_elem *elem, *elem_attr; /* Check if each define_subst has corresponding define_subst_attr. */ for (elem = define_subst_queue; elem ; elem = elem->next) @@ -2475,7 +2475,7 @@ mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED) static void gen_mnemonic_attr (void) { - struct queue_elem *elem; + class queue_elem *elem; rtx mnemonic_attr = NULL; htab_t mnemonic_htab; const char *str, *p; @@ -2552,7 +2552,7 @@ gen_mnemonic_attr (void) static void check_define_attr_duplicates () { - struct queue_elem *elem; + class queue_elem *elem; htab_t attr_htab; char * attr_name; void **slot; @@ -2648,7 +2648,7 @@ read_md_rtx (md_rtx_info *info) to use elided pattern numbers for anything. */ do { - struct queue_elem **queue, *elem; + class queue_elem **queue, *elem; /* Read all patterns from a given queue before moving on to the next. */ if (define_attr_queue != NULL) diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index a95ff46..a2736bc 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -200,7 +200,7 @@ static const size_t extra_order_size_table[] = { sizeof (struct function), sizeof (struct basic_block_def), sizeof (struct cgraph_node), - sizeof (struct loop), + sizeof (class loop), }; /* The total number of orders. */ diff --git a/gcc/gimple-loop-interchange.cc b/gcc/gimple-loop-interchange.cc index 1324489..b56155b 100644 --- a/gcc/gimple-loop-interchange.cc +++ b/gcc/gimple-loop-interchange.cc @@ -159,7 +159,7 @@ dump_reduction (reduction_p re) /* Dump LOOP's induction IV. */ static void -dump_induction (struct loop *loop, induction_p iv) +dump_induction (class loop *loop, induction_p iv) { fprintf (dump_file, " Induction: "); print_generic_expr (dump_file, iv->var, TDF_SLIM); @@ -175,7 +175,7 @@ dump_induction (struct loop *loop, induction_p iv) class loop_cand { public: - loop_cand (struct loop *, struct loop *); + loop_cand (class loop *, class loop *); ~loop_cand (); reduction_p find_reduction_by_stmt (gimple *); @@ -189,10 +189,10 @@ public: void undo_simple_reduction (reduction_p, bitmap); /* The loop itself. */ - struct loop *m_loop; + class loop *m_loop; /* The outer loop for interchange. It equals to loop if this loop cand itself represents the outer loop. */ - struct loop *m_outer; + class loop *m_outer; /* Vector of induction variables in loop. */ vec m_inductions; /* Vector of reduction variables in loop. */ @@ -211,7 +211,7 @@ public: /* Constructor. */ -loop_cand::loop_cand (struct loop *loop, struct loop *outer) +loop_cand::loop_cand (class loop *loop, class loop *outer) : m_loop (loop), m_outer (outer), m_exit (single_exit (loop)), m_bbs (get_loop_body (loop)), m_num_stmts (0), m_const_init_reduc (0) { @@ -241,7 +241,7 @@ loop_cand::~loop_cand () /* Return single use stmt of VAR in LOOP, otherwise return NULL. */ static gimple * -single_use_in_loop (tree var, struct loop *loop) +single_use_in_loop (tree var, class loop *loop) { gimple *stmt, *res = NULL; use_operand_p use_p; @@ -951,7 +951,7 @@ free_data_refs_with_aux (vec datarefs) class tree_loop_interchange { public: - tree_loop_interchange (vec loop_nest) + tree_loop_interchange (vec loop_nest) : m_loop_nest (loop_nest), m_niters_iv_var (NULL_TREE), m_dce_seeds (BITMAP_ALLOC (NULL)) { } ~tree_loop_interchange () { BITMAP_FREE (m_dce_seeds); } @@ -962,10 +962,10 @@ private: bool valid_data_dependences (unsigned, unsigned, vec); void interchange_loops (loop_cand &, loop_cand &); void map_inductions_to_loop (loop_cand &, loop_cand &); - void move_code_to_inner_loop (struct loop *, struct loop *, basic_block *); + void move_code_to_inner_loop (class loop *, class loop *, basic_block *); /* The whole loop nest in which interchange is ongoing. */ - vec m_loop_nest; + vec m_loop_nest; /* We create new IV which is only used in loop's exit condition check. In case of 3-level loop nest interchange, when we interchange the innermost two loops, new IV created in the middle level loop does @@ -1079,7 +1079,7 @@ tree_loop_interchange::interchange_loops (loop_cand &iloop, loop_cand &oloop) } /* Prepare niters for both loops. */ - struct loop *loop_nest = m_loop_nest[0]; + class loop *loop_nest = m_loop_nest[0]; edge instantiate_below = loop_preheader_edge (loop_nest); gsi = gsi_last_bb (loop_preheader_edge (loop_nest)->src); i_niters = number_of_latch_executions (iloop.m_loop); @@ -1214,8 +1214,8 @@ tree_loop_interchange::map_inductions_to_loop (loop_cand &src, loop_cand &tgt) /* Move stmts of outer loop to inner loop. */ void -tree_loop_interchange::move_code_to_inner_loop (struct loop *outer, - struct loop *inner, +tree_loop_interchange::move_code_to_inner_loop (class loop *outer, + class loop *inner, basic_block *outer_bbs) { basic_block oloop_exit_bb = single_exit (outer)->src; @@ -1276,7 +1276,7 @@ tree_loop_interchange::move_code_to_inner_loop (struct loop *outer, arr[i][j - 1][k] = 0; */ static void -compute_access_stride (struct loop *loop_nest, struct loop *loop, +compute_access_stride (class loop *loop_nest, class loop *loop, data_reference_p dr) { vec *strides = new vec (); @@ -1320,10 +1320,10 @@ compute_access_stride (struct loop *loop_nest, struct loop *loop, if (! chrec_contains_undetermined (scev)) { tree sl = scev; - struct loop *expected = loop; + class loop *expected = loop; while (TREE_CODE (sl) == POLYNOMIAL_CHREC) { - struct loop *sl_loop = get_chrec_loop (sl); + class loop *sl_loop = get_chrec_loop (sl); while (sl_loop != expected) { strides->safe_push (size_int (0)); @@ -1351,8 +1351,8 @@ compute_access_stride (struct loop *loop_nest, struct loop *loop, all data references. If access strides cannot be computed at least for two levels of loop for any data reference, it returns NULL. */ -static struct loop * -compute_access_strides (struct loop *loop_nest, struct loop *loop, +static class loop * +compute_access_strides (class loop *loop_nest, class loop *loop, vec datarefs) { unsigned i, j, num_loops = (unsigned) -1; @@ -1390,8 +1390,8 @@ compute_access_strides (struct loop *loop_nest, struct loop *loop, of loops that isn't in current LOOP_NEST. */ static void -prune_access_strides_not_in_loop (struct loop *loop_nest, - struct loop *innermost, +prune_access_strides_not_in_loop (class loop *loop_nest, + class loop *innermost, vec datarefs) { data_reference_p dr; @@ -1712,7 +1712,7 @@ public: nest with LOOP. */ static bool -proper_loop_form_for_interchange (struct loop *loop, struct loop **min_outer) +proper_loop_form_for_interchange (class loop *loop, class loop **min_outer) { edge e0, e1, exit; @@ -1811,14 +1811,14 @@ proper_loop_form_for_interchange (struct loop *loop, struct loop **min_outer) should be interchanged by looking into all DATAREFS. */ static bool -should_interchange_loop_nest (struct loop *loop_nest, struct loop *innermost, +should_interchange_loop_nest (class loop *loop_nest, class loop *innermost, vec datarefs) { unsigned idx = loop_depth (innermost) - loop_depth (loop_nest); gcc_assert (idx > 0); /* Check if any two adjacent loops should be interchanged. */ - for (struct loop *loop = innermost; + for (class loop *loop = innermost; loop != loop_nest; loop = loop_outer (loop), idx--) if (should_interchange_loops (idx, idx - 1, datarefs, 0, 0, loop == innermost, false)) @@ -1838,7 +1838,7 @@ tree_loop_interchange_compute_ddrs (vec loop_nest, vec *ddrs) { struct data_reference *a, *b; - struct loop *innermost = loop_nest.last (); + class loop *innermost = loop_nest.last (); for (unsigned i = 0; datarefs.iterate (i, &a); ++i) { @@ -1880,7 +1880,7 @@ tree_loop_interchange_compute_ddrs (vec loop_nest, /* Prune DATAREFS by removing any data reference not inside of LOOP. */ static inline void -prune_datarefs_not_in_loop (struct loop *loop, vec datarefs) +prune_datarefs_not_in_loop (class loop *loop, vec datarefs) { unsigned i, j; struct data_reference *dr; @@ -1907,10 +1907,10 @@ prune_datarefs_not_in_loop (struct loop *loop, vec datarefs) inner loop of that basic block's father loop. On success, return the outer loop of the result loop nest. */ -static struct loop * -prepare_data_references (struct loop *loop, vec *datarefs) +static class loop * +prepare_data_references (class loop *loop, vec *datarefs) { - struct loop *loop_nest = loop; + class loop *loop_nest = loop; vec *bb_refs; basic_block bb, *bbs = get_loop_body_in_dom_order (loop); @@ -1974,11 +1974,11 @@ prepare_data_references (struct loop *loop, vec *datarefs) in interchange. */ static bool -prepare_perfect_loop_nest (struct loop *loop, vec *loop_nest, +prepare_perfect_loop_nest (class loop *loop, vec *loop_nest, vec *datarefs, vec *ddrs) { - struct loop *start_loop = NULL, *innermost = loop; - struct loop *outermost = loops_for_fn (cfun)->tree_root; + class loop *start_loop = NULL, *innermost = loop; + class loop *outermost = loops_for_fn (cfun)->tree_root; /* Find loop nest from the innermost loop. The outermost is the innermost outer*/ @@ -2064,7 +2064,7 @@ pass_linterchange::execute (function *fun) return 0; bool changed_p = false; - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST) { vec loop_nest = vNULL; diff --git a/gcc/gimple-loop-jam.c b/gcc/gimple-loop-jam.c index 90ddbf3..11153f5 100644 --- a/gcc/gimple-loop-jam.c +++ b/gcc/gimple-loop-jam.c @@ -103,11 +103,11 @@ along with GCC; see the file COPYING3. If not see to the OLD loop or the outer loop of OLD now is inside LOOP. */ static void -merge_loop_tree (struct loop *loop, struct loop *old) +merge_loop_tree (class loop *loop, class loop *old) { basic_block *bbs; int i, n; - struct loop *subloop; + class loop *subloop; edge e; edge_iterator ei; @@ -186,11 +186,11 @@ bb_prevents_fusion_p (basic_block bb) If so return true, otherwise return false. */ static bool -unroll_jam_possible_p (struct loop *outer, struct loop *loop) +unroll_jam_possible_p (class loop *outer, class loop *loop) { basic_block *bbs; int i, n; - struct tree_niter_desc niter; + class tree_niter_desc niter; /* When fusing the loops we skip the latch block of the first one, so it mustn't have any effects to @@ -301,9 +301,9 @@ unroll_jam_possible_p (struct loop *outer, struct loop *loop) be in appropriate form. */ static void -fuse_loops (struct loop *loop) +fuse_loops (class loop *loop) { - struct loop *next = loop->next; + class loop *next = loop->next; while (next) { @@ -353,7 +353,7 @@ fuse_loops (struct loop *loop) merge_loop_tree (loop, next); gcc_assert (!next->num_nodes); - struct loop *ln = next->next; + class loop *ln = next->next; delete_loop (next); next = ln; } @@ -422,7 +422,7 @@ adjust_unroll_factor (struct data_dependence_relation *ddr, static unsigned int tree_loop_unroll_and_jam (void) { - struct loop *loop; + class loop *loop; bool changed = false; gcc_assert (scev_initialized_p ()); @@ -430,7 +430,7 @@ tree_loop_unroll_and_jam (void) /* Go through all innermost loops. */ FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST) { - struct loop *outer = loop_outer (loop); + class loop *outer = loop_outer (loop); if (loop_depth (loop) < 2 || optimize_loop_nest_for_size_p (outer)) @@ -442,7 +442,7 @@ tree_loop_unroll_and_jam (void) vec datarefs; vec dependences; unsigned unroll_factor, profit_unroll, removed; - struct tree_niter_desc desc; + class tree_niter_desc desc; bool unroll = false; auto_vec loop_nest; diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc index 468f586..be8c2d8 100644 --- a/gcc/gimple-loop-versioning.cc +++ b/gcc/gimple-loop-versioning.cc @@ -190,7 +190,7 @@ public: /* The loop containing STMT (cached for convenience). If multiple statements share the same address, they all belong to this loop. */ - struct loop *loop; + class loop *loop; /* A decomposition of the calculation into a sum of terms plus an optional base. When BASE is provided, it is never an SSA name. @@ -229,7 +229,7 @@ public: /* The outermost loop that can handle all the version checks described below. */ - struct loop *outermost; + class loop *outermost; /* The first entry in the list of blocks that belong to this loop (and not to subloops). m_next_block_in_loop provides the chain @@ -242,7 +242,7 @@ public: /* If versioning succeeds, this points the version of the loop that assumes the version conditions holds. */ - struct loop *optimized_loop; + class loop *optimized_loop; }; /* The main pass structure. */ @@ -285,9 +285,9 @@ private: loop_info &m_li; }; - loop_info &get_loop_info (struct loop *loop) { return m_loops[loop->num]; } + loop_info &get_loop_info (class loop *loop) { return m_loops[loop->num]; } - unsigned int max_insns_for_loop (struct loop *); + unsigned int max_insns_for_loop (class loop *); bool expensive_stmt_p (gimple *); void version_for_unity (gimple *, tree); @@ -298,7 +298,7 @@ private: inner_likelihood get_inner_likelihood (tree, unsigned HOST_WIDE_INT); void dump_inner_likelihood (address_info &, address_term_info &); void analyze_stride (address_info &, address_term_info &, - tree, struct loop *); + tree, class loop *); bool find_per_loop_multiplication (address_info &, address_term_info &); bool analyze_term_using_scevs (address_info &, address_term_info &); void analyze_arbitrary_term (address_info &, address_term_info &); @@ -309,15 +309,15 @@ private: bool analyze_block (basic_block); bool analyze_blocks (); - void prune_loop_conditions (struct loop *, vr_values *); + void prune_loop_conditions (class loop *, vr_values *); bool prune_conditions (); - void merge_loop_info (struct loop *, struct loop *); - void add_loop_to_queue (struct loop *); - bool decide_whether_loop_is_versionable (struct loop *); + void merge_loop_info (class loop *, class loop *); + void add_loop_to_queue (class loop *); + bool decide_whether_loop_is_versionable (class loop *); bool make_versioning_decisions (); - bool version_loop (struct loop *); + bool version_loop (class loop *); void implement_versioning_decisions (); /* The function we're optimizing. */ @@ -348,7 +348,7 @@ private: auto_vec m_next_block_in_loop; /* The list of loops that we've decided to version. */ - auto_vec m_loops_to_version; + auto_vec m_loops_to_version; /* A table of addresses in the current loop, keyed off their values but not their offsets. */ @@ -602,7 +602,7 @@ loop_versioning::~loop_versioning () interchange or outer-loop vectorization). */ unsigned int -loop_versioning::max_insns_for_loop (struct loop *loop) +loop_versioning::max_insns_for_loop (class loop *loop) { return (loop->inner ? PARAM_VALUE (PARAM_LOOP_VERSIONING_MAX_OUTER_INSNS) @@ -633,7 +633,7 @@ loop_versioning::expensive_stmt_p (gimple *stmt) void loop_versioning::version_for_unity (gimple *stmt, tree name) { - struct loop *loop = loop_containing_stmt (stmt); + class loop *loop = loop_containing_stmt (stmt); loop_info &li = get_loop_info (loop); if (bitmap_set_bit (&li.unity_names, SSA_NAME_VERSION (name))) @@ -641,7 +641,7 @@ loop_versioning::version_for_unity (gimple *stmt, tree name) /* This is the first time we've wanted to version LOOP for NAME. Keep track of the outermost loop that can handle all versioning checks in LI. */ - struct loop *outermost + class loop *outermost = outermost_invariant_loop_for_expr (loop, name); if (loop_depth (li.outermost) < loop_depth (outermost)) li.outermost = outermost; @@ -834,7 +834,7 @@ loop_versioning::dump_inner_likelihood (address_info &address, void loop_versioning::analyze_stride (address_info &address, address_term_info &term, - tree stride, struct loop *op_loop) + tree stride, class loop *op_loop) { term.stride = stride; @@ -895,7 +895,7 @@ loop_versioning::find_per_loop_multiplication (address_info &address, if (!mult || gimple_assign_rhs_code (mult) != MULT_EXPR) return false; - struct loop *mult_loop = loop_containing_stmt (mult); + class loop *mult_loop = loop_containing_stmt (mult); if (!loop_outer (mult_loop)) return false; @@ -937,7 +937,7 @@ loop_versioning::analyze_term_using_scevs (address_info &address, if (!setter) return false; - struct loop *wrt_loop = loop_containing_stmt (setter); + class loop *wrt_loop = loop_containing_stmt (setter); if (!loop_outer (wrt_loop)) return false; @@ -1199,7 +1199,7 @@ loop_versioning::record_address_fragment (gimple *stmt, /* Quick exit if no part of the address is calculated in STMT's loop, since such addresses have no versioning opportunities. */ - struct loop *loop = loop_containing_stmt (stmt); + class loop *loop = loop_containing_stmt (stmt); if (expr_invariant_in_loop_p (loop, expr)) return; @@ -1375,7 +1375,7 @@ loop_versioning::analyze_expr (gimple *stmt, tree expr) bool loop_versioning::analyze_block (basic_block bb) { - struct loop *loop = bb->loop_father; + class loop *loop = bb->loop_father; loop_info &li = get_loop_info (loop); for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -1424,7 +1424,7 @@ loop_versioning::analyze_blocks () versioning at that level could be useful in some cases. */ get_loop_info (get_loop (m_fn, 0)).rejected_p = true; - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) { loop_info &linfo = get_loop_info (loop); @@ -1435,7 +1435,7 @@ loop_versioning::analyze_blocks () /* See whether an inner loop prevents versioning of this loop. */ if (!linfo.rejected_p) - for (struct loop *inner = loop->inner; inner; inner = inner->next) + for (class loop *inner = loop->inner; inner; inner = inner->next) if (get_loop_info (inner).rejected_p) { linfo.rejected_p = true; @@ -1479,7 +1479,7 @@ loop_versioning::analyze_blocks () LOOP. */ void -loop_versioning::prune_loop_conditions (struct loop *loop, vr_values *vrs) +loop_versioning::prune_loop_conditions (class loop *loop, vr_values *vrs) { loop_info &li = get_loop_info (loop); @@ -1525,7 +1525,7 @@ loop_versioning::prune_conditions () OUTER. */ void -loop_versioning::merge_loop_info (struct loop *outer, struct loop *inner) +loop_versioning::merge_loop_info (class loop *outer, class loop *inner) { loop_info &inner_li = get_loop_info (inner); loop_info &outer_li = get_loop_info (outer); @@ -1549,7 +1549,7 @@ loop_versioning::merge_loop_info (struct loop *outer, struct loop *inner) /* Add LOOP to the queue of loops to version. */ void -loop_versioning::add_loop_to_queue (struct loop *loop) +loop_versioning::add_loop_to_queue (class loop *loop) { loop_info &li = get_loop_info (loop); @@ -1571,7 +1571,7 @@ loop_versioning::add_loop_to_queue (struct loop *loop) We have already made this decision for all inner loops of LOOP. */ bool -loop_versioning::decide_whether_loop_is_versionable (struct loop *loop) +loop_versioning::decide_whether_loop_is_versionable (class loop *loop) { loop_info &li = get_loop_info (loop); @@ -1579,7 +1579,7 @@ loop_versioning::decide_whether_loop_is_versionable (struct loop *loop) return false; /* Examine the decisions made for inner loops. */ - for (struct loop *inner = loop->inner; inner; inner = inner->next) + for (class loop *inner = loop->inner; inner; inner = inner->next) { loop_info &inner_li = get_loop_info (inner); if (inner_li.rejected_p) @@ -1631,7 +1631,7 @@ loop_versioning::decide_whether_loop_is_versionable (struct loop *loop) } /* Hoist all version checks from subloops to this loop. */ - for (struct loop *subloop = loop->inner; subloop; subloop = subloop->next) + for (class loop *subloop = loop->inner; subloop; subloop = subloop->next) merge_loop_info (loop, subloop); return true; @@ -1646,7 +1646,7 @@ loop_versioning::make_versioning_decisions () AUTO_DUMP_SCOPE ("make_versioning_decisions", dump_user_location_t::from_function_decl (m_fn->decl)); - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) { loop_info &linfo = get_loop_info (loop); @@ -1663,7 +1663,7 @@ loop_versioning::make_versioning_decisions () /* We can't version this loop, so individually version any subloops that would benefit and haven't been versioned yet. */ linfo.rejected_p = true; - for (struct loop *subloop = loop->inner; subloop; + for (class loop *subloop = loop->inner; subloop; subloop = subloop->next) if (get_loop_info (subloop).worth_versioning_p ()) add_loop_to_queue (subloop); @@ -1677,7 +1677,7 @@ loop_versioning::make_versioning_decisions () cached in the associated loop_info. Return true on success. */ bool -loop_versioning::version_loop (struct loop *loop) +loop_versioning::version_loop (class loop *loop) { loop_info &li = get_loop_info (loop); @@ -1739,7 +1739,7 @@ loop_versioning::implement_versioning_decisions () user-facing at this point. */ bool any_succeeded_p = false; - struct loop *loop; + class loop *loop; unsigned int i; FOR_EACH_VEC_ELT (m_loops_to_version, i, loop) if (version_loop (loop)) diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c index 4c68af8..46f5a01 100644 --- a/gcc/gimple-ssa-evrp-analyze.c +++ b/gcc/gimple-ssa-evrp-analyze.c @@ -262,7 +262,7 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb) use PHI arg ranges which may be still UNDEFINED but have to use VARYING for them. But we can still resort to SCEV for loop header PHIs. */ - struct loop *l; + class loop *l; if (scev_initialized_p () && interesting && (l = loop_containing_stmt (phi)) diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 1f50e3a..0bf64b3 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -2159,7 +2159,7 @@ public: virtual unsigned int execute (function *); private: - hash_map m_stores; + hash_map m_stores; /* Form a doubly-linked stack of the elements of m_stores, so that we can iterate over them in a predictable way. Using this order @@ -3097,7 +3097,7 @@ split_store::split_store (unsigned HOST_WIDE_INT bp, if there is exactly one original store in the range. */ static store_immediate_info * -find_constituent_stores (struct merged_store_group *group, +find_constituent_stores (class merged_store_group *group, vec *stores, unsigned int *first, unsigned HOST_WIDE_INT bitpos, @@ -3240,7 +3240,7 @@ count_multiple_uses (store_immediate_info *info) static unsigned int split_group (merged_store_group *group, bool allow_unaligned_store, bool allow_unaligned_load, bool bzero_first, - vec *split_stores, + vec *split_stores, unsigned *total_orig, unsigned *total_new) { @@ -3277,7 +3277,7 @@ split_group (merged_store_group *group, bool allow_unaligned_store, if (align_bitpos) align = least_bit_hwi (align_bitpos); bytepos = group->start / BITS_PER_UNIT; - struct split_store *store + split_store *store = new split_store (bytepos, group->width, align); unsigned int first = 0; find_constituent_stores (group, &store->orig_stores, @@ -3335,7 +3335,7 @@ split_group (merged_store_group *group, bool allow_unaligned_store, ret = 1; if (split_stores) { - struct split_store *store + split_store *store = new split_store (bytepos, group->stores[0]->bitsize, align_base); store->orig_stores.safe_push (group->stores[0]); store->orig = true; @@ -3462,7 +3462,7 @@ split_group (merged_store_group *group, bool allow_unaligned_store, if (split_stores) { - struct split_store *store + split_store *store = new split_store (try_pos, try_size, align); info = find_constituent_stores (group, &store->orig_stores, &first, try_bitpos, try_size); @@ -3483,7 +3483,7 @@ split_group (merged_store_group *group, bool allow_unaligned_store, if (total_orig) { unsigned int i; - struct split_store *store; + split_store *store; /* If we are reusing some original stores and any of the original SSA_NAMEs had multiple uses, we need to subtract those now before we add the new ones. */ @@ -3650,7 +3650,7 @@ imm_store_chain_info::output_merged_store (merged_store_group *group) if (orig_num_stmts < 2) return false; - auto_vec split_stores; + auto_vec split_stores; bool allow_unaligned_store = !STRICT_ALIGNMENT && PARAM_VALUE (PARAM_STORE_MERGING_ALLOW_UNALIGNED); bool allow_unaligned_load = allow_unaligned_store; @@ -4610,7 +4610,7 @@ pass_store_merging::process_store (gimple *stmt) if (!ins_stmt) memset (&n, 0, sizeof (n)); - struct imm_store_chain_info **chain_info = NULL; + class imm_store_chain_info **chain_info = NULL; if (base_addr) chain_info = m_stores.get (base_addr); @@ -4646,7 +4646,7 @@ pass_store_merging::process_store (gimple *stmt) /* Store aliases any existing chain? */ terminate_all_aliasing_chains (NULL, stmt); /* Start a new chain. */ - struct imm_store_chain_info *new_chain + class imm_store_chain_info *new_chain = new imm_store_chain_info (m_stores_head, base_addr); info = new store_immediate_info (const_bitsize, const_bitpos, const_bitregion_start, diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index aa5a856..d343da0 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -297,8 +297,8 @@ public: tree cached_basis; }; -typedef struct slsr_cand_d slsr_cand, *slsr_cand_t; -typedef const struct slsr_cand_d *const_slsr_cand_t; +typedef class slsr_cand_d slsr_cand, *slsr_cand_t; +typedef const class slsr_cand_d *const_slsr_cand_t; /* Pointers to candidates are chained together as part of a mapping from base expressions to the candidates that use them. */ @@ -354,7 +354,7 @@ public: basic_block init_bb; }; -typedef struct incr_info_d incr_info, *incr_info_t; +typedef class incr_info_d incr_info, *incr_info_t; /* Candidates are maintained in a vector. If candidate X dominates candidate Y, then X appears before Y in the vector; but the @@ -807,7 +807,7 @@ slsr_process_phi (gphi *phi, bool speed) unsigned i; tree arg0_base = NULL_TREE, base_type; slsr_cand_t c; - struct loop *cand_loop = gimple_bb (phi)->loop_father; + class loop *cand_loop = gimple_bb (phi)->loop_father; unsigned savings = 0; /* A CAND_PHI requires each of its arguments to have the same diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c index 73726c1..af39ff4 100644 --- a/gcc/gimple-ssa-warn-alloca.c +++ b/gcc/gimple-ssa-warn-alloca.c @@ -185,7 +185,7 @@ adjusted_warn_limit (bool idx) // MAX_SIZE is WARN_ALLOCA= adjusted for VLAs. It is the maximum size // in bytes we allow for arg. -static struct alloca_type_and_limit +static class alloca_type_and_limit alloca_call_type_by_arg (tree arg, tree arg_casted, edge e, unsigned HOST_WIDE_INT max_size) { @@ -326,7 +326,7 @@ is_max (tree x, wide_int max) // type to an unsigned type, set *INVALID_CASTED_TYPE to the // problematic signed type. -static struct alloca_type_and_limit +static class alloca_type_and_limit alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type) { gcc_assert (gimple_alloca_call_p (stmt)); @@ -459,7 +459,7 @@ alloca_call_type (gimple *stmt, bool is_vla, tree *invalid_casted_type) // If we couldn't find anything, try a few heuristics for things we // can easily determine. Check these misc cases but only accept // them if all predecessors have a known bound. - struct alloca_type_and_limit ret = alloca_type_and_limit (ALLOCA_OK); + class alloca_type_and_limit ret = alloca_type_and_limit (ALLOCA_OK); FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds) { gcc_assert (!len_casted || TYPE_UNSIGNED (TREE_TYPE (len_casted))); @@ -536,7 +536,7 @@ pass_walloca::execute (function *fun) continue; tree invalid_casted_type = NULL; - struct alloca_type_and_limit t + class alloca_type_and_limit t = alloca_call_type (stmt, is_vla, &invalid_casted_type); unsigned HOST_WIDE_INT adjusted_alloca_limit diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c index 3142b37..72a847d 100644 --- a/gcc/gimple-streamer-in.c +++ b/gcc/gimple-streamer-in.c @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see the file being read. IB is the input block to use for reading. */ static gphi * -input_phi (struct lto_input_block *ib, basic_block bb, struct data_in *data_in, +input_phi (class lto_input_block *ib, basic_block bb, class data_in *data_in, struct function *fn) { unsigned HOST_WIDE_INT ix; @@ -83,7 +83,7 @@ input_phi (struct lto_input_block *ib, basic_block bb, struct data_in *data_in, descriptors in DATA_IN. */ static gimple * -input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, +input_gimple_stmt (class lto_input_block *ib, class data_in *data_in, enum LTO_tags tag) { gimple *stmt; @@ -249,8 +249,8 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, FN is the function being processed. */ void -input_bb (struct lto_input_block *ib, enum LTO_tags tag, - struct data_in *data_in, struct function *fn, +input_bb (class lto_input_block *ib, enum LTO_tags tag, + class data_in *data_in, struct function *fn, int count_materialization_scale) { unsigned int index; diff --git a/gcc/gimple-streamer.h b/gcc/gimple-streamer.h index d0d144e..ee36192 100644 --- a/gcc/gimple-streamer.h +++ b/gcc/gimple-streamer.h @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-streamer.h" /* In gimple-streamer-in.c */ -void input_bb (struct lto_input_block *, enum LTO_tags, struct data_in *, +void input_bb (class lto_input_block *, enum LTO_tags, class data_in *, struct function *, int); /* In gimple-streamer-out.c */ diff --git a/gcc/godump.c b/gcc/godump.c index 39cce5e..ddb19fd 100644 --- a/gcc/godump.c +++ b/gcc/godump.c @@ -680,7 +680,7 @@ go_force_record_alignment (struct obstack *ob, const char *type_string, calls from go_format_type() itself. */ static bool -go_format_type (struct godump_container *container, tree type, +go_format_type (class godump_container *container, tree type, bool use_type_name, bool is_func_ok, unsigned int *p_art_i, bool is_anon_record_or_union) { @@ -1092,7 +1092,7 @@ go_format_type (struct godump_container *container, tree type, it. */ static void -go_output_type (struct godump_container *container) +go_output_type (class godump_container *container) { struct obstack *ob; @@ -1105,7 +1105,7 @@ go_output_type (struct godump_container *container) /* Output a function declaration. */ static void -go_output_fndecl (struct godump_container *container, tree decl) +go_output_fndecl (class godump_container *container, tree decl) { if (!go_format_type (container, TREE_TYPE (decl), false, true, NULL, false)) fprintf (go_dump_file, "// "); @@ -1119,7 +1119,7 @@ go_output_fndecl (struct godump_container *container, tree decl) /* Output a typedef or something like a struct definition. */ static void -go_output_typedef (struct godump_container *container, tree decl) +go_output_typedef (class godump_container *container, tree decl) { /* If we have an enum type, output the enum constants separately. */ @@ -1246,7 +1246,7 @@ go_output_typedef (struct godump_container *container, tree decl) /* Output a variable. */ static void -go_output_var (struct godump_container *container, tree decl) +go_output_var (class godump_container *container, tree decl) { bool is_valid; tree type_name; @@ -1335,7 +1335,7 @@ static const char * const keywords[] = { }; static void -keyword_hash_init (struct godump_container *container) +keyword_hash_init (class godump_container *container) { size_t i; size_t count = sizeof (keywords) / sizeof (keywords[0]); @@ -1355,7 +1355,7 @@ keyword_hash_init (struct godump_container *container) bool find_dummy_types (const char *const &ptr, godump_container *adata) { - struct godump_container *data = (struct godump_container *) adata; + class godump_container *data = (class godump_container *) adata; const char *type = (const char *) ptr; void **slot; void **islot; @@ -1372,7 +1372,7 @@ find_dummy_types (const char *const &ptr, godump_container *adata) static void go_finish (const char *filename) { - struct godump_container container; + class godump_container container; unsigned int ix; tree decl; diff --git a/gcc/graph.c b/gcc/graph.c index 33e4c03..5452822 100644 --- a/gcc/graph.c +++ b/gcc/graph.c @@ -197,7 +197,7 @@ draw_cfg_nodes_no_loops (pretty_printer *pp, struct function *fun) static void draw_cfg_nodes_for_loop (pretty_printer *pp, int funcdef_no, - struct loop *loop) + class loop *loop) { basic_block *body; unsigned int i; @@ -217,7 +217,7 @@ draw_cfg_nodes_for_loop (pretty_printer *pp, int funcdef_no, fillcolors[(loop_depth (loop) - 1) % 3], loop->num); - for (struct loop *inner = loop->inner; inner; inner = inner->next) + for (class loop *inner = loop->inner; inner; inner = inner->next) draw_cfg_nodes_for_loop (pp, funcdef_no, inner); if (loop->header == NULL) diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h index a728196..bd4249b 100644 --- a/gcc/hard-reg-set.h +++ b/gcc/hard-reg-set.h @@ -613,8 +613,8 @@ hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno) extern char global_regs[FIRST_PSEUDO_REGISTER]; -struct simplifiable_subreg; -struct subreg_shape; +class simplifiable_subreg; +class subreg_shape; struct simplifiable_subregs_hasher : nofree_ptr_hash { diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c index 424eac7..45f4149 100644 --- a/gcc/hsa-brig.c +++ b/gcc/hsa-brig.c @@ -150,9 +150,8 @@ struct hsa_brig_data_chunk /* Structure representing a BRIG section, holding and writing its data. */ -class hsa_brig_section +struct hsa_brig_section { -public: /* Section name that will be output to the BRIG. */ const char *section_name; /* Size in bytes of all data stored in the section. */ @@ -579,7 +578,7 @@ static void emit_immediate_operand (hsa_op_immed *imm); Return the offset of the directive. */ static unsigned -emit_directive_variable (struct hsa_symbol *symbol) +emit_directive_variable (class hsa_symbol *symbol) { struct BrigDirectiveVariable dirvar; unsigned name_offset; diff --git a/gcc/hsa-common.h b/gcc/hsa-common.h index 121c4ea..9122539 100644 --- a/gcc/hsa-common.h +++ b/gcc/hsa-common.h @@ -1068,7 +1068,7 @@ private: static inline hsa_bb * hsa_bb_for_bb (basic_block bb) { - return (struct hsa_bb *) bb->aux; + return (class hsa_bb *) bb->aux; } /* Class for hashing local hsa_symbols. */ @@ -1150,14 +1150,14 @@ public: hash_map m_string_constants_map; /* Vector of pointers to spill symbols. */ - vec m_spill_symbols; + vec m_spill_symbols; /* Vector of pointers to global variables and transformed string constants that are used by the function. */ - vec m_global_symbols; + vec m_global_symbols; /* Private function artificial variables. */ - vec m_private_variables; + vec m_private_variables; /* Vector of called function declarations. */ vec m_called_functions; @@ -1318,7 +1318,7 @@ hsa_internal_fn_hasher::equal (const value_type a, const compare_type b) } /* in hsa-common.c */ -extern struct hsa_function_representation *hsa_cfun; +extern class hsa_function_representation *hsa_cfun; extern hash_map *> *hsa_decl_kernel_dependencies; extern hsa_summary_t *hsa_summaries; extern hsa_symbol *hsa_num_threads; diff --git a/gcc/hsa-dump.c b/gcc/hsa-dump.c index 332d89d..2d85601 100644 --- a/gcc/hsa-dump.c +++ b/gcc/hsa-dump.c @@ -1229,7 +1229,7 @@ dump_hsa_cfun (FILE *f) FOR_ALL_BB_FN (bb, cfun) { - hsa_bb *hbb = (struct hsa_bb *) bb->aux; + hsa_bb *hbb = (class hsa_bb *) bb->aux; dump_hsa_bb (f, hbb); } } diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index 54d98a5..26e1e24 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -6070,7 +6070,7 @@ gen_function_def_parameters () for (parm = DECL_ARGUMENTS (cfun->decl); parm; parm = DECL_CHAIN (parm)) { - struct hsa_symbol **slot; + class hsa_symbol **slot; hsa_symbol *arg = new hsa_symbol (BRIG_TYPE_NONE, hsa_cfun->m_kern_p @@ -6128,7 +6128,7 @@ gen_function_def_parameters () if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl)))) { - struct hsa_symbol **slot; + class hsa_symbol **slot; hsa_cfun->m_output_arg = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_ARG, BRIG_LINKAGE_FUNCTION); diff --git a/gcc/hsa-regalloc.c b/gcc/hsa-regalloc.c index d0c1609..597bb66 100644 --- a/gcc/hsa-regalloc.c +++ b/gcc/hsa-regalloc.c @@ -256,7 +256,7 @@ dump_hsa_cfun_regalloc (FILE *f) FOR_ALL_BB_FN (bb, cfun) { - hsa_bb *hbb = (struct hsa_bb *) bb->aux; + hsa_bb *hbb = (class hsa_bb *) bb->aux; bitmap_print (dump_file, hbb->m_livein, "m_livein ", "\n"); dump_hsa_bb (f, hbb); bitmap_print (dump_file, hbb->m_liveout, "m_liveout ", "\n"); diff --git a/gcc/input.c b/gcc/input.c index baab42a..00301ef 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -124,14 +124,14 @@ public: location_t input_location = UNKNOWN_LOCATION; -struct line_maps *line_table; +class line_maps *line_table; /* A stashed copy of "line_table" for use by selftest::line_table_test. This needs to be a global so that it can be a GC root, and thus prevent the stashed copy from being garbage-collected if the GC runs during a line_table_test. */ -struct line_maps *saved_line_table; +class line_maps *saved_line_table; static fcache *fcache_tab; static const size_t fcache_tab_size = 16; @@ -980,7 +980,7 @@ dump_line_table_statistics (void) /* Get location one beyond the final location in ordinary map IDX. */ static location_t -get_end_location (struct line_maps *set, unsigned int idx) +get_end_location (class line_maps *set, unsigned int idx) { if (idx == LINEMAPS_ORDINARY_USED (set) - 1) return set->highest_location; @@ -2051,7 +2051,7 @@ test_lexer (const line_table_case &case_) /* Forward decls. */ -struct lexer_test; +class lexer_test; class lexer_test_options; /* A class for specifying options of a lexer_test. diff --git a/gcc/input.h b/gcc/input.h index 3e03820..c459bf2 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -23,8 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "line-map.h" -extern GTY(()) struct line_maps *line_table; -extern GTY(()) struct line_maps *saved_line_table; +extern GTY(()) class line_maps *line_table; +extern GTY(()) class line_maps *saved_line_table; /* A value which will never be used to represent a real location. */ #define UNKNOWN_LOCATION ((location_t) 0) diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 90f8e56..1067376 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -149,7 +149,7 @@ get_multi_vector_move (tree array_type, convert_optab optab) static void expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { - struct expand_operand ops[2]; + class expand_operand ops[2]; tree type, lhs, rhs; rtx target, mem; @@ -173,7 +173,7 @@ expand_load_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab) static void expand_store_lanes_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { - struct expand_operand ops[2]; + class expand_operand ops[2]; tree type, lhs, rhs; rtx target, reg; @@ -227,7 +227,7 @@ expand_GOMP_SIMT_ENTER_ALLOC (internal_fn, gcall *stmt) target = gen_reg_rtx (Pmode); rtx size = expand_normal (gimple_call_arg (stmt, 0)); rtx align = expand_normal (gimple_call_arg (stmt, 1)); - struct expand_operand ops[3]; + class expand_operand ops[3]; create_output_operand (&ops[0], target, Pmode); create_input_operand (&ops[1], size, Pmode); create_input_operand (&ops[2], align, Pmode); @@ -242,7 +242,7 @@ expand_GOMP_SIMT_EXIT (internal_fn, gcall *stmt) { gcc_checking_assert (!gimple_call_lhs (stmt)); rtx arg = expand_normal (gimple_call_arg (stmt, 0)); - struct expand_operand ops[1]; + class expand_operand ops[1]; create_input_operand (&ops[0], arg, Pmode); gcc_assert (targetm.have_omp_simt_exit ()); expand_insn (targetm.code_for_omp_simt_exit, 1, ops); @@ -285,7 +285,7 @@ expand_GOMP_SIMT_LAST_LANE (internal_fn, gcall *stmt) rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); rtx cond = expand_normal (gimple_call_arg (stmt, 0)); machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); - struct expand_operand ops[2]; + class expand_operand ops[2]; create_output_operand (&ops[0], target, mode); create_input_operand (&ops[1], cond, mode); gcc_assert (targetm.have_omp_simt_last_lane ()); @@ -304,7 +304,7 @@ expand_GOMP_SIMT_ORDERED_PRED (internal_fn, gcall *stmt) rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); rtx ctr = expand_normal (gimple_call_arg (stmt, 0)); machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); - struct expand_operand ops[2]; + class expand_operand ops[2]; create_output_operand (&ops[0], target, mode); create_input_operand (&ops[1], ctr, mode); gcc_assert (targetm.have_omp_simt_ordered ()); @@ -324,7 +324,7 @@ expand_GOMP_SIMT_VOTE_ANY (internal_fn, gcall *stmt) rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); rtx cond = expand_normal (gimple_call_arg (stmt, 0)); machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); - struct expand_operand ops[2]; + class expand_operand ops[2]; create_output_operand (&ops[0], target, mode); create_input_operand (&ops[1], cond, mode); gcc_assert (targetm.have_omp_simt_vote_any ()); @@ -345,7 +345,7 @@ expand_GOMP_SIMT_XCHG_BFLY (internal_fn, gcall *stmt) rtx src = expand_normal (gimple_call_arg (stmt, 0)); rtx idx = expand_normal (gimple_call_arg (stmt, 1)); machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); - struct expand_operand ops[3]; + class expand_operand ops[3]; create_output_operand (&ops[0], target, mode); create_input_operand (&ops[1], src, mode); create_input_operand (&ops[2], idx, SImode); @@ -366,7 +366,7 @@ expand_GOMP_SIMT_XCHG_IDX (internal_fn, gcall *stmt) rtx src = expand_normal (gimple_call_arg (stmt, 0)); rtx idx = expand_normal (gimple_call_arg (stmt, 1)); machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); - struct expand_operand ops[3]; + class expand_operand ops[3]; create_output_operand (&ops[0], target, mode); create_input_operand (&ops[1], src, mode); create_input_operand (&ops[2], idx, SImode); @@ -774,7 +774,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, : usubv4_optab, mode); if (icode != CODE_FOR_nothing) { - struct expand_operand ops[4]; + class expand_operand ops[4]; rtx_insn *last = get_last_insn (); res = gen_reg_rtx (mode); @@ -995,7 +995,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, : subv4_optab, mode); if (icode != CODE_FOR_nothing) { - struct expand_operand ops[4]; + class expand_operand ops[4]; rtx_insn *last = get_last_insn (); res = gen_reg_rtx (mode); @@ -1146,7 +1146,7 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan, enum insn_code icode = optab_handler (negv3_optab, mode); if (icode != CODE_FOR_nothing) { - struct expand_operand ops[3]; + class expand_operand ops[3]; rtx_insn *last = get_last_insn (); res = gen_reg_rtx (mode); @@ -1539,7 +1539,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, } if (icode != CODE_FOR_nothing) { - struct expand_operand ops[4]; + class expand_operand ops[4]; rtx_insn *last = get_last_insn (); res = gen_reg_rtx (mode); @@ -2475,7 +2475,7 @@ expand_call_mem_ref (tree type, gcall *stmt, int index) static void expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { - struct expand_operand ops[3]; + class expand_operand ops[3]; tree type, lhs, rhs, maskt; rtx mem, target, mask; insn_code icode; @@ -2510,7 +2510,7 @@ expand_mask_load_optab_fn (internal_fn, gcall *stmt, convert_optab optab) static void expand_mask_store_optab_fn (internal_fn, gcall *stmt, convert_optab optab) { - struct expand_operand ops[3]; + class expand_operand ops[3]; tree type, lhs, rhs, maskt; rtx mem, reg, mask; insn_code icode; @@ -2771,7 +2771,7 @@ expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab) HOST_WIDE_INT scale_int = tree_to_shwi (scale); rtx rhs_rtx = expand_normal (rhs); - struct expand_operand ops[6]; + class expand_operand ops[6]; int i = 0; create_address_operand (&ops[i++], base_rtx); create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset))); @@ -2805,7 +2805,7 @@ expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab) HOST_WIDE_INT scale_int = tree_to_shwi (scale); int i = 0; - struct expand_operand ops[6]; + class expand_operand ops[6]; create_output_operand (&ops[i++], lhs_rtx, TYPE_MODE (TREE_TYPE (lhs))); create_address_operand (&ops[i++], base_rtx); create_input_operand (&ops[i++], offset_rtx, TYPE_MODE (TREE_TYPE (offset))); diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index e62a9a0..0fd3650 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -381,8 +381,8 @@ static hash_map *clone_num_suffixes; /* Return the param lattices structure corresponding to the Ith formal parameter of the function described by INFO. */ -static inline struct ipcp_param_lattices * -ipa_get_parm_lattices (struct ipa_node_params *info, int i) +static inline class ipcp_param_lattices * +ipa_get_parm_lattices (class ipa_node_params *info, int i) { gcc_assert (i >= 0 && i < ipa_get_param_count (info)); gcc_checking_assert (!info->ipcp_orig_node); @@ -393,18 +393,18 @@ ipa_get_parm_lattices (struct ipa_node_params *info, int i) /* Return the lattice corresponding to the scalar value of the Ith formal parameter of the function described by INFO. */ static inline ipcp_lattice * -ipa_get_scalar_lat (struct ipa_node_params *info, int i) +ipa_get_scalar_lat (class ipa_node_params *info, int i) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); return &plats->itself; } /* Return the lattice corresponding to the scalar value of the Ith formal parameter of the function described by INFO. */ static inline ipcp_lattice * -ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i) +ipa_get_poly_ctx_lat (class ipa_node_params *info, int i) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); return &plats->ctxlat; } @@ -539,7 +539,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) fprintf (f, "\nLattices:\n"); FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { - struct ipa_node_params *info; + class ipa_node_params *info; info = IPA_NODE_REF (node); /* Skip constprop clones since we don't make lattices for them. */ @@ -550,7 +550,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) for (i = 0; i < count; i++) { struct ipcp_agg_lattice *aglat; - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); fprintf (f, " param [%d]: ", i); plats->itself.print (f, dump_sources, dump_benefits); fprintf (f, " ctxs: "); @@ -585,7 +585,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) static void determine_versionability (struct cgraph_node *node, - struct ipa_node_params *info) + class ipa_node_params *info) { const char *reason = NULL; @@ -823,7 +823,7 @@ ignore_edge_p (cgraph_edge *e) /* Allocate the arrays in TOPO and topologically sort the nodes into order. */ static void -build_toporder_info (struct ipa_topo_info *topo) +build_toporder_info (class ipa_topo_info *topo) { topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); @@ -837,7 +837,7 @@ build_toporder_info (struct ipa_topo_info *topo) TOPO. */ static void -free_toporder_info (struct ipa_topo_info *topo) +free_toporder_info (class ipa_topo_info *topo) { ipa_free_postorder_info (); free (topo->order); @@ -847,9 +847,9 @@ free_toporder_info (struct ipa_topo_info *topo) /* Add NODE to the stack in TOPO, unless it is already there. */ static inline void -push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node) +push_node_to_stack (class ipa_topo_info *topo, struct cgraph_node *node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); if (info->node_enqueued) return; info->node_enqueued = 1; @@ -860,7 +860,7 @@ push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node) is empty. */ static struct cgraph_node * -pop_node_from_stack (struct ipa_topo_info *topo) +pop_node_from_stack (class ipa_topo_info *topo) { if (topo->stack_top) { @@ -902,7 +902,7 @@ ipcp_lattice::set_contains_variable () not previously set as such. */ static inline bool -set_agg_lats_to_bottom (struct ipcp_param_lattices *plats) +set_agg_lats_to_bottom (class ipcp_param_lattices *plats) { bool ret = !plats->aggs_bottom; plats->aggs_bottom = true; @@ -913,7 +913,7 @@ set_agg_lats_to_bottom (struct ipcp_param_lattices *plats) return true if they were not previously marked as such. */ static inline bool -set_agg_lats_contain_variable (struct ipcp_param_lattices *plats) +set_agg_lats_contain_variable (class ipcp_param_lattices *plats) { bool ret = !plats->aggs_contain_variable; plats->aggs_contain_variable = true; @@ -1123,7 +1123,7 @@ ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision, return true is any of them has not been marked as such so far. */ static inline bool -set_all_contains_variable (struct ipcp_param_lattices *plats) +set_all_contains_variable (class ipcp_param_lattices *plats) { bool ret; ret = plats->itself.set_contains_variable (); @@ -1173,7 +1173,7 @@ set_single_call_flag (cgraph_node *node, void *) static void initialize_node_lattices (struct cgraph_node *node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); struct cgraph_edge *ie; bool disable = false, variable = false; int i; @@ -1203,7 +1203,7 @@ initialize_node_lattices (struct cgraph_node *node) for (i = 0; i < ipa_get_param_count (info); i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); plats->m_value_range.init (); } @@ -1211,7 +1211,7 @@ initialize_node_lattices (struct cgraph_node *node) { for (i = 0; i < ipa_get_param_count (info); i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); if (disable) { plats->itself.set_to_bottom (); @@ -1304,7 +1304,7 @@ ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input) passed. */ tree -ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc, +ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc, tree parm_type) { if (jfunc->type == IPA_JF_CONST) @@ -1422,7 +1422,7 @@ ipcp_verify_propagated_values (void) FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); int i, count = ipa_get_param_count (info); for (i = 0; i < count; i++) @@ -1674,7 +1674,7 @@ propagate_scalar_across_jump_function (struct cgraph_edge *cs, else if (jfunc->type == IPA_JF_PASS_THROUGH || jfunc->type == IPA_JF_ANCESTOR) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); ipcp_lattice *src_lat; int src_idx; bool ret; @@ -1736,7 +1736,7 @@ propagate_context_across_jump_function (cgraph_edge *cs, if (jfunc->type == IPA_JF_PASS_THROUGH || jfunc->type == IPA_JF_ANCESTOR) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); int src_idx; ipcp_lattice *src_lat; @@ -1812,7 +1812,7 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx, enum availability availability; cgraph_node *callee = cs->callee->function_symbol (&availability); - struct ipa_node_params *callee_info = IPA_NODE_REF (callee); + class ipa_node_params *callee_info = IPA_NODE_REF (callee); tree parm_type = ipa_get_type (callee_info, idx); /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the @@ -1835,7 +1835,7 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx, if (jfunc->type == IPA_JF_PASS_THROUGH || jfunc->type == IPA_JF_ANCESTOR) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); tree operand = NULL_TREE; enum tree_code code; unsigned src_idx; @@ -1855,7 +1855,7 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx, operand = build_int_cstu (size_type_node, offset); } - struct ipcp_param_lattices *src_lats + class ipcp_param_lattices *src_lats = ipa_get_parm_lattices (caller_info, src_idx); /* Try to propagate bits if src_lattice is bottom, but jfunc is known. @@ -1909,7 +1909,7 @@ ipa_vr_operation_and_type_effects (value_range_base *dst_vr, static bool propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, - struct ipcp_param_lattices *dest_plats, + class ipcp_param_lattices *dest_plats, tree param_type) { ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range; @@ -1928,10 +1928,10 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, if (TREE_CODE_CLASS (operation) == tcc_unary) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); tree operand_type = ipa_get_type (caller_info, src_idx); - struct ipcp_param_lattices *src_lats + class ipcp_param_lattices *src_lats = ipa_get_parm_lattices (caller_info, src_idx); if (src_lats->m_value_range.bottom_p ()) @@ -1974,7 +1974,7 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, aggs_by_ref to NEW_AGGS_BY_REF. */ static bool -set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats, +set_check_aggs_by_ref (class ipcp_param_lattices *dest_plats, bool new_aggs_by_ref) { if (dest_plats->aggs) @@ -2001,7 +2001,7 @@ set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats, true. */ static bool -merge_agg_lats_step (struct ipcp_param_lattices *dest_plats, +merge_agg_lats_step (class ipcp_param_lattices *dest_plats, HOST_WIDE_INT offset, HOST_WIDE_INT val_size, struct ipcp_agg_lattice ***aglat, bool pre_existing, bool *change) @@ -2079,8 +2079,8 @@ set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat) static bool merge_aggregate_lattices (struct cgraph_edge *cs, - struct ipcp_param_lattices *dest_plats, - struct ipcp_param_lattices *src_plats, + class ipcp_param_lattices *dest_plats, + class ipcp_param_lattices *src_plats, int src_idx, HOST_WIDE_INT offset_delta) { bool pre_existing = dest_plats->aggs != NULL; @@ -2134,7 +2134,7 @@ merge_aggregate_lattices (struct cgraph_edge *cs, rules about propagating values passed by reference. */ static bool -agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats, +agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats, struct ipa_jump_func *jfunc) { return src_plats->aggs @@ -2148,7 +2148,7 @@ agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats, static bool propagate_aggs_across_jump_function (struct cgraph_edge *cs, struct ipa_jump_func *jfunc, - struct ipcp_param_lattices *dest_plats) + class ipcp_param_lattices *dest_plats) { bool ret = false; @@ -2158,9 +2158,9 @@ propagate_aggs_across_jump_function (struct cgraph_edge *cs, if (jfunc->type == IPA_JF_PASS_THROUGH && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); - struct ipcp_param_lattices *src_plats; + class ipcp_param_lattices *src_plats; src_plats = ipa_get_parm_lattices (caller_info, src_idx); if (agg_pass_through_permissible_p (src_plats, jfunc)) @@ -2177,9 +2177,9 @@ propagate_aggs_across_jump_function (struct cgraph_edge *cs, else if (jfunc->type == IPA_JF_ANCESTOR && ipa_get_jf_ancestor_agg_preserved (jfunc)) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); - struct ipcp_param_lattices *src_plats; + class ipcp_param_lattices *src_plats; src_plats = ipa_get_parm_lattices (caller_info, src_idx); if (src_plats->aggs && src_plats->aggs_by_ref) @@ -2250,10 +2250,10 @@ call_passes_through_thunk_p (cgraph_edge *cs) static bool propagate_constants_across_call (struct cgraph_edge *cs) { - struct ipa_node_params *callee_info; + class ipa_node_params *callee_info; enum availability availability; cgraph_node *callee; - struct ipa_edge_args *args; + class ipa_edge_args *args; bool ret = false; int i, args_count, parms_count; @@ -2284,7 +2284,7 @@ propagate_constants_across_call (struct cgraph_edge *cs) for (; (i < args_count) && (i < parms_count); i++) { struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i); - struct ipcp_param_lattices *dest_plats; + class ipcp_param_lattices *dest_plats; tree param_type = ipa_get_type (callee_info, i); dest_plats = ipa_get_parm_lattices (callee_info, i); @@ -2563,7 +2563,7 @@ devirtualization_time_bonus (struct cgraph_node *node, for (ie = node->indirect_calls; ie; ie = ie->next_callee) { struct cgraph_node *callee; - struct ipa_fn_summary *isummary; + class ipa_fn_summary *isummary; enum availability avail; tree target; bool speculative; @@ -2645,7 +2645,7 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, gcc_assert (size_cost > 0); - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); if (max_count > profile_count::zero ()) { int factor = RDIV (count_sum.probability_in @@ -2692,7 +2692,7 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, vector. Return NULL if there are none. */ static vec * -context_independent_aggregate_values (struct ipcp_param_lattices *plats) +context_independent_aggregate_values (class ipcp_param_lattices *plats) { vec *res = NULL; @@ -2721,7 +2721,7 @@ context_independent_aggregate_values (struct ipcp_param_lattices *plats) it. */ static bool -gather_context_independent_values (struct ipa_node_params *info, +gather_context_independent_values (class ipa_node_params *info, vec *known_csts, vec *known_contexts, @@ -2746,7 +2746,7 @@ gather_context_independent_values (struct ipa_node_params *info, for (i = 0; i < count; i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); ipcp_lattice *lat = &plats->itself; if (lat->is_single_const ()) @@ -2863,7 +2863,7 @@ perform_estimation_of_a_value (cgraph_node *node, vec known_csts, static void estimate_local_effects (struct cgraph_node *node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); int i, count = ipa_get_param_count (info); vec known_csts; vec known_contexts; @@ -2943,7 +2943,7 @@ estimate_local_effects (struct cgraph_node *node) for (i = 0; i < count; i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); ipcp_lattice *lat = &plats->itself; ipcp_value *val; @@ -2977,7 +2977,7 @@ estimate_local_effects (struct cgraph_node *node) for (i = 0; i < count; i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); if (!plats->virt_call) continue; @@ -3012,7 +3012,7 @@ estimate_local_effects (struct cgraph_node *node) for (i = 0; i < count; i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipa_agg_jump_function *ajf; struct ipcp_agg_lattice *aglat; @@ -3129,12 +3129,12 @@ value_topo_info::add_val (ipcp_value *cur_val) static void add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); int i, count = ipa_get_param_count (info); for (i = 0; i < count; i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); ipcp_lattice *lat = &plats->itself; struct ipcp_agg_lattice *aglat; @@ -3169,7 +3169,7 @@ add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo) connected components. */ static void -propagate_constants_topo (struct ipa_topo_info *topo) +propagate_constants_topo (class ipa_topo_info *topo) { int i; @@ -3272,7 +3272,7 @@ value_topo_info::propagate_effects () summaries interprocedurally. */ static void -ipcp_propagate_stage (struct ipa_topo_info *topo) +ipcp_propagate_stage (class ipa_topo_info *topo) { struct cgraph_node *node; @@ -3283,12 +3283,12 @@ ipcp_propagate_stage (struct ipa_topo_info *topo) FOR_EACH_DEFINED_FUNCTION (node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); determine_versionability (node, info); if (node->has_gimple_body_p ()) { - info->lattices = XCNEWVEC (struct ipcp_param_lattices, + info->lattices = XCNEWVEC (class ipcp_param_lattices, ipa_get_param_count (info)); initialize_node_lattices (node); } @@ -3352,7 +3352,7 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node, if (cs && !agg_contents && !polymorphic) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); int c = ipa_get_controlled_uses (info, param_index); if (c != IPA_UNDESCRIBED_USE) { @@ -3461,7 +3461,7 @@ same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest) if (node == dest) return true; - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); return info->is_all_contexts_clone && info->ipcp_orig_node == dest; } @@ -3472,7 +3472,7 @@ static bool cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source *src, cgraph_node *dest, ipcp_value *dest_val) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); enum availability availability; cgraph_node *real_dest = cs->callee->function_symbol (&availability); @@ -3503,7 +3503,7 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source *src, return true; struct ipcp_agg_lattice *aglat; - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, + class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, src->index); if (src->offset == -1) return (plats->itself.is_single_const () @@ -3532,7 +3532,7 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, cgraph_node *dest, ipcp_value *) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); cgraph_node *real_dest = cs->callee->function_symbol (); if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) @@ -3546,7 +3546,7 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, && values_equal_for_ipcp_p (src->val->value, caller_info->known_contexts[src->index]); - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, + class ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, src->index); return plats->ctxlat.is_single_const () && values_equal_for_ipcp_p (src->val->value, @@ -3639,7 +3639,7 @@ gather_edges_for_value (ipcp_value *val, cgraph_node *dest, Return it or NULL if for some reason it cannot be created. */ static struct ipa_replace_map * -get_replacement_map (struct ipa_node_params *info, tree value, int parm_num) +get_replacement_map (class ipa_node_params *info, tree value, int parm_num) { struct ipa_replace_map *replace_map; @@ -3808,7 +3808,7 @@ create_specialized_node (struct cgraph_node *node, struct ipa_agg_replacement_value *aggvals, vec callers) { - struct ipa_node_params *new_info, *info = IPA_NODE_REF (node); + class ipa_node_params *new_info, *info = IPA_NODE_REF (node); vec *replace_trees = NULL; struct ipa_agg_replacement_value *av; struct cgraph_node *new_node; @@ -3942,7 +3942,7 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node, vec known_csts, vec callers) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); int i, count = ipa_get_param_count (info); for (i = 0; i < count; i++) @@ -4075,7 +4075,7 @@ find_more_contexts_for_caller_subset (cgraph_node *node, offsets (minus OFFSET) of lattices that contain only a single value. */ static vec -copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset) +copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset) { vec res = vNULL; @@ -4097,7 +4097,7 @@ copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset) subtracting OFFSET). */ static void -intersect_with_plats (struct ipcp_param_lattices *plats, +intersect_with_plats (class ipcp_param_lattices *plats, vec *inter, HOST_WIDE_INT offset) { @@ -4217,13 +4217,13 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, if (jfunc->type == IPA_JF_PASS_THROUGH && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); if (caller_info->ipcp_orig_node) { struct cgraph_node *orig_node = caller_info->ipcp_orig_node; - struct ipcp_param_lattices *orig_plats; + class ipcp_param_lattices *orig_plats; orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node), src_idx); if (agg_pass_through_permissible_p (orig_plats, jfunc)) @@ -4242,7 +4242,7 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, } else { - struct ipcp_param_lattices *src_plats; + class ipcp_param_lattices *src_plats; src_plats = ipa_get_parm_lattices (caller_info, src_idx); if (agg_pass_through_permissible_p (src_plats, jfunc)) { @@ -4264,9 +4264,9 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, else if (jfunc->type == IPA_JF_ANCESTOR && ipa_get_jf_ancestor_agg_preserved (jfunc)) { - struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); - struct ipcp_param_lattices *src_plats; + class ipcp_param_lattices *src_plats; HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc); if (caller_info->ipcp_orig_node) @@ -4341,7 +4341,7 @@ static struct ipa_agg_replacement_value * find_aggregate_values_for_callers_subset (struct cgraph_node *node, vec callers) { - struct ipa_node_params *dest_info = IPA_NODE_REF (node); + class ipa_node_params *dest_info = IPA_NODE_REF (node); struct ipa_agg_replacement_value *res; struct ipa_agg_replacement_value **tail = &res; struct cgraph_edge *cs; @@ -4359,7 +4359,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, struct cgraph_edge *cs; vec inter = vNULL; struct ipa_agg_jf_item *item; - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); int j; /* Among other things, the following check should deal with all by_ref @@ -4412,10 +4412,10 @@ static bool cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, struct cgraph_node *node) { - struct ipa_node_params *dest_info = IPA_NODE_REF (node); + class ipa_node_params *dest_info = IPA_NODE_REF (node); int count = ipa_get_param_count (dest_info); - struct ipa_node_params *caller_info; - struct ipa_edge_args *args; + class ipa_node_params *caller_info; + class ipa_edge_args *args; int i; caller_info = IPA_NODE_REF (cs->caller); @@ -4446,7 +4446,7 @@ static bool cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, struct cgraph_node *node) { - struct ipa_node_params *orig_node_info; + class ipa_node_params *orig_node_info; struct ipa_agg_replacement_value *aggval; int i, ec, count; @@ -4466,7 +4466,7 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, for (i = 0; i < count; i++) { static vec values = vec(); - struct ipcp_param_lattices *plats; + class ipcp_param_lattices *plats; bool interesting = false; for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) if (aggval->index == i) @@ -4722,7 +4722,7 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, static bool decide_whether_version_node (struct cgraph_node *node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); int i, count = ipa_get_param_count (info); vec known_csts; vec known_contexts; @@ -4742,7 +4742,7 @@ decide_whether_version_node (struct cgraph_node *node) for (i = 0; i < count;i++) { - struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); ipcp_lattice *lat = &plats->itself; ipcp_lattice *ctxlat = &plats->ctxlat; @@ -4832,7 +4832,7 @@ spread_undeadness (struct cgraph_node *node) if (ipa_edge_within_scc (cs)) { struct cgraph_node *callee; - struct ipa_node_params *info; + class ipa_node_params *info; callee = cs->callee->function_symbol (NULL); info = IPA_NODE_REF (callee); @@ -4895,7 +4895,7 @@ identify_dead_nodes (struct cgraph_node *node) TOPO and make specialized clones if deemed beneficial. */ static void -ipcp_decision_stage (struct ipa_topo_info *topo) +ipcp_decision_stage (class ipa_topo_info *topo) { int i; @@ -5069,7 +5069,7 @@ ipcp_store_vr_results (void) static unsigned int ipcp_driver (void) { - struct ipa_topo_info topo; + class ipa_topo_info topo; if (edge_clone_summaries == NULL) edge_clone_summaries = new edge_clone_summary_t (symtab); diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index a5e3a63..95e2d95 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -2974,7 +2974,7 @@ final_warning_record::grow_type_warnings (unsigned newlen) } } -struct final_warning_record *final_warning_records; +class final_warning_record *final_warning_records; /* Return vector containing possible targets of polymorphic call of type OTR_TYPE calling method OTR_TOKEN within type of OTR_OUTER_TYPE and OFFSET. diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 160261d..0998621 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -212,7 +212,7 @@ ipa_fn_summary::account_size_time (int size, sreal time, } if (!found) { - struct size_time_entry new_entry; + class size_time_entry new_entry; new_entry.size = size; new_entry.time = time; new_entry.exec_predicate = exec_pred; @@ -241,7 +241,7 @@ redirect_to_unreachable (struct cgraph_edge *e) e->make_direct (target); else e->redirect_callee (target); - struct ipa_call_summary *es = ipa_call_summaries->get (e); + class ipa_call_summary *es = ipa_call_summaries->get (e); e->inline_failed = CIF_UNREACHABLE; e->count = profile_count::zero (); es->call_stmt_size = 0; @@ -266,7 +266,7 @@ edge_set_predicate (struct cgraph_edge *e, predicate *predicate) && (!e->speculative || e->callee)) e = redirect_to_unreachable (e); - struct ipa_call_summary *es = ipa_call_summaries->get (e); + class ipa_call_summary *es = ipa_call_summaries->get (e); if (predicate && *predicate != true) { if (!es->predicate) @@ -328,7 +328,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, { clause_t clause = inline_p ? 0 : 1 << predicate::not_inlined_condition; clause_t nonspec_clause = 1 << predicate::not_inlined_condition; - struct ipa_fn_summary *info = ipa_fn_summaries->get (node); + class ipa_fn_summary *info = ipa_fn_summaries->get (node); int i; struct condition *c; @@ -428,7 +428,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, vec *known_aggs_ptr) { struct cgraph_node *callee = e->callee->ultimate_alias_target (); - struct ipa_fn_summary *info = ipa_fn_summaries->get (callee); + class ipa_fn_summary *info = ipa_fn_summaries->get (callee); vec known_vals = vNULL; vec known_aggs = vNULL; @@ -443,9 +443,9 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, && !e->call_stmt_cannot_inline_p && ((clause_ptr && info->conds) || known_vals_ptr || known_contexts_ptr)) { - struct ipa_node_params *caller_parms_info, *callee_pi; - struct ipa_edge_args *args = IPA_EDGE_REF (e); - struct ipa_call_summary *es = ipa_call_summaries->get (e); + class ipa_node_params *caller_parms_info, *callee_pi; + class ipa_edge_args *args = IPA_EDGE_REF (e); + class ipa_call_summary *es = ipa_call_summaries->get (e); int i, count = ipa_get_cs_argument_count (args); if (e->caller->global.inlined_to) @@ -604,7 +604,7 @@ ipa_fn_summary_t::duplicate (cgraph_node *src, { vec *entry = info->size_time_table; /* Use SRC parm info since it may not be copied yet. */ - struct ipa_node_params *parms_info = IPA_NODE_REF (src); + class ipa_node_params *parms_info = IPA_NODE_REF (src); vec known_vals = vNULL; int count = ipa_get_param_count (parms_info); int i, j; @@ -668,7 +668,7 @@ ipa_fn_summary_t::duplicate (cgraph_node *src, for (edge = dst->callees; edge; edge = next) { predicate new_predicate; - struct ipa_call_summary *es = ipa_call_summaries->get_create (edge); + class ipa_call_summary *es = ipa_call_summaries->get_create (edge); next = edge->next_callee; if (!edge->inline_failed) @@ -687,7 +687,7 @@ ipa_fn_summary_t::duplicate (cgraph_node *src, for (edge = dst->indirect_calls; edge; edge = next) { predicate new_predicate; - struct ipa_call_summary *es = ipa_call_summaries->get_create (edge); + class ipa_call_summary *es = ipa_call_summaries->get_create (edge); next = edge->next_callee; gcc_checking_assert (edge->inline_failed); @@ -744,8 +744,8 @@ ipa_fn_summary_t::duplicate (cgraph_node *src, void ipa_call_summary_t::duplicate (struct cgraph_edge *src, struct cgraph_edge *dst, - struct ipa_call_summary *srcinfo, - struct ipa_call_summary *info) + class ipa_call_summary *srcinfo, + class ipa_call_summary *info) { new (info) ipa_call_summary (*srcinfo); info->predicate = NULL; @@ -765,12 +765,12 @@ ipa_call_summary_t::duplicate (struct cgraph_edge *src, static void dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node, - struct ipa_fn_summary *info) + class ipa_fn_summary *info) { struct cgraph_edge *edge; for (edge = node->callees; edge; edge = edge->next_callee) { - struct ipa_call_summary *es = ipa_call_summaries->get (edge); + class ipa_call_summary *es = ipa_call_summaries->get (edge); struct cgraph_node *callee = edge->callee->ultimate_alias_target (); int i; @@ -821,7 +821,7 @@ dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node, } for (edge = node->indirect_calls; edge; edge = edge->next_callee) { - struct ipa_call_summary *es = ipa_call_summaries->get (edge); + class ipa_call_summary *es = ipa_call_summaries->get (edge); fprintf (f, "%*sindirect call loop depth:%2i freq:%4.2f size:%2i" " time: %2i", indent, "", @@ -844,7 +844,7 @@ ipa_dump_fn_summary (FILE *f, struct cgraph_node *node) { if (node->definition) { - struct ipa_fn_summary *s = ipa_fn_summaries->get (node); + class ipa_fn_summary *s = ipa_fn_summaries->get (node); if (s != NULL) { size_time_entry *e; @@ -1183,7 +1183,7 @@ eliminated_by_inlining_prob (ipa_func_body_info *fbi, gimple *stmt) static void set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, - struct ipa_fn_summary *summary, + class ipa_fn_summary *summary, basic_block bb) { gimple *last; @@ -1268,7 +1268,7 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi, static void set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, - struct ipa_fn_summary *summary, + class ipa_fn_summary *summary, basic_block bb) { gimple *lastg; @@ -1322,8 +1322,8 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, unshare_expr_without_location (max)); p = p1 & p2; } - *(struct predicate *) e->aux - = p.or_with (summary->conds, *(struct predicate *) e->aux); + *(class predicate *) e->aux + = p.or_with (summary->conds, *(class predicate *) e->aux); } } @@ -1334,7 +1334,7 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi, static void compute_bb_predicates (struct ipa_func_body_info *fbi, struct cgraph_node *node, - struct ipa_fn_summary *summary) + class ipa_fn_summary *summary) { struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); bool done = false; @@ -1368,7 +1368,7 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, predicate this_bb_predicate = *(predicate *) e->src->aux; if (e->aux) - this_bb_predicate &= (*(struct predicate *) e->aux); + this_bb_predicate &= (*(class predicate *) e->aux); p = p.or_with (summary->conds, this_bb_predicate); if (p == true) break; @@ -1407,7 +1407,7 @@ compute_bb_predicates (struct ipa_func_body_info *fbi, static predicate will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, - struct ipa_fn_summary *summary, + class ipa_fn_summary *summary, tree expr, vec nonconstant_names) { @@ -1478,7 +1478,7 @@ will_be_nonconstant_expr_predicate (ipa_func_body_info *fbi, static predicate will_be_nonconstant_predicate (struct ipa_func_body_info *fbi, - struct ipa_fn_summary *summary, + class ipa_fn_summary *summary, gimple *stmt, vec nonconstant_names) { @@ -1586,7 +1586,7 @@ struct record_modified_bb_info static basic_block get_minimal_bb (basic_block init_bb, basic_block use_bb) { - struct loop *l = find_common_loop (init_bb->loop_father, use_bb->loop_father); + class loop *l = find_common_loop (init_bb->loop_father, use_bb->loop_father); if (l && l->header->count < init_bb->count) return l->header; return init_bb; @@ -1797,7 +1797,7 @@ phi_result_unknown_predicate (ipa_func_body_info *fbi, NONCONSTANT_NAMES, if possible. */ static void -predicate_for_phi_result (struct ipa_fn_summary *summary, gphi *phi, +predicate_for_phi_result (class ipa_fn_summary *summary, gphi *phi, predicate *p, vec nonconstant_names) { @@ -1995,7 +1995,7 @@ analyze_function_body (struct cgraph_node *node, bool early) basic_block bb; struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); sreal freq; - struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node); + class ipa_fn_summary *info = ipa_fn_summaries->get_create (node); predicate bb_predicate; struct ipa_func_body_info fbi; vec nonconstant_names = vNULL; @@ -2236,7 +2236,7 @@ analyze_function_body (struct cgraph_node *node, bool early) if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "\t\tWill be eliminated by inlining\n"); - struct predicate p = bb_predicate & will_be_nonconstant; + class predicate p = bb_predicate & will_be_nonconstant; /* We can ignore statement when we proved it is never going to happen, but we cannot do that for call statements @@ -2285,7 +2285,7 @@ analyze_function_body (struct cgraph_node *node, bool early) if (nonconstant_names.exists () && !early) { - struct loop *loop; + class loop *loop; predicate loop_iterations = true; predicate loop_stride = true; @@ -2297,7 +2297,7 @@ analyze_function_body (struct cgraph_node *node, bool early) vec exits; edge ex; unsigned int j; - struct tree_niter_desc niter_desc; + class tree_niter_desc niter_desc; bb_predicate = *(predicate *) loop->header->aux; exits = get_loop_exit_edges (loop); @@ -2413,7 +2413,7 @@ compute_fn_summary (struct cgraph_node *node, bool early) { HOST_WIDE_INT self_stack_size; struct cgraph_edge *e; - struct ipa_fn_summary *info; + class ipa_fn_summary *info; gcc_assert (!node->global.inlined_to); @@ -2539,7 +2539,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, { tree target; struct cgraph_node *callee; - struct ipa_fn_summary *isummary; + class ipa_fn_summary *isummary; enum availability avail; bool speculative; @@ -2587,7 +2587,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size, vec known_aggs, ipa_hints *hints) { - struct ipa_call_summary *es = ipa_call_summaries->get (e); + class ipa_call_summary *es = ipa_call_summaries->get (e); int call_size = es->call_stmt_size; int call_time = es->call_stmt_time; int cur_size; @@ -2624,7 +2624,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, struct cgraph_edge *e; for (e = node->callees; e; e = e->next_callee) { - struct ipa_call_summary *es = ipa_call_summaries->get_create (e); + class ipa_call_summary *es = ipa_call_summaries->get_create (e); /* Do not care about zero sized builtins. */ if (e->inline_failed && !es->call_stmt_size) @@ -2655,7 +2655,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, } for (e = node->indirect_calls; e; e = e->next_callee) { - struct ipa_call_summary *es = ipa_call_summaries->get_create (e); + class ipa_call_summary *es = ipa_call_summaries->get_create (e); if (!es->predicate || es->predicate->evaluate (possible_truths)) estimate_edge_size_and_time (e, size, @@ -2690,7 +2690,7 @@ estimate_node_size_and_time (struct cgraph_node *node, vec inline_param_summary) { - struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node); + class ipa_fn_summary *info = ipa_fn_summaries->get_create (node); size_time_entry *e; int size = 0; sreal time = 0; @@ -2881,9 +2881,9 @@ remap_edge_change_prob (struct cgraph_edge *inlined_edge, if (ipa_node_params_sum) { int i; - struct ipa_edge_args *args = IPA_EDGE_REF (edge); - struct ipa_call_summary *es = ipa_call_summaries->get (edge); - struct ipa_call_summary *inlined_es + class ipa_edge_args *args = IPA_EDGE_REF (edge); + class ipa_call_summary *es = ipa_call_summaries->get (edge); + class ipa_call_summary *inlined_es = ipa_call_summaries->get (inlined_edge); if (es->param.length () == 0) @@ -2924,8 +2924,8 @@ remap_edge_change_prob (struct cgraph_edge *inlined_edge, static void remap_edge_summaries (struct cgraph_edge *inlined_edge, struct cgraph_node *node, - struct ipa_fn_summary *info, - struct ipa_fn_summary *callee_info, + class ipa_fn_summary *info, + class ipa_fn_summary *callee_info, vec operand_map, vec offset_map, clause_t possible_truths, @@ -2934,7 +2934,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, struct cgraph_edge *e, *next; for (e = node->callees; e; e = next) { - struct ipa_call_summary *es = ipa_call_summaries->get (e); + class ipa_call_summary *es = ipa_call_summaries->get (e); predicate p; next = e->next_callee; @@ -2960,7 +2960,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, } for (e = node->indirect_calls; e; e = next) { - struct ipa_call_summary *es = ipa_call_summaries->get (e); + class ipa_call_summary *es = ipa_call_summaries->get (e); predicate p; next = e->next_callee; @@ -2980,8 +2980,8 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, /* Same as remap_predicate, but set result into hint *HINT. */ static void -remap_hint_predicate (struct ipa_fn_summary *info, - struct ipa_fn_summary *callee_info, +remap_hint_predicate (class ipa_fn_summary *info, + class ipa_fn_summary *callee_info, predicate **hint, vec operand_map, vec offset_map, @@ -3013,7 +3013,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) ipa_fn_summary *callee_info = ipa_fn_summaries->get (edge->callee); struct cgraph_node *to = (edge->caller->global.inlined_to ? edge->caller->global.inlined_to : edge->caller); - struct ipa_fn_summary *info = ipa_fn_summaries->get (to); + class ipa_fn_summary *info = ipa_fn_summaries->get (to); clause_t clause = 0; /* not_inline is known to be false. */ size_time_entry *e; vec operand_map = vNULL; @@ -3021,7 +3021,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) int i; predicate toplev_predicate; predicate true_p = true; - struct ipa_call_summary *es = ipa_call_summaries->get (edge); + class ipa_call_summary *es = ipa_call_summaries->get (edge); if (es->predicate) toplev_predicate = *es->predicate; @@ -3034,7 +3034,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) evaluate_properties_for_edge (edge, true, &clause, NULL, NULL, NULL, NULL); if (ipa_node_params_sum && callee_info->conds) { - struct ipa_edge_args *args = IPA_EDGE_REF (edge); + class ipa_edge_args *args = IPA_EDGE_REF (edge); int count = ipa_get_cs_argument_count (args); int i; @@ -3127,7 +3127,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) void ipa_update_overall_fn_summary (struct cgraph_node *node) { - struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node); + class ipa_fn_summary *info = ipa_fn_summaries->get_create (node); size_time_entry *e; int i; @@ -3223,10 +3223,10 @@ ipa_fn_summary_generate (void) /* Write inline summary for edge E to OB. */ static void -read_ipa_call_summary (struct lto_input_block *ib, struct cgraph_edge *e, +read_ipa_call_summary (class lto_input_block *ib, struct cgraph_edge *e, bool prevails) { - struct ipa_call_summary *es = prevails + class ipa_call_summary *es = prevails ? ipa_call_summaries->get_create (e) : NULL; predicate p; int length, i; @@ -3277,7 +3277,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, const int cfg_offset = sizeof (struct lto_function_header); const int main_offset = cfg_offset + header->cfg_size; const int string_offset = main_offset + header->main_size; - struct data_in *data_in; + class data_in *data_in; unsigned int i, count2, j; unsigned int f_count; @@ -3292,7 +3292,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, { unsigned int index; struct cgraph_node *node; - struct ipa_fn_summary *info; + class ipa_fn_summary *info; lto_symtab_encoder_t encoder; struct bitpack_d bp; struct cgraph_edge *e; @@ -3349,7 +3349,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, gcc_assert (!info || !info->size_time_table); for (j = 0; j < count2; j++) { - struct size_time_entry e; + class size_time_entry e; e.size = streamer_read_uhwi (&ib); e.time = sreal::stream_in (&ib); @@ -3423,7 +3423,7 @@ ipa_fn_summary_read (void) static void write_ipa_call_summary (struct output_block *ob, struct cgraph_edge *e) { - struct ipa_call_summary *es = ipa_call_summaries->get (e); + class ipa_call_summary *es = ipa_call_summaries->get (e); int i; streamer_write_uhwi (ob, es->call_stmt_size); @@ -3471,7 +3471,7 @@ ipa_fn_summary_write (void) cgraph_node *cnode = dyn_cast (snode); if (cnode && cnode->definition && !cnode->alias) { - struct ipa_fn_summary *info = ipa_fn_summaries->get (cnode); + class ipa_fn_summary *info = ipa_fn_summaries->get (cnode); struct bitpack_d bp; struct cgraph_edge *edge; int i; diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h index 7b07704..55bc341 100644 --- a/gcc/ipa-fnsummary.h +++ b/gcc/ipa-fnsummary.h @@ -184,7 +184,7 @@ public: static ipa_fn_summary_t *create_ggc (symbol_table *symtab) { - struct ipa_fn_summary_t *summary = new (ggc_alloc ()) + class ipa_fn_summary_t *summary = new (ggc_alloc ()) ipa_fn_summary_t (symtab); summary->disable_insertion_hook (); return summary; diff --git a/gcc/ipa-hsa.c b/gcc/ipa-hsa.c index b48f94b..8af1d73 100644 --- a/gcc/ipa-hsa.c +++ b/gcc/ipa-hsa.c @@ -221,7 +221,7 @@ ipa_hsa_read_section (struct lto_file_decl_data *file_data, const char *data, const int cfg_offset = sizeof (struct lto_function_header); const int main_offset = cfg_offset + header->cfg_size; const int string_offset = main_offset + header->main_size; - struct data_in *data_in; + class data_in *data_in; unsigned int i; unsigned int count; diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c index 0713e12..4060c0e 100644 --- a/gcc/ipa-icf-gimple.c +++ b/gcc/ipa-icf-gimple.c @@ -614,8 +614,8 @@ func_checker::compare_loops (basic_block bb1, basic_block bb2) if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL)) return return_false (); - struct loop *l1 = bb1->loop_father; - struct loop *l2 = bb2->loop_father; + class loop *l1 = bb1->loop_father; + class loop *l2 = bb2->loop_father; if (l1 == NULL) return true; diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 7c486ed..2174fb7 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -482,7 +482,7 @@ sem_function::param_used_p (unsigned int i) if (ipa_node_params_sum == NULL) return true; - struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ()); + class ipa_node_params *parms_info = IPA_NODE_REF (get_node ()); if (vec_safe_length (parms_info->descriptors) <= i) return true; diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 6c77f32..a66af27 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -128,7 +128,7 @@ do_estimate_edge_time (struct cgraph_edge *edge) vec known_vals; vec known_contexts; vec known_aggs; - struct ipa_call_summary *es = ipa_call_summaries->get (edge); + class ipa_call_summary *es = ipa_call_summaries->get (edge); int min_size; callee = edge->callee->ultimate_alias_target (); @@ -264,7 +264,7 @@ int estimate_size_after_inlining (struct cgraph_node *node, struct cgraph_edge *edge) { - struct ipa_call_summary *es = ipa_call_summaries->get (edge); + class ipa_call_summary *es = ipa_call_summaries->get (edge); ipa_fn_summary *s = ipa_fn_summaries->get (node); if (!es->predicate || *es->predicate != false) { @@ -321,7 +321,7 @@ int estimate_growth (struct cgraph_node *node) { struct growth_data d = { node, false, false, 0 }; - struct ipa_fn_summary *info = ipa_fn_summaries->get (node); + class ipa_fn_summary *info = ipa_fn_summaries->get (node); node->call_for_symbol_and_aliases (do_estimate_growth_1, &d, true); diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 3475258..939d86e 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -1037,7 +1037,7 @@ edge_badness (struct cgraph_edge *edge, bool dump) int growth; sreal edge_time, unspec_edge_time; struct cgraph_node *callee = edge->callee->ultimate_alias_target (); - struct ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee); + class ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee); ipa_hints hints; cgraph_node *caller = (edge->caller->global.inlined_to ? edge->caller->global.inlined_to @@ -1799,7 +1799,7 @@ inline_small_functions (void) && (node->has_gimple_body_p () || node->thunk.thunk_p) && opt_for_fn (node->decl, optimize)) { - struct ipa_fn_summary *info = ipa_fn_summaries->get (node); + class ipa_fn_summary *info = ipa_fn_summaries->get (node); struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->aux; /* Do not account external functions, they will be optimized out diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c index 75d8ebc..705af03 100644 --- a/gcc/ipa-polymorphic-call.c +++ b/gcc/ipa-polymorphic-call.c @@ -688,8 +688,8 @@ ipa_polymorphic_call_context::stream_out (struct output_block *ob) const /* Stream in the context from IB and DATA_IN. */ void -ipa_polymorphic_call_context::stream_in (struct lto_input_block *ib, - struct data_in *data_in) +ipa_polymorphic_call_context::stream_in (class lto_input_block *ib, + class data_in *data_in) { struct bitpack_d bp = streamer_read_bitpack (ib); diff --git a/gcc/ipa-predicate.c b/gcc/ipa-predicate.c index 3b7c4df..49622e9 100644 --- a/gcc/ipa-predicate.c +++ b/gcc/ipa-predicate.c @@ -398,8 +398,8 @@ predicate::remap_after_duplication (clause_t possible_truths) for other purposes). */ predicate -predicate::remap_after_inlining (struct ipa_fn_summary *info, - struct ipa_fn_summary *callee_info, +predicate::remap_after_inlining (class ipa_fn_summary *info, + class ipa_fn_summary *callee_info, vec operand_map, vec offset_map, clause_t possible_truths, @@ -483,7 +483,7 @@ predicate::remap_after_inlining (struct ipa_fn_summary *info, /* Read predicate from IB. */ void -predicate::stream_in (struct lto_input_block *ib) +predicate::stream_in (class lto_input_block *ib) { clause_t clause; int k = 0; @@ -522,7 +522,7 @@ predicate::stream_out (struct output_block *ob) It can be NULL, which means this not a load from an aggregate. */ predicate -add_condition (struct ipa_fn_summary *summary, int operand_num, +add_condition (class ipa_fn_summary *summary, int operand_num, HOST_WIDE_INT size, struct agg_position_info *aggpos, enum tree_code code, tree val) { diff --git a/gcc/ipa-predicate.h b/gcc/ipa-predicate.h index e97754c..c2adba3 100644 --- a/gcc/ipa-predicate.h +++ b/gcc/ipa-predicate.h @@ -205,11 +205,11 @@ public: predicate remap_after_duplication (clause_t); /* Return predicate equal to THIS after inlining. */ - predicate remap_after_inlining (struct ipa_fn_summary *, - struct ipa_fn_summary *, + predicate remap_after_inlining (class ipa_fn_summary *, + class ipa_fn_summary *, vec, vec, clause_t, const predicate &); - void stream_in (struct lto_input_block *); + void stream_in (class lto_input_block *); void stream_out (struct output_block *); private: @@ -227,6 +227,6 @@ private: }; void dump_condition (FILE *f, conditions conditions, int cond); -predicate add_condition (struct ipa_fn_summary *summary, int operand_num, +predicate add_condition (class ipa_fn_summary *summary, int operand_num, HOST_WIDE_INT size, struct agg_position_info *aggpos, enum tree_code code, tree val); diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index c80ea7a..1fb939b 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -258,7 +258,7 @@ ipa_profile_read_summary (void) { const char *data; size_t len; - struct lto_input_block *ib + class lto_input_block *ib = lto_create_simple_input_block (file_data, LTO_section_ipa_profile, &data, &len); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index f5f8c75..344b78e 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -203,7 +203,7 @@ ipa_get_param_decl_index_1 (vec *descriptors, to INFO. */ int -ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree) +ipa_get_param_decl_index (class ipa_node_params *info, tree ptree) { return ipa_get_param_decl_index_1 (info->descriptors, ptree); } @@ -253,7 +253,7 @@ count_formal_params (tree fndecl) using ipa_initialize_node_params. */ void -ipa_dump_param (FILE *file, struct ipa_node_params *info, int i) +ipa_dump_param (FILE *file, class ipa_node_params *info, int i) { fprintf (file, "param #%i", i); if ((*info->descriptors)[i].decl_or_type) @@ -269,7 +269,7 @@ ipa_dump_param (FILE *file, struct ipa_node_params *info, int i) static bool ipa_alloc_node_params (struct cgraph_node *node, int param_count) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); if (!info->descriptors && param_count) { @@ -287,7 +287,7 @@ ipa_alloc_node_params (struct cgraph_node *node, int param_count) void ipa_initialize_node_params (struct cgraph_node *node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); if (!info->descriptors && ipa_alloc_node_params (node, count_formal_params (node->decl))) @@ -375,7 +375,7 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs) } } - struct ipa_polymorphic_call_context *ctx + class ipa_polymorphic_call_context *ctx = ipa_get_ith_polymorhic_call_context (IPA_EDGE_REF (cs), i); if (ctx && !ctx->useless_p ()) { @@ -432,7 +432,7 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) for (cs = node->indirect_calls; cs; cs = cs->next_callee) { - struct cgraph_indirect_call_info *ii; + class cgraph_indirect_call_info *ii; if (!ipa_edge_args_info_available_for_edge_p (cs)) continue; @@ -1190,7 +1190,7 @@ ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, static void compute_complex_assign_jump_func (struct ipa_func_body_info *fbi, - struct ipa_node_params *info, + class ipa_node_params *info, struct ipa_jump_func *jfunc, gcall *call, gimple *stmt, tree name, tree param_type) @@ -1346,7 +1346,7 @@ get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset) static void compute_complex_ancestor_jump_func (struct ipa_func_body_info *fbi, - struct ipa_node_params *info, + class ipa_node_params *info, struct ipa_jump_func *jfunc, gcall *call, gphi *phi) { @@ -1855,8 +1855,8 @@ static void ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, struct cgraph_edge *cs) { - struct ipa_node_params *info = IPA_NODE_REF (cs->caller); - struct ipa_edge_args *args = IPA_EDGE_REF (cs); + class ipa_node_params *info = IPA_NODE_REF (cs->caller); + class ipa_edge_args *args = IPA_EDGE_REF (cs); gcall *call = cs->call_stmt; int n, arg_num = gimple_call_num_args (call); bool useful_context = false; @@ -1880,7 +1880,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi, if (flag_devirtualize && POINTER_TYPE_P (TREE_TYPE (arg))) { tree instance; - struct ipa_polymorphic_call_context context (cs->caller->decl, + class ipa_polymorphic_call_context context (cs->caller->decl, arg, cs->call_stmt, &instance); context.get_dynamic_type (instance, arg, NULL, cs->call_stmt, @@ -2197,7 +2197,7 @@ static void ipa_analyze_indirect_call_uses (struct ipa_func_body_info *fbi, gcall *call, tree target) { - struct ipa_node_params *info = fbi->info; + class ipa_node_params *info = fbi->info; HOST_WIDE_INT offset; bool by_ref; @@ -2348,7 +2348,7 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi, if (TREE_CODE (obj) != SSA_NAME) return; - struct ipa_node_params *info = fbi->info; + class ipa_node_params *info = fbi->info; if (SSA_NAME_IS_DEFAULT_DEF (obj)) { struct ipa_jump_func jfunc; @@ -2380,7 +2380,7 @@ ipa_analyze_virtual_call_uses (struct ipa_func_body_info *fbi, } struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call); - struct cgraph_indirect_call_info *ii = cs->indirect_info; + class cgraph_indirect_call_info *ii = cs->indirect_info; ii->offset = anc_offset; ii->otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target)); ii->otr_type = obj_type_ref_class (target); @@ -2452,7 +2452,7 @@ ipa_analyze_stmt_uses (struct ipa_func_body_info *fbi, gimple *stmt) static bool visit_ref_for_mod_analysis (gimple *, tree op, tree, void *data) { - struct ipa_node_params *info = (struct ipa_node_params *) data; + class ipa_node_params *info = (class ipa_node_params *) data; op = get_base_address (op); if (op @@ -2500,7 +2500,7 @@ ipa_analyze_params_uses_in_bb (struct ipa_func_body_info *fbi, basic_block bb) static void ipa_analyze_controlled_uses (struct cgraph_node *node) { - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); for (int i = 0; i < ipa_get_param_count (info); i++) { @@ -2592,7 +2592,7 @@ void ipa_analyze_node (struct cgraph_node *node) { struct ipa_func_body_info fbi; - struct ipa_node_params *info; + class ipa_node_params *info; ipa_check_create_node_params (); ipa_check_create_edge_args (); @@ -2652,22 +2652,22 @@ static void update_jump_functions_after_inlining (struct cgraph_edge *cs, struct cgraph_edge *e) { - struct ipa_edge_args *top = IPA_EDGE_REF (cs); - struct ipa_edge_args *args = IPA_EDGE_REF (e); + class ipa_edge_args *top = IPA_EDGE_REF (cs); + class ipa_edge_args *args = IPA_EDGE_REF (e); int count = ipa_get_cs_argument_count (args); int i; for (i = 0; i < count; i++) { struct ipa_jump_func *dst = ipa_get_ith_jump_func (args, i); - struct ipa_polymorphic_call_context *dst_ctx + class ipa_polymorphic_call_context *dst_ctx = ipa_get_ith_polymorhic_call_context (args, i); if (dst->type == IPA_JF_ANCESTOR) { struct ipa_jump_func *src; int dst_fid = dst->value.ancestor.formal_id; - struct ipa_polymorphic_call_context *src_ctx + class ipa_polymorphic_call_context *src_ctx = ipa_get_ith_polymorhic_call_context (top, dst_fid); /* Variable number of arguments can cause havoc if we try to access @@ -2683,7 +2683,7 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, if (src_ctx && !src_ctx->useless_p ()) { - struct ipa_polymorphic_call_context ctx = *src_ctx; + class ipa_polymorphic_call_context ctx = *src_ctx; /* TODO: Make type preserved safe WRT contexts. */ if (!ipa_get_jf_ancestor_type_preserved (dst)) @@ -2753,12 +2753,12 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, int dst_fid = dst->value.pass_through.formal_id; src = ipa_get_ith_jump_func (top, dst_fid); bool dst_agg_p = ipa_get_jf_pass_through_agg_preserved (dst); - struct ipa_polymorphic_call_context *src_ctx + class ipa_polymorphic_call_context *src_ctx = ipa_get_ith_polymorhic_call_context (top, dst_fid); if (src_ctx && !src_ctx->useless_p ()) { - struct ipa_polymorphic_call_context ctx = *src_ctx; + class ipa_polymorphic_call_context ctx = *src_ctx; /* TODO: Make type preserved safe WRT contexts. */ if (!ipa_get_jf_pass_through_type_preserved (dst)) @@ -3231,7 +3231,7 @@ try_decrement_rdesc_refcount (struct ipa_jump_func *jfunc) static struct cgraph_edge * try_make_edge_direct_simple_call (struct cgraph_edge *ie, struct ipa_jump_func *jfunc, tree target_type, - struct ipa_node_params *new_root_info) + class ipa_node_params *new_root_info) { struct cgraph_edge *cs; tree target; @@ -3302,7 +3302,7 @@ ipa_impossible_devirt_target (struct cgraph_edge *ie, tree target) static struct cgraph_edge * try_make_edge_direct_virtual_call (struct cgraph_edge *ie, struct ipa_jump_func *jfunc, - struct ipa_polymorphic_call_context ctx) + class ipa_polymorphic_call_context ctx) { tree target = NULL; bool speculative = false; @@ -3412,9 +3412,9 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, struct cgraph_node *node, vec *new_edges) { - struct ipa_edge_args *top; + class ipa_edge_args *top; struct cgraph_edge *ie, *next_ie, *new_direct_edge; - struct ipa_node_params *new_root_info, *inlined_node_info; + class ipa_node_params *new_root_info, *inlined_node_info; bool res = false; ipa_check_create_edge_args (); @@ -3426,7 +3426,7 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, for (ie = node->indirect_calls; ie; ie = next_ie) { - struct cgraph_indirect_call_info *ici = ie->indirect_info; + class cgraph_indirect_call_info *ici = ie->indirect_info; struct ipa_jump_func *jfunc; int param_index; cgraph_node *spec_target = NULL; @@ -3583,11 +3583,11 @@ combine_controlled_uses_counters (int c, int d) static void propagate_controlled_uses (struct cgraph_edge *cs) { - struct ipa_edge_args *args = IPA_EDGE_REF (cs); + class ipa_edge_args *args = IPA_EDGE_REF (cs); struct cgraph_node *new_root = cs->caller->global.inlined_to ? cs->caller->global.inlined_to : cs->caller; - struct ipa_node_params *new_root_info = IPA_NODE_REF (new_root); - struct ipa_node_params *old_root_info = IPA_NODE_REF (cs->callee); + class ipa_node_params *new_root_info = IPA_NODE_REF (new_root); + class ipa_node_params *old_root_info = IPA_NODE_REF (cs->callee); int count, i; count = MIN (ipa_get_cs_argument_count (args), @@ -3881,7 +3881,7 @@ ipa_edge_args_sum_t::duplicate (cgraph_edge *src, cgraph_edge *dst, { struct cgraph_node *inline_root = dst->caller->global.inlined_to ? dst->caller->global.inlined_to : dst->caller; - struct ipa_node_params *root_info = IPA_NODE_REF (inline_root); + class ipa_node_params *root_info = IPA_NODE_REF (inline_root); int idx = ipa_get_jf_pass_through_formal_id (dst_jf); int c = ipa_get_controlled_uses (root_info, idx); @@ -4025,7 +4025,7 @@ void ipa_print_node_params (FILE *f, struct cgraph_node *node) { int i, count; - struct ipa_node_params *info; + class ipa_node_params *info; if (!node->definition) return; @@ -4173,10 +4173,10 @@ ipa_write_jump_function (struct output_block *ob, /* Read in jump function JUMP_FUNC from IB. */ static void -ipa_read_jump_function (struct lto_input_block *ib, +ipa_read_jump_function (class lto_input_block *ib, struct ipa_jump_func *jump_func, struct cgraph_edge *cs, - struct data_in *data_in, + class data_in *data_in, bool prevails) { enum jump_func_type jftype; @@ -4285,7 +4285,7 @@ static void ipa_write_indirect_edge_info (struct output_block *ob, struct cgraph_edge *cs) { - struct cgraph_indirect_call_info *ii = cs->indirect_info; + class cgraph_indirect_call_info *ii = cs->indirect_info; struct bitpack_d bp; streamer_write_hwi (ob, ii->param_index); @@ -4314,11 +4314,11 @@ ipa_write_indirect_edge_info (struct output_block *ob, relevant to indirect inlining from IB. */ static void -ipa_read_indirect_edge_info (struct lto_input_block *ib, - struct data_in *data_in, +ipa_read_indirect_edge_info (class lto_input_block *ib, + class data_in *data_in, struct cgraph_edge *cs) { - struct cgraph_indirect_call_info *ii = cs->indirect_info; + class cgraph_indirect_call_info *ii = cs->indirect_info; struct bitpack_d bp; ii->param_index = (int) streamer_read_hwi (ib); @@ -4348,7 +4348,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) { int node_ref; lto_symtab_encoder_t encoder; - struct ipa_node_params *info = IPA_NODE_REF (node); + class ipa_node_params *info = IPA_NODE_REF (node); int j; struct cgraph_edge *e; struct bitpack_d bp; @@ -4375,7 +4375,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) } for (e = node->callees; e; e = e->next_callee) { - struct ipa_edge_args *args = IPA_EDGE_REF (e); + class ipa_edge_args *args = IPA_EDGE_REF (e); streamer_write_uhwi (ob, ipa_get_cs_argument_count (args) * 2 @@ -4389,7 +4389,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) } for (e = node->indirect_calls; e; e = e->next_callee) { - struct ipa_edge_args *args = IPA_EDGE_REF (e); + class ipa_edge_args *args = IPA_EDGE_REF (e); streamer_write_uhwi (ob, ipa_get_cs_argument_count (args) * 2 @@ -4407,8 +4407,8 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) /* Stream in edge E from IB. */ static void -ipa_read_edge_info (struct lto_input_block *ib, - struct data_in *data_in, +ipa_read_edge_info (class lto_input_block *ib, + class data_in *data_in, struct cgraph_edge *e, bool prevails) { int count = streamer_read_uhwi (ib); @@ -4419,7 +4419,7 @@ ipa_read_edge_info (struct lto_input_block *ib, return; if (prevails && e->possibly_call_in_translation_unit_p ()) { - struct ipa_edge_args *args = IPA_EDGE_REF (e); + class ipa_edge_args *args = IPA_EDGE_REF (e); vec_safe_grow_cleared (args->jump_functions, count); if (contexts_computed) vec_safe_grow_cleared (args->polymorphic_call_contexts, count); @@ -4441,7 +4441,7 @@ ipa_read_edge_info (struct lto_input_block *ib, data_in, prevails); if (contexts_computed) { - struct ipa_polymorphic_call_context ctx; + class ipa_polymorphic_call_context ctx; ctx.stream_in (ib, data_in); } } @@ -4451,14 +4451,14 @@ ipa_read_edge_info (struct lto_input_block *ib, /* Stream in NODE info from IB. */ static void -ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, - struct data_in *data_in) +ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node, + class data_in *data_in) { int k; struct cgraph_edge *e; struct bitpack_d bp; bool prevails = node->prevailing_p (); - struct ipa_node_params *info = prevails ? IPA_NODE_REF (node) : NULL; + class ipa_node_params *info = prevails ? IPA_NODE_REF (node) : NULL; int param_count = streamer_read_uhwi (ib); if (prevails) @@ -4555,7 +4555,7 @@ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data, const int cfg_offset = sizeof (struct lto_function_header); const int main_offset = cfg_offset + header->cfg_size; const int string_offset = main_offset + header->main_size; - struct data_in *data_in; + class data_in *data_in; unsigned int i; unsigned int count; @@ -4803,7 +4803,7 @@ read_replacements_section (struct lto_file_decl_data *file_data, const int cfg_offset = sizeof (struct lto_function_header); const int main_offset = cfg_offset + header->cfg_size; const int string_offset = main_offset + header->main_size; - struct data_in *data_in; + class data_in *data_in; unsigned int i; unsigned int count; diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 7605911..6470c93 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -179,12 +179,12 @@ struct GTY (()) ipa_jump_func /* Information about zero/non-zero bits. The pointed to structure is shared betweed different jump functions. Use ipa_set_jfunc_bits to set this field. */ - struct ipa_bits *bits; + class ipa_bits *bits; /* Information about value range, containing valid data only when vr_known is true. The pointed to structure is shared betweed different jump functions. Use ipa_set_jfunc_vr to set this field. */ - struct value_range_base *m_vr; + class value_range_base *m_vr; enum jump_func_type type; /* Represents a value of a jump function. pass_through is used only in jump @@ -335,7 +335,7 @@ public: vec *descriptors; /* Pointer to an array of structures describing individual formal parameters. */ - struct ipcp_param_lattices * GTY((skip)) lattices; + class ipcp_param_lattices * GTY((skip)) lattices; /* Only for versioned nodes this field would not be NULL, it points to the node that IPA cp cloned from. */ struct cgraph_node * GTY((skip)) ipcp_orig_node; @@ -423,7 +423,7 @@ struct ipa_func_body_info cgraph_node *node; /* Its info. */ - struct ipa_node_params *info; + class ipa_node_params *info; /* Information about individual BBs. */ vec bb_infos; @@ -442,7 +442,7 @@ struct ipa_func_body_info /* Return the number of formal parameters. */ static inline int -ipa_get_param_count (struct ipa_node_params *info) +ipa_get_param_count (class ipa_node_params *info) { return vec_safe_length (info->descriptors); } @@ -453,7 +453,7 @@ ipa_get_param_count (struct ipa_node_params *info) WPA. */ static inline tree -ipa_get_param (struct ipa_node_params *info, int i) +ipa_get_param (class ipa_node_params *info, int i) { gcc_checking_assert (info->descriptors); gcc_checking_assert (!flag_wpa); @@ -466,7 +466,7 @@ ipa_get_param (struct ipa_node_params *info, int i) to INFO if it is known or NULL if not. */ static inline tree -ipa_get_type (struct ipa_node_params *info, int i) +ipa_get_type (class ipa_node_params *info, int i) { if (vec_safe_length (info->descriptors) <= (unsigned) i) return NULL; @@ -483,7 +483,7 @@ ipa_get_type (struct ipa_node_params *info, int i) to INFO. */ static inline int -ipa_get_param_move_cost (struct ipa_node_params *info, int i) +ipa_get_param_move_cost (class ipa_node_params *info, int i) { gcc_checking_assert (info->descriptors); return (*info->descriptors)[i].move_cost; @@ -493,7 +493,7 @@ ipa_get_param_move_cost (struct ipa_node_params *info, int i) associated with INFO to VAL. */ static inline void -ipa_set_param_used (struct ipa_node_params *info, int i, bool val) +ipa_set_param_used (class ipa_node_params *info, int i, bool val) { gcc_checking_assert (info->descriptors); (*info->descriptors)[i].used = val; @@ -503,7 +503,7 @@ ipa_set_param_used (struct ipa_node_params *info, int i, bool val) IPA_UNDESCRIBED_USE if there is a use that is not described by these structures. */ static inline int -ipa_get_controlled_uses (struct ipa_node_params *info, int i) +ipa_get_controlled_uses (class ipa_node_params *info, int i) { /* FIXME: introducing speculation causes out of bounds access here. */ if (vec_safe_length (info->descriptors) > (unsigned)i) @@ -514,7 +514,7 @@ ipa_get_controlled_uses (struct ipa_node_params *info, int i) /* Set the controlled counter of a given parameter. */ static inline void -ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) +ipa_set_controlled_uses (class ipa_node_params *info, int i, int val) { gcc_checking_assert (info->descriptors); (*info->descriptors)[i].controlled_uses = val; @@ -524,7 +524,7 @@ ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) function associated with INFO. */ static inline bool -ipa_is_param_used (struct ipa_node_params *info, int i) +ipa_is_param_used (class ipa_node_params *info, int i) { gcc_checking_assert (info->descriptors); return (*info->descriptors)[i].used; @@ -592,7 +592,7 @@ class GTY((for_user)) ipa_edge_args /* Return the number of actual arguments. */ static inline int -ipa_get_cs_argument_count (struct ipa_edge_args *args) +ipa_get_cs_argument_count (class ipa_edge_args *args) { return vec_safe_length (args->jump_functions); } @@ -602,15 +602,15 @@ ipa_get_cs_argument_count (struct ipa_edge_args *args) ipa_compute_jump_functions. */ static inline struct ipa_jump_func * -ipa_get_ith_jump_func (struct ipa_edge_args *args, int i) +ipa_get_ith_jump_func (class ipa_edge_args *args, int i) { return &(*args->jump_functions)[i]; } /* Returns a pointer to the polymorphic call context for the ith argument. NULL if contexts are not computed. */ -static inline struct ipa_polymorphic_call_context * -ipa_get_ith_polymorhic_call_context (struct ipa_edge_args *args, int i) +static inline class ipa_polymorphic_call_context * +ipa_get_ith_polymorhic_call_context (class ipa_edge_args *args, int i) { if (!args->polymorphic_call_contexts) return NULL; @@ -781,11 +781,11 @@ extern object_allocator > ipcp_poly_ctx_values_pool; template -class ipcp_value_source; +struct ipcp_value_source; extern object_allocator > ipcp_sources_pool; -class ipcp_agg_lattice; +struct ipcp_agg_lattice; extern object_allocator ipcp_agg_lattice_pool; @@ -795,15 +795,15 @@ void ipa_prop_write_jump_functions (void); void ipa_prop_read_jump_functions (void); void ipcp_write_transformation_summaries (void); void ipcp_read_transformation_summaries (void); -int ipa_get_param_decl_index (struct ipa_node_params *, tree); -tree ipa_value_from_jfunc (struct ipa_node_params *info, +int ipa_get_param_decl_index (class ipa_node_params *, tree); +tree ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc, tree type); unsigned int ipcp_transform_function (struct cgraph_node *node); ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *, cgraph_edge *, int, ipa_jump_func *); -void ipa_dump_param (FILE *, struct ipa_node_params *info, int i); +void ipa_dump_param (FILE *, class ipa_node_params *info, int i); void ipa_release_body_info (struct ipa_func_body_info *); tree ipa_get_callee_param_type (struct cgraph_edge *e, int i); diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index f5e5396..db91d2c1 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -122,7 +122,7 @@ public: enum malloc_state_e malloc_state; }; -typedef struct funct_state_d * funct_state; +typedef class funct_state_d * funct_state; /* The storage of the funct_state is abstracted because there is the possibility that it may be desirable to move this to the cgraph @@ -1014,7 +1014,7 @@ analyze_function (struct cgraph_node *fn, bool ipa) funct_state l; basic_block this_block; - l = XCNEW (struct funct_state_d); + l = XCNEW (class funct_state_d); l->pure_const_state = IPA_CONST; l->state_previously_known = IPA_NEITHER; l->looping_previously_known = true; @@ -1086,7 +1086,7 @@ end: } else { - struct loop *loop; + class loop *loop; scev_initialize (); FOR_EACH_LOOP (loop, 0) if (!finite_loop_p (loop)) @@ -1279,7 +1279,7 @@ pure_const_read_summary (void) { const char *data; size_t len; - struct lto_input_block *ib + class lto_input_block *ib = lto_create_simple_input_block (file_data, LTO_section_ipa_pure_const, &data, &len); diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h index 05e1058..0d8e509 100644 --- a/gcc/ipa-ref.h +++ b/gcc/ipa-ref.h @@ -22,8 +22,8 @@ along with GCC; see the file COPYING3. If not see #define GCC_IPA_REF_H struct cgraph_node; -class varpool_node; -class symtab_node; +struct varpool_node; +struct symtab_node; /* How the reference is done. */ diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index 7b2614f..78737aa 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -1069,7 +1069,7 @@ ipa_reference_read_optimization_summary (void) { const char *data; size_t len; - struct lto_input_block *ib + class lto_input_block *ib = lto_create_simple_input_block (file_data, LTO_section_ipa_reference, &data, &len); diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 44ae2c7..86b26d3 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -146,7 +146,7 @@ public: /* Best split point found. */ -struct split_point best_split_point; +class split_point best_split_point; /* Set of basic blocks that are not allowed to dominate a split point. */ @@ -193,7 +193,7 @@ test_nonssa_use (gimple *, tree t, tree, void *data) /* Dump split point CURRENT. */ static void -dump_split_point (FILE * file, struct split_point *current) +dump_split_point (FILE * file, class split_point *current) { fprintf (file, "Split point at BB %i\n" @@ -212,7 +212,7 @@ dump_split_point (FILE * file, struct split_point *current) Parameters are the same as for consider_split. */ static bool -verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars, +verify_non_ssa_vars (class split_point *current, bitmap non_ssa_vars, basic_block return_bb) { bitmap seen = BITMAP_ALLOC (NULL); @@ -406,7 +406,7 @@ dominated_by_forbidden (basic_block bb) /* For give split point CURRENT and return block RETURN_BB return 1 if ssa name VAL is set by split part and 0 otherwise. */ static bool -split_part_set_ssa_name_p (tree val, struct split_point *current, +split_part_set_ssa_name_p (tree val, class split_point *current, basic_block return_bb) { if (TREE_CODE (val) != SSA_NAME) @@ -423,7 +423,7 @@ split_part_set_ssa_name_p (tree val, struct split_point *current, See if we can split function here. */ static void -consider_split (struct split_point *current, bitmap non_ssa_vars, +consider_split (class split_point *current, bitmap non_ssa_vars, basic_block return_bb) { tree parm; @@ -1035,7 +1035,7 @@ find_split_points (basic_block return_bb, sreal overall_time, int overall_size) stack_entry first; vec stack = vNULL; basic_block bb; - struct split_point current; + class split_point current; current.header_time = overall_time; current.header_size = overall_size; @@ -1181,7 +1181,7 @@ find_split_points (basic_block return_bb, sreal overall_time, int overall_size) /* Split function at SPLIT_POINT. */ static void -split_function (basic_block return_bb, struct split_point *split_point, +split_function (basic_block return_bb, class split_point *split_point, bool add_tsan_func_exit) { vec args_to_pass = vNULL; diff --git a/gcc/ira-build.c b/gcc/ira-build.c index 83caa3a..c7457fa4 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -253,10 +253,10 @@ finish_loop_tree_nodes (void) loop designating the whole function when CFG loops are not built. */ static void -add_loop_to_tree (struct loop *loop) +add_loop_to_tree (class loop *loop) { int loop_num; - struct loop *parent; + class loop *parent; ira_loop_tree_node_t loop_node, parent_node; /* We cannot use loop node access macros here because of potential @@ -331,7 +331,7 @@ static void form_loop_tree (void) { basic_block bb; - struct loop *parent; + class loop *parent; ira_loop_tree_node_t bb_node, loop_node; /* We cannot use loop/bb node access macros because of potential @@ -2168,7 +2168,7 @@ low_pressure_loop_node_p (ira_loop_tree_node_t node) form a region from such loop if the target use stack register because reg-stack.c cannot deal with such edges. */ static bool -loop_with_complex_edge_p (struct loop *loop) +loop_with_complex_edge_p (class loop *loop) { int i; edge_iterator ei; diff --git a/gcc/ira-color.c b/gcc/ira-color.c index 8a90ae1..9923699 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -4557,7 +4557,7 @@ ira_reuse_stack_slot (int regno, poly_uint64 inherent_size, ira_allocno_t another_allocno, allocno = ira_regno_allocno_map[regno]; rtx x; bitmap_iterator bi; - struct ira_spilled_reg_stack_slot *slot = NULL; + class ira_spilled_reg_stack_slot *slot = NULL; ira_assert (! ira_use_lra_p); @@ -4669,7 +4669,7 @@ ira_reuse_stack_slot (int regno, poly_uint64 inherent_size, void ira_mark_new_stack_slot (rtx x, int regno, poly_uint64 total_size) { - struct ira_spilled_reg_stack_slot *slot; + class ira_spilled_reg_stack_slot *slot; int slot_num; ira_allocno_t allocno; diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 08848f0..92b7dfb 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -82,7 +82,7 @@ struct ira_loop_tree_node /* The node represents basic block if children == NULL. */ basic_block bb; /* NULL for loop. */ /* NULL for BB or for loop tree root if we did not build CFG loop tree. */ - struct loop *loop; + class loop *loop; /* NEXT/SUBLOOP_NEXT is the next node/loop-node of the same parent. SUBLOOP_NEXT is always NULL for BBs. */ ira_loop_tree_node_t subloop_next, next; @@ -613,7 +613,7 @@ extern int ira_spilled_reg_stack_slots_num; /* The following array contains info about spilled pseudo-registers stack slots used in current function so far. */ -extern struct ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots; +extern class ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots; /* Correspondingly overall cost of the allocation, cost of the allocnos assigned to hard-registers, cost of the allocnos assigned @@ -909,9 +909,9 @@ public: bool x_ira_prohibited_mode_move_regs_initialized_p; }; -extern struct target_ira_int default_target_ira_int; +extern class target_ira_int default_target_ira_int; #if SWITCHABLE_TARGET -extern struct target_ira_int *this_target_ira_int; +extern class target_ira_int *this_target_ira_int; #else #define this_target_ira_int (&default_target_ira_int) #endif diff --git a/gcc/ira.c b/gcc/ira.c index 214fdff..c58daba 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -394,10 +394,10 @@ along with GCC; see the file COPYING3. If not see #include "print-rtl.h" struct target_ira default_target_ira; -struct target_ira_int default_target_ira_int; +class target_ira_int default_target_ira_int; #if SWITCHABLE_TARGET struct target_ira *this_target_ira = &default_target_ira; -struct target_ira_int *this_target_ira_int = &default_target_ira_int; +class target_ira_int *this_target_ira_int = &default_target_ira_int; #endif /* A modified value of flag `-fira-verbose' used internally. */ @@ -411,7 +411,7 @@ int ira_spilled_reg_stack_slots_num; /* The following array contains info about spilled pseudo-registers stack slots used in current function so far. */ -struct ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots; +class ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots; /* Correspondingly overall cost of the allocation, overall cost before reload, cost of the allocnos assigned to hard-registers, cost of @@ -4061,7 +4061,7 @@ setup_reg_equiv (void) /* Print chain C to FILE. */ static void -print_insn_chain (FILE *file, struct insn_chain *c) +print_insn_chain (FILE *file, class insn_chain *c) { fprintf (file, "insn=%d, ", INSN_UID (c->insn)); bitmap_print (file, &c->live_throughout, "live_throughout: ", ", "); @@ -4073,7 +4073,7 @@ print_insn_chain (FILE *file, struct insn_chain *c) static void print_insn_chains (FILE *file) { - struct insn_chain *c; + class insn_chain *c; for (c = reload_insn_chain; c ; c = c->next) print_insn_chain (file, c); } @@ -4134,10 +4134,10 @@ static void build_insn_chain (void) { unsigned int i; - struct insn_chain **p = &reload_insn_chain; + class insn_chain **p = &reload_insn_chain; basic_block bb; - struct insn_chain *c = NULL; - struct insn_chain *next = NULL; + class insn_chain *c = NULL; + class insn_chain *next = NULL; auto_bitmap live_relevant_regs; auto_bitmap elim_regset; /* live_subregs is a vector used to keep accurate information about @@ -5467,11 +5467,11 @@ ira (FILE *f) { ira_spilled_reg_stack_slots_num = 0; ira_spilled_reg_stack_slots - = ((struct ira_spilled_reg_stack_slot *) + = ((class ira_spilled_reg_stack_slot *) ira_allocate (max_regno - * sizeof (struct ira_spilled_reg_stack_slot))); + * sizeof (class ira_spilled_reg_stack_slot))); memset ((void *)ira_spilled_reg_stack_slots, 0, - max_regno * sizeof (struct ira_spilled_reg_stack_slot)); + max_regno * sizeof (class ira_spilled_reg_stack_slot)); } } allocate_initial_values (); diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c index 89714be..0efe7b4 100644 --- a/gcc/loop-doloop.c +++ b/gcc/loop-doloop.c @@ -263,7 +263,7 @@ doloop_condition_get (rtx_insn *doloop_pat) describes the number of iterations of the loop. */ static bool -doloop_valid_p (struct loop *loop, struct niter_desc *desc) +doloop_valid_p (class loop *loop, class niter_desc *desc) { basic_block *body = get_loop_body (loop), bb; rtx_insn *insn; @@ -405,7 +405,7 @@ add_test (rtx cond, edge *e, basic_block dest) DOLOOP_SEQ. COUNT is the number of iterations of the LOOP. */ static void -doloop_modify (struct loop *loop, struct niter_desc *desc, +doloop_modify (class loop *loop, class niter_desc *desc, rtx_insn *doloop_seq, rtx condition, rtx count) { rtx counter_reg; @@ -603,7 +603,7 @@ record_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data) modified. */ static bool -doloop_optimize (struct loop *loop) +doloop_optimize (class loop *loop) { scalar_int_mode mode; rtx doloop_reg; @@ -614,7 +614,7 @@ doloop_optimize (struct loop *loop) unsigned level; HOST_WIDE_INT est_niter; int max_cost; - struct niter_desc *desc; + class niter_desc *desc; unsigned word_mode_size; unsigned HOST_WIDE_INT word_mode_max; int entered_at_top; @@ -754,7 +754,7 @@ doloop_optimize (struct loop *loop) void doloop_optimize_loops (void) { - struct loop *loop; + class loop *loop; if (optimize == 1) { diff --git a/gcc/loop-init.c b/gcc/loop-init.c index bdfa385..4b3bbcc 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -135,7 +135,7 @@ loop_optimizer_init (unsigned flags) void loop_optimizer_finalize (struct function *fn) { - struct loop *loop; + class loop *loop; basic_block bb; timevar_push (TV_LOOP_FINI); @@ -194,7 +194,7 @@ fix_loop_structure (bitmap changed_bbs) { basic_block bb; int record_exits = 0; - struct loop *loop; + class loop *loop; unsigned old_nloops, i; timevar_push (TV_LOOP_INIT); @@ -237,7 +237,7 @@ fix_loop_structure (bitmap changed_bbs) while (loop->inner) { - struct loop *ploop = loop->inner; + class loop *ploop = loop->inner; flow_loop_tree_node_remove (ploop); flow_loop_tree_node_add (loop_outer (loop), ploop); } diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index 4fc73d4..644ecfc 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -61,7 +61,7 @@ along with GCC; see the file COPYING3. If not see class loop_data { public: - struct loop *outermost_exit; /* The outermost exit of the loop. */ + class loop *outermost_exit; /* The outermost exit of the loop. */ bool has_call; /* True if the loop contains a call. */ /* Maximal register pressure inside loop for given register class (defined only for the pressure classes). */ @@ -71,7 +71,7 @@ public: bitmap_head regs_live; }; -#define LOOP_DATA(LOOP) ((struct loop_data *) (LOOP)->aux) +#define LOOP_DATA(LOOP) ((class loop_data *) (LOOP)->aux) /* The description of an use. */ @@ -144,7 +144,7 @@ struct invariant }; /* Currently processed loop. */ -static struct loop *curr_loop; +static class loop *curr_loop; /* Table of invariants indexed by the df_ref uid field. */ @@ -558,7 +558,7 @@ merge_identical_invariants (void) get_loop_body_in_dom_order. */ static void -compute_always_reached (struct loop *loop, basic_block *body, +compute_always_reached (class loop *loop, basic_block *body, bitmap may_exit, bitmap always_reached) { unsigned i; @@ -578,13 +578,13 @@ compute_always_reached (struct loop *loop, basic_block *body, additionally mark blocks that may exit due to a call. */ static void -find_exits (struct loop *loop, basic_block *body, +find_exits (class loop *loop, basic_block *body, bitmap may_exit, bitmap has_exit) { unsigned i; edge_iterator ei; edge e; - struct loop *outermost_exit = loop, *aexit; + class loop *outermost_exit = loop, *aexit; bool has_call = false; rtx_insn *insn; @@ -645,7 +645,7 @@ find_exits (struct loop *loop, basic_block *body, if (loop->aux == NULL) { - loop->aux = xcalloc (1, sizeof (struct loop_data)); + loop->aux = xcalloc (1, sizeof (class loop_data)); bitmap_initialize (&LOOP_DATA (loop)->regs_ref, ®_obstack); bitmap_initialize (&LOOP_DATA (loop)->regs_live, ®_obstack); } @@ -673,7 +673,7 @@ may_assign_reg_p (rtx x) BODY. */ static void -find_defs (struct loop *loop) +find_defs (class loop *loop) { if (dump_file) { @@ -1210,7 +1210,7 @@ find_invariants_bb (basic_block bb, bool always_reached, bool always_executed) ends due to a function call. */ static void -find_invariants_body (struct loop *loop, basic_block *body, +find_invariants_body (class loop *loop, basic_block *body, bitmap always_reached, bitmap always_executed) { unsigned i; @@ -1224,7 +1224,7 @@ find_invariants_body (struct loop *loop, basic_block *body, /* Finds invariants in LOOP. */ static void -find_invariants (struct loop *loop) +find_invariants (class loop *loop) { auto_bitmap may_exit; auto_bitmap always_reached; @@ -1687,7 +1687,7 @@ replace_uses (struct invariant *inv, rtx reg, bool in_group) the block preceding its header. */ static bool -can_move_invariant_reg (struct loop *loop, struct invariant *inv, rtx reg) +can_move_invariant_reg (class loop *loop, struct invariant *inv, rtx reg) { df_ref def, use; unsigned int dest_regno, defs_in_loop_count = 0; @@ -1760,7 +1760,7 @@ can_move_invariant_reg (struct loop *loop, struct invariant *inv, rtx reg) otherwise. */ static bool -move_invariant_reg (struct loop *loop, unsigned invno) +move_invariant_reg (class loop *loop, unsigned invno) { struct invariant *inv = invariants[invno]; struct invariant *repr = invariants[inv->eqto]; @@ -1866,7 +1866,7 @@ fail: in TEMPORARY_REGS. */ static void -move_invariants (struct loop *loop) +move_invariants (class loop *loop) { struct invariant *inv; unsigned i; @@ -1939,7 +1939,7 @@ free_inv_motion_data (void) /* Move the invariants out of the LOOP. */ static void -move_single_loop_invariants (struct loop *loop) +move_single_loop_invariants (class loop *loop) { init_inv_motion_data (); @@ -1954,9 +1954,9 @@ move_single_loop_invariants (struct loop *loop) /* Releases the auxiliary data for LOOP. */ static void -free_loop_data (struct loop *loop) +free_loop_data (class loop *loop) { - struct loop_data *data = LOOP_DATA (loop); + class loop_data *data = LOOP_DATA (loop); if (!data) return; @@ -2035,7 +2035,7 @@ change_pressure (int regno, bool incr_p) static void mark_regno_live (int regno) { - struct loop *loop; + class loop *loop; for (loop = curr_loop; loop != current_loops->tree_root; @@ -2104,7 +2104,7 @@ mark_ref_regs (rtx x) code = GET_CODE (x); if (code == REG) { - struct loop *loop; + class loop *loop; for (loop = curr_loop; loop != current_loops->tree_root; @@ -2136,12 +2136,12 @@ calculate_loop_reg_pressure (void) basic_block bb; rtx_insn *insn; rtx link; - struct loop *loop, *parent; + class loop *loop, *parent; FOR_EACH_LOOP (loop, 0) if (loop->aux == NULL) { - loop->aux = xcalloc (1, sizeof (struct loop_data)); + loop->aux = xcalloc (1, sizeof (class loop_data)); bitmap_initialize (&LOOP_DATA (loop)->regs_ref, ®_obstack); bitmap_initialize (&LOOP_DATA (loop)->regs_live, ®_obstack); } @@ -2253,7 +2253,7 @@ calculate_loop_reg_pressure (void) void move_loop_invariants (void) { - struct loop *loop; + class loop *loop; if (optimize == 1) df_live_add_problem (); diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c index f078a68..2274cc3 100644 --- a/gcc/loop-iv.c +++ b/gcc/loop-iv.c @@ -89,7 +89,7 @@ class biv_entry { public: unsigned regno; /* The register of the biv. */ - struct rtx_iv iv; /* Value of the biv. */ + class rtx_iv iv; /* Value of the biv. */ }; static bool clean_slate = true; @@ -97,7 +97,7 @@ static bool clean_slate = true; static unsigned int iv_ref_table_size = 0; /* Table of rtx_ivs indexed by the df_ref uid field. */ -static struct rtx_iv ** iv_ref_table; +static class rtx_iv ** iv_ref_table; /* Induction variable stored at the reference. */ #define DF_REF_IV(REF) iv_ref_table[DF_REF_ID (REF)] @@ -105,7 +105,7 @@ static struct rtx_iv ** iv_ref_table; /* The current loop. */ -static struct loop *current_loop; +static class loop *current_loop; /* Hashtable helper. */ @@ -136,7 +136,7 @@ biv_entry_hasher::equal (const biv_entry *b, const rtx_def *r) static hash_table *bivs; -static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *); +static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, class rtx_iv *); /* Return the RTX code corresponding to the IV extend code EXTEND. */ static inline enum rtx_code @@ -156,9 +156,9 @@ iv_extend_to_rtx_code (enum iv_extend_code extend) /* Dumps information about IV to FILE. */ -extern void dump_iv_info (FILE *, struct rtx_iv *); +extern void dump_iv_info (FILE *, class rtx_iv *); void -dump_iv_info (FILE *file, struct rtx_iv *iv) +dump_iv_info (FILE *file, class rtx_iv *iv) { if (!iv->base) { @@ -204,9 +204,9 @@ check_iv_ref_table_size (void) if (iv_ref_table_size < DF_DEFS_TABLE_SIZE ()) { unsigned int new_size = DF_DEFS_TABLE_SIZE () + (DF_DEFS_TABLE_SIZE () / 4); - iv_ref_table = XRESIZEVEC (struct rtx_iv *, iv_ref_table, new_size); + iv_ref_table = XRESIZEVEC (class rtx_iv *, iv_ref_table, new_size); memset (&iv_ref_table[iv_ref_table_size], 0, - (new_size - iv_ref_table_size) * sizeof (struct rtx_iv *)); + (new_size - iv_ref_table_size) * sizeof (class rtx_iv *)); iv_ref_table_size = new_size; } } @@ -245,7 +245,7 @@ static void clear_iv_info (void) { unsigned i, n_defs = DF_DEFS_TABLE_SIZE (); - struct rtx_iv *iv; + class rtx_iv *iv; check_iv_ref_table_size (); for (i = 0; i < n_defs; i++) @@ -265,7 +265,7 @@ clear_iv_info (void) /* Prepare the data for an induction variable analysis of a LOOP. */ void -iv_analysis_loop_init (struct loop *loop) +iv_analysis_loop_init (class loop *loop) { current_loop = loop; @@ -303,7 +303,7 @@ latch_dominating_def (rtx reg, df_ref *def) { df_ref single_rd = NULL, adef; unsigned regno = REGNO (reg); - struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (current_loop->latch); + class df_rd_bb_info *bb_info = DF_RD_BB_INFO (current_loop->latch); for (adef = DF_REG_DEF_CHAIN (regno); adef; adef = DF_REF_NEXT_REG (adef)) { @@ -386,7 +386,7 @@ iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def) consistency with other iv manipulation functions that may fail). */ static bool -iv_constant (struct rtx_iv *iv, scalar_int_mode mode, rtx cst) +iv_constant (class rtx_iv *iv, scalar_int_mode mode, rtx cst) { iv->mode = mode; iv->base = cst; @@ -403,7 +403,7 @@ iv_constant (struct rtx_iv *iv, scalar_int_mode mode, rtx cst) /* Evaluates application of subreg to MODE on IV. */ static bool -iv_subreg (struct rtx_iv *iv, scalar_int_mode mode) +iv_subreg (class rtx_iv *iv, scalar_int_mode mode) { /* If iv is invariant, just calculate the new value. */ if (iv->step == const0_rtx @@ -445,7 +445,7 @@ iv_subreg (struct rtx_iv *iv, scalar_int_mode mode) /* Evaluates application of EXTEND to MODE on IV. */ static bool -iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode) +iv_extend (class rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode) { /* If iv is invariant, just calculate the new value. */ if (iv->step == const0_rtx @@ -483,7 +483,7 @@ iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode) /* Evaluates negation of IV. */ static bool -iv_neg (struct rtx_iv *iv) +iv_neg (class rtx_iv *iv) { if (iv->extend == IV_UNKNOWN_EXTEND) { @@ -506,7 +506,7 @@ iv_neg (struct rtx_iv *iv) /* Evaluates addition or subtraction (according to OP) of IV1 to IV0. */ static bool -iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op) +iv_add (class rtx_iv *iv0, class rtx_iv *iv1, enum rtx_code op) { scalar_int_mode mode; rtx arg; @@ -576,7 +576,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op) /* Evaluates multiplication of IV by constant CST. */ static bool -iv_mult (struct rtx_iv *iv, rtx mby) +iv_mult (class rtx_iv *iv, rtx mby) { scalar_int_mode mode = iv->extend_mode; @@ -601,7 +601,7 @@ iv_mult (struct rtx_iv *iv, rtx mby) /* Evaluates shift of IV by constant CST. */ static bool -iv_shift (struct rtx_iv *iv, rtx mby) +iv_shift (class rtx_iv *iv, rtx mby) { scalar_int_mode mode = iv->extend_mode; @@ -811,9 +811,9 @@ get_biv_step (df_ref last_def, scalar_int_mode outer_mode, rtx reg, /* Records information that DEF is induction variable IV. */ static void -record_iv (df_ref def, struct rtx_iv *iv) +record_iv (df_ref def, class rtx_iv *iv) { - struct rtx_iv *recorded_iv = XNEW (struct rtx_iv); + class rtx_iv *recorded_iv = XNEW (class rtx_iv); *recorded_iv = *iv; check_iv_ref_table_size (); @@ -824,9 +824,9 @@ record_iv (df_ref def, struct rtx_iv *iv) IV and return true. Otherwise return false. */ static bool -analyzed_for_bivness_p (rtx def, struct rtx_iv *iv) +analyzed_for_bivness_p (rtx def, class rtx_iv *iv) { - struct biv_entry *biv = bivs->find_with_hash (def, REGNO (def)); + class biv_entry *biv = bivs->find_with_hash (def, REGNO (def)); if (!biv) return false; @@ -836,9 +836,9 @@ analyzed_for_bivness_p (rtx def, struct rtx_iv *iv) } static void -record_biv (rtx def, struct rtx_iv *iv) +record_biv (rtx def, class rtx_iv *iv) { - struct biv_entry *biv = XNEW (struct biv_entry); + class biv_entry *biv = XNEW (class biv_entry); biv_entry **slot = bivs->find_slot_with_hash (def, REGNO (def), INSERT); biv->regno = REGNO (def); @@ -851,7 +851,7 @@ record_biv (rtx def, struct rtx_iv *iv) to *IV. OUTER_MODE is the mode of DEF. */ static bool -iv_analyze_biv (scalar_int_mode outer_mode, rtx def, struct rtx_iv *iv) +iv_analyze_biv (scalar_int_mode outer_mode, rtx def, class rtx_iv *iv) { rtx inner_step, outer_step; scalar_int_mode inner_mode; @@ -929,11 +929,11 @@ iv_analyze_biv (scalar_int_mode outer_mode, rtx def, struct rtx_iv *iv) bool iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs, - struct rtx_iv *iv) + class rtx_iv *iv) { rtx mby = NULL_RTX; rtx op0 = NULL_RTX, op1 = NULL_RTX; - struct rtx_iv iv0, iv1; + class rtx_iv iv0, iv1; enum rtx_code code = GET_CODE (rhs); scalar_int_mode omode = mode; @@ -1040,7 +1040,7 @@ iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs, /* Analyzes iv DEF and stores the result to *IV. */ static bool -iv_analyze_def (df_ref def, struct rtx_iv *iv) +iv_analyze_def (df_ref def, class rtx_iv *iv) { rtx_insn *insn = DF_REF_INSN (def); rtx reg = DF_REF_REG (def); @@ -1104,7 +1104,7 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv) mode of OP. */ static bool -iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, struct rtx_iv *iv) +iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, class rtx_iv *iv) { df_ref def = NULL; enum iv_grd_result res; @@ -1165,7 +1165,7 @@ iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, struct rtx_iv *iv) mode of VAL. */ bool -iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, struct rtx_iv *iv) +iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, class rtx_iv *iv) { rtx reg; @@ -1190,7 +1190,7 @@ iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, struct rtx_iv *iv) /* Analyzes definition of DEF in INSN and stores the result to IV. */ bool -iv_analyze_result (rtx_insn *insn, rtx def, struct rtx_iv *iv) +iv_analyze_result (rtx_insn *insn, rtx def, class rtx_iv *iv) { df_ref adef; @@ -1210,7 +1210,7 @@ iv_analyze_result (rtx_insn *insn, rtx def, struct rtx_iv *iv) bool biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg) { - struct rtx_iv iv; + class rtx_iv iv; df_ref def, last_def; if (!simple_reg_p (reg)) @@ -1232,7 +1232,7 @@ biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg) /* Calculates value of IV at ITERATION-th iteration. */ rtx -get_iv_value (struct rtx_iv *iv, rtx iteration) +get_iv_value (class rtx_iv *iv, rtx iteration) { rtx val; @@ -1851,7 +1851,7 @@ eliminate_implied_conditions (enum rtx_code op, rtx *head, rtx tail) is a list, its elements are assumed to be combined using OP. */ static void -simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr) +simplify_using_initial_values (class loop *loop, enum rtx_code op, rtx *expr) { bool expression_valid; rtx head, tail, last_valid_expr; @@ -2072,8 +2072,8 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr) is SIGNED_P to DESC. */ static void -shorten_into_mode (struct rtx_iv *iv, scalar_int_mode mode, - enum rtx_code cond, bool signed_p, struct niter_desc *desc) +shorten_into_mode (class rtx_iv *iv, scalar_int_mode mode, + enum rtx_code cond, bool signed_p, class niter_desc *desc) { rtx mmin, mmax, cond_over, cond_under; @@ -2131,8 +2131,8 @@ shorten_into_mode (struct rtx_iv *iv, scalar_int_mode mode, some assumptions to DESC). */ static bool -canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1, - enum rtx_code cond, struct niter_desc *desc) +canonicalize_iv_subregs (class rtx_iv *iv0, class rtx_iv *iv1, + enum rtx_code cond, class niter_desc *desc) { scalar_int_mode comp_mode; bool signed_p; @@ -2247,7 +2247,7 @@ canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1, expression for the number of iterations, before we tried to simplify it. */ static uint64_t -determine_max_iter (struct loop *loop, struct niter_desc *desc, rtx old_niter) +determine_max_iter (class loop *loop, class niter_desc *desc, rtx old_niter) { rtx niter = desc->niter_expr; rtx mmin, mmax, cmp; @@ -2305,11 +2305,11 @@ determine_max_iter (struct loop *loop, struct niter_desc *desc, rtx old_niter) (basically its rtl version), complicated by things like subregs. */ static void -iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition, - struct niter_desc *desc) +iv_number_of_iterations (class loop *loop, rtx_insn *insn, rtx condition, + class niter_desc *desc) { rtx op0, op1, delta, step, bound, may_xform, tmp, tmp0, tmp1; - struct rtx_iv iv0, iv1; + class rtx_iv iv0, iv1; rtx assumption, may_not_xform; enum rtx_code cond; machine_mode nonvoid_mode; @@ -2867,7 +2867,7 @@ fail: into DESC. */ static void -check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc) +check_simple_exit (class loop *loop, edge e, class niter_desc *desc) { basic_block exit_bb; rtx condition; @@ -2915,12 +2915,12 @@ check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc) /* Finds a simple exit of LOOP and stores its description into DESC. */ void -find_simple_exit (struct loop *loop, struct niter_desc *desc) +find_simple_exit (class loop *loop, class niter_desc *desc) { unsigned i; basic_block *body; edge e; - struct niter_desc act; + class niter_desc act; bool any = false; edge_iterator ei; @@ -3018,10 +3018,10 @@ find_simple_exit (struct loop *loop, struct niter_desc *desc) /* Creates a simple loop description of LOOP if it was not computed already. */ -struct niter_desc * -get_simple_loop_desc (struct loop *loop) +class niter_desc * +get_simple_loop_desc (class loop *loop) { - struct niter_desc *desc = simple_loop_desc (loop); + class niter_desc *desc = simple_loop_desc (loop); if (desc) return desc; @@ -3038,9 +3038,9 @@ get_simple_loop_desc (struct loop *loop) /* Releases simple loop description for LOOP. */ void -free_simple_loop_desc (struct loop *loop) +free_simple_loop_desc (class loop *loop) { - struct niter_desc *desc = simple_loop_desc (loop); + class niter_desc *desc = simple_loop_desc (loop); if (!desc) return; diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index 1b4c73b..63fccd2 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -163,19 +163,19 @@ struct opt_info basic_block loop_preheader; /* The loop preheader basic block. */ }; -static void decide_unroll_stupid (struct loop *, int); -static void decide_unroll_constant_iterations (struct loop *, int); -static void decide_unroll_runtime_iterations (struct loop *, int); -static void unroll_loop_stupid (struct loop *); +static void decide_unroll_stupid (class loop *, int); +static void decide_unroll_constant_iterations (class loop *, int); +static void decide_unroll_runtime_iterations (class loop *, int); +static void unroll_loop_stupid (class loop *); static void decide_unrolling (int); -static void unroll_loop_constant_iterations (struct loop *); -static void unroll_loop_runtime_iterations (struct loop *); -static struct opt_info *analyze_insns_in_loop (struct loop *); +static void unroll_loop_constant_iterations (class loop *); +static void unroll_loop_runtime_iterations (class loop *); +static struct opt_info *analyze_insns_in_loop (class loop *); static void opt_info_start_duplication (struct opt_info *); static void apply_opt_in_copies (struct opt_info *, unsigned, bool, bool); static void free_opt_info (struct opt_info *); -static struct var_to_expand *analyze_insn_to_expand_var (struct loop*, rtx_insn *); -static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx, int *); +static struct var_to_expand *analyze_insn_to_expand_var (class loop*, rtx_insn *); +static bool referenced_in_one_insn_in_loop_p (class loop *, rtx, int *); static struct iv_to_split *analyze_iv_to_split_insn (rtx_insn *); static void expand_var_during_unrolling (struct var_to_expand *, rtx_insn *); static void insert_var_expansion_initialization (struct var_to_expand *, @@ -189,7 +189,7 @@ static rtx get_expansion (struct var_to_expand *); appropriate given the dump or -fopt-info settings. */ static void -report_unroll (struct loop *loop, dump_location_t locus) +report_unroll (class loop *loop, dump_location_t locus) { dump_flags_t report_flags = MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS; @@ -215,7 +215,7 @@ report_unroll (struct loop *loop, dump_location_t locus) static void decide_unrolling (int flags) { - struct loop *loop; + class loop *loop; /* Scan the loops, inner ones first. */ FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) @@ -279,7 +279,7 @@ decide_unrolling (int flags) void unroll_loops (int flags) { - struct loop *loop; + class loop *loop; bool changed = false; /* Now decide rest of unrolling. */ @@ -322,9 +322,9 @@ unroll_loops (int flags) /* Check whether exit of the LOOP is at the end of loop body. */ static bool -loop_exit_at_end_p (struct loop *loop) +loop_exit_at_end_p (class loop *loop) { - struct niter_desc *desc = get_simple_loop_desc (loop); + class niter_desc *desc = get_simple_loop_desc (loop); rtx_insn *insn; /* We should never have conditional in latch block. */ @@ -347,10 +347,10 @@ loop_exit_at_end_p (struct loop *loop) and how much. */ static void -decide_unroll_constant_iterations (struct loop *loop, int flags) +decide_unroll_constant_iterations (class loop *loop, int flags) { unsigned nunroll, nunroll_by_av, best_copies, best_unroll = 0, n_copies, i; - struct niter_desc *desc; + class niter_desc *desc; widest_int iterations; /* If we were not asked to unroll this loop, just return back silently. */ @@ -480,14 +480,14 @@ decide_unroll_constant_iterations (struct loop *loop, int flags) } */ static void -unroll_loop_constant_iterations (struct loop *loop) +unroll_loop_constant_iterations (class loop *loop) { unsigned HOST_WIDE_INT niter; unsigned exit_mod; unsigned i; edge e; unsigned max_unroll = loop->lpt_decision.times; - struct niter_desc *desc = get_simple_loop_desc (loop); + class niter_desc *desc = get_simple_loop_desc (loop); bool exit_at_end = loop_exit_at_end_p (loop); struct opt_info *opt_info = NULL; bool ok; @@ -667,10 +667,10 @@ unroll_loop_constant_iterations (struct loop *loop) /* Decide whether to unroll LOOP iterating runtime computable number of times and how much. */ static void -decide_unroll_runtime_iterations (struct loop *loop, int flags) +decide_unroll_runtime_iterations (class loop *loop, int flags) { unsigned nunroll, nunroll_by_av, i; - struct niter_desc *desc; + class niter_desc *desc; widest_int iterations; /* If we were not asked to unroll this loop, just return back silently. */ @@ -881,7 +881,7 @@ compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, } */ static void -unroll_loop_runtime_iterations (struct loop *loop) +unroll_loop_runtime_iterations (class loop *loop) { rtx old_niter, niter, tmp; rtx_insn *init_code, *branch_code; @@ -894,7 +894,7 @@ unroll_loop_runtime_iterations (struct loop *loop) edge e; bool extra_zero_check, last_may_exit; unsigned max_unroll = loop->lpt_decision.times; - struct niter_desc *desc = get_simple_loop_desc (loop); + class niter_desc *desc = get_simple_loop_desc (loop); bool exit_at_end = loop_exit_at_end_p (loop); struct opt_info *opt_info = NULL; bool ok; @@ -1152,10 +1152,10 @@ unroll_loop_runtime_iterations (struct loop *loop) /* Decide whether to unroll LOOP stupidly and how much. */ static void -decide_unroll_stupid (struct loop *loop, int flags) +decide_unroll_stupid (class loop *loop, int flags) { unsigned nunroll, nunroll_by_av, i; - struct niter_desc *desc; + class niter_desc *desc; widest_int iterations; /* If we were not asked to unroll this loop, just return back silently. */ @@ -1250,10 +1250,10 @@ decide_unroll_stupid (struct loop *loop, int flags) } */ static void -unroll_loop_stupid (struct loop *loop) +unroll_loop_stupid (class loop *loop) { unsigned nunroll = loop->lpt_decision.times; - struct niter_desc *desc = get_simple_loop_desc (loop); + class niter_desc *desc = get_simple_loop_desc (loop); struct opt_info *opt_info = NULL; bool ok; @@ -1301,7 +1301,7 @@ unroll_loop_stupid (struct loop *loop) variable. */ static bool -referenced_in_one_insn_in_loop_p (struct loop *loop, rtx reg, +referenced_in_one_insn_in_loop_p (class loop *loop, rtx reg, int *debug_uses) { basic_block *body, bb; @@ -1329,7 +1329,7 @@ referenced_in_one_insn_in_loop_p (struct loop *loop, rtx reg, /* Reset the DEBUG_USES debug insns in LOOP that reference REG. */ static void -reset_debug_uses_in_loop (struct loop *loop, rtx reg, int debug_uses) +reset_debug_uses_in_loop (class loop *loop, rtx reg, int debug_uses) { basic_block *body, bb; unsigned i; @@ -1378,7 +1378,7 @@ reset_debug_uses_in_loop (struct loop *loop, rtx reg, int debug_uses) */ static struct var_to_expand * -analyze_insn_to_expand_var (struct loop *loop, rtx_insn *insn) +analyze_insn_to_expand_var (class loop *loop, rtx_insn *insn) { rtx set, dest, src; struct var_to_expand *ves; @@ -1519,7 +1519,7 @@ static struct iv_to_split * analyze_iv_to_split_insn (rtx_insn *insn) { rtx set, dest; - struct rtx_iv iv; + class rtx_iv iv; struct iv_to_split *ivts; scalar_int_mode mode; bool ok; @@ -1571,7 +1571,7 @@ analyze_iv_to_split_insn (rtx_insn *insn) is undefined for the return value. */ static struct opt_info * -analyze_insns_in_loop (struct loop *loop) +analyze_insns_in_loop (class loop *loop) { basic_block *body, bb; unsigned i; diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c index e583bca..943da88 100644 --- a/gcc/lra-eliminations.c +++ b/gcc/lra-eliminations.c @@ -100,7 +100,7 @@ public: of eliminating a register in favor of another. If there is more than one way of eliminating a particular register, the most preferred should be specified first. */ -static struct lra_elim_table *reg_eliminate = 0; +static class lra_elim_table *reg_eliminate = 0; /* This is an intermediate structure to initialize the table. It has exactly the members provided by ELIMINABLE_REGS. */ @@ -118,7 +118,7 @@ static const struct elim_table_1 static void print_elim_table (FILE *f) { - struct lra_elim_table *ep; + class lra_elim_table *ep; for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { @@ -142,7 +142,7 @@ lra_debug_elim_table (void) VALUE. Setup FRAME_POINTER_NEEDED if elimination from frame pointer to stack pointer is not possible anymore. */ static void -setup_can_eliminate (struct lra_elim_table *ep, bool value) +setup_can_eliminate (class lra_elim_table *ep, bool value) { ep->can_eliminate = ep->prev_can_eliminate = value; if (! value @@ -156,12 +156,12 @@ setup_can_eliminate (struct lra_elim_table *ep, bool value) or NULL if none. The elimination table may contain more than one elimination for the same hard register, but this map specifies the one that we are currently using. */ -static struct lra_elim_table *elimination_map[FIRST_PSEUDO_REGISTER]; +static class lra_elim_table *elimination_map[FIRST_PSEUDO_REGISTER]; /* When an eliminable hard register becomes not eliminable, we use the following special structure to restore original offsets for the register. */ -static struct lra_elim_table self_elim_table; +static class lra_elim_table self_elim_table; /* Offsets should be used to restore original offsets for eliminable hard register which just became not eliminable. Zero, @@ -177,7 +177,7 @@ static void setup_elimination_map (void) { int i; - struct lra_elim_table *ep; + class lra_elim_table *ep; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) elimination_map[i] = NULL; @@ -242,7 +242,7 @@ form_sum (rtx x, rtx y) int lra_get_elimination_hard_regno (int hard_regno) { - struct lra_elim_table *ep; + class lra_elim_table *ep; if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER) return hard_regno; @@ -253,11 +253,11 @@ lra_get_elimination_hard_regno (int hard_regno) /* Return elimination which will be used for hard reg REG, NULL otherwise. */ -static struct lra_elim_table * +static class lra_elim_table * get_elimination (rtx reg) { int hard_regno; - struct lra_elim_table *ep; + class lra_elim_table *ep; lra_assert (REG_P (reg)); if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER) @@ -334,7 +334,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode, poly_int64 update_sp_offset, bool full_p) { enum rtx_code code = GET_CODE (x); - struct lra_elim_table *ep; + class lra_elim_table *ep; rtx new_rtx; int i, j; const char *fmt; @@ -731,7 +731,7 @@ static void mark_not_eliminable (rtx x, machine_mode mem_mode) { enum rtx_code code = GET_CODE (x); - struct lra_elim_table *ep; + class lra_elim_table *ep; int i, j; const char *fmt; poly_int64 offset = 0; @@ -901,7 +901,7 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, int i; rtx substed_operand[MAX_RECOG_OPERANDS]; rtx orig_operand[MAX_RECOG_OPERANDS]; - struct lra_elim_table *ep; + class lra_elim_table *ep; rtx plus_src, plus_cst_src; lra_insn_recog_data_t id; struct lra_static_insn_data *static_id; @@ -1109,7 +1109,7 @@ static bool update_reg_eliminate (bitmap insns_with_changed_offsets) { bool prev, result; - struct lra_elim_table *ep, *ep1; + class lra_elim_table *ep, *ep1; HARD_REG_SET temp_hard_reg_set; targetm.compute_frame_layout (); @@ -1214,12 +1214,12 @@ update_reg_eliminate (bitmap insns_with_changed_offsets) static void init_elim_table (void) { - struct lra_elim_table *ep; + class lra_elim_table *ep; bool value_p; const struct elim_table_1 *ep1; if (!reg_eliminate) - reg_eliminate = XCNEWVEC (struct lra_elim_table, NUM_ELIMINABLE_REGS); + reg_eliminate = XCNEWVEC (class lra_elim_table, NUM_ELIMINABLE_REGS); memset (self_elim_offsets, 0, sizeof (self_elim_offsets)); /* Initiate member values which will be never changed. */ @@ -1262,7 +1262,7 @@ init_elimination (void) bool stop_to_sp_elimination_p; basic_block bb; rtx_insn *insn; - struct lra_elim_table *ep; + class lra_elim_table *ep; init_elim_table (); FOR_EACH_BB_FN (bb, cfun) @@ -1296,7 +1296,7 @@ void lra_eliminate_reg_if_possible (rtx *loc) { int regno; - struct lra_elim_table *ep; + class lra_elim_table *ep; lra_assert (REG_P (*loc)); if ((regno = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER @@ -1340,7 +1340,7 @@ lra_eliminate (bool final_p, bool first_p) unsigned int uid; bitmap_head insns_with_changed_offsets; bitmap_iterator bi; - struct lra_elim_table *ep; + class lra_elim_table *ep; gcc_assert (! final_p || ! first_p); diff --git a/gcc/lra-int.h b/gcc/lra-int.h index cc47c4d..f8db969 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -119,7 +119,7 @@ public: }; /* References to the common info about each register. */ -extern struct lra_reg *lra_reg_info; +extern class lra_reg *lra_reg_info; extern HARD_REG_SET hard_regs_spilled_into; @@ -244,7 +244,7 @@ public: struct lra_insn_reg *regs; }; -typedef struct lra_insn_recog_data *lra_insn_recog_data_t; +typedef class lra_insn_recog_data *lra_insn_recog_data_t; /* Whether the clobber is used temporary in LRA. */ #define LRA_TEMP_CLOBBER_P(x) \ diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index 975e523..96aa7c4 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -394,7 +394,7 @@ public: }; /* Array for all BB data. Indexed by the corresponding BB index. */ -typedef struct bb_data_pseudos *bb_data_t; +typedef class bb_data_pseudos *bb_data_t; /* All basic block data are referred through the following array. */ static bb_data_t bb_data; @@ -470,7 +470,7 @@ initiate_live_solver (void) { bitmap_initialize (&all_hard_regs_bitmap, ®_obstack); bitmap_set_range (&all_hard_regs_bitmap, 0, FIRST_PSEUDO_REGISTER); - bb_data = XNEWVEC (struct bb_data_pseudos, last_basic_block_for_fn (cfun)); + bb_data = XNEWVEC (class bb_data_pseudos, last_basic_block_for_fn (cfun)); bitmap_initialize (&all_blocks, ®_obstack); basic_block bb; diff --git a/gcc/lra-remat.c b/gcc/lra-remat.c index 51d3543..6a5bf4f 100644 --- a/gcc/lra-remat.c +++ b/gcc/lra-remat.c @@ -145,7 +145,7 @@ public: }; /* Array for all BB data. Indexed by the corresponding BB index. */ -typedef struct remat_bb_data *remat_bb_data_t; +typedef class remat_bb_data *remat_bb_data_t; /* Basic blocks for data flow problems -- all bocks except the special ones. */ @@ -510,7 +510,7 @@ create_remat_bb_data (void) basic_block bb; remat_bb_data_t bb_info; - remat_bb_data = XNEWVEC (struct remat_bb_data, + remat_bb_data = XNEWVEC (class remat_bb_data, last_basic_block_for_fn (cfun)); FOR_ALL_BB_FN (bb, cfun) { diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index 5db94dc..c73d501 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -122,7 +122,7 @@ public: /* Array containing info about the stack slots. The array element is indexed by the stack slot number in the range [0..slots_num). */ -static struct slot *slots; +static class slot *slots; /* The number of the stack slots currently existing. */ static int slots_num; @@ -587,7 +587,7 @@ lra_spill (void) spill_hard_reg[i] = NULL_RTX; pseudo_slots[i].mem = NULL_RTX; } - slots = XNEWVEC (struct slot, regs_num); + slots = XNEWVEC (class slot, regs_num); /* Sort regnos according their usage frequencies. */ qsort (pseudo_regnos, n, sizeof (int), regno_freq_compare); n = assign_spill_hard_regs (pseudo_regnos, n); diff --git a/gcc/lra.c b/gcc/lra.c index 982a3cc..af40f43 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -972,7 +972,7 @@ lra_set_insn_recog_data (rtx_insn *insn) /* It might be a new simple insn which is not recognized yet. */ INSN_CODE (insn) = icode = recog_memoized (insn); } - data = XNEW (struct lra_insn_recog_data); + data = XNEW (class lra_insn_recog_data); lra_insn_recog_data[uid] = data; data->insn = insn; data->used_insn_alternative = LRA_UNKNOWN_ALT; @@ -1306,7 +1306,7 @@ lra_set_used_insn_alternative_by_uid (int uid, int alt) /* The size of the following array. */ static int reg_info_size; /* Common info about each register. */ -struct lra_reg *lra_reg_info; +class lra_reg *lra_reg_info; HARD_REG_SET hard_regs_spilled_into; @@ -1356,7 +1356,7 @@ init_reg_info (void) last_reg_value = 0; reg_info_size = max_reg_num () * 3 / 2 + 1; - lra_reg_info = XNEWVEC (struct lra_reg, reg_info_size); + lra_reg_info = XNEWVEC (class lra_reg, reg_info_size); for (i = 0; i < reg_info_size; i++) initialize_lra_reg_info_element (i); copy_vec.truncate (0); @@ -1385,7 +1385,7 @@ expand_reg_info (void) if (reg_info_size > max_reg_num ()) return; reg_info_size = max_reg_num () * 3 / 2 + 1; - lra_reg_info = XRESIZEVEC (struct lra_reg, lra_reg_info, reg_info_size); + lra_reg_info = XRESIZEVEC (class lra_reg, lra_reg_info, reg_info_size); for (i = old; i < reg_info_size; i++) initialize_lra_reg_info_element (i); } diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 4dfa286..bc0f010 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -1012,7 +1012,7 @@ output_symtab (void) /* Return identifier encoded in IB as a plain string. */ static tree -read_identifier (struct lto_input_block *ib) +read_identifier (class lto_input_block *ib) { unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1); tree id; @@ -1032,7 +1032,7 @@ read_identifier (struct lto_input_block *ib) /* Return string encoded in IB, NULL if string is empty. */ static const char * -read_string (struct lto_input_block *ib) +read_string (class lto_input_block *ib) { unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1); const char *str; @@ -1203,7 +1203,7 @@ get_alias_symbol (tree decl) static struct cgraph_node * input_node (struct lto_file_decl_data *file_data, - struct lto_input_block *ib, + class lto_input_block *ib, enum LTO_symtab_tags tag, vec nodes) { @@ -1326,7 +1326,7 @@ input_node (struct lto_file_decl_data *file_data, static varpool_node * input_varpool_node (struct lto_file_decl_data *file_data, - struct lto_input_block *ib) + class lto_input_block *ib) { int decl_index; tree var_decl; @@ -1402,7 +1402,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, Return the node read or overwriten. */ static void -input_ref (struct lto_input_block *ib, +input_ref (class lto_input_block *ib, symtab_node *referring_node, vec nodes) { @@ -1428,7 +1428,7 @@ input_ref (struct lto_input_block *ib, indirect_unknown_callee set). */ static void -input_edge (struct lto_input_block *ib, vec nodes, +input_edge (class lto_input_block *ib, vec nodes, bool indirect) { struct cgraph_node *caller, *callee; @@ -1496,7 +1496,7 @@ input_edge (struct lto_input_block *ib, vec nodes, static vec input_cgraph_1 (struct lto_file_decl_data *file_data, - struct lto_input_block *ib) + class lto_input_block *ib) { enum LTO_symtab_tags tag; vec nodes = vNULL; @@ -1573,7 +1573,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, /* Input ipa_refs. */ static void -input_refs (struct lto_input_block *ib, +input_refs (class lto_input_block *ib, vec nodes) { int count; @@ -1596,7 +1596,7 @@ input_refs (struct lto_input_block *ib, /* Input profile_info from IB. */ static void -input_profile_summary (struct lto_input_block *ib, +input_profile_summary (class lto_input_block *ib, struct lto_file_decl_data *file_data) { unsigned int runs = streamer_read_uhwi (ib); @@ -1693,7 +1693,7 @@ input_symtab (void) { const char *data; size_t len; - struct lto_input_block *ib; + class lto_input_block *ib; vec nodes; ib = lto_create_simple_input_block (file_data, LTO_section_symtab_nodes, @@ -1750,7 +1750,7 @@ input_offload_tables (bool do_force_output) { const char *data; size_t len; - struct lto_input_block *ib + class lto_input_block *ib = lto_create_simple_input_block (file_data, LTO_section_offload_table, &data, &len); if (!ib) @@ -1909,7 +1909,7 @@ output_cgraph_opt_summary (void) static void input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED, - struct lto_input_block *ib_main ATTRIBUTE_UNUSED) + class lto_input_block *ib_main ATTRIBUTE_UNUSED) { } @@ -1917,8 +1917,8 @@ input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED, static void input_node_opt_summary (struct cgraph_node *node, - struct lto_input_block *ib_main, - struct data_in *data_in) + class lto_input_block *ib_main, + class data_in *data_in) { int i; int count; @@ -1973,7 +1973,7 @@ input_cgraph_opt_section (struct lto_file_decl_data *file_data, const int cfg_offset = sizeof (struct lto_function_header); const int main_offset = cfg_offset + header->cfg_size; const int string_offset = main_offset + header->main_size; - struct data_in *data_in; + class data_in *data_in; unsigned int i; unsigned int count; diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c index 80fdb03..4c28701 100644 --- a/gcc/lto-section-in.c +++ b/gcc/lto-section-in.c @@ -228,7 +228,7 @@ lto_free_raw_section_data (struct lto_file_decl_data *file_data, raw pointer to the section is returned in DATAR and LEN. These are used to free the section. Return NULL if the section is not present. */ -struct lto_input_block * +class lto_input_block * lto_create_simple_input_block (struct lto_file_decl_data *file_data, enum lto_section_type section_type, const char **datar, size_t *len) @@ -257,7 +257,7 @@ lto_create_simple_input_block (struct lto_file_decl_data *file_data, void lto_destroy_simple_input_block (struct lto_file_decl_data *file_data, enum lto_section_type section_type, - struct lto_input_block *ib, + class lto_input_block *ib, const char *data, size_t len) { delete ib; @@ -437,7 +437,7 @@ lto_free_function_in_decl_state_for_node (symtab_node *node) /* Report read pass end of the section. */ void -lto_section_overrun (struct lto_input_block *ib) +lto_section_overrun (class lto_input_block *ib) { fatal_error (input_location, "bytecode stream: trying to read %d bytes " "after the end of the input buffer", ib->p - ib->len); diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 49fd573..155805b 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -84,7 +84,7 @@ lto_tag_check_set (enum LTO_tags actual, int ntags, ...) /* Read LENGTH bytes from STREAM to ADDR. */ void -lto_input_data_block (struct lto_input_block *ib, void *addr, size_t length) +lto_input_data_block (class lto_input_block *ib, void *addr, size_t length) { size_t i; unsigned char *const buffer = (unsigned char *) addr; @@ -232,7 +232,7 @@ lto_location_cache::revert_location_cache () void lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, - struct data_in *data_in) + class data_in *data_in) { static const char *stream_file; static int stream_line; @@ -287,7 +287,7 @@ lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, void lto_input_location (location_t *loc, struct bitpack_d *bp, - struct data_in *data_in) + class data_in *data_in) { data_in->location_cache.input_location (loc, bp, data_in); } @@ -297,7 +297,7 @@ lto_input_location (location_t *loc, struct bitpack_d *bp, discarded. */ location_t -stream_input_location_now (struct bitpack_d *bp, struct data_in *data_in) +stream_input_location_now (struct bitpack_d *bp, class data_in *data_in) { location_t loc; stream_input_location (&loc, bp, data_in); @@ -313,7 +313,7 @@ stream_input_location_now (struct bitpack_d *bp, struct data_in *data_in) function scope for the read tree. */ tree -lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in, +lto_input_tree_ref (class lto_input_block *ib, class data_in *data_in, struct function *fn, enum LTO_tags tag) { unsigned HOST_WIDE_INT ix_u; @@ -378,7 +378,7 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in, block IB, using descriptors in DATA_IN. */ static struct eh_catch_d * -lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in, +lto_input_eh_catch_list (class lto_input_block *ib, class data_in *data_in, eh_catch *last_p) { eh_catch first; @@ -424,7 +424,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in, in DATA_IN. */ static eh_region -input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix) +input_eh_region (class lto_input_block *ib, class data_in *data_in, int ix) { enum LTO_tags tag; eh_region r; @@ -499,7 +499,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix) in DATA_IN. */ static eh_landing_pad -input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix) +input_eh_lp (class lto_input_block *ib, class data_in *data_in, int ix) { enum LTO_tags tag; eh_landing_pad lp; @@ -603,7 +603,7 @@ lto_init_eh (void) in DATA_IN. */ static void -input_eh_regions (struct lto_input_block *ib, struct data_in *data_in, +input_eh_regions (class lto_input_block *ib, class data_in *data_in, struct function *fn) { HOST_WIDE_INT i, root_region, len; @@ -714,7 +714,7 @@ make_new_block (struct function *fn, unsigned int index) /* Read the CFG for function FN from input block IB. */ static void -input_cfg (struct lto_input_block *ib, struct data_in *data_in, +input_cfg (class lto_input_block *ib, class data_in *data_in, struct function *fn) { unsigned int bb_count; @@ -807,7 +807,7 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in, continue; } - struct loop *loop = alloc_loop (); + class loop *loop = alloc_loop (); loop->header = BASIC_BLOCK_FOR_FN (fn, header_index); loop->header->loop_father = loop; @@ -847,7 +847,7 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in, block IB. */ static void -input_ssa_names (struct lto_input_block *ib, struct data_in *data_in, +input_ssa_names (class lto_input_block *ib, class data_in *data_in, struct function *fn) { unsigned int i, size; @@ -964,8 +964,8 @@ fixup_call_stmt_edges (struct cgraph_node *orig, gimple **stmts) using input block IB. */ static void -input_struct_function_base (struct function *fn, struct data_in *data_in, - struct lto_input_block *ib) +input_struct_function_base (struct function *fn, class data_in *data_in, + class lto_input_block *ib) { struct bitpack_d bp; int len; @@ -1029,8 +1029,8 @@ input_struct_function_base (struct function *fn, struct data_in *data_in, /* Read the body of function FN_DECL from DATA_IN using input block IB. */ static void -input_function (tree fn_decl, struct data_in *data_in, - struct lto_input_block *ib, struct lto_input_block *ib_cfg) +input_function (tree fn_decl, class data_in *data_in, + class lto_input_block *ib, class lto_input_block *ib_cfg) { struct function *fn; enum LTO_tags tag; @@ -1233,8 +1233,8 @@ input_function (tree fn_decl, struct data_in *data_in, /* Read the body of function FN_DECL from DATA_IN using input block IB. */ static void -input_constructor (tree var, struct data_in *data_in, - struct lto_input_block *ib) +input_constructor (tree var, class data_in *data_in, + class lto_input_block *ib) { DECL_INITIAL (var) = stream_read_tree (ib, data_in); } @@ -1251,7 +1251,7 @@ lto_read_body_or_constructor (struct lto_file_decl_data *file_data, struct symta const char *data, enum lto_section_type section_type) { const struct lto_function_header *header; - struct data_in *data_in; + class data_in *data_in; int cfg_offset; int main_offset; int string_offset; @@ -1364,7 +1364,7 @@ vec dref_queue; input block IB using the per-file context in DATA_IN. */ static void -lto_read_tree_1 (struct lto_input_block *ib, struct data_in *data_in, tree expr) +lto_read_tree_1 (class lto_input_block *ib, class data_in *data_in, tree expr) { /* Read all the bitfield values in EXPR. Note that for LTO, we only write language-independent bitfields, so no more unpacking is @@ -1402,7 +1402,7 @@ lto_read_tree_1 (struct lto_input_block *ib, struct data_in *data_in, tree expr) input block IB using the per-file context in DATA_IN. */ static tree -lto_read_tree (struct lto_input_block *ib, struct data_in *data_in, +lto_read_tree (class lto_input_block *ib, class data_in *data_in, enum LTO_tags tag, hashval_t hash) { /* Instantiate a new tree node. */ @@ -1425,7 +1425,7 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in, following in the IB, DATA_IN stream. */ hashval_t -lto_input_scc (struct lto_input_block *ib, struct data_in *data_in, +lto_input_scc (class lto_input_block *ib, class data_in *data_in, unsigned *len, unsigned *entry_len) { /* A blob of unnamed tree nodes, fill the cache from it and @@ -1482,7 +1482,7 @@ lto_input_scc (struct lto_input_block *ib, struct data_in *data_in, to previously read nodes. */ tree -lto_input_tree_1 (struct lto_input_block *ib, struct data_in *data_in, +lto_input_tree_1 (class lto_input_block *ib, class data_in *data_in, enum LTO_tags tag, hashval_t hash) { tree result; @@ -1532,7 +1532,7 @@ lto_input_tree_1 (struct lto_input_block *ib, struct data_in *data_in, } tree -lto_input_tree (struct lto_input_block *ib, struct data_in *data_in) +lto_input_tree (class lto_input_block *ib, class data_in *data_in) { enum LTO_tags tag; @@ -1564,7 +1564,7 @@ lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base) const struct lto_simple_header_with_strings *header = (const struct lto_simple_header_with_strings *) data; int string_offset; - struct data_in *data_in; + class data_in *data_in; tree str; if (! data) @@ -1612,7 +1612,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data) const struct lto_simple_header_with_strings *header = (const struct lto_simple_header_with_strings *) data; int string_offset; - struct data_in *data_in; + class data_in *data_in; string_offset = sizeof (*header) + header->main_size; lto_input_block ib (data + sizeof (*header), header->main_size, NULL); @@ -1727,12 +1727,12 @@ lto_reader_init (void) table to use with LEN strings. RESOLUTIONS is the vector of linker resolutions (NULL if not using a linker plugin). */ -struct data_in * +class data_in * lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings, unsigned len, vec resolutions) { - struct data_in *data_in = new (struct data_in); + class data_in *data_in = new (class data_in); data_in->file_data = file_data; data_in->strings = strings; data_in->strings_len = len; @@ -1745,7 +1745,7 @@ lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings, /* Remove DATA_IN. */ void -lto_data_in_delete (struct data_in *data_in) +lto_data_in_delete (class data_in *data_in) { data_in->globals_resolution.release (); streamer_tree_cache_delete (data_in->reader_cache); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 49ca5ce..35dcae4 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1911,7 +1911,7 @@ output_cfg (struct output_block *ob, struct function *fn) /* Output each loop, skipping the tree root which has number zero. */ for (unsigned i = 1; i < number_of_loops (fn); ++i) { - struct loop *loop = get_loop (fn, i); + class loop *loop = get_loop (fn, i); /* Write the index of the loop header. That's enough to rebuild the loop tree on the reader side. Stream -1 for an unused diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index d5dbeb7..3c35d8a 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -308,7 +308,7 @@ public: /* Tree merging did suceed; throw away recent changes. */ void revert_location_cache (); void input_location (location_t *loc, struct bitpack_d *bp, - struct data_in *data_in); + class data_in *data_in); lto_location_cache () : loc_cache (), accepted_length (0), current_file (NULL), current_line (0), current_col (0), current_sysp (false), current_loc (UNKNOWN_LOCATION) @@ -759,13 +759,13 @@ public: /* In lto-section-in.c */ -extern struct lto_input_block * lto_create_simple_input_block ( +extern class lto_input_block * lto_create_simple_input_block ( struct lto_file_decl_data *, enum lto_section_type, const char **, size_t *); extern void lto_destroy_simple_input_block (struct lto_file_decl_data *, enum lto_section_type, - struct lto_input_block *, const char *, size_t); + class lto_input_block *, const char *, size_t); extern void lto_set_in_hooks (struct lto_file_decl_data **, lto_get_section_data_f *, lto_free_section_data_f *); @@ -795,7 +795,7 @@ extern struct lto_in_decl_state *lto_get_function_in_decl_state ( struct lto_file_decl_data *, tree); extern void lto_free_function_in_decl_state (struct lto_in_decl_state *); extern void lto_free_function_in_decl_state_for_node (symtab_node *); -extern void lto_section_overrun (struct lto_input_block *) ATTRIBUTE_NORETURN; +extern void lto_section_overrun (class lto_input_block *) ATTRIBUTE_NORETURN; extern void lto_value_range_error (const char *, HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT) ATTRIBUTE_NORETURN; @@ -860,23 +860,23 @@ extern void lto_input_constructors_and_inits (struct lto_file_decl_data *, const char *); extern void lto_input_toplevel_asms (struct lto_file_decl_data *, int); extern void lto_input_mode_table (struct lto_file_decl_data *); -extern struct data_in *lto_data_in_create (struct lto_file_decl_data *, +extern class data_in *lto_data_in_create (struct lto_file_decl_data *, const char *, unsigned, vec ); -extern void lto_data_in_delete (struct data_in *); -extern void lto_input_data_block (struct lto_input_block *, void *, size_t); -void lto_input_location (location_t *, struct bitpack_d *, struct data_in *); +extern void lto_data_in_delete (class data_in *); +extern void lto_input_data_block (class lto_input_block *, void *, size_t); +void lto_input_location (location_t *, struct bitpack_d *, class data_in *); location_t stream_input_location_now (struct bitpack_d *bp, - struct data_in *data); -tree lto_input_tree_ref (struct lto_input_block *, struct data_in *, + class data_in *data); +tree lto_input_tree_ref (class lto_input_block *, class data_in *, struct function *, enum LTO_tags); void lto_tag_check_set (enum LTO_tags, int, ...); void lto_init_eh (void); -hashval_t lto_input_scc (struct lto_input_block *, struct data_in *, +hashval_t lto_input_scc (class lto_input_block *, class data_in *, unsigned *, unsigned *); -tree lto_input_tree_1 (struct lto_input_block *, struct data_in *, +tree lto_input_tree_1 (class lto_input_block *, class data_in *, enum LTO_tags, hashval_t hash); -tree lto_input_tree (struct lto_input_block *, struct data_in *); +tree lto_input_tree (class lto_input_block *, class data_in *); /* In lto-streamer-out.c */ @@ -931,14 +931,14 @@ void select_what_to_stream (void); void cl_target_option_stream_out (struct output_block *, struct bitpack_d *, struct cl_target_option *); -void cl_target_option_stream_in (struct data_in *, +void cl_target_option_stream_in (class data_in *, struct bitpack_d *, struct cl_target_option *); void cl_optimization_stream_out (struct output_block *, struct bitpack_d *, struct cl_optimization *); -void cl_optimization_stream_in (struct data_in *, +void cl_optimization_stream_in (class data_in *, struct bitpack_d *, struct cl_optimization *); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index f3796f5..83d166d 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,6 +1,18 @@ 2019-07-09 Martin Sebor PR c++/61339 + * lto-common.c (lto_splay_tree_new): : Change class-key of PODs + to struct and others to class. + (mentions_vars_p): Same. + (register_resolution): Same. + (lto_register_var_decl_in_symtab): Same. + (lto_register_function_decl_in_symtab): Same. + (cmp_tree): Same. + (lto_read_decls): Same. + +2019-07-09 Martin Sebor + + PR c++/61339 * lto-dump.c: Change class-key from class to struct and vice versa to match convention and avoid -Wclass-is-pod and -Wstruct-no-pod. diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c index 3c6d7b2..c9d9781 100644 --- a/gcc/lto/lto-common.c +++ b/gcc/lto/lto-common.c @@ -179,7 +179,7 @@ lto_splay_tree_new (void) input. */ static const uint32_t * -lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data, +lto_read_in_decl_state (class data_in *data_in, const uint32_t *data, struct lto_in_decl_state *state) { uint32_t ix; @@ -868,7 +868,7 @@ mentions_vars_p (tree t) /* Return the resolution for the decl with index INDEX from DATA_IN. */ static enum ld_plugin_symbol_resolution -get_resolution (struct data_in *data_in, unsigned index) +get_resolution (class data_in *data_in, unsigned index) { if (data_in->globals_resolution.exists ()) { @@ -911,7 +911,7 @@ register_resolution (struct lto_file_decl_data *file_data, tree decl, different files. */ static void -lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl, +lto_register_var_decl_in_symtab (class data_in *data_in, tree decl, unsigned ix) { tree context; @@ -936,7 +936,7 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl, file being read. */ static void -lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl, +lto_register_function_decl_in_symtab (class data_in *data_in, tree decl, unsigned ix) { /* If this variable has already been declared, queue the @@ -949,7 +949,7 @@ lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl, /* Check if T is a decl and needs register its resolution info. */ static void -lto_maybe_register_decl (struct data_in *data_in, tree t, unsigned ix) +lto_maybe_register_decl (class data_in *data_in, tree t, unsigned ix) { if (TREE_CODE (t) == VAR_DECL) lto_register_var_decl_in_symtab (data_in, t, ix); @@ -1624,7 +1624,7 @@ cmp_tree (const void *p1_, const void *p2_) that was successful, otherwise return false. */ static bool -unify_scc (struct data_in *data_in, unsigned from, +unify_scc (class data_in *data_in, unsigned from, unsigned len, unsigned scc_entry_len, hashval_t scc_hash) { bool unified_p = false; @@ -1787,7 +1787,7 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, const int decl_offset = sizeof (struct lto_decl_header); const int main_offset = decl_offset + header->decl_state_size; const int string_offset = main_offset + header->main_size; - struct data_in *data_in; + class data_in *data_in; unsigned int i; const uint32_t *data_ptr, *data_end; uint32_t num_decl_states; diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 9954ea5..c355594 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -211,7 +211,7 @@ static int sms_order_nodes (ddg_ptr, int, int *, int *); static void set_node_sched_params (ddg_ptr); static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *); static void permute_partial_schedule (partial_schedule_ptr, rtx_insn *); -static void generate_prolog_epilog (partial_schedule_ptr, struct loop *, +static void generate_prolog_epilog (partial_schedule_ptr, class loop *, rtx, rtx); static int calculate_stage_count (partial_schedule_ptr, int); static void calculate_must_precede_follow (ddg_node_ptr, int, int, @@ -1124,7 +1124,7 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage, /* Generate the instructions (including reg_moves) for prolog & epilog. */ static void -generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop, +generate_prolog_epilog (partial_schedule_ptr ps, class loop *loop, rtx count_reg, rtx count_init) { int i; @@ -1181,7 +1181,7 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop, /* Mark LOOP as software pipelined so the later scheduling passes don't touch it. */ static void -mark_loop_unsched (struct loop *loop) +mark_loop_unsched (class loop *loop) { unsigned i; basic_block *bbs = get_loop_body (loop); @@ -1195,7 +1195,7 @@ mark_loop_unsched (struct loop *loop) /* Return true if all the BBs of the loop are empty except the loop header. */ static bool -loop_single_full_bb_p (struct loop *loop) +loop_single_full_bb_p (class loop *loop) { unsigned i; basic_block *bbs = get_loop_body (loop); @@ -1251,7 +1251,7 @@ dump_insn_location (rtx_insn *insn) /* Return true if the loop is in its canonical form and false if not. i.e. SIMPLE_SMS_LOOP_P and have one preheader block, and single exit. */ static bool -loop_canon_p (struct loop *loop) +loop_canon_p (class loop *loop) { if (loop->inner || !loop_outer (loop)) @@ -1294,7 +1294,7 @@ loop_canon_p (struct loop *loop) make it one by splitting the first entry edge and redirecting the others to the new BB. */ static void -canon_loop (struct loop *loop) +canon_loop (class loop *loop) { edge e; edge_iterator i; @@ -1346,7 +1346,7 @@ sms_schedule (void) int maxii, max_asap; partial_schedule_ptr ps; basic_block bb = NULL; - struct loop *loop; + class loop *loop; basic_block condition_bb = NULL; edge latch_edge; HOST_WIDE_INT trip_count, max_trip_count; diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c index 1de445b..c007ec1 100644 --- a/gcc/omp-expand.c +++ b/gcc/omp-expand.c @@ -2516,7 +2516,7 @@ expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts, if (e2) { - struct loop *loop = alloc_loop (); + class loop *loop = alloc_loop (); loop->header = new_header; loop->latch = e2->src; add_loop (loop, body_bb->loop_father); @@ -3477,14 +3477,14 @@ expand_omp_for_generic (struct omp_region *region, /* We enter expand_omp_for_generic with a loop. This original loop may have its own loop struct, or it may be part of an outer loop struct (which may be the fake loop). */ - struct loop *outer_loop = entry_bb->loop_father; + class loop *outer_loop = entry_bb->loop_father; bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop; add_bb_to_loop (l2_bb, outer_loop); /* We've added a new loop around the original loop. Allocate the corresponding loop struct. */ - struct loop *new_loop = alloc_loop (); + class loop *new_loop = alloc_loop (); new_loop->header = l0_bb; new_loop->latch = l2_bb; add_loop (new_loop, outer_loop); @@ -3494,7 +3494,7 @@ expand_omp_for_generic (struct omp_region *region, if (!orig_loop_has_loop_struct && !gimple_omp_for_combined_p (fd->for_stmt)) { - struct loop *orig_loop = alloc_loop (); + class loop *orig_loop = alloc_loop (); orig_loop->header = l1_bb; /* The loop may have multiple latches. */ add_loop (orig_loop, new_loop); @@ -4356,7 +4356,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, set_immediate_dominator (CDI_DOMINATORS, exit3_bb, exit_bb); } - struct loop *loop = body_bb->loop_father; + class loop *loop = body_bb->loop_father; if (loop != entry_bb->loop_father) { gcc_assert (broken_loop || loop->header == body_bb); @@ -5104,8 +5104,8 @@ expand_omp_for_static_chunk (struct omp_region *region, if (!broken_loop) { - struct loop *loop = body_bb->loop_father; - struct loop *trip_loop = alloc_loop (); + class loop *loop = body_bb->loop_father; + class loop *trip_loop = alloc_loop (); trip_loop->header = iter_part_bb; trip_loop->latch = trip_update_bb; add_loop (trip_loop, iter_part_bb->loop_father); @@ -5523,7 +5523,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd) if (!broken_loop) { - struct loop *loop = alloc_loop (); + class loop *loop = alloc_loop (); loop->header = l1_bb; loop->latch = cont_bb; add_loop (loop, l1_bb->loop_father); @@ -5944,7 +5944,7 @@ expand_omp_taskloop_for_inner (struct omp_region *region, if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt)) { - struct loop *loop = alloc_loop (); + class loop *loop = alloc_loop (); loop->header = body_bb; if (collapse_bb == NULL) loop->latch = cont_bb; @@ -6461,12 +6461,12 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd) { /* We now have one, two or three nested loops. Update the loop structures. */ - struct loop *parent = entry_bb->loop_father; - struct loop *body = body_bb->loop_father; + class loop *parent = entry_bb->loop_father; + class loop *body = body_bb->loop_father; if (chunking) { - struct loop *chunk_loop = alloc_loop (); + class loop *chunk_loop = alloc_loop (); chunk_loop->header = head_bb; chunk_loop->latch = bottom_bb; add_loop (chunk_loop, parent); @@ -6482,7 +6482,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd) if (parent) { - struct loop *body_loop = alloc_loop (); + class loop *body_loop = alloc_loop (); body_loop->header = body_bb; body_loop->latch = cont_bb; add_loop (body_loop, parent); @@ -6490,7 +6490,7 @@ expand_oacc_for (struct omp_region *region, struct omp_for_data *fd) if (fd->tiling) { /* Insert tiling's element loop. */ - struct loop *inner_loop = alloc_loop (); + class loop *inner_loop = alloc_loop (); inner_loop->header = elem_body_bb; inner_loop->latch = elem_cont_bb; add_loop (inner_loop, body_loop); @@ -7475,7 +7475,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, /* Remove GIMPLE_OMP_ATOMIC_STORE. */ gsi_remove (&si, true); - struct loop *loop = alloc_loop (); + class loop *loop = alloc_loop (); loop->header = loop_header; loop->latch = store_bb; add_loop (loop, loop_header->loop_father); @@ -7625,14 +7625,14 @@ static void mark_loops_in_oacc_kernels_region (basic_block region_entry, basic_block region_exit) { - struct loop *outer = region_entry->loop_father; + class loop *outer = region_entry->loop_father; gcc_assert (region_exit == NULL || outer == region_exit->loop_father); /* Don't parallelize the kernels region if it contains more than one outer loop. */ unsigned int nr_outer_loops = 0; - struct loop *single_outer = NULL; - for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next) + class loop *single_outer = NULL; + for (class loop *loop = outer->inner; loop != NULL; loop = loop->next) { gcc_assert (loop_outer (loop) == outer); @@ -7649,14 +7649,14 @@ mark_loops_in_oacc_kernels_region (basic_block region_entry, if (nr_outer_loops != 1) return; - for (struct loop *loop = single_outer->inner; + for (class loop *loop = single_outer->inner; loop != NULL; loop = loop->inner) if (loop->next) return; /* Mark the loops in the region. */ - for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner) + for (class loop *loop = single_outer; loop != NULL; loop = loop->inner) loop->in_oacc_kernels_region = true; } diff --git a/gcc/omp-offload.c b/gcc/omp-offload.c index c8a281c..da788d9 100644 --- a/gcc/omp-offload.c +++ b/gcc/omp-offload.c @@ -389,8 +389,8 @@ oacc_xform_loop (gcall *call) || !global_options_set.x_flag_tree_loop_vectorize)) { basic_block bb = gsi_bb (gsi); - struct loop *parent = bb->loop_father; - struct loop *body = parent->inner; + class loop *parent = bb->loop_father; + class loop *body = parent->inner; parent->force_vectorize = true; parent->safelen = INT_MAX; diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c index 472e202..caa8da3 100644 --- a/gcc/omp-simd-clone.c +++ b/gcc/omp-simd-clone.c @@ -1194,7 +1194,7 @@ simd_clone_adjust (struct cgraph_node *node) gimple *g; basic_block incr_bb = NULL; - struct loop *loop = NULL; + class loop *loop = NULL; /* Create a new BB right before the original exit BB, to hold the iteration increment and the condition/branch. */ diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c index 4116bfe..2a06696 100644 --- a/gcc/optabs-query.c +++ b/gcc/optabs-query.c @@ -120,7 +120,7 @@ get_traditional_extraction_insn (extraction_insn *insn, POS_OP is the operand number of the bit position. */ static bool -get_optab_extraction_insn (struct extraction_insn *insn, +get_optab_extraction_insn (class extraction_insn *insn, enum extraction_type type, machine_mode mode, direct_optab reg_optab, direct_optab misalign_optab, int pos_op) diff --git a/gcc/optabs.c b/gcc/optabs.c index 18ca737..193cd91 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -250,7 +250,7 @@ rtx expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op, rtx target, int unsignedp) { - struct expand_operand eops[4]; + class expand_operand eops[4]; tree oprnd0, oprnd1, oprnd2; machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode; optab widen_pattern_optab; @@ -344,7 +344,7 @@ rtx expand_ternary_op (machine_mode mode, optab ternary_optab, rtx op0, rtx op1, rtx op2, rtx target, int unsignedp) { - struct expand_operand ops[4]; + class expand_operand ops[4]; enum insn_code icode = optab_handler (ternary_optab, mode); gcc_assert (optab_handler (ternary_optab, mode) != CODE_FOR_nothing); @@ -413,7 +413,7 @@ expand_vector_broadcast (machine_mode vmode, rtx op) insn_code icode = optab_handler (vec_duplicate_optab, vmode); if (icode != CODE_FOR_nothing) { - struct expand_operand ops[2]; + class expand_operand ops[2]; create_output_operand (&ops[0], NULL_RTX, vmode); create_input_operand (&ops[1], op, GET_MODE (op)); expand_insn (icode, 2, ops); @@ -1039,7 +1039,7 @@ expand_binop_directly (enum insn_code icode, machine_mode mode, optab binoptab, machine_mode xmode0 = insn_data[(int) icode].operand[1].mode; machine_mode xmode1 = insn_data[(int) icode].operand[2].mode; machine_mode mode0, mode1, tmp_mode; - struct expand_operand ops[3]; + class expand_operand ops[3]; bool commutative_p; rtx_insn *pat; rtx xop0 = op0, xop1 = op1; @@ -2012,7 +2012,7 @@ expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1, if (optab_handler (unoptab, mode) != CODE_FOR_nothing) { - struct expand_operand ops[3]; + class expand_operand ops[3]; enum insn_code icode = optab_handler (unoptab, mode); create_fixed_operand (&ops[0], targ0); @@ -2084,7 +2084,7 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1, if (optab_handler (binoptab, mode) != CODE_FOR_nothing) { - struct expand_operand ops[4]; + class expand_operand ops[4]; enum insn_code icode = optab_handler (binoptab, mode); machine_mode mode0 = insn_data[icode].operand[1].mode; machine_mode mode1 = insn_data[icode].operand[2].mode; @@ -2724,7 +2724,7 @@ expand_unop_direct (machine_mode mode, optab unoptab, rtx op0, rtx target, { if (optab_handler (unoptab, mode) != CODE_FOR_nothing) { - struct expand_operand ops[2]; + class expand_operand ops[2]; enum insn_code icode = optab_handler (unoptab, mode); rtx_insn *last = get_last_insn (); rtx_insn *pat; @@ -3578,7 +3578,7 @@ bool maybe_emit_unop_insn (enum insn_code icode, rtx target, rtx op0, enum rtx_code code) { - struct expand_operand ops[2]; + class expand_operand ops[2]; rtx_insn *pat; create_output_operand (&ops[0], target, GET_MODE (target)); @@ -4289,7 +4289,7 @@ emit_indirect_jump (rtx loc) sorry ("indirect jumps are not available on this target"); else { - struct expand_operand ops[1]; + class expand_operand ops[1]; create_address_operand (&ops[0], loc); expand_jump_insn (targetm.code_for_indirect_jump, 1, ops); emit_barrier (); @@ -4394,7 +4394,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, OPTAB_WIDEN, &comparison, &cmpmode); if (comparison) { - struct expand_operand ops[4]; + class expand_operand ops[4]; create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], comparison); @@ -4460,7 +4460,7 @@ emit_conditional_neg_or_complement (rtx target, rtx_code code, target = gen_reg_rtx (mode); rtx_insn *last = get_last_insn (); - struct expand_operand ops[4]; + class expand_operand ops[4]; create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], cond); @@ -4548,7 +4548,7 @@ emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1, &comparison, &cmode); if (comparison) { - struct expand_operand ops[4]; + class expand_operand ops[4]; create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], comparison); @@ -5414,7 +5414,7 @@ vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode, tree t_op0, tree t_op1, bool unsignedp, enum insn_code icode, unsigned int opno) { - struct expand_operand ops[2]; + class expand_operand ops[2]; rtx rtx_op0, rtx_op1; machine_mode m0, m1; enum rtx_code rcode = get_rtx_code (tcode, unsignedp); @@ -5509,7 +5509,7 @@ expand_vec_perm_1 (enum insn_code icode, rtx target, { machine_mode tmode = GET_MODE (target); machine_mode smode = GET_MODE (sel); - struct expand_operand ops[4]; + class expand_operand ops[4]; gcc_assert (GET_MODE_CLASS (smode) == MODE_VECTOR_INT || mode_for_int_vector (tmode).require () == smode); @@ -5596,7 +5596,7 @@ expand_vec_perm_const (machine_mode mode, rtx v0, rtx v1, rtx shift_amt = shift_amt_for_vec_perm_mask (mode, indices, shift_optab); if (shift_amt) { - struct expand_operand ops[3]; + class expand_operand ops[3]; if (shift_code != CODE_FOR_nothing) { create_output_operand (&ops[0], target, mode); @@ -5782,7 +5782,7 @@ rtx expand_vec_cond_mask_expr (tree vec_cond_type, tree op0, tree op1, tree op2, rtx target) { - struct expand_operand ops[4]; + class expand_operand ops[4]; machine_mode mode = TYPE_MODE (vec_cond_type); machine_mode mask_mode = TYPE_MODE (TREE_TYPE (op0)); enum insn_code icode = get_vcond_mask_icode (mode, mask_mode); @@ -5814,7 +5814,7 @@ rtx expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2, rtx target) { - struct expand_operand ops[6]; + class expand_operand ops[6]; enum insn_code icode; rtx comparison, rtx_op1, rtx_op2; machine_mode mode = TYPE_MODE (vec_cond_type); @@ -5884,7 +5884,7 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2, rtx expand_vec_series_expr (machine_mode vmode, rtx op0, rtx op1, rtx target) { - struct expand_operand ops[3]; + class expand_operand ops[3]; enum insn_code icode; machine_mode emode = GET_MODE_INNER (vmode); @@ -5904,7 +5904,7 @@ expand_vec_series_expr (machine_mode vmode, rtx op0, rtx op1, rtx target) rtx expand_vec_cmp_expr (tree type, tree exp, rtx target) { - struct expand_operand ops[4]; + class expand_operand ops[4]; enum insn_code icode; rtx comparison; machine_mode mask_mode = TYPE_MODE (type); @@ -5945,7 +5945,7 @@ rtx expand_mult_highpart (machine_mode mode, rtx op0, rtx op1, rtx target, bool uns_p) { - struct expand_operand eops[3]; + class expand_operand eops[3]; enum insn_code icode; int method, i; machine_mode wmode; @@ -6098,7 +6098,7 @@ maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model) icode = direct_optab_handler (atomic_exchange_optab, mode); if (icode != CODE_FOR_nothing) { - struct expand_operand ops[4]; + class expand_operand ops[4]; create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); @@ -6136,7 +6136,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val, if (icode != CODE_FOR_nothing) { - struct expand_operand ops[3]; + class expand_operand ops[3]; create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); create_input_operand (&ops[2], val, mode); @@ -6196,7 +6196,7 @@ static rtx maybe_emit_atomic_test_and_set (rtx target, rtx mem, enum memmodel model) { machine_mode pat_bool_mode; - struct expand_operand ops[3]; + class expand_operand ops[3]; if (!targetm.have_atomic_test_and_set ()) return NULL_RTX; @@ -6366,7 +6366,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval, enum memmodel fail_model) { machine_mode mode = GET_MODE (mem); - struct expand_operand ops[8]; + class expand_operand ops[8]; enum insn_code icode; rtx target_oval, target_bool = NULL_RTX; rtx libfunc; @@ -6568,7 +6568,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model) icode = direct_optab_handler (atomic_load_optab, mode); if (icode != CODE_FOR_nothing) { - struct expand_operand ops[3]; + class expand_operand ops[3]; rtx_insn *last = get_last_insn (); if (is_mm_seq_cst (model)) expand_memory_blockage (); @@ -6621,7 +6621,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) { machine_mode mode = GET_MODE (mem); enum insn_code icode; - struct expand_operand ops[3]; + class expand_operand ops[3]; /* If the target supports the store directly, great. */ icode = direct_optab_handler (atomic_store_optab, mode); @@ -6831,7 +6831,7 @@ maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem, rtx val, bool use_memmodel, enum memmodel model, bool after) { machine_mode mode = GET_MODE (mem); - struct expand_operand ops[4]; + class expand_operand ops[4]; enum insn_code icode; int op_counter = 0; int num_ops; @@ -7145,7 +7145,7 @@ valid_multiword_target_p (rtx target) of that rtx if so. */ void -create_integer_operand (struct expand_operand *op, poly_int64 intval) +create_integer_operand (class expand_operand *op, poly_int64 intval) { create_expand_operand (op, EXPAND_INTEGER, gen_int_mode (intval, MAX_MODE_INT), @@ -7157,7 +7157,7 @@ create_integer_operand (struct expand_operand *op, poly_int64 intval) static bool maybe_legitimize_operand_same_code (enum insn_code icode, unsigned int opno, - struct expand_operand *op) + class expand_operand *op) { /* See if the operand matches in its current form. */ if (insn_operand_matches (icode, opno, op->value)) @@ -7199,7 +7199,7 @@ maybe_legitimize_operand_same_code (enum insn_code icode, unsigned int opno, static bool maybe_legitimize_operand (enum insn_code icode, unsigned int opno, - struct expand_operand *op) + class expand_operand *op) { machine_mode mode, imode; bool old_volatile_ok, result; @@ -7281,7 +7281,7 @@ maybe_legitimize_operand (enum insn_code icode, unsigned int opno, TYPE is the type of VALUE. */ void -create_convert_operand_from_type (struct expand_operand *op, +create_convert_operand_from_type (class expand_operand *op, rtx value, tree type) { create_convert_operand_from (op, value, TYPE_MODE (type), @@ -7296,8 +7296,8 @@ create_convert_operand_from_type (struct expand_operand *op, static inline bool can_reuse_operands_p (enum insn_code icode, unsigned int opno1, unsigned int opno2, - const struct expand_operand *op1, - const struct expand_operand *op2) + const class expand_operand *op1, + const class expand_operand *op2) { /* Check requirements that are common to all types. */ if (op1->type != op2->type @@ -7332,7 +7332,7 @@ can_reuse_operands_p (enum insn_code icode, bool maybe_legitimize_operands (enum insn_code icode, unsigned int opno, - unsigned int nops, struct expand_operand *ops) + unsigned int nops, class expand_operand *ops) { rtx_insn *last = get_last_insn (); rtx *orig_values = XALLOCAVEC (rtx, nops); @@ -7374,7 +7374,7 @@ maybe_legitimize_operands (enum insn_code icode, unsigned int opno, rtx_insn * maybe_gen_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops) + class expand_operand *ops) { gcc_assert (nops == (unsigned int) insn_data[(int) icode].n_generator_args); if (!maybe_legitimize_operands (icode, 0, nops, ops)) @@ -7418,7 +7418,7 @@ maybe_gen_insn (enum insn_code icode, unsigned int nops, bool maybe_expand_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops) + class expand_operand *ops) { rtx_insn *pat = maybe_gen_insn (icode, nops, ops); if (pat) @@ -7433,7 +7433,7 @@ maybe_expand_insn (enum insn_code icode, unsigned int nops, bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops) + class expand_operand *ops) { rtx_insn *pat = maybe_gen_insn (icode, nops, ops); if (pat) @@ -7449,7 +7449,7 @@ maybe_expand_jump_insn (enum insn_code icode, unsigned int nops, void expand_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops) + class expand_operand *ops) { if (!maybe_expand_insn (icode, nops, ops)) gcc_unreachable (); @@ -7459,7 +7459,7 @@ expand_insn (enum insn_code icode, unsigned int nops, void expand_jump_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops) + class expand_operand *ops) { if (!maybe_expand_jump_insn (icode, nops, ops)) gcc_unreachable (); diff --git a/gcc/optabs.h b/gcc/optabs.h index ca7e063..0654107 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -71,7 +71,7 @@ public: to their default values. */ static inline void -create_expand_operand (struct expand_operand *op, +create_expand_operand (class expand_operand *op, enum expand_operand_type type, rtx value, machine_mode mode, bool unsigned_p, poly_int64 int_value = 0) @@ -87,7 +87,7 @@ create_expand_operand (struct expand_operand *op, /* Make OP describe an operand that must use rtx X, even if X is volatile. */ static inline void -create_fixed_operand (struct expand_operand *op, rtx x) +create_fixed_operand (class expand_operand *op, rtx x) { create_expand_operand (op, EXPAND_FIXED, x, VOIDmode, false); } @@ -98,7 +98,7 @@ create_fixed_operand (struct expand_operand *op, rtx x) be ignored in that case. */ static inline void -create_output_operand (struct expand_operand *op, rtx x, +create_output_operand (class expand_operand *op, rtx x, machine_mode mode) { create_expand_operand (op, EXPAND_OUTPUT, x, mode, false); @@ -110,7 +110,7 @@ create_output_operand (struct expand_operand *op, rtx x, as an operand. */ static inline void -create_input_operand (struct expand_operand *op, rtx value, +create_input_operand (class expand_operand *op, rtx value, machine_mode mode) { create_expand_operand (op, EXPAND_INPUT, value, mode, false); @@ -120,7 +120,7 @@ create_input_operand (struct expand_operand *op, rtx value, to mode MODE. UNSIGNED_P says whether VALUE is unsigned. */ static inline void -create_convert_operand_to (struct expand_operand *op, rtx value, +create_convert_operand_to (class expand_operand *op, rtx value, machine_mode mode, bool unsigned_p) { create_expand_operand (op, EXPAND_CONVERT_TO, value, mode, unsigned_p); @@ -132,7 +132,7 @@ create_convert_operand_to (struct expand_operand *op, rtx value, UNSIGNED_P says whether VALUE is unsigned. */ static inline void -create_convert_operand_from (struct expand_operand *op, rtx value, +create_convert_operand_from (class expand_operand *op, rtx value, machine_mode mode, bool unsigned_p) { create_expand_operand (op, EXPAND_CONVERT_FROM, value, mode, unsigned_p); @@ -143,12 +143,12 @@ create_convert_operand_from (struct expand_operand *op, rtx value, of the address, but it may need to be converted to Pmode first. */ static inline void -create_address_operand (struct expand_operand *op, rtx value) +create_address_operand (class expand_operand *op, rtx value) { create_expand_operand (op, EXPAND_ADDRESS, value, Pmode, false); } -extern void create_integer_operand (struct expand_operand *, poly_int64); +extern void create_integer_operand (class expand_operand *, poly_int64); /* Passed to expand_simple_binop and expand_binop to say which options to try to use if the requested operation can't be open-coded on the @@ -336,21 +336,21 @@ rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel, extern bool insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand); extern bool valid_multiword_target_p (rtx); -extern void create_convert_operand_from_type (struct expand_operand *op, +extern void create_convert_operand_from_type (class expand_operand *op, rtx value, tree type); extern bool maybe_legitimize_operands (enum insn_code icode, unsigned int opno, unsigned int nops, - struct expand_operand *ops); + class expand_operand *ops); extern rtx_insn *maybe_gen_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops); + class expand_operand *ops); extern bool maybe_expand_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops); + class expand_operand *ops); extern bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops); + class expand_operand *ops); extern void expand_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops); + class expand_operand *ops); extern void expand_jump_insn (enum insn_code icode, unsigned int nops, - struct expand_operand *ops); + class expand_operand *ops); extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp); diff --git a/gcc/optinfo.h b/gcc/optinfo.h index 670b09a..04786b4 100644 --- a/gcc/optinfo.h +++ b/gcc/optinfo.h @@ -65,7 +65,7 @@ along with GCC; see the file COPYING3. If not see /* Forward decls. */ -struct opt_pass; +class opt_pass; class optinfo_item; /* Return true if any of the active optinfo destinations make use diff --git a/gcc/poly-int.h b/gcc/poly-int.h index 635f1eb..0ccdf68 100644 --- a/gcc/poly-int.h +++ b/gcc/poly-int.h @@ -29,7 +29,7 @@ along with GCC; see the file COPYING3. If not see #ifndef HAVE_POLY_INT_H #define HAVE_POLY_INT_H -template class poly_int_pod; +template struct poly_int_pod; template class poly_int; /* poly_coeff_traiits describes the properties of a poly_int diff --git a/gcc/predict.c b/gcc/predict.c index 766f418..07f66aa 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -87,10 +87,10 @@ static void dump_prediction (FILE *, enum br_predictor, int, basic_block, enum predictor_reason, edge); static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction, - struct loop *in_loop = NULL); + class loop *in_loop = NULL); static void predict_paths_leading_to_edge (edge, enum br_predictor, enum prediction, - struct loop *in_loop = NULL); + class loop *in_loop = NULL); static bool can_predict_insn_p (const rtx_insn *); static HOST_WIDE_INT get_predictor_value (br_predictor, HOST_WIDE_INT); static void determine_unlikely_bbs (); @@ -355,7 +355,7 @@ optimize_insn_for_speed_p (void) /* Return TRUE when LOOP should be optimized for size. */ bool -optimize_loop_for_size_p (struct loop *loop) +optimize_loop_for_size_p (class loop *loop) { return optimize_bb_for_size_p (loop->header); } @@ -363,7 +363,7 @@ optimize_loop_for_size_p (struct loop *loop) /* Return TRUE when LOOP should be optimized for speed. */ bool -optimize_loop_for_speed_p (struct loop *loop) +optimize_loop_for_speed_p (class loop *loop) { return optimize_bb_for_speed_p (loop->header); } @@ -371,9 +371,9 @@ optimize_loop_for_speed_p (struct loop *loop) /* Return TRUE when LOOP nest should be optimized for speed. */ bool -optimize_loop_nest_for_speed_p (struct loop *loop) +optimize_loop_nest_for_speed_p (class loop *loop) { - struct loop *l = loop; + class loop *l = loop; if (optimize_loop_for_speed_p (loop)) return true; l = loop->inner; @@ -399,7 +399,7 @@ optimize_loop_nest_for_speed_p (struct loop *loop) /* Return TRUE when LOOP nest should be optimized for size. */ bool -optimize_loop_nest_for_size_p (struct loop *loop) +optimize_loop_nest_for_size_p (class loop *loop) { return !optimize_loop_nest_for_speed_p (loop); } @@ -1471,7 +1471,7 @@ get_base_value (tree t) Otherwise return false and set LOOP_INVAIANT to NULL. */ static bool -is_comparison_with_loop_invariant_p (gcond *stmt, struct loop *loop, +is_comparison_with_loop_invariant_p (gcond *stmt, class loop *loop, tree *loop_invariant, enum tree_code *compare_code, tree *loop_step, @@ -1637,7 +1637,7 @@ predicted_by_loop_heuristics_p (basic_block bb) In this loop, we will predict the branch inside the loop to be taken. */ static void -predict_iv_comparison (struct loop *loop, basic_block bb, +predict_iv_comparison (class loop *loop, basic_block bb, tree loop_bound_var, tree loop_iv_base_var, enum tree_code loop_bound_code, @@ -1896,9 +1896,9 @@ predict_extra_loop_exits (edge exit_edge) static void predict_loops (void) { - struct loop *loop; + class loop *loop; basic_block bb; - hash_set with_recursion(10); + hash_set with_recursion(10); FOR_EACH_BB_FN (bb, cfun) { @@ -1923,9 +1923,9 @@ predict_loops (void) basic_block bb, *bbs; unsigned j, n_exits = 0; vec exits; - struct tree_niter_desc niter_desc; + class tree_niter_desc niter_desc; edge ex; - struct nb_iter_bound *nb_iter; + class nb_iter_bound *nb_iter; enum tree_code loop_bound_code = ERROR_MARK; tree loop_bound_step = NULL; tree loop_bound_var = NULL; @@ -3135,7 +3135,7 @@ static void predict_paths_for_bb (basic_block cur, basic_block bb, enum br_predictor pred, enum prediction taken, - bitmap visited, struct loop *in_loop = NULL) + bitmap visited, class loop *in_loop = NULL) { edge e; edge_iterator ei; @@ -3201,7 +3201,7 @@ predict_paths_for_bb (basic_block cur, basic_block bb, static void predict_paths_leading_to (basic_block bb, enum br_predictor pred, - enum prediction taken, struct loop *in_loop) + enum prediction taken, class loop *in_loop) { predict_paths_for_bb (bb, bb, pred, taken, auto_bitmap (), in_loop); } @@ -3210,7 +3210,7 @@ predict_paths_leading_to (basic_block bb, enum br_predictor pred, static void predict_paths_leading_to_edge (edge e, enum br_predictor pred, - enum prediction taken, struct loop *in_loop) + enum prediction taken, class loop *in_loop) { bool has_nonloop_edge = false; edge_iterator ei; @@ -3400,9 +3400,9 @@ propagate_freq (basic_block head, bitmap tovisit) /* Estimate frequencies in loops at same nest level. */ static void -estimate_loops_at_level (struct loop *first_loop) +estimate_loops_at_level (class loop *first_loop) { - struct loop *loop; + class loop *loop; for (loop = first_loop; loop; loop = loop->next) { @@ -4052,7 +4052,7 @@ pass_profile::execute (function *fun) profile_status_for_fn (fun) = PROFILE_GUESSED; if (dump_file && (dump_flags & TDF_DETAILS)) { - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) if (loop->header->count.initialized_p ()) fprintf (dump_file, "Loop got predicted %d to iterate %i times.\n", diff --git a/gcc/predict.h b/gcc/predict.h index c1f2f03..5149a97 100644 --- a/gcc/predict.h +++ b/gcc/predict.h @@ -68,10 +68,10 @@ extern bool optimize_edge_for_size_p (edge); extern bool optimize_edge_for_speed_p (edge); extern bool optimize_insn_for_size_p (void); extern bool optimize_insn_for_speed_p (void); -extern bool optimize_loop_for_size_p (struct loop *); -extern bool optimize_loop_for_speed_p (struct loop *); -extern bool optimize_loop_nest_for_speed_p (struct loop *); -extern bool optimize_loop_nest_for_size_p (struct loop *); +extern bool optimize_loop_for_size_p (class loop *); +extern bool optimize_loop_for_speed_p (class loop *); +extern bool optimize_loop_nest_for_speed_p (class loop *); +extern bool optimize_loop_nest_for_size_p (class loop *); extern bool predictable_edge_p (edge); extern void rtl_profile_for_bb (basic_block); extern void rtl_profile_for_edge (edge); diff --git a/gcc/profile-count.c b/gcc/profile-count.c index 2b774a7..6198675 100644 --- a/gcc/profile-count.c +++ b/gcc/profile-count.c @@ -125,7 +125,7 @@ profile_count::differs_from_p (profile_count other) const /* Stream THIS from IB. */ profile_count -profile_count::stream_in (struct lto_input_block *ib) +profile_count::stream_in (class lto_input_block *ib) { profile_count ret; ret.m_val = streamer_read_gcov_count (ib); @@ -216,7 +216,7 @@ profile_probability::differs_lot_from_p (profile_probability other) const /* Stream THIS from IB. */ profile_probability -profile_probability::stream_in (struct lto_input_block *ib) +profile_probability::stream_in (class lto_input_block *ib) { profile_probability ret; ret.m_val = streamer_read_uhwi (ib); diff --git a/gcc/profile-count.h b/gcc/profile-count.h index e584aab..ef84ddc 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see #define GCC_PROFILE_COUNT_H struct function; -class profile_count; +struct profile_count; /* Quality of the profile count. Because gengtype does not support enums inside of classes, this is in global namespace. */ @@ -154,7 +154,7 @@ class GTY((user)) profile_probability uint32_t m_val : 29; enum profile_quality m_quality : 3; - friend class profile_count; + friend struct profile_count; public: profile_probability (): m_val (uninitialized_probability), m_quality (GUESSED) @@ -615,7 +615,7 @@ public: profile_count count2) const; /* LTO streaming support. */ - static profile_probability stream_in (struct lto_input_block *); + static profile_probability stream_in (class lto_input_block *); void stream_out (struct output_block *); void stream_out (struct lto_output_stream *); }; @@ -1201,7 +1201,7 @@ public: profile_quality quality = PRECISE); /* LTO streaming support. */ - static profile_count stream_in (struct lto_input_block *); + static profile_count stream_in (class lto_input_block *); void stream_out (struct output_block *); void stream_out (struct lto_output_stream *); }; diff --git a/gcc/profile.c b/gcc/profile.c index e3f8c55..441cb8e 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -1370,7 +1370,7 @@ branch_prob (bool thunk) if (flag_branch_probabilities && (profile_status_for_fn (cfun) == PROFILE_READ)) { - struct loop *loop; + class loop *loop; if (dump_file && (dump_flags & TDF_DETAILS)) report_predictor_hitrates (); diff --git a/gcc/regrename.c b/gcc/regrename.c index 7dbbeb9..73c0ced 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -116,7 +116,7 @@ static unsigned current_id; static vec id_to_chain; /* List of currently open chains. */ -static struct du_head *open_chains; +static class du_head *open_chains; /* Bitmap of open chains. The bits set always match the list found in open_chains. */ @@ -135,7 +135,7 @@ static HARD_REG_SET live_hard_regs; static operand_rr_info *cur_operand; /* Set while scanning RTL if a register dies. Used to tie chains. */ -static struct du_head *terminated_this_insn; +static class du_head *terminated_this_insn; /* Return the chain corresponding to id number ID. Take into account that chains may have been merged. */ @@ -192,7 +192,7 @@ free_chain_data (void) another chain whose id is ID. */ static void -mark_conflict (struct du_head *chains, unsigned id) +mark_conflict (class du_head *chains, unsigned id) { while (chains) { @@ -205,7 +205,7 @@ mark_conflict (struct du_head *chains, unsigned id) use THIS_DU which is part of the chain HEAD. */ static void -record_operand_use (struct du_head *head, struct du_chain *this_du) +record_operand_use (class du_head *head, struct du_chain *this_du) { if (cur_operand == NULL || cur_operand->failed) return; @@ -227,7 +227,7 @@ static du_head_p create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc, rtx_insn *insn, enum reg_class cl) { - struct du_head *head = XOBNEW (&rename_obstack, struct du_head); + class du_head *head = XOBNEW (&rename_obstack, class du_head); struct du_chain *this_du; int nregs; @@ -288,7 +288,7 @@ create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc, set the corresponding bits in *PSET. */ static void -merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head) +merge_overlapping_regs (HARD_REG_SET *pset, class du_head *head) { bitmap_iterator bi; unsigned i; @@ -309,7 +309,7 @@ merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head) static bool check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg, - struct du_head *this_head, HARD_REG_SET this_unavailable) + class du_head *this_head, HARD_REG_SET this_unavailable) { machine_mode mode = GET_MODE (*this_head->first->loc); int nregs = hard_regno_nregs (new_reg, mode); @@ -561,7 +561,7 @@ public: /* Initialize a rename_info structure P for basic block BB, which starts a new scan. */ static void -init_rename_info (struct bb_rename_info *p, basic_block bb) +init_rename_info (class bb_rename_info *p, basic_block bb) { int i; df_ref def; @@ -616,7 +616,7 @@ init_rename_info (struct bb_rename_info *p, basic_block bb) /* Record in RI that the block corresponding to it has an incoming live value, described by CHAIN. */ static void -set_incoming_from_chain (struct bb_rename_info *ri, du_head_p chain) +set_incoming_from_chain (class bb_rename_info *ri, du_head_p chain) { int i; int incoming_nregs = ri->incoming[chain->regno].nregs; @@ -690,7 +690,7 @@ merge_chains (du_head_p c1, du_head_p c2) void regrename_analyze (bitmap bb_mask) { - struct bb_rename_info *rename_info; + class bb_rename_info *rename_info; int i; basic_block bb; int n_bbs; @@ -700,11 +700,11 @@ regrename_analyze (bitmap bb_mask) n_bbs = pre_and_rev_post_order_compute (NULL, inverse_postorder, false); /* Gather some information about the blocks in this function. */ - rename_info = XCNEWVEC (struct bb_rename_info, n_basic_blocks_for_fn (cfun)); + rename_info = XCNEWVEC (class bb_rename_info, n_basic_blocks_for_fn (cfun)); i = 0; FOR_EACH_BB_FN (bb, cfun) { - struct bb_rename_info *ri = rename_info + i; + class bb_rename_info *ri = rename_info + i; ri->bb = bb; if (bb_mask != NULL && !bitmap_bit_p (bb_mask, bb->index)) bb->aux = NULL; @@ -725,13 +725,13 @@ regrename_analyze (bitmap bb_mask) for (i = 0; i < n_bbs; i++) { basic_block bb1 = BASIC_BLOCK_FOR_FN (cfun, inverse_postorder[i]); - struct bb_rename_info *this_info; + class bb_rename_info *this_info; bool success; edge e; edge_iterator ei; int old_length = id_to_chain.length (); - this_info = (struct bb_rename_info *) bb1->aux; + this_info = (class bb_rename_info *) bb1->aux; if (this_info == NULL) continue; @@ -771,15 +771,15 @@ regrename_analyze (bitmap bb_mask) will be used to pre-open chains when processing the successors. */ FOR_EACH_EDGE (e, ei, bb1->succs) { - struct bb_rename_info *dest_ri; - struct du_head *chain; + class bb_rename_info *dest_ri; + class du_head *chain; if (dump_file) fprintf (dump_file, "successor block %d\n", e->dest->index); if (e->flags & (EDGE_EH | EDGE_ABNORMAL)) continue; - dest_ri = (struct bb_rename_info *)e->dest->aux; + dest_ri = (class bb_rename_info *)e->dest->aux; if (dest_ri == NULL) continue; for (chain = open_chains; chain; chain = chain->next_chain) @@ -808,7 +808,7 @@ regrename_analyze (bitmap bb_mask) edges). */ FOR_EACH_BB_FN (bb, cfun) { - struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux; + class bb_rename_info *bb_ri = (class bb_rename_info *) bb->aux; unsigned j; bitmap_iterator bi; @@ -822,12 +822,12 @@ regrename_analyze (bitmap bb_mask) { edge e; edge_iterator ei; - struct du_head *chain = regrename_chain_from_id (j); + class du_head *chain = regrename_chain_from_id (j); int n_preds_used = 0, n_preds_joined = 0; FOR_EACH_EDGE (e, ei, bb->preds) { - struct bb_rename_info *src_ri; + class bb_rename_info *src_ri; unsigned k; bitmap_iterator bi2; HARD_REG_SET live; @@ -842,14 +842,14 @@ regrename_analyze (bitmap bb_mask) if (e->flags & (EDGE_EH | EDGE_ABNORMAL)) continue; - src_ri = (struct bb_rename_info *)e->src->aux; + src_ri = (class bb_rename_info *)e->src->aux; if (src_ri == NULL) continue; EXECUTE_IF_SET_IN_BITMAP (&src_ri->open_chains_set, 0, k, bi2) { - struct du_head *outgoing_chain = regrename_chain_from_id (k); + class du_head *outgoing_chain = regrename_chain_from_id (k); if (outgoing_chain->regno == chain->regno && outgoing_chain->nregs == chain->nregs) @@ -873,7 +873,7 @@ regrename_analyze (bitmap bb_mask) } FOR_EACH_BB_FN (bb, cfun) { - struct bb_rename_info *bb_ri = (struct bb_rename_info *) bb->aux; + class bb_rename_info *bb_ri = (class bb_rename_info *) bb->aux; unsigned j; bitmap_iterator bi; @@ -887,13 +887,13 @@ regrename_analyze (bitmap bb_mask) { edge e; edge_iterator ei; - struct du_head *chain = regrename_chain_from_id (j); + class du_head *chain = regrename_chain_from_id (j); int n_succs_used = 0, n_succs_joined = 0; FOR_EACH_EDGE (e, ei, bb->succs) { bool printed = false; - struct bb_rename_info *dest_ri; + class bb_rename_info *dest_ri; unsigned k; bitmap_iterator bi2; HARD_REG_SET live; @@ -905,14 +905,14 @@ regrename_analyze (bitmap bb_mask) n_succs_used++; - dest_ri = (struct bb_rename_info *)e->dest->aux; + dest_ri = (class bb_rename_info *)e->dest->aux; if (dest_ri == NULL) continue; EXECUTE_IF_SET_IN_BITMAP (&dest_ri->incoming_open_chains_set, 0, k, bi2) { - struct du_head *incoming_chain = regrename_chain_from_id (k); + class du_head *incoming_chain = regrename_chain_from_id (k); if (incoming_chain->regno == chain->regno && incoming_chain->nregs == chain->nregs) @@ -959,7 +959,7 @@ regrename_analyze (bitmap bb_mask) numbering in its subpatterns. */ bool -regrename_do_replace (struct du_head *head, int reg) +regrename_do_replace (class du_head *head, int reg) { struct du_chain *chain; unsigned int base_regno = head->regno; @@ -969,7 +969,7 @@ regrename_do_replace (struct du_head *head, int reg) for (chain = head->first; chain; chain = chain->next_use) { unsigned int regno = ORIGINAL_REGNO (*chain->loc); - struct reg_attrs *attr = REG_ATTRS (*chain->loc); + class reg_attrs *attr = REG_ATTRS (*chain->loc); int reg_ptr = REG_POINTER (*chain->loc); if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno) @@ -1053,7 +1053,7 @@ static void note_sets_clobbers (rtx x, const_rtx set, void *data) { enum rtx_code code = *(enum rtx_code *)data; - struct du_head *chain; + class du_head *chain; if (GET_CODE (x) == SUBREG) x = SUBREG_REG (x); @@ -1070,7 +1070,7 @@ static void scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action, enum op_type type) { - struct du_head **p; + class du_head **p; rtx x = *loc; unsigned this_regno = REGNO (x); int this_nregs = REG_NREGS (x); @@ -1116,8 +1116,8 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions act for (p = &open_chains; *p;) { - struct du_head *head = *p; - struct du_head *next = head->next_chain; + class du_head *head = *p; + class du_head *next = head->next_chain; int exact_match = (head->regno == this_regno && head->nregs == this_nregs); int superset = (this_regno <= head->regno @@ -1588,7 +1588,7 @@ record_out_operands (rtx_insn *insn, bool earlyclobber, insn_rr_info *insn_info) rtx op = *loc; enum reg_class cl = alternative_class (op_alt, opn); - struct du_head *prev_open; + class du_head *prev_open; if (recog_data.operand_type[opn] != OP_OUT || op_alt[opn].earlyclobber != earlyclobber) @@ -1835,7 +1835,7 @@ build_def_use (basic_block bb) requires a caller-saved reg. */ if (CALL_P (insn)) { - struct du_head *p; + class du_head *p; for (p = open_chains; p; p = p->next_chain) p->need_caller_save_reg = 1; } diff --git a/gcc/regrename.h b/gcc/regrename.h index e9f2823..2fe12d5 100644 --- a/gcc/regrename.h +++ b/gcc/regrename.h @@ -26,11 +26,11 @@ class du_head { public: /* The next chain. */ - struct du_head *next_chain; + class du_head *next_chain; /* The first and last elements of this chain. */ struct du_chain *first, *last; /* The chain that this chain is tied to. */ - struct du_head *tied_chain; + class du_head *tied_chain; /* Describes the register being tracked. */ unsigned regno; int nregs; @@ -56,7 +56,7 @@ public: unsigned int target_data_2; }; -typedef struct du_head *du_head_p; +typedef class du_head *du_head_p; /* This struct describes a single occurrence of a register. */ struct du_chain @@ -82,7 +82,7 @@ struct operand_rr_info /* Holds either the chain for the operand itself, or for the registers in a memory operand. */ struct du_chain *chains[MAX_REGS_PER_ADDRESS]; - struct du_head *heads[MAX_REGS_PER_ADDRESS]; + class du_head *heads[MAX_REGS_PER_ADDRESS]; }; /* A struct to hold a vector of operand_rr_info structures describing the diff --git a/gcc/reload.h b/gcc/reload.h index edfeebf..eb49771 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -282,11 +282,11 @@ class insn_chain { public: /* Links to the neighbor instructions. */ - struct insn_chain *next, *prev; + class insn_chain *next, *prev; /* Link through a chains set up by calculate_needs_all_insns, containing all insns that need reloading. */ - struct insn_chain *next_need_reload; + class insn_chain *next_need_reload; /* The rtx of the insn. */ rtx_insn *insn; @@ -320,10 +320,10 @@ public: /* A chain of insn_chain structures to describe all non-note insns in a function. */ -extern struct insn_chain *reload_insn_chain; +extern class insn_chain *reload_insn_chain; /* Allocate a new insn_chain structure. */ -extern struct insn_chain *new_insn_chain (void); +extern class insn_chain *new_insn_chain (void); #endif #if defined SET_HARD_REG_BIT diff --git a/gcc/reload1.c b/gcc/reload1.c index 3ad6f1d..38ee356 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -243,14 +243,14 @@ static char *reload_insn_firstobj; /* List of insn_chain instructions, one for every insn that reload needs to examine. */ -struct insn_chain *reload_insn_chain; +class insn_chain *reload_insn_chain; /* TRUE if we potentially left dead insns in the insn stream and want to run DCE immediately after reload, FALSE otherwise. */ static bool need_dce; /* List of all insns needing reloads. */ -static struct insn_chain *insns_need_reload; +static class insn_chain *insns_need_reload; /* This structure is used to record information about register eliminations. Each array entry describes one possible way of eliminating a register @@ -336,10 +336,10 @@ static int num_labels; static void replace_pseudos_in (rtx *, machine_mode, rtx); static void maybe_fix_stack_asms (void); -static void copy_reloads (struct insn_chain *); +static void copy_reloads (class insn_chain *); static void calculate_needs_all_insns (int); -static int find_reg (struct insn_chain *, int); -static void find_reload_regs (struct insn_chain *); +static int find_reg (class insn_chain *, int); +static void find_reload_regs (class insn_chain *); static void select_reload_regs (void); static void delete_caller_save_insns (void); @@ -368,7 +368,7 @@ static void spill_hard_reg (unsigned int, int); static int finish_spills (int); static void scan_paradoxical_subregs (rtx); static void count_pseudo (int); -static void order_regs_for_reload (struct insn_chain *); +static void order_regs_for_reload (class insn_chain *); static void reload_as_needed (int); static void forget_old_reloads_1 (rtx, const_rtx, void *); static void forget_marked_reloads (regset); @@ -382,19 +382,19 @@ static int reload_reg_free_for_value_p (int, int, int, enum reload_type, rtx, rtx, int, int); static int free_for_value_p (int, machine_mode, int, enum reload_type, rtx, rtx, int, int); -static int allocate_reload_reg (struct insn_chain *, int, int); +static int allocate_reload_reg (class insn_chain *, int, int); static int conflicts_with_override (rtx); static void failed_reload (rtx_insn *, int); static int set_reload_reg (int, int); -static void choose_reload_regs_init (struct insn_chain *, rtx *); -static void choose_reload_regs (struct insn_chain *); -static void emit_input_reload_insns (struct insn_chain *, struct reload *, +static void choose_reload_regs_init (class insn_chain *, rtx *); +static void choose_reload_regs (class insn_chain *); +static void emit_input_reload_insns (class insn_chain *, struct reload *, rtx, int); -static void emit_output_reload_insns (struct insn_chain *, struct reload *, +static void emit_output_reload_insns (class insn_chain *, struct reload *, int); -static void do_input_reload (struct insn_chain *, struct reload *, int); -static void do_output_reload (struct insn_chain *, struct reload *, int); -static void emit_reload_insns (struct insn_chain *); +static void do_input_reload (class insn_chain *, struct reload *, int); +static void do_output_reload (class insn_chain *, struct reload *, int); +static void emit_reload_insns (class insn_chain *); static void delete_output_reload (rtx_insn *, int, int, rtx); static void delete_address_reloads (rtx_insn *, rtx_insn *); static void delete_address_reloads_1 (rtx_insn *, rtx, rtx_insn *); @@ -467,17 +467,17 @@ init_reload (void) } /* List of insn chains that are currently unused. */ -static struct insn_chain *unused_insn_chains = 0; +static class insn_chain *unused_insn_chains = 0; /* Allocate an empty insn_chain structure. */ -struct insn_chain * +class insn_chain * new_insn_chain (void) { - struct insn_chain *c; + class insn_chain *c; if (unused_insn_chains == 0) { - c = XOBNEW (&reload_obstack, struct insn_chain); + c = XOBNEW (&reload_obstack, class insn_chain); INIT_REG_SET (&c->live_throughout); INIT_REG_SET (&c->dead_or_set); } @@ -1315,7 +1315,7 @@ maybe_fix_stack_asms (void) #ifdef STACK_REGS const char *constraints[MAX_RECOG_OPERANDS]; machine_mode operand_mode[MAX_RECOG_OPERANDS]; - struct insn_chain *chain; + class insn_chain *chain; for (chain = reload_insn_chain; chain != 0; chain = chain->next) { @@ -1414,7 +1414,7 @@ maybe_fix_stack_asms (void) /* Copy the global variables n_reloads and rld into the corresponding elts of CHAIN. */ static void -copy_reloads (struct insn_chain *chain) +copy_reloads (class insn_chain *chain) { chain->n_reloads = n_reloads; chain->rld = XOBNEWVEC (&reload_obstack, struct reload, n_reloads); @@ -1428,8 +1428,8 @@ copy_reloads (struct insn_chain *chain) static void calculate_needs_all_insns (int global) { - struct insn_chain **pprev_reload = &insns_need_reload; - struct insn_chain *chain, *next = 0; + class insn_chain **pprev_reload = &insns_need_reload; + class insn_chain *chain, *next = 0; something_needs_elimination = 0; @@ -1725,7 +1725,7 @@ count_pseudo (int reg) contents of BAD_SPILL_REGS for the insn described by CHAIN. */ static void -order_regs_for_reload (struct insn_chain *chain) +order_regs_for_reload (class insn_chain *chain) { unsigned i; HARD_REG_SET used_by_pseudos; @@ -1809,7 +1809,7 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int reg) /* Find reload register to use for reload number ORDER. */ static int -find_reg (struct insn_chain *chain, int order) +find_reg (class insn_chain *chain, int order) { int rnum = reload_order[order]; struct reload *rl = rld + rnum; @@ -1954,7 +1954,7 @@ find_reg (struct insn_chain *chain, int order) for a smaller class even though it belongs to that class. */ static void -find_reload_regs (struct insn_chain *chain) +find_reload_regs (class insn_chain *chain) { int i; @@ -2016,7 +2016,7 @@ find_reload_regs (struct insn_chain *chain) static void select_reload_regs (void) { - struct insn_chain *chain; + class insn_chain *chain; /* Try to satisfy the needs for each insn. */ for (chain = insns_need_reload; chain != 0; @@ -2029,13 +2029,13 @@ select_reload_regs (void) static void delete_caller_save_insns (void) { - struct insn_chain *c = reload_insn_chain; + class insn_chain *c = reload_insn_chain; while (c != 0) { while (c != 0 && c->is_caller_save_insn) { - struct insn_chain *next = c->next; + class insn_chain *next = c->next; rtx_insn *insn = c->insn; if (c == reload_insn_chain) @@ -4194,7 +4194,7 @@ spill_hard_reg (unsigned int regno, int cant_eliminate) static int finish_spills (int global) { - struct insn_chain *chain; + class insn_chain *chain; int something_changed = 0; unsigned i; reg_set_iterator rsi; @@ -4459,7 +4459,7 @@ fixup_eh_region_note (rtx_insn *insn, rtx_insn *prev, rtx_insn *next) static void reload_as_needed (int live_known) { - struct insn_chain *chain; + class insn_chain *chain; #if AUTO_INC_DEC int i; #endif @@ -6092,7 +6092,7 @@ set_reload_reg (int i, int r) we didn't change anything. */ static int -allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r, +allocate_reload_reg (class insn_chain *chain ATTRIBUTE_UNUSED, int r, int last_reload) { int i, pass, count; @@ -6223,7 +6223,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r, is the array we use to restore the reg_rtx field for every reload. */ static void -choose_reload_regs_init (struct insn_chain *chain, rtx *save_reload_reg_rtx) +choose_reload_regs_init (class insn_chain *chain, rtx *save_reload_reg_rtx) { int i; @@ -6324,7 +6324,7 @@ compute_reload_subreg_offset (machine_mode outermode, finding a reload reg in the proper class. */ static void -choose_reload_regs (struct insn_chain *chain) +choose_reload_regs (class insn_chain *chain) { rtx_insn *insn = chain->insn; int i, j; @@ -7113,7 +7113,7 @@ reload_adjust_reg_for_icode (rtx *reload_reg, rtx alt_reload_reg, has the number J. OLD contains the value to be used as input. */ static void -emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, +emit_input_reload_insns (class insn_chain *chain, struct reload *rl, rtx old, int j) { rtx_insn *insn = chain->insn; @@ -7573,7 +7573,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, /* Generate insns to for the output reload RL, which is for the insn described by CHAIN and has the number J. */ static void -emit_output_reload_insns (struct insn_chain *chain, struct reload *rl, +emit_output_reload_insns (class insn_chain *chain, struct reload *rl, int j) { rtx reloadreg; @@ -7779,7 +7779,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl, /* Do input reloading for reload RL, which is for the insn described by CHAIN and has the number J. */ static void -do_input_reload (struct insn_chain *chain, struct reload *rl, int j) +do_input_reload (class insn_chain *chain, struct reload *rl, int j) { rtx_insn *insn = chain->insn; rtx old = (rl->in && MEM_P (rl->in) @@ -7880,7 +7880,7 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j) ??? At some point we need to support handling output reloads of JUMP_INSNs or insns that set cc0. */ static void -do_output_reload (struct insn_chain *chain, struct reload *rl, int j) +do_output_reload (class insn_chain *chain, struct reload *rl, int j) { rtx note, old; rtx_insn *insn = chain->insn; @@ -7986,7 +7986,7 @@ inherit_piecemeal_p (int dest ATTRIBUTE_UNUSED, /* Output insns to reload values in and out of the chosen reload regs. */ static void -emit_reload_insns (struct insn_chain *chain) +emit_reload_insns (class insn_chain *chain) { rtx_insn *insn = chain->insn; diff --git a/gcc/rtl.h b/gcc/rtl.h index ad2f3cd..039ab05 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -210,7 +210,7 @@ union rtunion tree rt_tree; basic_block rt_bb; mem_attrs *rt_mem; - struct constant_descriptor_rtx *rt_constant; + class constant_descriptor_rtx *rt_constant; struct dw_cfi_node *rt_cfi; }; @@ -3726,7 +3726,7 @@ struct GTY(()) target_rtl { rtx x_static_reg_base_value[FIRST_PSEUDO_REGISTER]; /* The default memory attributes for each mode. */ - struct mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE]; + class mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE]; /* Track if RTL has been initialized. */ bool target_specific_initialized; @@ -3760,10 +3760,10 @@ extern struct target_rtl *this_target_rtl; #ifndef GENERATOR_FILE /* Return the attributes of a MEM rtx. */ -static inline const struct mem_attrs * +static inline const class mem_attrs * get_mem_attrs (const_rtx x) { - struct mem_attrs *attrs; + class mem_attrs *attrs; attrs = MEM_ATTRS (x); if (!attrs) diff --git a/gcc/sanopt.c b/gcc/sanopt.c index bf9fdc9..00ade87 100644 --- a/gcc/sanopt.c +++ b/gcc/sanopt.c @@ -354,7 +354,7 @@ maybe_get_dominating_check (auto_vec &v) /* Optimize away redundant UBSAN_NULL calls. */ static bool -maybe_optimize_ubsan_null_ifn (struct sanopt_ctx *ctx, gimple *stmt) +maybe_optimize_ubsan_null_ifn (class sanopt_ctx *ctx, gimple *stmt) { gcc_assert (gimple_call_num_args (stmt) == 3); tree ptr = gimple_call_arg (stmt, 0); @@ -591,7 +591,7 @@ maybe_optimize_ubsan_ptr_ifn (sanopt_ctx *ctx, gimple *stmt) when we can actually optimize. */ static bool -maybe_optimize_ubsan_vptr_ifn (struct sanopt_ctx *ctx, gimple *stmt) +maybe_optimize_ubsan_vptr_ifn (class sanopt_ctx *ctx, gimple *stmt) { gcc_assert (gimple_call_num_args (stmt) == 5); sanopt_tree_triplet triplet; @@ -695,7 +695,7 @@ can_remove_asan_check (auto_vec &v, tree len, basic_block bb) /* Optimize away redundant ASAN_CHECK calls. */ static bool -maybe_optimize_asan_check_ifn (struct sanopt_ctx *ctx, gimple *stmt) +maybe_optimize_asan_check_ifn (class sanopt_ctx *ctx, gimple *stmt) { gcc_assert (gimple_call_num_args (stmt) == 4); tree ptr = gimple_call_arg (stmt, 1); @@ -768,7 +768,7 @@ maybe_optimize_asan_check_ifn (struct sanopt_ctx *ctx, gimple *stmt) anything anymore. CTX is a sanopt context. */ static void -sanopt_optimize_walker (basic_block bb, struct sanopt_ctx *ctx) +sanopt_optimize_walker (basic_block bb, class sanopt_ctx *ctx) { basic_block son; gimple_stmt_iterator gsi; @@ -887,7 +887,7 @@ sanopt_optimize_walker (basic_block bb, struct sanopt_ctx *ctx) static int sanopt_optimize (function *fun, bool *contains_asan_mark) { - struct sanopt_ctx ctx; + class sanopt_ctx ctx; ctx.asan_num_accesses = 0; ctx.contains_asan_mark = false; diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 28b9d38..5cb4a46 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -475,16 +475,16 @@ static int deps_may_trap_p (const_rtx); static void add_dependence_1 (rtx_insn *, rtx_insn *, enum reg_note); static void add_dependence_list (rtx_insn *, rtx_insn_list *, int, enum reg_note, bool); -static void add_dependence_list_and_free (struct deps_desc *, rtx_insn *, +static void add_dependence_list_and_free (class deps_desc *, rtx_insn *, rtx_insn_list **, int, enum reg_note, bool); static void delete_all_dependences (rtx_insn *); static void chain_to_prev_insn (rtx_insn *); -static void flush_pending_lists (struct deps_desc *, rtx_insn *, int, int); -static void sched_analyze_1 (struct deps_desc *, rtx, rtx_insn *); -static void sched_analyze_2 (struct deps_desc *, rtx, rtx_insn *); -static void sched_analyze_insn (struct deps_desc *, rtx, rtx_insn *); +static void flush_pending_lists (class deps_desc *, rtx_insn *, int, int); +static void sched_analyze_1 (class deps_desc *, rtx, rtx_insn *); +static void sched_analyze_2 (class deps_desc *, rtx, rtx_insn *); +static void sched_analyze_insn (class deps_desc *, rtx, rtx_insn *); static bool sched_has_condition_p (const rtx_insn *); static int conditions_mutex_p (const_rtx, const_rtx, bool, bool); @@ -1574,7 +1574,7 @@ add_dependence_list (rtx_insn *insn, rtx_insn_list *list, int uncond, newly created dependencies. */ static void -add_dependence_list_and_free (struct deps_desc *deps, rtx_insn *insn, +add_dependence_list_and_free (class deps_desc *deps, rtx_insn *insn, rtx_insn_list **listp, int uncond, enum reg_note dep_type, bool hard) { @@ -1708,7 +1708,7 @@ chain_to_prev_insn (rtx_insn *insn) so that we can do memory aliasing on it. */ static void -add_insn_mem_dependence (struct deps_desc *deps, bool read_p, +add_insn_mem_dependence (class deps_desc *deps, bool read_p, rtx_insn *insn, rtx mem) { rtx_insn_list **insn_list; @@ -1749,7 +1749,7 @@ add_insn_mem_dependence (struct deps_desc *deps, bool read_p, dependencies for a read operation, similarly with FOR_WRITE. */ static void -flush_pending_lists (struct deps_desc *deps, rtx_insn *insn, int for_read, +flush_pending_lists (class deps_desc *deps, rtx_insn *insn, int for_read, int for_write) { if (for_write) @@ -1953,7 +1953,7 @@ create_insn_reg_set (int regno, rtx insn) /* Set up insn register uses for INSN and dependency context DEPS. */ static void -setup_insn_reg_uses (struct deps_desc *deps, rtx_insn *insn) +setup_insn_reg_uses (class deps_desc *deps, rtx_insn *insn) { unsigned i; reg_set_iterator rsi; @@ -2245,7 +2245,7 @@ static bool can_start_lhs_rhs_p; /* Extend reg info for the deps context DEPS given that we have just generated a register numbered REGNO. */ static void -extend_deps_reg_info (struct deps_desc *deps, int regno) +extend_deps_reg_info (class deps_desc *deps, int regno) { int max_regno = regno + 1; @@ -2294,7 +2294,7 @@ maybe_extend_reg_info_p (void) CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE. */ static void -sched_analyze_reg (struct deps_desc *deps, int regno, machine_mode mode, +sched_analyze_reg (class deps_desc *deps, int regno, machine_mode mode, enum rtx_code ref, rtx_insn *insn) { /* We could emit new pseudos in renaming. Extend the reg structures. */ @@ -2382,7 +2382,7 @@ sched_analyze_reg (struct deps_desc *deps, int regno, machine_mode mode, destination of X, and reads of everything mentioned. */ static void -sched_analyze_1 (struct deps_desc *deps, rtx x, rtx_insn *insn) +sched_analyze_1 (class deps_desc *deps, rtx x, rtx_insn *insn) { rtx dest = XEXP (x, 0); enum rtx_code code = GET_CODE (x); @@ -2556,7 +2556,7 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx_insn *insn) /* Analyze the uses of memory and registers in rtx X in INSN. */ static void -sched_analyze_2 (struct deps_desc *deps, rtx x, rtx_insn *insn) +sched_analyze_2 (class deps_desc *deps, rtx x, rtx_insn *insn) { int i; int j; @@ -2890,7 +2890,7 @@ get_implicit_reg_pending_clobbers (HARD_REG_SET *temp, rtx_insn *insn) /* Analyze an INSN with pattern X to find all dependencies. */ static void -sched_analyze_insn (struct deps_desc *deps, rtx x, rtx_insn *insn) +sched_analyze_insn (class deps_desc *deps, rtx x, rtx_insn *insn) { RTX_CODE code = GET_CODE (x); rtx link; @@ -3648,7 +3648,7 @@ chain_to_prev_insn_p (rtx_insn *insn) /* Analyze INSN with DEPS as a context. */ void -deps_analyze_insn (struct deps_desc *deps, rtx_insn *insn) +deps_analyze_insn (class deps_desc *deps, rtx_insn *insn) { if (sched_deps_info->start_insn) sched_deps_info->start_insn (insn); @@ -3815,7 +3815,7 @@ deps_analyze_insn (struct deps_desc *deps, rtx_insn *insn) /* Initialize DEPS for the new block beginning with HEAD. */ void -deps_start_bb (struct deps_desc *deps, rtx_insn *head) +deps_start_bb (class deps_desc *deps, rtx_insn *head) { gcc_assert (!deps->readonly); @@ -3834,7 +3834,7 @@ deps_start_bb (struct deps_desc *deps, rtx_insn *head) /* Analyze every insn between HEAD and TAIL inclusive, creating backward dependencies for each insn. */ void -sched_analyze (struct deps_desc *deps, rtx_insn *head, rtx_insn *tail) +sched_analyze (class deps_desc *deps, rtx_insn *head, rtx_insn *tail) { rtx_insn *insn; @@ -3928,10 +3928,10 @@ sched_free_deps (rtx_insn *head, rtx_insn *tail, bool resolved_p) /* Initialize variables for region data dependence analysis. When LAZY_REG_LAST is true, do not allocate reg_last array - of struct deps_desc immediately. */ + of class deps_desc immediately. */ void -init_deps (struct deps_desc *deps, bool lazy_reg_last) +init_deps (class deps_desc *deps, bool lazy_reg_last) { int max_reg = (reload_completed ? FIRST_PSEUDO_REGISTER : max_reg_num ()); @@ -3968,7 +3968,7 @@ init_deps (struct deps_desc *deps, bool lazy_reg_last) /* Init only reg_last field of DEPS, which was not allocated before as we inited DEPS lazily. */ void -init_deps_reg_last (struct deps_desc *deps) +init_deps_reg_last (class deps_desc *deps) { gcc_assert (deps && deps->max_reg > 0); gcc_assert (deps->reg_last == NULL); @@ -3980,7 +3980,7 @@ init_deps_reg_last (struct deps_desc *deps) /* Free insn lists found in DEPS. */ void -free_deps (struct deps_desc *deps) +free_deps (class deps_desc *deps) { unsigned i; reg_set_iterator rsi; @@ -4028,7 +4028,7 @@ free_deps (struct deps_desc *deps) /* Remove INSN from dependence contexts DEPS. */ void -remove_from_deps (struct deps_desc *deps, rtx_insn *insn) +remove_from_deps (class deps_desc *deps, rtx_insn *insn) { int removed; unsigned i; diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c index 4875eef..a594b49 100644 --- a/gcc/sched-ebb.c +++ b/gcc/sched-ebb.c @@ -472,7 +472,7 @@ basic_block schedule_ebb (rtx_insn *head, rtx_insn *tail, bool modulo_scheduling) { basic_block first_bb, target_bb; - struct deps_desc tmp_deps; + class deps_desc tmp_deps; bool success; /* Blah. We should fix the rest of the code not to get confused by diff --git a/gcc/sched-int.h b/gcc/sched-int.h index 5fef221..fca1bcf 100644 --- a/gcc/sched-int.h +++ b/gcc/sched-int.h @@ -571,7 +571,7 @@ public: BOOL_BITFIELD readonly : 1; }; -typedef struct deps_desc *deps_t; +typedef class deps_desc *deps_t; /* This structure holds some state of the current scheduling pass, and contains some function pointers that abstract out some of the non-generic @@ -1347,14 +1347,14 @@ extern bool sched_insns_conditions_mutex_p (const rtx_insn *, const rtx_insn *); extern bool sched_insn_is_legitimate_for_speculation_p (const rtx_insn *, ds_t); extern void add_dependence (rtx_insn *, rtx_insn *, enum reg_note); -extern void sched_analyze (struct deps_desc *, rtx_insn *, rtx_insn *); -extern void init_deps (struct deps_desc *, bool); -extern void init_deps_reg_last (struct deps_desc *); -extern void free_deps (struct deps_desc *); +extern void sched_analyze (class deps_desc *, rtx_insn *, rtx_insn *); +extern void init_deps (class deps_desc *, bool); +extern void init_deps_reg_last (class deps_desc *); +extern void free_deps (class deps_desc *); extern void init_deps_global (void); extern void finish_deps_global (void); -extern void deps_analyze_insn (struct deps_desc *, rtx_insn *); -extern void remove_from_deps (struct deps_desc *, rtx_insn *); +extern void deps_analyze_insn (class deps_desc *, rtx_insn *); +extern void remove_from_deps (class deps_desc *, rtx_insn *); extern void init_insn_reg_pressure_info (rtx_insn *); extern void get_implicit_reg_pending_clobbers (HARD_REG_SET *, rtx_insn *); @@ -1377,7 +1377,7 @@ extern void haifa_note_reg_use (int); extern void maybe_extend_reg_info_p (void); -extern void deps_start_bb (struct deps_desc *, rtx_insn *); +extern void deps_start_bb (class deps_desc *, rtx_insn *); extern enum reg_note ds_to_dt (ds_t); extern bool deps_pools_are_empty_p (void); @@ -1509,7 +1509,7 @@ extern void dump_rgn_dependencies_dot (const char *); extern void free_rgn_deps (void); extern int contributes_to_priority (rtx_insn *, rtx_insn *); extern void extend_rgns (int *, int *, sbitmap, int *); -extern void deps_join (struct deps_desc *, struct deps_desc *); +extern void deps_join (class deps_desc *, class deps_desc *); extern void rgn_setup_common_sched_info (void); extern void rgn_setup_sched_infos (void); diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index d400130..59ee6a0 100644 --- a/gcc/sched-rgn.c +++ b/gcc/sched-rgn.c @@ -248,7 +248,7 @@ static void compute_block_dependences (int); static void schedule_region (int); static void concat_insn_mem_list (rtx_insn_list *, rtx_expr_list *, rtx_insn_list **, rtx_expr_list **); -static void propagate_deps (int, struct deps_desc *); +static void propagate_deps (int, class deps_desc *); static void free_pending_lists (void); /* Functions for construction of the control flow graph. */ @@ -2583,7 +2583,7 @@ add_branch_dependences (rtx_insn *head, rtx_insn *tail) the variables of its predecessors. When the analysis for a bb completes, we save the contents to the corresponding bb_deps[bb] variable. */ -static struct deps_desc *bb_deps; +static class deps_desc *bb_deps; static void concat_insn_mem_list (rtx_insn_list *copy_insns, @@ -2608,7 +2608,7 @@ concat_insn_mem_list (rtx_insn_list *copy_insns, /* Join PRED_DEPS to the SUCC_DEPS. */ void -deps_join (struct deps_desc *succ_deps, struct deps_desc *pred_deps) +deps_join (class deps_desc *succ_deps, class deps_desc *pred_deps) { unsigned reg; reg_set_iterator rsi; @@ -2670,7 +2670,7 @@ deps_join (struct deps_desc *succ_deps, struct deps_desc *pred_deps) /* After computing the dependencies for block BB, propagate the dependencies found in TMP_DEPS to the successors of the block. */ static void -propagate_deps (int bb, struct deps_desc *pred_deps) +propagate_deps (int bb, class deps_desc *pred_deps) { basic_block block = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (bb)); edge_iterator ei; @@ -2727,7 +2727,7 @@ static void compute_block_dependences (int bb) { rtx_insn *head, *tail; - struct deps_desc tmp_deps; + class deps_desc tmp_deps; tmp_deps = bb_deps[bb]; @@ -3351,7 +3351,7 @@ sched_rgn_compute_dependencies (int rgn) init_deps_global (); /* Initializations for region data dependence analysis. */ - bb_deps = XNEWVEC (struct deps_desc, current_nr_blocks); + bb_deps = XNEWVEC (class deps_desc, current_nr_blocks); for (bb = 0; bb < current_nr_blocks; bb++) init_deps (bb_deps + bb, false); diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c index 6dec1be..bb8016b 100644 --- a/gcc/sel-sched-ir.c +++ b/gcc/sel-sched-ir.c @@ -61,7 +61,7 @@ struct succs_info current_succs; static struct common_sched_info_def sel_common_sched_info; /* The loop nest being pipelined. */ -struct loop *current_loop_nest; +class loop *current_loop_nest; /* LOOP_NESTS is a vector containing the corresponding loop nest for each region. */ @@ -424,7 +424,7 @@ reset_target_context (tc_t tc, bool clean_p) } /* Functions to work with dependence contexts. - Dc (aka deps context, aka deps_t, aka struct deps_desc *) is short for dependence + Dc (aka deps context, aka deps_t, aka class deps_desc *) is short for dependence context. It accumulates information about processed insns to decide if current insn is dependent on the processed ones. */ @@ -440,7 +440,7 @@ copy_deps_context (deps_t to, deps_t from) static deps_t alloc_deps_context (void) { - return XNEW (struct deps_desc); + return XNEW (class deps_desc); } /* Allocate and initialize dep context. */ @@ -2749,7 +2749,7 @@ init_id_from_df (idata_t id, insn_t insn, bool force_unique_p) static void deps_init_id (idata_t id, insn_t insn, bool force_unique_p) { - struct deps_desc _dc, *dc = &_dc; + class deps_desc _dc, *dc = &_dc; deps_init_id_data.where = DEPS_IN_NOWHERE; deps_init_id_data.id = id; @@ -3390,7 +3390,7 @@ has_dependence_p (expr_t expr, insn_t pred, ds_t **has_dep_pp) { int i; ds_t ds; - struct deps_desc *dc; + class deps_desc *dc; if (INSN_SIMPLEJUMP_P (pred)) /* Unconditional jump is just a transfer of control flow. @@ -5397,7 +5397,7 @@ change_loops_latches (basic_block from, basic_block to) if (current_loop_nest) { - struct loop *loop; + class loop *loop; for (loop = current_loop_nest; loop; loop = loop_outer (loop)) if (considered_for_pipelining_p (loop) && loop->latch == from) @@ -6002,11 +6002,11 @@ bb_top_order_comparator (const void *x, const void *y) /* Create a region for LOOP and return its number. If we don't want to pipeline LOOP, return -1. */ static int -make_region_from_loop (struct loop *loop) +make_region_from_loop (class loop *loop) { unsigned int i; int new_rgn_number = -1; - struct loop *inner; + class loop *inner; /* Basic block index, to be assigned to BLOCK_TO_BB. */ int bb_ord_index = 0; @@ -6095,9 +6095,9 @@ make_region_from_loop_preheader (vec *&loop_blocks) pipelined before outer loops. Returns true when a region for LOOP is created. */ static bool -make_regions_from_loop_nest (struct loop *loop) +make_regions_from_loop_nest (class loop *loop) { - struct loop *cur_loop; + class loop *cur_loop; int rgn_number; /* Traverse all inner nodes of the loop. */ @@ -6133,7 +6133,7 @@ sel_init_pipelining (void) recompute_rev_top_order (); } -/* Returns a struct loop for region RGN. */ +/* Returns a class loop for region RGN. */ loop_p get_loop_nest_for_rgn (unsigned int rgn) { @@ -6147,7 +6147,7 @@ get_loop_nest_for_rgn (unsigned int rgn) /* True when LOOP was included into pipelining regions. */ bool -considered_for_pipelining_p (struct loop *loop) +considered_for_pipelining_p (class loop *loop) { if (loop_depth (loop) == 0) return false; @@ -6249,7 +6249,7 @@ make_regions_from_the_rest (void) /* Free data structures used in pipelining of loops. */ void sel_finish_pipelining (void) { - struct loop *loop; + class loop *loop; /* Release aux fields so we don't free them later by mistake. */ FOR_EACH_LOOP (loop, 0) @@ -6324,7 +6324,7 @@ sel_is_loop_preheader_p (basic_block bb) { if (current_loop_nest) { - struct loop *outer; + class loop *outer; if (preheader_removed) return false; diff --git a/gcc/sel-sched-ir.h b/gcc/sel-sched-ir.h index 2a24a92..b5824ae 100644 --- a/gcc/sel-sched-ir.h +++ b/gcc/sel-sched-ir.h @@ -746,7 +746,7 @@ public: htab_t transformed_insns; /* A context incapsulating this insn. */ - struct deps_desc deps_context; + class deps_desc deps_context; /* This field is initialized at the beginning of scheduling and is used to handle sched group instructions. If it is non-null, then it points @@ -775,7 +775,7 @@ public: BOOL_BITFIELD after_stall_p : 1; }; -typedef struct _sel_insn_data sel_insn_data_def; +typedef class _sel_insn_data sel_insn_data_def; typedef sel_insn_data_def *sel_insn_data_t; extern vec s_i_d; @@ -954,7 +954,7 @@ extern vec sel_region_bb_info; extern bitmap_head *forced_ebb_heads; /* The loop nest being pipelined. */ -extern struct loop *current_loop_nest; +extern class loop *current_loop_nest; /* Saves pipelined blocks. Bitmap is indexed by bb->index. */ extern sbitmap bbs_pipelined; @@ -1043,7 +1043,7 @@ extern bool in_current_region_p (basic_block); static inline bool inner_loop_header_p (basic_block bb) { - struct loop *inner_loop; + class loop *inner_loop; if (!current_loop_nest) return false; @@ -1069,7 +1069,7 @@ inner_loop_header_p (basic_block bb) /* Return exit edges of LOOP, filtering out edges with the same dest bb. */ static inline vec -get_loop_exit_edges_unique_dests (const struct loop *loop) +get_loop_exit_edges_unique_dests (const class loop *loop) { vec edges = vNULL; struct loop_exit *exit; @@ -1142,8 +1142,8 @@ get_all_loop_exits (basic_block bb) /* And now check whether we should skip over inner loop. */ if (inner_loop_header_p (bb)) { - struct loop *this_loop; - struct loop *pred_loop = NULL; + class loop *this_loop; + class loop *pred_loop = NULL; int i; unsigned this_depth; edge e; @@ -1642,7 +1642,7 @@ extern void sel_init_pipelining (void); extern void sel_finish_pipelining (void); extern void sel_sched_region (int); extern loop_p get_loop_nest_for_rgn (unsigned int); -extern bool considered_for_pipelining_p (struct loop *); +extern bool considered_for_pipelining_p (class loop *); extern void make_region_from_loop_preheader (vec *&); extern void sel_add_loop_preheaders (bb_vec_t *); extern bool sel_is_loop_preheader_p (basic_block); diff --git a/gcc/selftest.h b/gcc/selftest.h index 6152ef5..75b2cd8 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -150,7 +150,7 @@ class auto_fix_quotes The following struct describes a particular case within our test matrix. */ -struct line_table_case; +class line_table_case; /* A class for overriding the global "line_table" within a selftest, restoring its value afterwards. At most one instance of this diff --git a/gcc/sese.c b/gcc/sese.c index e904731..4b3065a 100644 --- a/gcc/sese.c +++ b/gcc/sese.c @@ -149,7 +149,7 @@ sese_build_liveouts (sese_info_p region) sese_info_p new_sese_info (edge entry, edge exit) { - sese_info_p region = XNEW (struct sese_info_t); + sese_info_p region = XNEW (class sese_info_t); region->region.entry = entry; region->region.exit = exit; @@ -217,10 +217,10 @@ sese_insert_phis_for_liveouts (sese_info_p region, basic_block bb, /* Returns the outermost loop in SCOP that contains BB. */ -struct loop * +class loop * outermost_loop_in_sese_1 (sese_l ®ion, basic_block bb) { - struct loop *nest; + class loop *nest; nest = bb->loop_father; while (loop_outer (nest) diff --git a/gcc/sese.h b/gcc/sese.h index 0319da6..6a62bb6 100644 --- a/gcc/sese.h +++ b/gcc/sese.h @@ -101,7 +101,7 @@ public: extern sese_info_p new_sese_info (edge, edge); extern void free_sese_info (sese_info_p); extern void sese_insert_phis_for_liveouts (sese_info_p, basic_block, edge, edge); -extern struct loop *outermost_loop_in_sese (sese_l &, basic_block); +extern class loop *outermost_loop_in_sese (sese_l &, basic_block); extern tree scalar_evolution_in_region (const sese_l &, loop_p, tree); extern bool scev_analyzable_p (tree, sese_l &); extern bool invariant_in_sese_p_rec (tree, const sese_l &, bool *); @@ -156,7 +156,7 @@ defined_in_sese_p (tree name, const sese_l &r) /* Returns true when LOOP is in REGION. */ static inline bool -loop_in_sese_p (struct loop *loop, const sese_l ®ion) +loop_in_sese_p (class loop *loop, const sese_l ®ion) { return (bb_in_sese_p (loop->header, region) && bb_in_sese_p (loop->latch, region)); @@ -272,7 +272,7 @@ typedef struct gimple_poly_bb /* Return the innermost loop that contains the basic block GBB. */ -static inline struct loop * +static inline class loop * gbb_loop (gimple_poly_bb_p gbb) { return GBB_BB (gbb)->loop_father; diff --git a/gcc/sreal.c b/gcc/sreal.c index b991652..5418481 100644 --- a/gcc/sreal.c +++ b/gcc/sreal.c @@ -258,7 +258,7 @@ sreal::stream_out (struct output_block *ob) /* Read sreal value from IB. */ sreal -sreal::stream_in (struct lto_input_block *ib) +sreal::stream_in (class lto_input_block *ib) { sreal val; val.m_sig = streamer_read_hwi (ib); diff --git a/gcc/sreal.h b/gcc/sreal.h index aa3327b..cb363d4 100644 --- a/gcc/sreal.h +++ b/gcc/sreal.h @@ -34,7 +34,7 @@ along with GCC; see the file COPYING3. If not see #define SREAL_ABS(v) (v < 0 ? -v: v) struct output_block; -struct lto_input_block; +class lto_input_block; /* Structure for holding a simple real number. */ class sreal @@ -53,7 +53,7 @@ public: int64_t to_int () const; double to_double () const; void stream_out (struct output_block *); - static sreal stream_in (struct lto_input_block *); + static sreal stream_in (class lto_input_block *); sreal operator+ (const sreal &other) const; sreal operator- (const sreal &other) const; sreal operator* (const sreal &other) const; diff --git a/gcc/streamer-hooks.h b/gcc/streamer-hooks.h index 2a45513..14d158e 100644 --- a/gcc/streamer-hooks.h +++ b/gcc/streamer-hooks.h @@ -25,8 +25,8 @@ along with GCC; see the file COPYING3. If not see /* Forward declarations to avoid including unnecessary headers. */ struct output_block; -struct lto_input_block; -struct data_in; +class lto_input_block; +class data_in; /* Streamer hooks. These functions do additional processing as needed by the module. There are two types of callbacks, those that @@ -49,10 +49,10 @@ struct streamer_hooks { to the buffer where to read from and a data_in instance with tables and descriptors needed by the unpickling routines. It returns the tree instantiated from the stream. */ - tree (*read_tree) (struct lto_input_block *, struct data_in *); + tree (*read_tree) (class lto_input_block *, class data_in *); /* [REQ] Called by every streaming routine that needs to read a location. */ - void (*input_location) (location_t *, struct bitpack_d *, struct data_in *); + void (*input_location) (location_t *, struct bitpack_d *, class data_in *); /* [REQ] Called by every streaming routine that needs to write a location. */ void (*output_location) (struct output_block *, struct bitpack_d *, location_t); diff --git a/gcc/target-globals.c b/gcc/target-globals.c index 94a465c..8928fc1 100644 --- a/gcc/target-globals.c +++ b/gcc/target-globals.c @@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see #include "lower-subreg.h" #if SWITCHABLE_TARGET -struct target_globals default_target_globals = { +class target_globals default_target_globals = { &default_target_flag_state, &default_target_regs, &default_target_rtl, @@ -61,11 +61,11 @@ struct target_globals default_target_globals = { &default_target_lower_subreg }; -struct target_globals * +class target_globals * save_target_globals (void) { - struct target_globals *g = ggc_cleared_alloc (); - g->flag_state = XCNEW (struct target_flag_state); + class target_globals *g = ggc_cleared_alloc (); + g->flag_state = XCNEW (class target_flag_state); g->regs = XCNEW (struct target_regs); g->rtl = ggc_cleared_alloc (); g->recog = XCNEW (struct target_recog); @@ -76,7 +76,7 @@ save_target_globals (void) g->libfuncs = ggc_cleared_alloc (); g->cfgloop = XCNEW (struct target_cfgloop); g->ira = XCNEW (struct target_ira); - g->ira_int = XCNEW (struct target_ira_int); + g->ira_int = XCNEW (class target_ira_int); g->builtins = XCNEW (struct target_builtins); g->gcse = XCNEW (struct target_gcse); g->bb_reorder = XCNEW (struct target_bb_reorder); @@ -91,10 +91,10 @@ save_target_globals (void) correctly when a previous function has changed *this_target_optabs. */ -struct target_globals * +class target_globals * save_target_globals_default_opts () { - struct target_globals *globals; + class target_globals *globals; if (optimization_current_node != optimization_default_node) { diff --git a/gcc/target-globals.h b/gcc/target-globals.h index 57cb42f..ceb216a 100644 --- a/gcc/target-globals.h +++ b/gcc/target-globals.h @@ -21,7 +21,7 @@ along with GCC; see the file COPYING3. If not see #define TARGET_GLOBALS_H 1 #if SWITCHABLE_TARGET -extern struct target_flag_state *this_target_flag_state; +extern class target_flag_state *this_target_flag_state; extern struct target_regs *this_target_regs; extern struct target_rtl *this_target_rtl; extern struct target_recog *this_target_recog; @@ -32,7 +32,7 @@ extern struct target_optabs *this_target_optabs; extern struct target_libfuncs *this_target_libfuncs; extern struct target_cfgloop *this_target_cfgloop; extern struct target_ira *this_target_ira; -extern struct target_ira_int *this_target_ira_int; +extern class target_ira_int *this_target_ira_int; extern struct target_builtins *this_target_builtins; extern struct target_gcse *this_target_gcse; extern struct target_bb_reorder *this_target_bb_reorder; @@ -43,7 +43,7 @@ class GTY(()) target_globals { public: ~target_globals (); - struct target_flag_state *GTY((skip)) flag_state; + class target_flag_state *GTY((skip)) flag_state; struct target_regs *GTY((skip)) regs; struct target_rtl *rtl; struct target_recog *GTY((skip)) recog; @@ -54,7 +54,7 @@ public: struct target_libfuncs *libfuncs; struct target_cfgloop *GTY((skip)) cfgloop; struct target_ira *GTY((skip)) ira; - struct target_ira_int *GTY((skip)) ira_int; + class target_ira_int *GTY((skip)) ira_int; struct target_builtins *GTY((skip)) builtins; struct target_gcse *GTY((skip)) gcse; struct target_bb_reorder *GTY((skip)) bb_reorder; @@ -62,13 +62,13 @@ public: }; #if SWITCHABLE_TARGET -extern struct target_globals default_target_globals; +extern class target_globals default_target_globals; -extern struct target_globals *save_target_globals (void); -extern struct target_globals *save_target_globals_default_opts (void); +extern class target_globals *save_target_globals (void); +extern class target_globals *save_target_globals_default_opts (void); static inline void -restore_target_globals (struct target_globals *g) +restore_target_globals (class target_globals *g) { this_target_flag_state = g->flag_state; this_target_regs = g->regs; diff --git a/gcc/target.def b/gcc/target.def index 4165405..7cc0f37 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1970,7 +1970,7 @@ DEFHOOK "non-NULL, it identifies the loop being vectorized; otherwise a single block " "is being vectorized.", void *, - (struct loop *loop_info), + (class loop *loop_info), default_init_cost) /* Target function to record N statements of the given kind using the @@ -1987,7 +1987,7 @@ DEFHOOK "revised.", unsigned, (void *data, int count, enum vect_cost_for_stmt kind, - struct _stmt_vec_info *stmt_info, int misalign, + class _stmt_vec_info *stmt_info, int misalign, enum vect_cost_model_location where), default_add_stmt_cost) @@ -2665,7 +2665,7 @@ the loop is to be unrolled. The parameter @var{loop} is a pointer to\n\ the loop, which is going to be checked for unrolling. This target hook\n\ is required only when the target has special constraints like maximum\n\ number of memory accesses.", - unsigned, (unsigned nunroll, struct loop *loop), + unsigned, (unsigned nunroll, class loop *loop), NULL) /* True if X is a legitimate MODE-mode immediate operand. */ @@ -3182,7 +3182,7 @@ DEFHOOK version of this hook assumes the system C library errno location\ is either a declaration of type int or accessed by dereferencing\ a pointer to int.", - bool, (struct ao_ref *ref), + bool, (ao_ref *ref), default_ref_may_alias_errno) /* Support for named address spaces. */ @@ -4243,7 +4243,7 @@ for a particular loop. The parameter @var{loop} is a pointer to the loop.\n\ This target hook is required only when the target supports low-overhead\n\ loops, and will help ivopts to make some decisions.\n\ The default version of this hook returns false.", - bool, (struct loop *loop), + bool, (class loop *loop), default_predict_doloop_p) DEFHOOK diff --git a/gcc/target.h b/gcc/target.h index 008932b..633e384 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -138,20 +138,20 @@ struct _dep; struct ddg; /* This is defined in cfgloop.h . */ -struct loop; +class loop; /* This is defined in ifcvt.h. */ struct noce_if_info; /* This is defined in tree-ssa-alias.h. */ -struct ao_ref; +class ao_ref; /* This is defined in tree-vectorizer.h. */ -struct _stmt_vec_info; +class _stmt_vec_info; /* These are defined in tree-vect-stmts.c. */ -extern tree stmt_vectype (struct _stmt_vec_info *); -extern bool stmt_in_inner_loop_p (struct _stmt_vec_info *); +extern tree stmt_vectype (class _stmt_vec_info *); +extern bool stmt_in_inner_loop_p (class _stmt_vec_info *); /* Assembler instructions for creating various kinds of integer object. */ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 676885b..fa797b4 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -651,7 +651,7 @@ default_has_ifunc_p (void) if the target can take advantage of it. */ bool -default_predict_doloop_p (struct loop *loop ATTRIBUTE_UNUSED) +default_predict_doloop_p (class loop *loop ATTRIBUTE_UNUSED) { return false; } @@ -1366,7 +1366,7 @@ default_empty_mask_is_expensive (unsigned ifn) array of three unsigned ints, set it to zero, and return its address. */ void * -default_init_cost (struct loop *loop_info ATTRIBUTE_UNUSED) +default_init_cost (class loop *loop_info ATTRIBUTE_UNUSED) { unsigned *cost = XNEWVEC (unsigned, 3); cost[vect_prologue] = cost[vect_body] = cost[vect_epilogue] = 0; @@ -1379,7 +1379,7 @@ default_init_cost (struct loop *loop_info ATTRIBUTE_UNUSED) unsigned default_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind, - struct _stmt_vec_info *stmt_info, int misalign, + class _stmt_vec_info *stmt_info, int misalign, enum vect_cost_model_location where) { unsigned *cost = (unsigned *) data; diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 50b03ce..ca2e37d 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -85,7 +85,7 @@ extern bool default_fixed_point_supported_p (void); extern bool default_has_ifunc_p (void); -extern bool default_predict_doloop_p (struct loop *); +extern bool default_predict_doloop_p (class loop *); extern const char * default_invalid_within_doloop (const rtx_insn *); extern tree default_builtin_vectorized_function (unsigned int, tree, tree); @@ -114,9 +114,9 @@ extern machine_mode default_split_reduction (machine_mode); extern void default_autovectorize_vector_sizes (vector_sizes *, bool); extern opt_machine_mode default_get_mask_mode (poly_uint64, poly_uint64); extern bool default_empty_mask_is_expensive (unsigned); -extern void *default_init_cost (struct loop *); +extern void *default_init_cost (class loop *); extern unsigned default_add_stmt_cost (void *, int, enum vect_cost_for_stmt, - struct _stmt_vec_info *, int, + class _stmt_vec_info *, int, enum vect_cost_model_location); extern void default_finish_cost (void *, unsigned *, unsigned *, unsigned *); extern void default_destroy_cost_data (void *); @@ -188,7 +188,7 @@ extern bool default_target_option_valid_attribute_p (tree, tree, tree, int); extern bool default_target_option_pragma_parse (tree, tree); extern bool default_target_can_inline_p (tree, tree); extern bool default_valid_pointer_mode (scalar_int_mode); -extern bool default_ref_may_alias_errno (struct ao_ref *); +extern bool default_ref_may_alias_errno (class ao_ref *); extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t); extern scalar_int_mode default_addr_space_address_mode (addr_space_t); extern bool default_addr_space_valid_pointer_mode (scalar_int_mode, diff --git a/gcc/toplev.c b/gcc/toplev.c index 116be7b..2567fe2 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -159,9 +159,9 @@ HOST_WIDE_INT random_seed; the support provided depends on the backend. */ rtx stack_limit_rtx; -struct target_flag_state default_target_flag_state; +class target_flag_state default_target_flag_state; #if SWITCHABLE_TARGET -struct target_flag_state *this_target_flag_state = &default_target_flag_state; +class target_flag_state *this_target_flag_state = &default_target_flag_state; #else #define this_target_flag_state (&default_target_flag_state) #endif diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index ee7e010..976cf3c 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -675,7 +675,7 @@ aff_combination_mult (aff_tree *c1, aff_tree *c2, aff_tree *r) element exists. If IDX is not NULL, it is set to the index of VAL in COMB. */ -static struct aff_comb_elt * +static class aff_comb_elt * aff_combination_find_elt (aff_tree *comb, tree val, unsigned *idx) { unsigned i; @@ -716,7 +716,7 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED, tree e; gimple *def; widest_int scale; - struct name_expansion *exp; + class name_expansion *exp; aff_combination_zero (&to_add, comb->type); for (i = 0; i < comb->n; i++) @@ -795,7 +795,7 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED, default: continue; } - exp = XNEW (struct name_expansion); + exp = XNEW (class name_expansion); exp->in_progress = 1; if (!*cache) *cache = new hash_map; @@ -932,7 +932,7 @@ aff_combination_constant_multiple_p (aff_tree *val, aff_tree *div, for (i = 0; i < div->n; i++) { - struct aff_comb_elt *elt + class aff_comb_elt *elt = aff_combination_find_elt (val, div->elts[i].val, NULL); if (!elt) return false; diff --git a/gcc/tree-affine.h b/gcc/tree-affine.h index 23c6096..2164820 100644 --- a/gcc/tree-affine.h +++ b/gcc/tree-affine.h @@ -56,7 +56,7 @@ public: The coefficients are always sign extended from the precision of TYPE (regardless of signedness of TYPE). */ - struct aff_comb_elt elts[MAX_AFF_ELTS]; + class aff_comb_elt elts[MAX_AFF_ELTS]; /* Remainder of the expression. Usually NULL, used only if there are more than MAX_AFF_ELTS elements. Type of REST will be either sizetype for @@ -64,7 +64,7 @@ public: tree rest; }; -struct name_expansion; +class name_expansion; void aff_combination_const (aff_tree *, tree, const poly_widest_int &); void aff_combination_elt (aff_tree *, tree, tree); diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 0396aa9..5c67d02 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -256,7 +256,7 @@ build_gimple_cfg (gimple_seq seq) come immediately before the condition in BB, if any. */ static void -replace_loop_annotate_in_block (basic_block bb, struct loop *loop) +replace_loop_annotate_in_block (basic_block bb, class loop *loop) { gimple_stmt_iterator gsi = gsi_last_bb (bb); gimple *stmt = gsi_stmt (gsi); @@ -311,7 +311,7 @@ replace_loop_annotate_in_block (basic_block bb, struct loop *loop) static void replace_loop_annotate (void) { - struct loop *loop; + class loop *loop; basic_block bb; gimple_stmt_iterator gsi; gimple *stmt; @@ -1996,7 +1996,7 @@ replace_uses_by (tree name, tree val) /* Also update the trees stored in loop structures. */ if (current_loops) { - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, 0) { @@ -2223,7 +2223,7 @@ remove_bb (basic_block bb) if (current_loops) { - struct loop *loop = bb->loop_father; + class loop *loop = bb->loop_father; /* If a loop gets removed, clean up the information associated with it. */ @@ -2547,7 +2547,7 @@ dump_cfg_stats (FILE *file) num_edges = 0; FOR_EACH_BB_FN (bb, cfun) num_edges += EDGE_COUNT (bb->succs); - size = num_edges * sizeof (struct edge_def); + size = num_edges * sizeof (class edge_def); total += size; fprintf (file, fmt_str_2, "Edges", num_edges, SIZE_AMOUNT (size)); @@ -6383,7 +6383,7 @@ gimple_duplicate_sese_region (edge entry, edge exit, { unsigned i; bool free_region_copy = false, copying_header = false; - struct loop *loop = entry->dest->loop_father; + class loop *loop = entry->dest->loop_father; edge exit_copy; vec doms = vNULL; edge redirected; @@ -6549,8 +6549,8 @@ gimple_duplicate_sese_tail (edge entry, edge exit, { unsigned i; bool free_region_copy = false; - struct loop *loop = exit->dest->loop_father; - struct loop *orig_loop = entry->dest->loop_father; + class loop *loop = exit->dest->loop_father; + class loop *orig_loop = entry->dest->loop_father; basic_block switch_bb, entry_bb, nentry_bb; vec doms; profile_count total_count = profile_count::uninitialized (), @@ -6563,7 +6563,7 @@ gimple_duplicate_sese_tail (edge entry, edge exit, gphi_iterator psi; gphi *phi; tree def; - struct loop *target, *aloop, *cloop; + class loop *target, *aloop, *cloop; gcc_assert (EDGE_COUNT (exit->src->succs) == 2); exits[0] = exit; @@ -7040,7 +7040,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, /* Move BB from its current loop to the copy in the new function. */ if (current_loops) { - struct loop *new_loop = (struct loop *)bb->loop_father->aux; + class loop *new_loop = (class loop *)bb->loop_father->aux; if (new_loop) bb->loop_father = new_loop; } @@ -7304,7 +7304,7 @@ replace_block_vars_by_duplicates (tree block, hash_map *vars_map, static void fixup_loop_arrays_after_move (struct function *fn1, struct function *fn2, - struct loop *loop) + class loop *loop) { /* Discard it from the old loop array. */ (*get_loops (fn1))[loop->num] = NULL; @@ -7464,8 +7464,8 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, edge_iterator ei; htab_t new_label_map; hash_map *eh_map; - struct loop *loop = entry_bb->loop_father; - struct loop *loop0 = get_loop (saved_cfun, 0); + class loop *loop = entry_bb->loop_father; + class loop *loop0 = get_loop (saved_cfun, 0); struct move_stmt_d d; /* If ENTRY does not strictly dominate EXIT, this cannot be an SESE @@ -7573,8 +7573,8 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, { if (bb->loop_father->header == bb) { - struct loop *this_loop = bb->loop_father; - struct loop *outer = loop_outer (this_loop); + class loop *this_loop = bb->loop_father; + class loop *outer = loop_outer (this_loop); if (outer == loop /* If the SESE region contains some bbs ending with a noreturn call, those are considered to belong @@ -7614,7 +7614,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, /* Fix up orig_loop_num. If the block referenced in it has been moved to dest_cfun, update orig_loop_num field, otherwise clear it. */ - struct loop *dloop; + class loop *dloop; signed char *moved_orig_loop_num = NULL; FOR_EACH_LOOP_FN (dest_cfun, dloop, 0) if (dloop->orig_loop_num) @@ -7722,14 +7722,14 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, loop0->aux = NULL; /* Loop sizes are no longer correct, fix them up. */ loop->num_nodes -= num_nodes; - for (struct loop *outer = loop_outer (loop); + for (class loop *outer = loop_outer (loop); outer; outer = loop_outer (outer)) outer->num_nodes -= num_nodes; loop0->num_nodes -= bbs.length () - num_nodes; if (saved_cfun->has_simduid_loops || saved_cfun->has_force_vectorize_loops) { - struct loop *aloop; + class loop *aloop; for (i = 0; vec_safe_iterate (loops->larray, i, &aloop); i++) if (aloop != NULL) { @@ -8180,14 +8180,14 @@ print_loops_bb (FILE *file, basic_block bb, int indent, int verbosity) } } -static void print_loop_and_siblings (FILE *, struct loop *, int, int); +static void print_loop_and_siblings (FILE *, class loop *, int, int); /* Pretty print LOOP on FILE, indented INDENT spaces. Following VERBOSITY level this outputs the contents of the loop, or just its structure. */ static void -print_loop (FILE *file, struct loop *loop, int indent, int verbosity) +print_loop (FILE *file, class loop *loop, int indent, int verbosity) { char *s_indent; basic_block bb; @@ -8253,7 +8253,7 @@ print_loop (FILE *file, struct loop *loop, int indent, int verbosity) loop, or just its structure. */ static void -print_loop_and_siblings (FILE *file, struct loop *loop, int indent, +print_loop_and_siblings (FILE *file, class loop *loop, int indent, int verbosity) { if (loop == NULL) @@ -8280,13 +8280,13 @@ print_loops (FILE *file, int verbosity) /* Dump a loop. */ DEBUG_FUNCTION void -debug (struct loop &ref) +debug (class loop &ref) { print_loop (stderr, &ref, 0, /*verbosity*/0); } DEBUG_FUNCTION void -debug (struct loop *ptr) +debug (class loop *ptr) { if (ptr) debug (*ptr); @@ -8297,13 +8297,13 @@ debug (struct loop *ptr) /* Dump a loop verbosely. */ DEBUG_FUNCTION void -debug_verbose (struct loop &ref) +debug_verbose (class loop &ref) { print_loop (stderr, &ref, 0, /*verbosity*/3); } DEBUG_FUNCTION void -debug_verbose (struct loop *ptr) +debug_verbose (class loop *ptr) { if (ptr) debug (*ptr); @@ -8323,7 +8323,7 @@ debug_loops (int verbosity) /* Print on stderr the code of LOOP, at some VERBOSITY level. */ DEBUG_FUNCTION void -debug_loop (struct loop *loop, int verbosity) +debug_loop (class loop *loop, int verbosity) { print_loop (stderr, loop, 0, verbosity); } diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index 836f8e8..7329161 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -83,12 +83,12 @@ extern void dump_function_to_file (tree, FILE *, dump_flags_t); extern void debug_function (tree, dump_flags_t); extern void print_loops_bb (FILE *, basic_block, int, int); extern void print_loops (FILE *, int); -extern void debug (struct loop &ref); -extern void debug (struct loop *ptr); -extern void debug_verbose (struct loop &ref); -extern void debug_verbose (struct loop *ptr); +extern void debug (class loop &ref); +extern void debug (class loop *ptr); +extern void debug_verbose (class loop &ref); +extern void debug_verbose (class loop *ptr); extern void debug_loops (int); -extern void debug_loop (struct loop *, int); +extern void debug_loop (class loop *, int); extern void debug_loop_num (unsigned, int); extern void remove_edge_and_dominated_blocks (edge); extern bool gimple_purge_dead_eh_edges (basic_block); diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c index f50fd20..5ed62260 100644 --- a/gcc/tree-chrec.c +++ b/gcc/tree-chrec.c @@ -52,8 +52,8 @@ chrec_fold_plus_poly_poly (enum tree_code code, tree poly1) { tree left, right; - struct loop *loop0 = get_chrec_loop (poly0); - struct loop *loop1 = get_chrec_loop (poly1); + class loop *loop0 = get_chrec_loop (poly0); + class loop *loop1 = get_chrec_loop (poly1); tree rtype = code == POINTER_PLUS_EXPR ? chrec_type (poly1) : type; gcc_assert (poly0); @@ -144,8 +144,8 @@ chrec_fold_multiply_poly_poly (tree type, { tree t0, t1, t2; int var; - struct loop *loop0 = get_chrec_loop (poly0); - struct loop *loop1 = get_chrec_loop (poly1); + class loop *loop0 = get_chrec_loop (poly0); + class loop *loop1 = get_chrec_loop (poly1); gcc_assert (poly0); gcc_assert (poly1); @@ -539,7 +539,7 @@ chrec_evaluate (unsigned var, tree chrec, tree n, unsigned int k) { tree arg0, arg1, binomial_n_k; tree type = TREE_TYPE (chrec); - struct loop *var_loop = get_loop (cfun, var); + class loop *var_loop = get_loop (cfun, var); while (TREE_CODE (chrec) == POLYNOMIAL_CHREC && flow_loop_nested_p (var_loop, get_chrec_loop (chrec))) @@ -720,7 +720,7 @@ tree hide_evolution_in_other_loops_than_loop (tree chrec, unsigned loop_num) { - struct loop *loop = get_loop (cfun, loop_num), *chloop; + class loop *loop = get_loop (cfun, loop_num), *chloop; if (automatically_generated_chrec_p (chrec)) return chrec; @@ -761,7 +761,7 @@ chrec_component_in_loop_num (tree chrec, bool right) { tree component; - struct loop *loop = get_loop (cfun, loop_num), *chloop; + class loop *loop = get_loop (cfun, loop_num), *chloop; if (automatically_generated_chrec_p (chrec)) return chrec; @@ -843,7 +843,7 @@ reset_evolution_in_loop (unsigned loop_num, tree chrec, tree new_evol) { - struct loop *loop = get_loop (cfun, loop_num); + class loop *loop = get_loop (cfun, loop_num); if (POINTER_TYPE_P (chrec_type (chrec))) gcc_assert (ptrofftype_p (chrec_type (new_evol))); @@ -939,7 +939,7 @@ is_multivariate_chrec (const_tree chrec) static bool chrec_contains_symbols (const_tree chrec, hash_set &visited, - struct loop *loop) + class loop *loop) { int i, n; @@ -977,7 +977,7 @@ chrec_contains_symbols (const_tree chrec, hash_set &visited, the chrec is considered as a SYMBOL. */ bool -chrec_contains_symbols (const_tree chrec, struct loop* loop) +chrec_contains_symbols (const_tree chrec, class loop* loop) { hash_set visited; return chrec_contains_symbols (chrec, visited, loop); @@ -1296,7 +1296,7 @@ nb_vars_in_chrec (tree chrec) the conversion succeeded, false otherwise. */ bool -convert_affine_scev (struct loop *loop, tree type, +convert_affine_scev (class loop *loop, tree type, tree *base, tree *step, gimple *at_stmt, bool use_overflow_semantics, tree from) { @@ -1427,7 +1427,7 @@ chrec_convert_1 (tree type, tree chrec, gimple *at_stmt, { tree ct, res; tree base, step; - struct loop *loop; + class loop *loop; if (automatically_generated_chrec_p (chrec)) return chrec; @@ -1563,7 +1563,7 @@ chrec_convert_aggressive (tree type, tree chrec, bool *fold_conversions) if (!*fold_conversions && evolution_function_is_affine_p (chrec)) { tree base, step; - struct loop *loop; + class loop *loop; loop = get_chrec_loop (chrec); base = CHREC_LEFT (chrec); diff --git a/gcc/tree-chrec.h b/gcc/tree-chrec.h index 3b5c090..423d8fb 100644 --- a/gcc/tree-chrec.h +++ b/gcc/tree-chrec.h @@ -77,13 +77,13 @@ extern tree hide_evolution_in_other_loops_than_loop (tree, unsigned); extern tree reset_evolution_in_loop (unsigned, tree, tree); extern tree chrec_merge (tree, tree); extern void for_each_scev_op (tree *, bool (*) (tree *, void *), void *); -extern bool convert_affine_scev (struct loop *, tree, tree *, tree *, gimple *, +extern bool convert_affine_scev (class loop *, tree, tree *, tree *, gimple *, bool, tree = NULL); /* Observers. */ extern bool eq_evolutions_p (const_tree, const_tree); extern bool is_multivariate_chrec (const_tree); -extern bool chrec_contains_symbols (const_tree, struct loop * = NULL); +extern bool chrec_contains_symbols (const_tree, class loop * = NULL); extern bool chrec_contains_symbols_defined_in_loop (const_tree, unsigned); extern bool chrec_contains_undetermined (const_tree); extern bool tree_contains_chrecs (const_tree, int *); diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 9ea8638..b5dde47 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1908,7 +1908,7 @@ struct GTY(()) tree_optimization_option { /* Forward declaration, defined in target-globals.h. */ -struct GTY(()) target_globals; +class GTY(()) target_globals; /* Target options used by a function. */ @@ -1916,7 +1916,7 @@ struct GTY(()) tree_target_option { struct tree_base base; /* Target globals for the corresponding target option. */ - struct target_globals *globals; + class target_globals *globals; /* The optimization options used by the user. */ struct cl_target_option *opts; diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 4dc03ef..df1a7b8 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -127,7 +127,7 @@ static struct datadep_stats static bool subscript_dependence_tester_1 (struct data_dependence_relation *, unsigned int, unsigned int, - struct loop *); + class loop *); /* Returns true iff A divides B. */ static inline bool @@ -448,7 +448,7 @@ dump_data_dependence_relation (FILE *outf, else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) { unsigned int i; - struct loop *loopi; + class loop *loopi; subscript *sub; FOR_EACH_VEC_ELT (DDR_SUBSCRIPTS (ddr), i, sub) @@ -873,7 +873,7 @@ canonicalize_base_object_address (tree addr) opt_result dr_analyze_innermost (innermost_loop_behavior *drb, tree ref, - struct loop *loop, const gimple *stmt) + class loop *loop, const gimple *stmt) { poly_int64 pbitsize, pbitpos; tree base, poffset; @@ -1351,7 +1351,7 @@ data_ref_compare_tree (tree t1, tree t2) check. */ opt_result -runtime_alias_check_p (ddr_p ddr, struct loop *loop, bool speed_p) +runtime_alias_check_p (ddr_p ddr, class loop *loop, bool speed_p) { if (dump_enabled_p ()) dump_printf (MSG_NOTE, @@ -1624,7 +1624,7 @@ prune_runtime_alias_test_list (vec *alias_pairs, Note evolution step of index needs to be considered in comparison. */ static bool -create_intersect_range_checks_index (struct loop *loop, tree *cond_expr, +create_intersect_range_checks_index (class loop *loop, tree *cond_expr, const dr_with_seg_len& dr_a, const dr_with_seg_len& dr_b) { @@ -1858,7 +1858,7 @@ get_segment_min_max (const dr_with_seg_len &d, tree *seg_min_out, || (DR_B_addr_0 + DER_B_segment_length_0) <= DR_A_addr_0)) */ static void -create_intersect_range_checks (struct loop *loop, tree *cond_expr, +create_intersect_range_checks (class loop *loop, tree *cond_expr, const dr_with_seg_len& dr_a, const dr_with_seg_len& dr_b) { @@ -1917,7 +1917,7 @@ create_intersect_range_checks (struct loop *loop, tree *cond_expr, that controls which version of the loop gets executed at runtime. */ void -create_runtime_alias_checks (struct loop *loop, +create_runtime_alias_checks (class loop *loop, vec *alias_pairs, tree * cond_expr) { @@ -2197,7 +2197,7 @@ conflict_fn_no_dependence (void) /* Returns true if the address of OBJ is invariant in LOOP. */ static bool -object_address_invariant_in_loop_p (const struct loop *loop, const_tree obj) +object_address_invariant_in_loop_p (const class loop *loop, const_tree obj) { while (handled_component_p (obj)) { @@ -2231,7 +2231,7 @@ object_address_invariant_in_loop_p (const struct loop *loop, const_tree obj) bool dr_may_alias_p (const struct data_reference *a, const struct data_reference *b, - struct loop *loop_nest) + class loop *loop_nest) { tree addr_a = DR_BASE_OBJECT (a); tree addr_b = DR_BASE_OBJECT (b); @@ -2892,7 +2892,7 @@ analyze_ziv_subscript (tree chrec_a, chrec_dont_know. */ static tree -max_stmt_executions_tree (struct loop *loop) +max_stmt_executions_tree (class loop *loop) { widest_int nit; @@ -3046,7 +3046,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference)) { HOST_WIDE_INT numiter; - struct loop *loop = get_chrec_loop (chrec_b); + class loop *loop = get_chrec_loop (chrec_b); *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node)); tmp = fold_build2 (EXACT_DIV_EXPR, type, @@ -3127,7 +3127,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference)) { HOST_WIDE_INT numiter; - struct loop *loop = get_chrec_loop (chrec_b); + class loop *loop = get_chrec_loop (chrec_b); *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node)); tmp = fold_build2 (EXACT_DIV_EXPR, type, difference, @@ -4023,7 +4023,7 @@ analyze_miv_subscript (tree chrec_a, conflict_function **overlaps_a, conflict_function **overlaps_b, tree *last_conflicts, - struct loop *loop_nest) + class loop *loop_nest) { tree type, difference; @@ -4125,7 +4125,7 @@ analyze_overlapping_iterations (tree chrec_a, tree chrec_b, conflict_function **overlap_iterations_a, conflict_function **overlap_iterations_b, - tree *last_conflicts, struct loop *loop_nest) + tree *last_conflicts, class loop *loop_nest) { unsigned int lnn = loop_nest->num; @@ -4275,7 +4275,7 @@ build_classic_dist_vector_1 (struct data_dependence_relation *ddr, { unsigned i; lambda_vector init_v = lambda_vector_new (DDR_NB_LOOPS (ddr)); - struct loop *loop = DDR_LOOP_NEST (ddr)[0]; + class loop *loop = DDR_LOOP_NEST (ddr)[0]; for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++) { @@ -4426,7 +4426,7 @@ add_other_self_distances (struct data_dependence_relation *ddr) unsigned i; int index_carry = DDR_NB_LOOPS (ddr); subscript *sub; - struct loop *loop = DDR_LOOP_NEST (ddr)[0]; + class loop *loop = DDR_LOOP_NEST (ddr)[0]; FOR_EACH_VEC_ELT (DDR_SUBSCRIPTS (ddr), i, sub) { @@ -4546,7 +4546,7 @@ same_access_functions (const struct data_dependence_relation *ddr) static bool build_classic_dist_vector (struct data_dependence_relation *ddr, - struct loop *loop_nest) + class loop *loop_nest) { bool init_b = false; int index_carry = DDR_NB_LOOPS (ddr); @@ -4733,7 +4733,7 @@ build_classic_dir_vector (struct data_dependence_relation *ddr) static bool subscript_dependence_tester_1 (struct data_dependence_relation *ddr, unsigned int a_index, unsigned int b_index, - struct loop *loop_nest) + class loop *loop_nest) { unsigned int i; tree last_conflicts; @@ -4792,7 +4792,7 @@ subscript_dependence_tester_1 (struct data_dependence_relation *ddr, static void subscript_dependence_tester (struct data_dependence_relation *ddr, - struct loop *loop_nest) + class loop *loop_nest) { if (subscript_dependence_tester_1 (ddr, 0, 1, loop_nest)) dependence_stats.num_dependence_dependent++; @@ -4807,7 +4807,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr, static bool access_functions_are_affine_or_constant_p (const struct data_reference *a, - const struct loop *loop_nest) + const class loop *loop_nest) { unsigned int i; vec fns = DR_ACCESS_FNS (a); @@ -4832,7 +4832,7 @@ access_functions_are_affine_or_constant_p (const struct data_reference *a, void compute_affine_dependence (struct data_dependence_relation *ddr, - struct loop *loop_nest) + class loop *loop_nest) { struct data_reference *dra = DDR_A (ddr); struct data_reference *drb = DDR_B (ddr); @@ -4975,7 +4975,7 @@ get_references_in_stmt (gimple *stmt, vec *references) { case IFN_GOMP_SIMD_LANE: { - struct loop *loop = gimple_bb (stmt)->loop_father; + class loop *loop = gimple_bb (stmt)->loop_father; tree uid = gimple_call_arg (stmt, 0); gcc_assert (TREE_CODE (uid) == SSA_NAME); if (loop == NULL @@ -5117,7 +5117,7 @@ loop_nest_has_data_refs (loop_p loop) loop of the loop nest in which the references should be analyzed. */ opt_result -find_data_references_in_stmt (struct loop *nest, gimple *stmt, +find_data_references_in_stmt (class loop *nest, gimple *stmt, vec *datarefs) { unsigned i; @@ -5176,7 +5176,7 @@ graphite_find_data_references_in_stmt (edge nest, loop_p loop, gimple *stmt, difficult case, returns NULL_TREE otherwise. */ tree -find_data_references_in_bb (struct loop *loop, basic_block bb, +find_data_references_in_bb (class loop *loop, basic_block bb, vec *datarefs) { gimple_stmt_iterator bsi; @@ -5206,7 +5206,7 @@ find_data_references_in_bb (struct loop *loop, basic_block bb, arithmetic as if they were array accesses, etc. */ tree -find_data_references_in_loop (struct loop *loop, +find_data_references_in_loop (class loop *loop, vec *datarefs) { basic_block bb, *bbs; @@ -5331,7 +5331,7 @@ get_base_for_alignment (tree addr, unsigned int *max_alignment) /* Recursive helper function. */ static bool -find_loop_nest_1 (struct loop *loop, vec *loop_nest) +find_loop_nest_1 (class loop *loop, vec *loop_nest) { /* Inner loops of the nest should not contain siblings. Example: when there are two consecutive loops, @@ -5362,7 +5362,7 @@ find_loop_nest_1 (struct loop *loop, vec *loop_nest) appear in the classic distance vector. */ bool -find_loop_nest (struct loop *loop, vec *loop_nest) +find_loop_nest (class loop *loop, vec *loop_nest) { loop_nest->safe_push (loop); if (loop->inner) @@ -5378,7 +5378,7 @@ find_loop_nest (struct loop *loop, vec *loop_nest) COMPUTE_SELF_AND_READ_READ_DEPENDENCES is TRUE. */ bool -compute_data_dependences_for_loop (struct loop *loop, +compute_data_dependences_for_loop (class loop *loop, bool compute_self_and_read_read_dependences, vec *loop_nest, vec *datarefs, diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h index d7cd98d..998937f 100644 --- a/gcc/tree-data-ref.h +++ b/gcc/tree-data-ref.h @@ -421,8 +421,8 @@ typedef struct data_dependence_relation *ddr_p; opt_result dr_analyze_innermost (innermost_loop_behavior *, tree, - struct loop *, const gimple *); -extern bool compute_data_dependences_for_loop (struct loop *, bool, + class loop *, const gimple *); +extern bool compute_data_dependences_for_loop (class loop *, bool, vec *, vec *, vec *); @@ -443,15 +443,15 @@ extern void free_dependence_relation (struct data_dependence_relation *); extern void free_dependence_relations (vec ); extern void free_data_ref (data_reference_p); extern void free_data_refs (vec ); -extern opt_result find_data_references_in_stmt (struct loop *, gimple *, +extern opt_result find_data_references_in_stmt (class loop *, gimple *, vec *); extern bool graphite_find_data_references_in_stmt (edge, loop_p, gimple *, vec *); -tree find_data_references_in_loop (struct loop *, vec *); +tree find_data_references_in_loop (class loop *, vec *); bool loop_nest_has_data_refs (loop_p loop); struct data_reference *create_data_ref (edge, loop_p, tree, gimple *, bool, bool); -extern bool find_loop_nest (struct loop *, vec *); +extern bool find_loop_nest (class loop *, vec *); extern struct data_dependence_relation *initialize_data_dependence_relation (struct data_reference *, struct data_reference *, vec); extern void compute_affine_dependence (struct data_dependence_relation *, @@ -460,7 +460,7 @@ extern void compute_self_dependence (struct data_dependence_relation *); extern bool compute_all_dependences (vec , vec *, vec, bool); -extern tree find_data_references_in_bb (struct loop *, basic_block, +extern tree find_data_references_in_bb (class loop *, basic_block, vec *); extern unsigned int dr_alignment (innermost_loop_behavior *); extern tree get_base_for_alignment (tree, unsigned int *); @@ -475,15 +475,15 @@ dr_alignment (data_reference *dr) } extern bool dr_may_alias_p (const struct data_reference *, - const struct data_reference *, struct loop *); + const struct data_reference *, class loop *); extern bool dr_equal_offsets_p (struct data_reference *, struct data_reference *); -extern opt_result runtime_alias_check_p (ddr_p, struct loop *, bool); +extern opt_result runtime_alias_check_p (ddr_p, class loop *, bool); extern int data_ref_compare_tree (tree, tree); extern void prune_runtime_alias_test_list (vec *, poly_uint64); -extern void create_runtime_alias_checks (struct loop *, +extern void create_runtime_alias_checks (class loop *, vec *, tree*); extern tree dr_direction_indicator (struct data_reference *); extern tree dr_zero_step_indicator (struct data_reference *); @@ -574,7 +574,7 @@ ddr_dependence_level (ddr_p ddr) static inline int index_in_loop_nest (int var, vec loop_nest) { - struct loop *loopi; + class loop *loopi; int var_index; for (var_index = 0; loop_nest.iterate (var_index, &loopi); var_index++) diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 98566e3..d9e540f 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -502,7 +502,7 @@ fold_build_cond_expr (tree type, tree cond, tree rhs, tree lhs) cd-equivalent if they are executed under the same condition. */ static inline void -add_to_predicate_list (struct loop *loop, basic_block bb, tree nc) +add_to_predicate_list (class loop *loop, basic_block bb, tree nc) { tree bc, *tp; basic_block dom_bb; @@ -567,7 +567,7 @@ add_to_predicate_list (struct loop *loop, basic_block bb, tree nc) the loop to be if-converted. */ static void -add_to_dst_predicate_list (struct loop *loop, edge e, +add_to_dst_predicate_list (class loop *loop, edge e, tree prev_cond, tree cond) { if (!flow_bb_inside_loop_p (loop, e->dest)) @@ -584,7 +584,7 @@ add_to_dst_predicate_list (struct loop *loop, edge e, /* Return true if one of the successor edges of BB exits LOOP. */ static bool -bb_with_exit_edge_p (struct loop *loop, basic_block bb) +bb_with_exit_edge_p (class loop *loop, basic_block bb) { edge e; edge_iterator ei; @@ -661,7 +661,7 @@ phi_convertible_by_degenerating_args (gphi *phi) ANY_COMPLICATED_PHI if PHI is complicated. */ static bool -if_convertible_phi_p (struct loop *loop, basic_block bb, gphi *phi) +if_convertible_phi_p (class loop *loop, basic_block bb, gphi *phi) { if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -756,7 +756,7 @@ idx_within_array_bound (tree ref, tree *idx, void *dta) widest_int niter, valid_niter, delta, wi_step; tree ev, init, step; tree low, high; - struct loop *loop = (struct loop*) dta; + class loop *loop = (class loop*) dta; /* Only support within-bound access for array references. */ if (TREE_CODE (ref) != ARRAY_REF) @@ -822,7 +822,7 @@ idx_within_array_bound (tree ref, tree *idx, void *dta) static bool ref_within_array_bound (gimple *stmt, tree ref) { - struct loop *loop = loop_containing_stmt (stmt); + class loop *loop = loop_containing_stmt (stmt); gcc_assert (loop != NULL); return for_each_index (&ref, idx_within_array_bound, loop); @@ -1128,7 +1128,7 @@ all_preds_critical_p (basic_block bb) inside LOOP. */ static bool -if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb) +if_convertible_bb_p (class loop *loop, basic_block bb, basic_block exit_bb) { edge e; edge_iterator ei; @@ -1197,7 +1197,7 @@ pred_blocks_visited_p (basic_block bb, bitmap *visited) predecessors are already selected. */ static basic_block * -get_loop_body_in_if_conv_order (const struct loop *loop) +get_loop_body_in_if_conv_order (const class loop *loop) { basic_block *blocks, *blocks_in_bfs_order; basic_block bb; @@ -1344,7 +1344,7 @@ predicate_bbs (loop_p loop) /* Build region by adding loop pre-header and post-header blocks. */ static vec -build_region (struct loop *loop) +build_region (class loop *loop) { vec region = vNULL; basic_block exit_bb = NULL; @@ -1378,7 +1378,7 @@ build_region (struct loop *loop) in if_convertible_loop_p. */ static bool -if_convertible_loop_p_1 (struct loop *loop, vec *refs) +if_convertible_loop_p_1 (class loop *loop, vec *refs) { unsigned int i; basic_block exit_bb = NULL; @@ -1518,7 +1518,7 @@ if_convertible_loop_p_1 (struct loop *loop, vec *refs) - if its basic blocks and phi nodes are if convertible. */ static bool -if_convertible_loop_p (struct loop *loop) +if_convertible_loop_p (class loop *loop) { edge e; edge_iterator ei; @@ -1597,7 +1597,7 @@ is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1, gimple *header_phi = NULL; enum tree_code reduction_op; basic_block bb = gimple_bb (phi); - struct loop *loop = bb->loop_father; + class loop *loop = bb->loop_father; edge latch_e = loop_latch_edge (loop); imm_use_iterator imm_iter; use_operand_p use_p; @@ -2004,7 +2004,7 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi) LOOP->header block with conditional modify expressions. */ static void -predicate_all_scalar_phis (struct loop *loop) +predicate_all_scalar_phis (class loop *loop) { basic_block bb; unsigned int orig_loop_num_nodes = loop->num_nodes; @@ -2526,7 +2526,7 @@ remove_conditions_and_labels (loop_p loop) blocks. Replace PHI nodes with conditional modify expressions. */ static void -combine_blocks (struct loop *loop) +combine_blocks (class loop *loop) { basic_block bb, exit_bb, merge_target_bb; unsigned int orig_loop_num_nodes = loop->num_nodes; @@ -2719,12 +2719,12 @@ combine_blocks (struct loop *loop) out of LOOP_VECTORIZED must have 100% probability so the profile remains consistent after the condition is folded in the vectorizer. */ -static struct loop * -version_loop_for_if_conversion (struct loop *loop, vec *preds) +static class loop * +version_loop_for_if_conversion (class loop *loop, vec *preds) { basic_block cond_bb; tree cond = make_ssa_name (boolean_type_node); - struct loop *new_loop; + class loop *new_loop; gimple *g; gimple_stmt_iterator gsi; unsigned int save_length; @@ -2781,7 +2781,7 @@ version_loop_for_if_conversion (struct loop *loop, vec *preds) inner loop's exit block. */ static bool -versionable_outer_loop_p (struct loop *loop) +versionable_outer_loop_p (class loop *loop) { if (!loop_outer (loop) || loop->dont_vectorize @@ -2815,7 +2815,7 @@ versionable_outer_loop_p (struct loop *loop) Last restriction is valid only if AGGRESSIVE_IF_CONV is false. */ static bool -ifcvt_split_critical_edges (struct loop *loop, bool aggressive_if_conv) +ifcvt_split_critical_edges (class loop *loop, bool aggressive_if_conv) { basic_block *body; basic_block bb; @@ -2982,11 +2982,11 @@ ifcvt_local_dce (basic_block bb) changed. */ unsigned int -tree_if_conversion (struct loop *loop, vec *preds) +tree_if_conversion (class loop *loop, vec *preds) { unsigned int todo = 0; bool aggressive_if_conv; - struct loop *rloop; + class loop *rloop; bitmap exit_bbs; again: @@ -3001,7 +3001,7 @@ tree_if_conversion (struct loop *loop, vec *preds) aggressive_if_conv = loop->force_vectorize; if (!aggressive_if_conv) { - struct loop *outer_loop = loop_outer (loop); + class loop *outer_loop = loop_outer (loop); if (outer_loop && outer_loop->force_vectorize) aggressive_if_conv = true; } @@ -3027,10 +3027,10 @@ tree_if_conversion (struct loop *loop, vec *preds) || any_complicated_phi || flag_tree_loop_if_convert != 1) { - struct loop *vloop + class loop *vloop = (versionable_outer_loop_p (loop_outer (loop)) ? loop_outer (loop) : loop); - struct loop *nloop = version_loop_for_if_conversion (vloop, preds); + class loop *nloop = version_loop_for_if_conversion (vloop, preds); if (nloop == NULL) goto cleanup; if (vloop != loop) @@ -3138,7 +3138,7 @@ pass_if_conversion::gate (function *fun) unsigned int pass_if_conversion::execute (function *fun) { - struct loop *loop; + class loop *loop; unsigned todo = 0; if (number_of_loops (fun) <= 1) diff --git a/gcc/tree-if-conv.h b/gcc/tree-if-conv.h index c136ebb..a83380b 100644 --- a/gcc/tree-if-conv.h +++ b/gcc/tree-if-conv.h @@ -19,6 +19,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_IF_CONV_H #define GCC_TREE_IF_CONV_H -unsigned int tree_if_conversion (struct loop *, vec * = NULL); +unsigned int tree_if_conversion (class loop *, vec * = NULL); #endif /* GCC_TREE_IF_CONV_H */ diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 42e4597..4311309 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2804,15 +2804,15 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb) static void copy_loops (copy_body_data *id, - struct loop *dest_parent, struct loop *src_parent) + class loop *dest_parent, class loop *src_parent) { - struct loop *src_loop = src_parent->inner; + class loop *src_loop = src_parent->inner; while (src_loop) { if (!id->blocks_to_copy || bitmap_bit_p (id->blocks_to_copy, src_loop->header->index)) { - struct loop *dest_loop = alloc_loop (); + class loop *dest_loop = alloc_loop (); /* Assign the new loop its header and latch and associate those with the new loop. */ diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index 3881aaf..8178486 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -506,7 +506,7 @@ bb_top_order_cmp (const void *x, const void *y) statements in loop copies. */ static void -stmts_from_loop (struct loop *loop, vec *stmts) +stmts_from_loop (class loop *loop, vec *stmts) { unsigned int i; basic_block *bbs = get_loop_body_in_custom_order (loop, bb_top_order_cmp); @@ -564,7 +564,7 @@ free_rdg (struct graph *rdg) collected and recorded in global data DATAREFS_VEC. */ static struct graph * -build_rdg (struct loop *loop, control_dependences *cd) +build_rdg (class loop *loop, control_dependences *cd) { struct graph *rdg; @@ -787,10 +787,10 @@ stmt_has_scalar_dependences_outside_loop (loop_p loop, gimple *stmt) /* Return a copy of LOOP placed before LOOP. */ -static struct loop * -copy_loop_before (struct loop *loop) +static class loop * +copy_loop_before (class loop *loop) { - struct loop *res; + class loop *res; edge preheader = loop_preheader_edge (loop); initialize_original_copy_tables (); @@ -805,7 +805,7 @@ copy_loop_before (struct loop *loop) /* Creates an empty basic block after LOOP. */ static void -create_bb_after_loop (struct loop *loop) +create_bb_after_loop (class loop *loop) { edge exit = single_exit (loop); @@ -822,7 +822,7 @@ create_bb_after_loop (struct loop *loop) basic blocks of a loop are taken in dom order. */ static void -generate_loops_for_partition (struct loop *loop, partition *partition, +generate_loops_for_partition (class loop *loop, partition *partition, bool copy_p) { unsigned i; @@ -994,7 +994,7 @@ const_with_all_bytes_same (tree val) /* Generate a call to memset for PARTITION in LOOP. */ static void -generate_memset_builtin (struct loop *loop, partition *partition) +generate_memset_builtin (class loop *loop, partition *partition) { gimple_stmt_iterator gsi; tree mem, fn, nb_bytes; @@ -1048,7 +1048,7 @@ generate_memset_builtin (struct loop *loop, partition *partition) /* Generate a call to memcpy for PARTITION in LOOP. */ static void -generate_memcpy_builtin (struct loop *loop, partition *partition) +generate_memcpy_builtin (class loop *loop, partition *partition) { gimple_stmt_iterator gsi; gimple *fn_call; @@ -1092,7 +1092,7 @@ generate_memcpy_builtin (struct loop *loop, partition *partition) /* Remove and destroy the loop LOOP. */ static void -destroy_loop (struct loop *loop) +destroy_loop (class loop *loop) { unsigned nbbs = loop->num_nodes; edge exit = single_exit (loop); @@ -1169,7 +1169,7 @@ destroy_loop (struct loop *loop) /* Generates code for PARTITION. Return whether LOOP needs to be destroyed. */ static bool -generate_code_for_partition (struct loop *loop, +generate_code_for_partition (class loop *loop, partition *partition, bool copy_p) { switch (partition->kind) @@ -1346,7 +1346,7 @@ build_rdg_partition_for_vertex (struct graph *rdg, int v) data references. */ static bool -find_single_drs (struct loop *loop, struct graph *rdg, partition *partition, +find_single_drs (class loop *loop, struct graph *rdg, partition *partition, data_reference_p *dst_dr, data_reference_p *src_dr) { unsigned i; @@ -1469,7 +1469,7 @@ compute_access_range (loop_p loop_nest, data_reference_p dr, tree *base, { location_t loc = gimple_location (DR_STMT (dr)); basic_block bb = gimple_bb (DR_STMT (dr)); - struct loop *loop = bb->loop_father; + class loop *loop = bb->loop_father; tree ref = DR_REF (dr); tree access_base = build_fold_addr_expr (ref); tree access_size = TYPE_SIZE_UNIT (TREE_TYPE (ref)); @@ -2426,7 +2426,7 @@ data_ref_segment_size (struct data_reference *dr, tree niters) DR. */ static inline bool -latch_dominated_by_data_ref (struct loop *loop, data_reference *dr) +latch_dominated_by_data_ref (class loop *loop, data_reference *dr) { return dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src, gimple_bb (DR_STMT (dr))); @@ -2436,7 +2436,7 @@ latch_dominated_by_data_ref (struct loop *loop, data_reference *dr) data dependence relations ALIAS_DDRS. */ static void -compute_alias_check_pairs (struct loop *loop, vec *alias_ddrs, +compute_alias_check_pairs (class loop *loop, vec *alias_ddrs, vec *comp_alias_pairs) { unsigned int i; @@ -2508,11 +2508,11 @@ compute_alias_check_pairs (struct loop *loop, vec *alias_ddrs, static void version_loop_by_alias_check (vec *partitions, - struct loop *loop, vec *alias_ddrs) + class loop *loop, vec *alias_ddrs) { profile_probability prob; basic_block cond_bb; - struct loop *nloop; + class loop *nloop; tree lhs, arg0, cond_expr = NULL_TREE; gimple_seq cond_stmts = NULL; gimple *call_stmt = NULL; @@ -2723,7 +2723,7 @@ fuse_memset_builtins (vec *partitions) ALIAS_DDRS contains ddrs which need runtime alias check. */ static void -finalize_partitions (struct loop *loop, vec *partitions, +finalize_partitions (class loop *loop, vec *partitions, vec *alias_ddrs) { unsigned i; @@ -2780,7 +2780,7 @@ finalize_partitions (struct loop *loop, vec *partitions, Set *DESTROY_P to whether LOOP needs to be destroyed. */ static int -distribute_loop (struct loop *loop, vec stmts, +distribute_loop (class loop *loop, vec stmts, control_dependences *cd, int *nb_calls, bool *destroy_p, bool only_patterns_p) { @@ -3060,7 +3060,7 @@ public: WORK_LIST. Return false if there is nothing for distribution. */ static bool -find_seed_stmts_for_distribution (struct loop *loop, vec *work_list) +find_seed_stmts_for_distribution (class loop *loop, vec *work_list) { basic_block *bbs = get_loop_body_in_dom_order (loop); @@ -3114,10 +3114,10 @@ find_seed_stmts_for_distribution (struct loop *loop, vec *work_list) /* Given innermost LOOP, return the outermost enclosing loop that forms a perfect loop nest. */ -static struct loop * -prepare_perfect_loop_nest (struct loop *loop) +static class loop * +prepare_perfect_loop_nest (class loop *loop) { - struct loop *outer = loop_outer (loop); + class loop *outer = loop_outer (loop); tree niters = number_of_latch_executions (loop); /* TODO: We only support the innermost 3-level loop nest distribution @@ -3143,7 +3143,7 @@ prepare_perfect_loop_nest (struct loop *loop) unsigned int pass_loop_distribution::execute (function *fun) { - struct loop *loop; + class loop *loop; bool changed = false; basic_block bb; control_dependences *cd = NULL; diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index 6b8c8cd..f5cb411 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -412,7 +412,7 @@ lambda_transform_legal_p (lambda_trans_matrix trans, in parallel). */ static bool -loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack) +loop_parallel_p (class loop *loop, struct obstack * parloop_obstack) { vec dependence_relations; vec datarefs; @@ -468,7 +468,7 @@ loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack) BB_IRREDUCIBLE_LOOP flag. */ static inline bool -loop_has_blocks_with_irreducible_flag (struct loop *loop) +loop_has_blocks_with_irreducible_flag (class loop *loop) { unsigned i; basic_block *bbs = get_loop_body_in_dom_order (loop); @@ -572,7 +572,7 @@ reduc_stmt_res (gimple *stmt) the loop described in DATA. */ int -initialize_reductions (reduction_info **slot, struct loop *loop) +initialize_reductions (reduction_info **slot, class loop *loop) { tree init; tree type, arg; @@ -1034,7 +1034,7 @@ add_field_for_name (name_to_copy_elt **slot, tree type) reduction's data structure. */ int -create_phi_for_local_result (reduction_info **slot, struct loop *loop) +create_phi_for_local_result (reduction_info **slot, class loop *loop) { struct reduction_info *const reduc = *slot; edge e; @@ -1158,11 +1158,11 @@ create_call_for_reduction_1 (reduction_info **slot, struct clsn_data *clsn_data) LD_ST_DATA describes the shared data structure where shared data is stored in and loaded from. */ static void -create_call_for_reduction (struct loop *loop, +create_call_for_reduction (class loop *loop, reduction_info_table_type *reduction_list, struct clsn_data *ld_st_data) { - reduction_list->traverse (loop); + reduction_list->traverse (loop); /* Find the fallthru edge from GIMPLE_OMP_CONTINUE. */ basic_block continue_bb = single_pred (loop->latch); ld_st_data->load_bb = FALLTHRU_EDGE (continue_bb)->dest; @@ -1640,7 +1640,7 @@ replace_uses_in_bb_by (tree name, tree val, basic_block bb) bound. */ static void -transform_to_exit_first_loop_alt (struct loop *loop, +transform_to_exit_first_loop_alt (class loop *loop, reduction_info_table_type *reduction_list, tree bound) { @@ -1797,7 +1797,7 @@ transform_to_exit_first_loop_alt (struct loop *loop, transformation is successful. */ static bool -try_transform_to_exit_first_loop_alt (struct loop *loop, +try_transform_to_exit_first_loop_alt (class loop *loop, reduction_info_table_type *reduction_list, tree nit) { @@ -1916,7 +1916,7 @@ try_transform_to_exit_first_loop_alt (struct loop *loop, LOOP. */ static void -transform_to_exit_first_loop (struct loop *loop, +transform_to_exit_first_loop (class loop *loop, reduction_info_table_type *reduction_list, tree nit) { @@ -2030,7 +2030,7 @@ transform_to_exit_first_loop (struct loop *loop, that number is to be determined later. */ static void -create_parallel_loop (struct loop *loop, tree loop_fn, tree data, +create_parallel_loop (class loop *loop, tree loop_fn, tree data, tree new_data, unsigned n_threads, location_t loc, bool oacc_kernels_p) { @@ -2266,9 +2266,9 @@ num_phis (basic_block bb, bool count_virtual_p) REDUCTION_LIST describes the reductions existent in the LOOP. */ static void -gen_parallel_loop (struct loop *loop, +gen_parallel_loop (class loop *loop, reduction_info_table_type *reduction_list, - unsigned n_threads, struct tree_niter_desc *niter, + unsigned n_threads, class tree_niter_desc *niter, bool oacc_kernels_p) { tree many_iterations_cond, type, nit; @@ -2441,7 +2441,7 @@ gen_parallel_loop (struct loop *loop, /* Generate initializations for reductions. */ if (!reduction_list->is_empty ()) - reduction_list->traverse (loop); + reduction_list->traverse (loop); /* Eliminate the references to local variables from the loop. */ gcc_assert (single_exit (loop)); @@ -2489,7 +2489,7 @@ gen_parallel_loop (struct loop *loop, /* Returns true when LOOP contains vector phi nodes. */ static bool -loop_has_vector_phi_nodes (struct loop *loop ATTRIBUTE_UNUSED) +loop_has_vector_phi_nodes (class loop *loop ATTRIBUTE_UNUSED) { unsigned i; basic_block *bbs = get_loop_body_in_dom_order (loop); @@ -2695,7 +2695,7 @@ gather_scalar_reductions (loop_p loop, reduction_info_table_type *reduction_list /* Try to initialize NITER for code generation part. */ static bool -try_get_loop_niter (loop_p loop, struct tree_niter_desc *niter) +try_get_loop_niter (loop_p loop, class tree_niter_desc *niter) { edge exit = single_dom_exit (loop); @@ -2737,7 +2737,7 @@ get_omp_data_i_param (void) and return addr. Otherwise, return NULL_TREE. */ static tree -find_reduc_addr (struct loop *loop, gphi *phi) +find_reduc_addr (class loop *loop, gphi *phi) { edge e = loop_preheader_edge (loop); tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e); @@ -2907,7 +2907,7 @@ try_create_reduction_list (loop_p loop, /* Return true if LOOP contains phis with ADDR_EXPR in args. */ static bool -loop_has_phi_with_address_arg (struct loop *loop) +loop_has_phi_with_address_arg (class loop *loop) { basic_block *bbs = get_loop_body (loop); bool res = false; @@ -3244,7 +3244,7 @@ oacc_entry_exit_single_gang (bitmap in_loop_bbs, vec region_bbs, outside LOOP by guarding them such that only a single gang executes them. */ static bool -oacc_entry_exit_ok (struct loop *loop, +oacc_entry_exit_ok (class loop *loop, reduction_info_table_type *reduction_list) { basic_block *loop_bbs = get_loop_body_in_dom_order (loop); @@ -3289,9 +3289,9 @@ parallelize_loops (bool oacc_kernels_p) { unsigned n_threads; bool changed = false; - struct loop *loop; - struct loop *skip_loop = NULL; - struct tree_niter_desc niter_desc; + class loop *loop; + class loop *skip_loop = NULL; + class tree_niter_desc niter_desc; struct obstack parloop_obstack; HOST_WIDE_INT estimated; diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 7b83293..1c8df3d 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -132,7 +132,7 @@ protected: } }; -class varpool_node; +struct varpool_node; struct cgraph_node; struct lto_symtab_encoder_d; diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index dfb2146..299c45e 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -735,7 +735,7 @@ determine_offset (struct data_reference *a, struct data_reference *b, it is executed whenever the loop is entered. */ static basic_block -last_always_executed_block (struct loop *loop) +last_always_executed_block (class loop *loop) { unsigned i; vec exits = get_loop_exit_edges (loop); @@ -752,7 +752,7 @@ last_always_executed_block (struct loop *loop) /* Splits dependence graph on DATAREFS described by DEPENDS to components. */ static struct component * -split_data_refs_to_components (struct loop *loop, +split_data_refs_to_components (class loop *loop, vec datarefs, vec depends) { @@ -896,7 +896,7 @@ split_data_refs_to_components (struct loop *loop, comps[ca] = comp; } - dataref = XCNEW (struct dref_d); + dataref = XCNEW (class dref_d); dataref->ref = dr; dataref->stmt = DR_STMT (dr); dataref->offset = 0; @@ -931,7 +931,7 @@ end: loop. */ static bool -suitable_component_p (struct loop *loop, struct component *comp) +suitable_component_p (class loop *loop, struct component *comp) { unsigned i; dref a, first; @@ -987,7 +987,7 @@ suitable_component_p (struct loop *loop, struct component *comp) the beginning of this file. LOOP is the current loop. */ static struct component * -filter_suitable_components (struct loop *loop, struct component *comps) +filter_suitable_components (class loop *loop, struct component *comps) { struct component **comp, *act; @@ -1232,7 +1232,7 @@ valid_initializer_p (struct data_reference *ref, is the root of the current chain. */ static gphi * -find_looparound_phi (struct loop *loop, dref ref, dref root) +find_looparound_phi (class loop *loop, dref ref, dref root) { tree name, init, init_ref; gphi *phi = NULL; @@ -1296,7 +1296,7 @@ find_looparound_phi (struct loop *loop, dref ref, dref root) static void insert_looparound_copy (chain_p chain, dref ref, gphi *phi) { - dref nw = XCNEW (struct dref_d), aref; + dref nw = XCNEW (class dref_d), aref; unsigned i; nw->stmt = phi; @@ -1321,7 +1321,7 @@ insert_looparound_copy (chain_p chain, dref ref, gphi *phi) (also, it may allow us to combine chains together). */ static void -add_looparound_copies (struct loop *loop, chain_p chain) +add_looparound_copies (class loop *loop, chain_p chain) { unsigned i; dref ref, root = get_chain_root (chain); @@ -1346,7 +1346,7 @@ add_looparound_copies (struct loop *loop, chain_p chain) loop. */ static void -determine_roots_comp (struct loop *loop, +determine_roots_comp (class loop *loop, struct component *comp, vec *chains) { @@ -1436,7 +1436,7 @@ determine_roots_comp (struct loop *loop, separates the references to CHAINS. LOOP is the current loop. */ static void -determine_roots (struct loop *loop, +determine_roots (class loop *loop, struct component *comps, vec *chains) { struct component *comp; @@ -1653,7 +1653,7 @@ predcom_tmp_var (tree ref, unsigned i, bitmap tmp_vars) temporary variables are marked in TMP_VARS. */ static void -initialize_root_vars (struct loop *loop, chain_p chain, bitmap tmp_vars) +initialize_root_vars (class loop *loop, chain_p chain, bitmap tmp_vars) { unsigned i; unsigned n = chain->length; @@ -1707,7 +1707,7 @@ initialize_root_vars (struct loop *loop, chain_p chain, bitmap tmp_vars) In this case, we can use these invariant values directly after LOOP. */ static bool -is_inv_store_elimination_chain (struct loop *loop, chain_p chain) +is_inv_store_elimination_chain (class loop *loop, chain_p chain) { if (chain->length == 0 || chain->type != CT_STORE_STORE) return false; @@ -1801,7 +1801,7 @@ initialize_root_vars_store_elim_1 (chain_p chain) of the newly created root variables are marked in TMP_VARS. */ static void -initialize_root_vars_store_elim_2 (struct loop *loop, +initialize_root_vars_store_elim_2 (class loop *loop, chain_p chain, bitmap tmp_vars) { unsigned i, n = chain->length; @@ -1886,7 +1886,7 @@ initialize_root_vars_store_elim_2 (struct loop *loop, (CHAIN->length - 1) iterations. */ static void -finalize_eliminated_stores (struct loop *loop, chain_p chain) +finalize_eliminated_stores (class loop *loop, chain_p chain) { unsigned i, n = chain->length; @@ -1914,7 +1914,7 @@ finalize_eliminated_stores (struct loop *loop, chain_p chain) initializer. */ static void -initialize_root_vars_lm (struct loop *loop, dref root, bool written, +initialize_root_vars_lm (class loop *loop, dref root, bool written, vec *vars, vec inits, bitmap tmp_vars) { @@ -1962,7 +1962,7 @@ initialize_root_vars_lm (struct loop *loop, dref root, bool written, created temporary variables are marked in TMP_VARS. */ static void -execute_load_motion (struct loop *loop, chain_p chain, bitmap tmp_vars) +execute_load_motion (class loop *loop, chain_p chain, bitmap tmp_vars) { auto_vec vars; dref a; @@ -2103,7 +2103,7 @@ remove_stmt (gimple *stmt) Uids of the newly created temporary variables are marked in TMP_VARS.*/ static void -execute_pred_commoning_chain (struct loop *loop, chain_p chain, +execute_pred_commoning_chain (class loop *loop, chain_p chain, bitmap tmp_vars) { unsigned i; @@ -2234,7 +2234,7 @@ determine_unroll_factor (vec chains) Uids of the newly created temporary variables are marked in TMP_VARS. */ static void -execute_pred_commoning (struct loop *loop, vec chains, +execute_pred_commoning (class loop *loop, vec chains, bitmap tmp_vars) { chain_p chain; @@ -2317,7 +2317,7 @@ struct epcc_data }; static void -execute_pred_commoning_cbck (struct loop *loop, void *data) +execute_pred_commoning_cbck (class loop *loop, void *data) { struct epcc_data *const dta = (struct epcc_data *) data; @@ -2333,7 +2333,7 @@ execute_pred_commoning_cbck (struct loop *loop, void *data) the header of the LOOP. */ static void -base_names_in_chain_on (struct loop *loop, tree name, tree var) +base_names_in_chain_on (class loop *loop, tree name, tree var) { gimple *stmt, *phi; imm_use_iterator iter; @@ -2366,7 +2366,7 @@ base_names_in_chain_on (struct loop *loop, tree name, tree var) for those we want to perform this. */ static void -eliminate_temp_copies (struct loop *loop, bitmap tmp_vars) +eliminate_temp_copies (class loop *loop, bitmap tmp_vars) { edge e; gphi *phi; @@ -2751,7 +2751,7 @@ combine_chains (chain_p ch1, chain_p ch2) for (i = 0; (ch1->refs.iterate (i, &r1) && ch2->refs.iterate (i, &r2)); i++) { - nw = XCNEW (struct dref_d); + nw = XCNEW (class dref_d); nw->stmt = stmt_combining_refs (r1, r2); nw->distance = r1->distance; @@ -2801,7 +2801,7 @@ pcom_stmt_dominates_stmt_p (gimple *s1, gimple *s2) /* Try to combine the CHAINS in LOOP. */ static void -try_combine_chains (struct loop *loop, vec *chains) +try_combine_chains (class loop *loop, vec *chains) { unsigned i, j; chain_p ch1, ch2, cch; @@ -2911,7 +2911,7 @@ try_combine_chains (struct loop *loop, vec *chains) otherwise. */ static bool -prepare_initializers_chain_store_elim (struct loop *loop, chain_p chain) +prepare_initializers_chain_store_elim (class loop *loop, chain_p chain) { unsigned i, n = chain->length; @@ -2978,7 +2978,7 @@ prepare_initializers_chain_store_elim (struct loop *loop, chain_p chain) impossible because one of these initializers may trap, true otherwise. */ static bool -prepare_initializers_chain (struct loop *loop, chain_p chain) +prepare_initializers_chain (class loop *loop, chain_p chain) { unsigned i, n = (chain->type == CT_INVARIANT) ? 1 : chain->length; struct data_reference *dr = get_chain_root (chain)->ref; @@ -3034,7 +3034,7 @@ prepare_initializers_chain (struct loop *loop, chain_p chain) be used because the initializers might trap. */ static void -prepare_initializers (struct loop *loop, vec chains) +prepare_initializers (class loop *loop, vec chains) { chain_p chain; unsigned i; @@ -3056,7 +3056,7 @@ prepare_initializers (struct loop *loop, vec chains) if finalizer code for CHAIN can be generated, otherwise false. */ static bool -prepare_finalizers_chain (struct loop *loop, chain_p chain) +prepare_finalizers_chain (class loop *loop, chain_p chain) { unsigned i, n = chain->length; struct data_reference *dr = get_chain_root (chain)->ref; @@ -3104,7 +3104,7 @@ prepare_finalizers_chain (struct loop *loop, chain_p chain) if finalizer code generation for CHAINS breaks loop closed ssa form. */ static bool -prepare_finalizers (struct loop *loop, vec chains) +prepare_finalizers (class loop *loop, vec chains) { chain_p chain; unsigned i; @@ -3143,7 +3143,7 @@ prepare_finalizers (struct loop *loop, vec chains) /* Insert all initializing gimple stmts into loop's entry edge. */ static void -insert_init_seqs (struct loop *loop, vec chains) +insert_init_seqs (class loop *loop, vec chains) { unsigned i; edge entry = loop_preheader_edge (loop); @@ -3161,14 +3161,14 @@ insert_init_seqs (struct loop *loop, vec chains) form was corrupted. */ static unsigned -tree_predictive_commoning_loop (struct loop *loop) +tree_predictive_commoning_loop (class loop *loop) { vec datarefs; vec dependences; struct component *components; vec chains = vNULL; unsigned unroll_factor; - struct tree_niter_desc desc; + class tree_niter_desc desc; bool unroll = false, loop_closed_ssa = false; edge exit; @@ -3304,7 +3304,7 @@ end: ; unsigned tree_predictive_commoning (void) { - struct loop *loop; + class loop *loop; unsigned ret = 0, changed = 0; initialize_original_copy_tables (); diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 08c882e..4b72a25 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -286,8 +286,8 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "case-cfn-macros.h" -static tree analyze_scalar_evolution_1 (struct loop *, tree); -static tree analyze_scalar_evolution_for_address_of (struct loop *loop, +static tree analyze_scalar_evolution_1 (class loop *, tree); +static tree analyze_scalar_evolution_for_address_of (class loop *loop, tree var); /* The cached information about an SSA name with version NAME_VERSION, @@ -445,7 +445,7 @@ loop_phi_node_p (gimple *phi) */ tree -compute_overall_effect_of_inner_loop (struct loop *loop, tree evolution_fn) +compute_overall_effect_of_inner_loop (class loop *loop, tree evolution_fn) { bool val = false; @@ -454,7 +454,7 @@ compute_overall_effect_of_inner_loop (struct loop *loop, tree evolution_fn) else if (TREE_CODE (evolution_fn) == POLYNOMIAL_CHREC) { - struct loop *inner_loop = get_chrec_loop (evolution_fn); + class loop *inner_loop = get_chrec_loop (evolution_fn); if (inner_loop == loop || flow_loop_nested_p (loop, inner_loop)) @@ -593,7 +593,7 @@ add_to_evolution_1 (unsigned loop_nb, tree chrec_before, tree to_add, gimple *at_stmt) { tree type, left, right; - struct loop *loop = get_loop (cfun, loop_nb), *chloop; + class loop *loop = get_loop (cfun, loop_nb), *chloop; switch (TREE_CODE (chrec_before)) { @@ -840,7 +840,7 @@ add_to_evolution (unsigned loop_nb, tree chrec_before, enum tree_code code, analyze, then give up. */ gcond * -get_loop_exit_condition (const struct loop *loop) +get_loop_exit_condition (const class loop *loop) { gcond *res = NULL; edge exit_edge = single_exit (loop); @@ -876,14 +876,14 @@ enum t_bool { }; -static t_bool follow_ssa_edge (struct loop *loop, gimple *, gphi *, +static t_bool follow_ssa_edge (class loop *loop, gimple *, gphi *, tree *, int); /* Follow the ssa edge into the binary expression RHS0 CODE RHS1. Return true if the strongly connected component has been found. */ static t_bool -follow_ssa_edge_binary (struct loop *loop, gimple *at_stmt, +follow_ssa_edge_binary (class loop *loop, gimple *at_stmt, tree type, tree rhs0, enum tree_code code, tree rhs1, gphi *halting_phi, tree *evolution_of_loop, int limit) @@ -1018,7 +1018,7 @@ follow_ssa_edge_binary (struct loop *loop, gimple *at_stmt, Return true if the strongly connected component has been found. */ static t_bool -follow_ssa_edge_expr (struct loop *loop, gimple *at_stmt, tree expr, +follow_ssa_edge_expr (class loop *loop, gimple *at_stmt, tree expr, gphi *halting_phi, tree *evolution_of_loop, int limit) { @@ -1109,7 +1109,7 @@ follow_ssa_edge_expr (struct loop *loop, gimple *at_stmt, tree expr, Return true if the strongly connected component has been found. */ static t_bool -follow_ssa_edge_in_rhs (struct loop *loop, gimple *stmt, +follow_ssa_edge_in_rhs (class loop *loop, gimple *stmt, gphi *halting_phi, tree *evolution_of_loop, int limit) { @@ -1170,7 +1170,7 @@ backedge_phi_arg_p (gphi *phi, int i) static inline t_bool follow_ssa_edge_in_condition_phi_branch (int i, - struct loop *loop, + class loop *loop, gphi *condition_phi, gphi *halting_phi, tree *evolution_of_branch, @@ -1205,7 +1205,7 @@ follow_ssa_edge_in_condition_phi_branch (int i, loop. */ static t_bool -follow_ssa_edge_in_condition_phi (struct loop *loop, +follow_ssa_edge_in_condition_phi (class loop *loop, gphi *condition_phi, gphi *halting_phi, tree *evolution_of_loop, int limit) @@ -1252,12 +1252,12 @@ follow_ssa_edge_in_condition_phi (struct loop *loop, considered as a single statement. */ static t_bool -follow_ssa_edge_inner_loop_phi (struct loop *outer_loop, +follow_ssa_edge_inner_loop_phi (class loop *outer_loop, gphi *loop_phi_node, gphi *halting_phi, tree *evolution_of_loop, int limit) { - struct loop *loop = loop_containing_stmt (loop_phi_node); + class loop *loop = loop_containing_stmt (loop_phi_node); tree ev = analyze_scalar_evolution (loop, PHI_RESULT (loop_phi_node)); /* Sometimes, the inner loop is too difficult to analyze, and the @@ -1299,10 +1299,10 @@ follow_ssa_edge_inner_loop_phi (struct loop *outer_loop, path that is analyzed on the return walk. */ static t_bool -follow_ssa_edge (struct loop *loop, gimple *def, gphi *halting_phi, +follow_ssa_edge (class loop *loop, gimple *def, gphi *halting_phi, tree *evolution_of_loop, int limit) { - struct loop *def_loop; + class loop *def_loop; if (gimple_nop_p (def)) return t_false; @@ -1374,7 +1374,7 @@ follow_ssa_edge (struct loop *loop, gimple *def, gphi *halting_phi, See PR41488. */ static tree -simplify_peeled_chrec (struct loop *loop, tree arg, tree init_cond) +simplify_peeled_chrec (class loop *loop, tree arg, tree init_cond) { aff_tree aff1, aff2; tree ev, left, right, type, step_val; @@ -1432,7 +1432,7 @@ analyze_evolution_in_loop (gphi *loop_phi_node, { int i, n = gimple_phi_num_args (loop_phi_node); tree evolution_function = chrec_not_analyzed_yet; - struct loop *loop = loop_containing_stmt (loop_phi_node); + class loop *loop = loop_containing_stmt (loop_phi_node); basic_block bb; static bool simplify_peeled_chrec_p = true; @@ -1560,7 +1560,7 @@ analyze_initial_condition (gphi *loop_phi_node) { int i, n; tree init_cond = chrec_not_analyzed_yet; - struct loop *loop = loop_containing_stmt (loop_phi_node); + class loop *loop = loop_containing_stmt (loop_phi_node); if (dump_file && (dump_flags & TDF_SCEV)) { @@ -1617,10 +1617,10 @@ analyze_initial_condition (gphi *loop_phi_node) /* Analyze the scalar evolution for LOOP_PHI_NODE. */ static tree -interpret_loop_phi (struct loop *loop, gphi *loop_phi_node) +interpret_loop_phi (class loop *loop, gphi *loop_phi_node) { tree res; - struct loop *phi_loop = loop_containing_stmt (loop_phi_node); + class loop *phi_loop = loop_containing_stmt (loop_phi_node); tree init_cond; gcc_assert (phi_loop == loop); @@ -1654,7 +1654,7 @@ interpret_loop_phi (struct loop *loop, gphi *loop_phi_node) analyzed. */ static tree -interpret_condition_phi (struct loop *loop, gphi *condition_phi) +interpret_condition_phi (class loop *loop, gphi *condition_phi) { int i, n = gimple_phi_num_args (condition_phi); tree res = chrec_not_analyzed_yet; @@ -1688,7 +1688,7 @@ interpret_condition_phi (struct loop *loop, gphi *condition_phi) analyze the effect of an inner loop: see interpret_loop_phi. */ static tree -interpret_rhs_expr (struct loop *loop, gimple *at_stmt, +interpret_rhs_expr (class loop *loop, gimple *at_stmt, tree type, tree rhs1, enum tree_code code, tree rhs2) { tree res, chrec1, chrec2, ctype; @@ -1958,7 +1958,7 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt, /* Interpret the expression EXPR. */ static tree -interpret_expr (struct loop *loop, gimple *at_stmt, tree expr) +interpret_expr (class loop *loop, gimple *at_stmt, tree expr) { enum tree_code code; tree type = TREE_TYPE (expr), op0, op1; @@ -1980,7 +1980,7 @@ interpret_expr (struct loop *loop, gimple *at_stmt, tree expr) /* Interpret the rhs of the assignment STMT. */ static tree -interpret_gimple_assign (struct loop *loop, gimple *stmt) +interpret_gimple_assign (class loop *loop, gimple *stmt) { tree type = TREE_TYPE (gimple_assign_lhs (stmt)); enum tree_code code = gimple_assign_rhs_code (stmt); @@ -2001,11 +2001,11 @@ interpret_gimple_assign (struct loop *loop, gimple *stmt) /* Helper recursive function. */ static tree -analyze_scalar_evolution_1 (struct loop *loop, tree var) +analyze_scalar_evolution_1 (class loop *loop, tree var) { gimple *def; basic_block bb; - struct loop *def_loop; + class loop *def_loop; tree res; if (TREE_CODE (var) != SSA_NAME) @@ -2025,7 +2025,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var) if (loop != def_loop) { res = analyze_scalar_evolution_1 (def_loop, var); - struct loop *loop_to_skip = superloop_at_depth (def_loop, + class loop *loop_to_skip = superloop_at_depth (def_loop, loop_depth (loop) + 1); res = compute_overall_effect_of_inner_loop (loop_to_skip, res); if (chrec_contains_symbols_defined_in_loop (res, loop->num)) @@ -2077,7 +2077,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var) */ tree -analyze_scalar_evolution (struct loop *loop, tree var) +analyze_scalar_evolution (class loop *loop, tree var) { tree res; @@ -2122,7 +2122,7 @@ analyze_scalar_evolution (struct loop *loop, tree var) /* Analyzes and returns the scalar evolution of VAR address in LOOP. */ static tree -analyze_scalar_evolution_for_address_of (struct loop *loop, tree var) +analyze_scalar_evolution_for_address_of (class loop *loop, tree var) { return analyze_scalar_evolution (loop, build_fold_addr_expr (var)); } @@ -2178,7 +2178,7 @@ analyze_scalar_evolution_for_address_of (struct loop *loop, tree var) */ static tree -analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop, +analyze_scalar_evolution_in_loop (class loop *wrto_loop, class loop *use_loop, tree version, bool *folded_casts) { bool val = false; @@ -2278,7 +2278,7 @@ get_instantiated_value_entry (instantiate_cache_type &cache, static tree loop_closed_phi_def (tree var) { - struct loop *loop; + class loop *loop; edge exit; gphi *phi; gphi_iterator psi; @@ -2302,7 +2302,7 @@ loop_closed_phi_def (tree var) return NULL_TREE; } -static tree instantiate_scev_r (edge, struct loop *, struct loop *, +static tree instantiate_scev_r (edge, class loop *, class loop *, tree, bool *, int); /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW @@ -2322,13 +2322,13 @@ static tree instantiate_scev_r (edge, struct loop *, struct loop *, static tree instantiate_scev_name (edge instantiate_below, - struct loop *evolution_loop, struct loop *inner_loop, + class loop *evolution_loop, class loop *inner_loop, tree chrec, bool *fold_conversions, int size_expr) { tree res; - struct loop *def_loop; + class loop *def_loop; basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (chrec)); /* A parameter, nothing to do. */ @@ -2472,7 +2472,7 @@ instantiate_scev_name (edge instantiate_below, static tree instantiate_scev_poly (edge instantiate_below, - struct loop *evolution_loop, struct loop *, + class loop *evolution_loop, class loop *, tree chrec, bool *fold_conversions, int size_expr) { tree op1; @@ -2517,7 +2517,7 @@ instantiate_scev_poly (edge instantiate_below, static tree instantiate_scev_binary (edge instantiate_below, - struct loop *evolution_loop, struct loop *inner_loop, + class loop *evolution_loop, class loop *inner_loop, tree chrec, enum tree_code code, tree type, tree c0, tree c1, bool *fold_conversions, int size_expr) @@ -2585,7 +2585,7 @@ instantiate_scev_binary (edge instantiate_below, static tree instantiate_scev_convert (edge instantiate_below, - struct loop *evolution_loop, struct loop *inner_loop, + class loop *evolution_loop, class loop *inner_loop, tree chrec, tree type, tree op, bool *fold_conversions, int size_expr) { @@ -2636,7 +2636,7 @@ instantiate_scev_convert (edge instantiate_below, static tree instantiate_scev_not (edge instantiate_below, - struct loop *evolution_loop, struct loop *inner_loop, + class loop *evolution_loop, class loop *inner_loop, tree chrec, enum tree_code code, tree type, tree op, bool *fold_conversions, int size_expr) @@ -2687,7 +2687,7 @@ instantiate_scev_not (edge instantiate_below, static tree instantiate_scev_r (edge instantiate_below, - struct loop *evolution_loop, struct loop *inner_loop, + class loop *evolution_loop, class loop *inner_loop, tree chrec, bool *fold_conversions, int size_expr) { @@ -2761,7 +2761,7 @@ instantiate_scev_r (edge instantiate_below, a function parameter. */ tree -instantiate_scev (edge instantiate_below, struct loop *evolution_loop, +instantiate_scev (edge instantiate_below, class loop *evolution_loop, tree chrec) { tree res; @@ -2810,7 +2810,7 @@ instantiate_scev (edge instantiate_below, struct loop *evolution_loop, of an expression. */ tree -resolve_mixers (struct loop *loop, tree chrec, bool *folded_casts) +resolve_mixers (class loop *loop, tree chrec, bool *folded_casts) { bool destr = false; bool fold_conversions = false; @@ -2859,10 +2859,10 @@ resolve_mixers (struct loop *loop, tree chrec, bool *folded_casts) the loop body has been executed 6 times. */ tree -number_of_latch_executions (struct loop *loop) +number_of_latch_executions (class loop *loop) { edge exit; - struct tree_niter_desc niter_desc; + class tree_niter_desc niter_desc; tree may_be_zero; tree res; @@ -3047,7 +3047,7 @@ gather_stats_on_scev_database (void) void scev_initialize (void) { - struct loop *loop; + class loop *loop; gcc_assert (! scev_initialized_p ()); @@ -3085,7 +3085,7 @@ scev_reset_htab (void) void scev_reset (void) { - struct loop *loop; + class loop *loop; scev_reset_htab (); @@ -3104,7 +3104,7 @@ scev_reset (void) hypotetical IVs to be inserted into code. */ bool -iv_can_overflow_p (struct loop *loop, tree type, tree base, tree step) +iv_can_overflow_p (class loop *loop, tree type, tree base, tree step) { widest_int nit; wide_int base_min, base_max, step_min, step_max, type_min, type_max; @@ -3267,7 +3267,7 @@ derive_simple_iv_with_niters (tree ev, tree *niters) infinite. */ bool -simple_iv_with_niters (struct loop *wrto_loop, struct loop *use_loop, +simple_iv_with_niters (class loop *wrto_loop, class loop *use_loop, tree op, affine_iv *iv, tree *iv_niters, bool allow_nonconstant_step) { @@ -3407,7 +3407,7 @@ simple_iv_with_niters (struct loop *wrto_loop, struct loop *use_loop, affine iv unconditionally. */ bool -simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op, +simple_iv (class loop *wrto_loop, class loop *use_loop, tree op, affine_iv *iv, bool allow_nonconstant_step) { return simple_iv_with_niters (wrto_loop, use_loop, op, iv, @@ -3565,7 +3565,7 @@ expression_expensive_p (tree expr) /* Do final value replacement for LOOP, return true if we did anything. */ bool -final_value_replacement_loop (struct loop *loop) +final_value_replacement_loop (class loop *loop) { /* If we do not know exact number of iterations of the loop, we cannot replace the final value. */ @@ -3584,7 +3584,7 @@ final_value_replacement_loop (struct loop *loop) /* Set stmt insertion pointer. All stmts are inserted before this point. */ gimple_stmt_iterator gsi = gsi_after_labels (exit->dest); - struct loop *ex_loop + class loop *ex_loop = superloop_at_depth (loop, loop_depth (exit->dest->loop_father) + 1); diff --git a/gcc/tree-scalar-evolution.h b/gcc/tree-scalar-evolution.h index 621a57c..d4d6ec5 100644 --- a/gcc/tree-scalar-evolution.h +++ b/gcc/tree-scalar-evolution.h @@ -21,27 +21,27 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_SCALAR_EVOLUTION_H #define GCC_TREE_SCALAR_EVOLUTION_H -extern tree number_of_latch_executions (struct loop *); -extern gcond *get_loop_exit_condition (const struct loop *); +extern tree number_of_latch_executions (class loop *); +extern gcond *get_loop_exit_condition (const class loop *); extern void scev_initialize (void); extern bool scev_initialized_p (void); extern void scev_reset (void); extern void scev_reset_htab (void); extern void scev_finalize (void); -extern tree analyze_scalar_evolution (struct loop *, tree); -extern tree instantiate_scev (edge, struct loop *, tree); -extern tree resolve_mixers (struct loop *, tree, bool *); +extern tree analyze_scalar_evolution (class loop *, tree); +extern tree instantiate_scev (edge, class loop *, tree); +extern tree resolve_mixers (class loop *, tree, bool *); extern void gather_stats_on_scev_database (void); -extern bool final_value_replacement_loop (struct loop *); +extern bool final_value_replacement_loop (class loop *); extern unsigned int scev_const_prop (void); extern bool expression_expensive_p (tree); -extern bool simple_iv_with_niters (struct loop *, struct loop *, tree, +extern bool simple_iv_with_niters (class loop *, class loop *, tree, struct affine_iv *, tree *, bool); -extern bool simple_iv (struct loop *, struct loop *, tree, struct affine_iv *, +extern bool simple_iv (class loop *, class loop *, tree, struct affine_iv *, bool); -extern bool iv_can_overflow_p (struct loop *, tree, tree, tree); -extern tree compute_overall_effect_of_inner_loop (struct loop *, tree); +extern bool iv_can_overflow_p (class loop *, tree, tree, tree); +extern tree compute_overall_effect_of_inner_loop (class loop *, tree); /* Returns the basic block preceding LOOP, or the CFG entry block when the loop is function's body. */ @@ -58,14 +58,14 @@ block_before_loop (loop_p loop) be analyzed and instantiated. */ static inline tree -instantiate_parameters (struct loop *loop, tree chrec) +instantiate_parameters (class loop *loop, tree chrec) { return instantiate_scev (loop_preheader_edge (loop), loop, chrec); } /* Returns the loop of the polynomial chrec CHREC. */ -static inline struct loop * +static inline class loop * get_chrec_loop (const_tree chrec) { return get_loop (cfun, CHREC_VARIABLE (chrec)); diff --git a/gcc/tree-ssa-address.h b/gcc/tree-ssa-address.h index 9812f36..05a2321 100644 --- a/gcc/tree-ssa-address.h +++ b/gcc/tree-ssa-address.h @@ -33,9 +33,9 @@ extern void get_address_description (tree, struct mem_address *); extern tree tree_mem_ref_addr (tree, tree); extern bool valid_mem_ref_p (machine_mode, addr_space_t, struct mem_address *); extern void move_fixed_address_to_symbol (struct mem_address *, - struct aff_tree *); + class aff_tree *); tree create_mem_ref (gimple_stmt_iterator *, tree, - struct aff_tree *, tree, tree, tree, bool); + class aff_tree *, tree, tree, tree, bool); extern void copy_ref_info (tree, tree); tree maybe_fold_tmr (tree); diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index c73fbab..6398c1e 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -411,7 +411,7 @@ find_obviously_necessary_stmts (bool aggressive) /* Prevent the empty possibly infinite loops from being removed. */ if (aggressive) { - struct loop *loop; + class loop *loop; if (mark_irreducible_loops ()) FOR_EACH_BB_FN (bb, cfun) { diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 17c852d..2d03866 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -395,7 +395,7 @@ edge_info::record_simple_equiv (tree lhs, tree rhs) void free_dom_edge_info (edge e) { - class edge_info *edge_info = (struct edge_info *)e->aux; + class edge_info *edge_info = (class edge_info *)e->aux; if (edge_info) delete edge_info; @@ -543,7 +543,7 @@ record_edge_info (basic_block bb) bool can_infer_simple_equiv = !(HONOR_SIGNED_ZEROS (op0) && real_zerop (op0)); - struct edge_info *edge_info; + class edge_info *edge_info; edge_info = new class edge_info (true_edge); record_conditions (&edge_info->cond_equivalences, cond, inverted); @@ -567,7 +567,7 @@ record_edge_info (basic_block bb) bool can_infer_simple_equiv = !(HONOR_SIGNED_ZEROS (op1) && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1))); - struct edge_info *edge_info; + class edge_info *edge_info; edge_info = new class edge_info (true_edge); record_conditions (&edge_info->cond_equivalences, cond, inverted); diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index e9ae8e0..9908794 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -79,7 +79,7 @@ var_map_base_fini (var_map map) function. */ var_map -init_var_map (int size, struct loop *loop) +init_var_map (int size, class loop *loop) { var_map map; @@ -852,7 +852,7 @@ remove_unused_locals (void) if (cfun->has_simduid_loops) { - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, 0) if (loop->simduid && !is_used_p (loop->simduid)) loop->simduid = NULL_TREE; diff --git a/gcc/tree-ssa-live.h b/gcc/tree-ssa-live.h index 78b033b..5bef4d5 100644 --- a/gcc/tree-ssa-live.h +++ b/gcc/tree-ssa-live.h @@ -80,7 +80,7 @@ typedef struct _var_map /* Value used to represent no partition number. */ #define NO_PARTITION -1 -extern var_map init_var_map (int, struct loop* = NULL); +extern var_map init_var_map (int, class loop* = NULL); extern void delete_var_map (var_map); extern int var_union (var_map, tree, tree); extern void partition_view_normal (var_map); diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index 25f562b..d92d7c8 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -48,7 +48,7 @@ along with GCC; see the file COPYING3. If not see amount. */ static bool -should_duplicate_loop_header_p (basic_block header, struct loop *loop, +should_duplicate_loop_header_p (basic_block header, class loop *loop, int *limit) { gimple_stmt_iterator bsi; @@ -211,7 +211,7 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, /* Checks whether LOOP is a do-while style loop. */ static bool -do_while_loop_p (struct loop *loop) +do_while_loop_p (class loop *loop) { gimple *stmt = last_stmt (loop->latch); @@ -268,7 +268,7 @@ class ch_base : public gimple_opt_pass unsigned int copy_headers (function *fun); /* Return true to copy headers of LOOP or false to skip. */ - virtual bool process_loop_p (struct loop *loop) = 0; + virtual bool process_loop_p (class loop *loop) = 0; }; const pass_data pass_data_ch = @@ -301,7 +301,7 @@ public: protected: /* ch_base method: */ - virtual bool process_loop_p (struct loop *loop); + virtual bool process_loop_p (class loop *loop); }; // class pass_ch const pass_data pass_data_ch_vect = @@ -339,7 +339,7 @@ public: protected: /* ch_base method: */ - virtual bool process_loop_p (struct loop *loop); + virtual bool process_loop_p (class loop *loop); }; // class pass_ch_vect /* For all loops, copy the condition at the end of the loop body in front @@ -349,7 +349,7 @@ protected: unsigned int ch_base::copy_headers (function *fun) { - struct loop *loop; + class loop *loop; basic_block header; edge exit, entry; basic_block *bbs, *copied_bbs; @@ -549,7 +549,7 @@ pass_ch_vect::execute (function *fun) /* Apply header copying according to a very simple test of do-while shape. */ bool -pass_ch::process_loop_p (struct loop *loop) +pass_ch::process_loop_p (class loop *loop) { return !do_while_loop_p (loop); } @@ -557,7 +557,7 @@ pass_ch::process_loop_p (struct loop *loop) /* Apply header-copying to loops where we might enable vectorization. */ bool -pass_ch_vect::process_loop_p (struct loop *loop) +pass_ch_vect::process_loop_p (class loop *loop) { if (!flag_tree_loop_vectorize && !loop->force_vectorize) return false; diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index f8bcabc..12176e0 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -75,13 +75,13 @@ along with GCC; see the file COPYING3. If not see struct lim_aux_data { - struct loop *max_loop; /* The outermost loop in that the statement + class loop *max_loop; /* The outermost loop in that the statement is invariant. */ - struct loop *tgt_loop; /* The loop out of that we want to move the + class loop *tgt_loop; /* The loop out of that we want to move the invariant. */ - struct loop *always_executed_in; + class loop *always_executed_in; /* The outermost loop for that we are sure the statement is executed if the loop is entered. */ @@ -160,7 +160,7 @@ struct mem_ref_hasher : nofree_ptr_hash static inline bool equal (const im_mem_ref *, const ao_ref *); }; -/* A hash function for struct im_mem_ref object OBJ. */ +/* A hash function for class im_mem_ref object OBJ. */ inline hashval_t mem_ref_hasher::hash (const im_mem_ref *mem) @@ -168,7 +168,7 @@ mem_ref_hasher::hash (const im_mem_ref *mem) return mem->hash; } -/* An equality function for struct im_mem_ref object MEM1 with +/* An equality function for class im_mem_ref object MEM1 with memory reference OBJ2. */ inline bool @@ -226,15 +226,15 @@ static struct static bitmap_obstack lim_bitmap_obstack; static obstack mem_ref_obstack; -static bool ref_indep_loop_p (struct loop *, im_mem_ref *); -static bool ref_always_accessed_p (struct loop *, im_mem_ref *, bool); +static bool ref_indep_loop_p (class loop *, im_mem_ref *); +static bool ref_always_accessed_p (class loop *, im_mem_ref *, bool); /* Minimum cost of an expensive expression. */ #define LIM_EXPENSIVE ((unsigned) PARAM_VALUE (PARAM_LIM_EXPENSIVE)) /* The outermost loop for which execution of the header guarantees that the block will be executed. */ -#define ALWAYS_EXECUTED_IN(BB) ((struct loop *) (BB)->aux) +#define ALWAYS_EXECUTED_IN(BB) ((class loop *) (BB)->aux) #define SET_ALWAYS_EXECUTED_IN(BB, VAL) ((BB)->aux = (void *) (VAL)) /* ID of the shared unanalyzable mem. */ @@ -396,12 +396,12 @@ movement_possibility (gimple *stmt) other operands, i.e. the outermost loop enclosing LOOP in that the value of DEF is invariant. */ -static struct loop * -outermost_invariant_loop (tree def, struct loop *loop) +static class loop * +outermost_invariant_loop (tree def, class loop *loop) { gimple *def_stmt; basic_block def_bb; - struct loop *max_loop; + class loop *max_loop; struct lim_aux_data *lim_data; if (!def) @@ -444,12 +444,12 @@ outermost_invariant_loop (tree def, struct loop *loop) If DEF is not invariant in LOOP, return false. Otherwise return TRUE. */ static bool -add_dependency (tree def, struct lim_aux_data *data, struct loop *loop, +add_dependency (tree def, struct lim_aux_data *data, class loop *loop, bool add_cost) { gimple *def_stmt = SSA_NAME_DEF_STMT (def); basic_block def_bb = gimple_bb (def_stmt); - struct loop *max_loop; + class loop *max_loop; struct lim_aux_data *def_data; if (!def_bb) @@ -560,10 +560,10 @@ stmt_cost (gimple *stmt) REF is independent. If REF is not independent in LOOP, NULL is returned instead. */ -static struct loop * -outermost_indep_loop (struct loop *outer, struct loop *loop, im_mem_ref *ref) +static class loop * +outermost_indep_loop (class loop *outer, class loop *loop, im_mem_ref *ref) { - struct loop *aloop; + class loop *aloop; if (ref->stored && bitmap_bit_p (ref->stored, loop->num)) return NULL; @@ -649,8 +649,8 @@ static bool determine_max_movement (gimple *stmt, bool must_preserve_exec) { basic_block bb = gimple_bb (stmt); - struct loop *loop = bb->loop_father; - struct loop *level; + class loop *loop = bb->loop_father; + class loop *level; struct lim_aux_data *lim_data = get_lim_data (stmt); tree val; ssa_op_iter iter; @@ -777,9 +777,9 @@ determine_max_movement (gimple *stmt, bool must_preserve_exec) operands) is hoisted at least out of the loop LEVEL. */ static void -set_level (gimple *stmt, struct loop *orig_loop, struct loop *level) +set_level (gimple *stmt, class loop *orig_loop, class loop *level) { - struct loop *stmt_loop = gimple_bb (stmt)->loop_father; + class loop *stmt_loop = gimple_bb (stmt)->loop_father; struct lim_aux_data *lim_data; gimple *dep_stmt; unsigned i; @@ -974,7 +974,7 @@ invariantness_dom_walker::before_dom_children (basic_block bb) gimple_stmt_iterator bsi; gimple *stmt; bool maybe_never = ALWAYS_EXECUTED_IN (bb) == NULL; - struct loop *outermost = ALWAYS_EXECUTED_IN (bb); + class loop *outermost = ALWAYS_EXECUTED_IN (bb); struct lim_aux_data *lim_data; if (!loop_outer (bb->loop_father)) @@ -1053,7 +1053,7 @@ invariantness_dom_walker::before_dom_children (basic_block bb) { tree op0 = gimple_assign_rhs1 (stmt); tree op1 = gimple_assign_rhs2 (stmt); - struct loop *ol1 = outermost_invariant_loop (op1, + class loop *ol1 = outermost_invariant_loop (op1, loop_containing_stmt (stmt)); /* If divisor is invariant, convert a/b to a*(1/b), allowing reciprocal @@ -1112,7 +1112,7 @@ invariantness_dom_walker::before_dom_children (basic_block bb) unsigned int move_computations_worker (basic_block bb) { - struct loop *level; + class loop *level; unsigned cost = 0; struct lim_aux_data *lim_data; unsigned int todo = 0; @@ -1296,7 +1296,7 @@ move_computations (void) static bool may_move_till (tree ref, tree *index, void *data) { - struct loop *loop = (struct loop *) data, *max_loop; + class loop *loop = (class loop *) data, *max_loop; /* If REF is an array reference, check also that the step and the lower bound is invariant in LOOP. */ @@ -1325,7 +1325,7 @@ may_move_till (tree ref, tree *index, void *data) moved out of the LOOP. ORIG_LOOP is the loop in that EXPR is used. */ static void -force_move_till_op (tree op, struct loop *orig_loop, struct loop *loop) +force_move_till_op (tree op, class loop *orig_loop, class loop *loop) { gimple *stmt; @@ -1348,8 +1348,8 @@ force_move_till_op (tree op, struct loop *orig_loop, struct loop *loop) struct fmt_data { - struct loop *loop; - struct loop *orig_loop; + class loop *loop; + class loop *orig_loop; }; static bool @@ -1374,7 +1374,7 @@ force_move_till (tree ref, tree *index, void *data) /* A function to free the mem_ref object OBJ. */ static void -memref_free (struct im_mem_ref *mem) +memref_free (class im_mem_ref *mem) { mem->accesses_in_loop.release (); } @@ -1385,7 +1385,7 @@ memref_free (struct im_mem_ref *mem) static im_mem_ref * mem_ref_alloc (ao_ref *mem, unsigned hash, unsigned id) { - im_mem_ref *ref = XOBNEW (&mem_ref_obstack, struct im_mem_ref); + im_mem_ref *ref = XOBNEW (&mem_ref_obstack, class im_mem_ref); if (mem) ref->mem = *mem; else @@ -1418,7 +1418,7 @@ record_mem_ref_loc (im_mem_ref *ref, gimple *stmt, tree *loc) necessary. Return whether a bit was changed. */ static bool -set_ref_stored_in_loop (im_mem_ref *ref, struct loop *loop) +set_ref_stored_in_loop (im_mem_ref *ref, class loop *loop) { if (!ref->stored) ref->stored = BITMAP_ALLOC (&lim_bitmap_obstack); @@ -1428,7 +1428,7 @@ set_ref_stored_in_loop (im_mem_ref *ref, struct loop *loop) /* Marks reference REF as stored in LOOP. */ static void -mark_ref_stored (im_mem_ref *ref, struct loop *loop) +mark_ref_stored (im_mem_ref *ref, class loop *loop) { while (loop != current_loops->tree_root && set_ref_stored_in_loop (ref, loop)) @@ -1441,7 +1441,7 @@ mark_ref_stored (im_mem_ref *ref, struct loop *loop) well. */ static void -gather_mem_refs_stmt (struct loop *loop, gimple *stmt) +gather_mem_refs_stmt (class loop *loop, gimple *stmt) { tree *mem = NULL; hashval_t hash; @@ -1583,8 +1583,8 @@ sort_bbs_in_loop_postorder_cmp (const void *bb1_, const void *bb2_) { basic_block bb1 = *(basic_block *)const_cast(bb1_); basic_block bb2 = *(basic_block *)const_cast(bb2_); - struct loop *loop1 = bb1->loop_father; - struct loop *loop2 = bb2->loop_father; + class loop *loop1 = bb1->loop_father; + class loop *loop2 = bb2->loop_father; if (loop1->num == loop2->num) return bb1->index - bb2->index; return bb_loop_postorder[loop1->num] < bb_loop_postorder[loop2->num] ? -1 : 1; @@ -1597,8 +1597,8 @@ sort_locs_in_loop_postorder_cmp (const void *loc1_, const void *loc2_) { mem_ref_loc *loc1 = (mem_ref_loc *)const_cast(loc1_); mem_ref_loc *loc2 = (mem_ref_loc *)const_cast(loc2_); - struct loop *loop1 = gimple_bb (loc1->stmt)->loop_father; - struct loop *loop2 = gimple_bb (loc2->stmt)->loop_father; + class loop *loop1 = gimple_bb (loc1->stmt)->loop_father; + class loop *loop2 = gimple_bb (loc2->stmt)->loop_father; if (loop1->num == loop2->num) return 0; return bb_loop_postorder[loop1->num] < bb_loop_postorder[loop2->num] ? -1 : 1; @@ -1611,7 +1611,7 @@ analyze_memory_references (void) { gimple_stmt_iterator bsi; basic_block bb, *bbs; - struct loop *loop, *outer; + class loop *loop, *outer; unsigned i, n; /* Collect all basic-blocks in loops and sort them after their @@ -1702,9 +1702,9 @@ mem_refs_may_alias_p (im_mem_ref *mem1, im_mem_ref *mem2, static int find_ref_loc_in_loop_cmp (const void *loop_, const void *loc_) { - struct loop *loop = (struct loop *)const_cast(loop_); + class loop *loop = (class loop *)const_cast(loop_); mem_ref_loc *loc = (mem_ref_loc *)const_cast(loc_); - struct loop *loc_loop = gimple_bb (loc->stmt)->loop_father; + class loop *loc_loop = gimple_bb (loc->stmt)->loop_father; if (loop->num == loc_loop->num || flow_loop_nested_p (loop, loc_loop)) return 0; @@ -1719,7 +1719,7 @@ find_ref_loc_in_loop_cmp (const void *loop_, const void *loc_) template static bool -for_all_locs_in_loop (struct loop *loop, im_mem_ref *ref, FN fn) +for_all_locs_in_loop (class loop *loop, im_mem_ref *ref, FN fn) { unsigned i; mem_ref_loc *loc; @@ -1776,7 +1776,7 @@ rewrite_mem_ref_loc::operator () (mem_ref_loc *loc) /* Rewrites all references to REF in LOOP by variable TMP_VAR. */ static void -rewrite_mem_refs (struct loop *loop, im_mem_ref *ref, tree tmp_var) +rewrite_mem_refs (class loop *loop, im_mem_ref *ref, tree tmp_var) { for_all_locs_in_loop (loop, ref, rewrite_mem_ref_loc (tmp_var)); } @@ -1801,7 +1801,7 @@ first_mem_ref_loc_1::operator () (mem_ref_loc *loc) /* Returns the first reference location to REF in LOOP. */ static mem_ref_loc * -first_mem_ref_loc (struct loop *loop, im_mem_ref *ref) +first_mem_ref_loc (class loop *loop, im_mem_ref *ref) { mem_ref_loc *locp = NULL; for_all_locs_in_loop (loop, ref, first_mem_ref_loc_1 (&locp)); @@ -2049,7 +2049,7 @@ sm_set_flag_if_changed::operator () (mem_ref_loc *loc) set, set an appropriate flag indicating the store. */ static tree -execute_sm_if_changed_flag_set (struct loop *loop, im_mem_ref *ref, +execute_sm_if_changed_flag_set (class loop *loop, im_mem_ref *ref, hash_set *bbs) { tree flag; @@ -2065,7 +2065,7 @@ execute_sm_if_changed_flag_set (struct loop *loop, im_mem_ref *ref, to the reference from the temporary variable are emitted to exits. */ static void -execute_sm (struct loop *loop, vec exits, im_mem_ref *ref) +execute_sm (class loop *loop, vec exits, im_mem_ref *ref) { tree tmp_var, store_flag = NULL_TREE; unsigned i; @@ -2141,7 +2141,7 @@ execute_sm (struct loop *loop, vec exits, im_mem_ref *ref) edges of the LOOP. */ static void -hoist_memory_references (struct loop *loop, bitmap mem_refs, +hoist_memory_references (class loop *loop, bitmap mem_refs, vec exits) { im_mem_ref *ref; @@ -2158,17 +2158,17 @@ hoist_memory_references (struct loop *loop, bitmap mem_refs, class ref_always_accessed { public: - ref_always_accessed (struct loop *loop_, bool stored_p_) + ref_always_accessed (class loop *loop_, bool stored_p_) : loop (loop_), stored_p (stored_p_) {} bool operator () (mem_ref_loc *loc); - struct loop *loop; + class loop *loop; bool stored_p; }; bool ref_always_accessed::operator () (mem_ref_loc *loc) { - struct loop *must_exec; + class loop *must_exec; if (!get_lim_data (loc->stmt)) return false; @@ -2198,7 +2198,7 @@ ref_always_accessed::operator () (mem_ref_loc *loc) make sure REF is always stored to in LOOP. */ static bool -ref_always_accessed_p (struct loop *loop, im_mem_ref *ref, bool stored_p) +ref_always_accessed_p (class loop *loop, im_mem_ref *ref, bool stored_p) { return for_all_locs_in_loop (loop, ref, ref_always_accessed (loop, stored_p)); @@ -2234,7 +2234,7 @@ refs_independent_p (im_mem_ref *ref1, im_mem_ref *ref2) and its super-loops. */ static void -record_dep_loop (struct loop *loop, im_mem_ref *ref, bool stored_p) +record_dep_loop (class loop *loop, im_mem_ref *ref, bool stored_p) { /* We can propagate dependent-in-loop bits up the loop hierarchy to all outer loops. */ @@ -2247,7 +2247,7 @@ record_dep_loop (struct loop *loop, im_mem_ref *ref, bool stored_p) references in LOOP. */ static bool -ref_indep_loop_p_1 (struct loop *loop, im_mem_ref *ref, bool stored_p) +ref_indep_loop_p_1 (class loop *loop, im_mem_ref *ref, bool stored_p) { stored_p |= (ref->stored && bitmap_bit_p (ref->stored, loop->num)); @@ -2268,7 +2268,7 @@ ref_indep_loop_p_1 (struct loop *loop, im_mem_ref *ref, bool stored_p) if (bitmap_bit_p (&ref->dep_loop, LOOP_DEP_BIT (loop->num, stored_p))) return false; - struct loop *inner = loop->inner; + class loop *inner = loop->inner; while (inner) { if (!ref_indep_loop_p_1 (inner, ref, stored_p)) @@ -2328,7 +2328,7 @@ ref_indep_loop_p_1 (struct loop *loop, im_mem_ref *ref, bool stored_p) LOOP. */ static bool -ref_indep_loop_p (struct loop *loop, im_mem_ref *ref) +ref_indep_loop_p (class loop *loop, im_mem_ref *ref) { gcc_checking_assert (MEM_ANALYZABLE (ref)); @@ -2338,7 +2338,7 @@ ref_indep_loop_p (struct loop *loop, im_mem_ref *ref) /* Returns true if we can perform store motion of REF from LOOP. */ static bool -can_sm_ref_p (struct loop *loop, im_mem_ref *ref) +can_sm_ref_p (class loop *loop, im_mem_ref *ref) { tree base; @@ -2379,7 +2379,7 @@ can_sm_ref_p (struct loop *loop, im_mem_ref *ref) motion was performed in one of the outer loops. */ static void -find_refs_for_sm (struct loop *loop, bitmap sm_executed, bitmap refs_to_sm) +find_refs_for_sm (class loop *loop, bitmap sm_executed, bitmap refs_to_sm) { bitmap refs = &memory_accesses.all_refs_stored_in_loop[loop->num]; unsigned i; @@ -2399,7 +2399,7 @@ find_refs_for_sm (struct loop *loop, bitmap sm_executed, bitmap refs_to_sm) on its exits). */ static bool -loop_suitable_for_sm (struct loop *loop ATTRIBUTE_UNUSED, +loop_suitable_for_sm (class loop *loop ATTRIBUTE_UNUSED, vec exits) { unsigned i; @@ -2417,10 +2417,10 @@ loop_suitable_for_sm (struct loop *loop ATTRIBUTE_UNUSED, store motion was executed in one of the outer loops. */ static void -store_motion_loop (struct loop *loop, bitmap sm_executed) +store_motion_loop (class loop *loop, bitmap sm_executed) { vec exits = get_loop_exit_edges (loop); - struct loop *subloop; + class loop *subloop; bitmap sm_in_loop = BITMAP_ALLOC (&lim_bitmap_obstack); if (loop_suitable_for_sm (loop, exits)) @@ -2443,7 +2443,7 @@ store_motion_loop (struct loop *loop, bitmap sm_executed) static void store_motion (void) { - struct loop *loop; + class loop *loop; bitmap sm_executed = BITMAP_ALLOC (&lim_bitmap_obstack); for (loop = current_loops->tree_root->inner; loop != NULL; loop = loop->next) @@ -2459,12 +2459,12 @@ store_motion (void) blocks that contain a nonpure call. */ static void -fill_always_executed_in_1 (struct loop *loop, sbitmap contains_call) +fill_always_executed_in_1 (class loop *loop, sbitmap contains_call) { basic_block bb = NULL, *bbs, last = NULL; unsigned i; edge e; - struct loop *inn_loop = loop; + class loop *inn_loop = loop; if (ALWAYS_EXECUTED_IN (loop->header) == NULL) { @@ -2537,7 +2537,7 @@ static void fill_always_executed_in (void) { basic_block bb; - struct loop *loop; + class loop *loop; auto_sbitmap contains_call (last_basic_block_for_fn (cfun)); bitmap_clear (contains_call); @@ -2564,7 +2564,7 @@ fill_always_executed_in (void) static void tree_ssa_lim_initialize (void) { - struct loop *loop; + class loop *loop; unsigned i; bitmap_obstack_initialize (&lim_bitmap_obstack); diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index eb0c1c9..5952cad 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -82,7 +82,7 @@ enum unroll_level if they are not NULL. */ void -create_canonical_iv (struct loop *loop, edge exit, tree niter, +create_canonical_iv (class loop *loop, edge exit, tree niter, tree *var_before = NULL, tree *var_after = NULL) { edge in; @@ -161,7 +161,7 @@ struct loop_size /* Return true if OP in STMT will be constant after peeling LOOP. */ static bool -constant_after_peeling (tree op, gimple *stmt, struct loop *loop) +constant_after_peeling (tree op, gimple *stmt, class loop *loop) { if (is_gimple_min_invariant (op)) return true; @@ -211,7 +211,7 @@ constant_after_peeling (tree op, gimple *stmt, struct loop *loop) Stop estimating after UPPER_BOUND is met. Return true in this case. */ static bool -tree_estimate_loop_size (struct loop *loop, edge exit, edge edge_to_cancel, +tree_estimate_loop_size (class loop *loop, edge exit, edge edge_to_cancel, struct loop_size *size, int upper_bound) { basic_block *body = get_loop_body (loop); @@ -441,7 +441,7 @@ estimated_unrolled_size (struct loop_size *size, The other cases are hopefully rare and will be cleaned up later. */ static edge -loop_edge_to_cancel (struct loop *loop) +loop_edge_to_cancel (class loop *loop) { vec exits; unsigned i; @@ -495,9 +495,9 @@ loop_edge_to_cancel (struct loop *loop) known to not be executed. */ static bool -remove_exits_and_undefined_stmts (struct loop *loop, unsigned int npeeled) +remove_exits_and_undefined_stmts (class loop *loop, unsigned int npeeled) { - struct nb_iter_bound *elt; + class nb_iter_bound *elt; bool changed = false; for (elt = loop->bounds; elt; elt = elt->next) @@ -553,9 +553,9 @@ remove_exits_and_undefined_stmts (struct loop *loop, unsigned int npeeled) discovered. */ static bool -remove_redundant_iv_tests (struct loop *loop) +remove_redundant_iv_tests (class loop *loop) { - struct nb_iter_bound *elt; + class nb_iter_bound *elt; bool changed = false; if (!loop->any_upper_bound) @@ -569,7 +569,7 @@ remove_redundant_iv_tests (struct loop *loop) { basic_block bb = gimple_bb (elt->stmt); edge exit_edge = EDGE_SUCC (bb, 0); - struct tree_niter_desc niter; + class tree_niter_desc niter; if (!loop_exit_edge_p (loop, exit_edge)) exit_edge = EDGE_SUCC (bb, 1); @@ -629,7 +629,7 @@ unloop_loops (bitmap loop_closed_ssa_invalidated, { while (loops_to_unloop.length ()) { - struct loop *loop = loops_to_unloop.pop (); + class loop *loop = loops_to_unloop.pop (); int n_unroll = loops_to_unloop_nunroll.pop (); basic_block latch = loop->latch; edge latch_edge = loop_latch_edge (loop); @@ -688,7 +688,7 @@ unloop_loops (bitmap loop_closed_ssa_invalidated, a summary of the unroll to the dump file. */ static bool -try_unroll_loop_completely (struct loop *loop, +try_unroll_loop_completely (class loop *loop, edge exit, tree niter, bool may_be_zero, enum unroll_level ul, HOST_WIDE_INT maxiter, @@ -986,7 +986,7 @@ estimated_peeled_sequence_size (struct loop_size *size, Parameters are the same as for try_unroll_loops_completely */ static bool -try_peel_loop (struct loop *loop, +try_peel_loop (class loop *loop, edge exit, tree niter, bool may_be_zero, HOST_WIDE_INT maxiter) { @@ -1155,7 +1155,7 @@ try_peel_loop (struct loop *loop, Returns true if cfg is changed. */ static bool -canonicalize_loop_induction_variables (struct loop *loop, +canonicalize_loop_induction_variables (class loop *loop, bool create_iv, enum unroll_level ul, bool try_eval, bool allow_peel) { @@ -1164,7 +1164,7 @@ canonicalize_loop_induction_variables (struct loop *loop, HOST_WIDE_INT maxiter; bool modified = false; dump_user_location_t locus; - struct tree_niter_desc niter_desc; + class tree_niter_desc niter_desc; bool may_be_zero = false; /* For unrolling allow conditional constant or zero iterations, thus @@ -1282,7 +1282,7 @@ canonicalize_loop_induction_variables (struct loop *loop, unsigned int canonicalize_induction_variables (void) { - struct loop *loop; + class loop *loop; bool changed = false; bool irred_invalidated = false; bitmap loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL); @@ -1324,11 +1324,11 @@ canonicalize_induction_variables (void) static bool tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer, - bitmap father_bbs, struct loop *loop) + bitmap father_bbs, class loop *loop) { - struct loop *loop_father; + class loop *loop_father; bool changed = false; - struct loop *inner; + class loop *inner; enum unroll_level ul; unsigned num = number_of_loops (cfun); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index cb189ab..fd5e99b 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -121,7 +121,7 @@ along with GCC; see the file COPYING3. If not see exists. */ static inline HOST_WIDE_INT -avg_loop_niter (struct loop *loop) +avg_loop_niter (class loop *loop) { HOST_WIDE_INT niter = estimated_stmt_executions_int (loop); if (niter == -1) @@ -398,7 +398,7 @@ struct iv_group /* Number of IV candidates in the cost_map. */ unsigned n_map_members; /* The costs wrto the iv candidates. */ - struct cost_pair *cost_map; + class cost_pair *cost_map; /* The selected candidate for the group. */ struct iv_cand *selected; /* Uses in the group. */ @@ -551,7 +551,7 @@ iv_inv_expr_hasher::equal (const iv_inv_expr_ent *expr1, struct ivopts_data { /* The currently optimized loop. */ - struct loop *current_loop; + class loop *current_loop; location_t loop_loc; /* Numbers of iterations for all exits of the current loop. */ @@ -629,7 +629,7 @@ public: unsigned bad_groups; /* Candidate assigned to a use, together with the related costs. */ - struct cost_pair **cand_for_group; + class cost_pair **cand_for_group; /* Number of times each candidate is used. */ unsigned *n_cand_uses; @@ -668,10 +668,10 @@ struct iv_ca_delta struct iv_group *group; /* An old assignment (for rollback purposes). */ - struct cost_pair *old_cp; + class cost_pair *old_cp; /* A new assignment. */ - struct cost_pair *new_cp; + class cost_pair *new_cp; /* Next change in the list. */ struct iv_ca_delta *next; @@ -704,7 +704,7 @@ static comp_cost force_expr_to_var_cost (tree, bool); /* The single loop exit if it dominates the latch, NULL otherwise. */ edge -single_dom_exit (struct loop *loop) +single_dom_exit (class loop *loop) { edge exit = single_exit (loop); @@ -885,7 +885,7 @@ name_info (struct ivopts_data *data, tree name) emitted in LOOP. */ static bool -stmt_after_ip_normal_pos (struct loop *loop, gimple *stmt) +stmt_after_ip_normal_pos (class loop *loop, gimple *stmt) { basic_block bb = ip_normal_pos (loop), sbb = gimple_bb (stmt); @@ -926,7 +926,7 @@ stmt_after_inc_pos (struct iv_cand *cand, gimple *stmt, bool true_if_equal) CAND is incremented in LOOP. */ static bool -stmt_after_increment (struct loop *loop, struct iv_cand *cand, gimple *stmt) +stmt_after_increment (class loop *loop, struct iv_cand *cand, gimple *stmt) { switch (cand->pos) { @@ -976,10 +976,10 @@ contains_abnormal_ssa_name_p (tree expr) /* Returns the structure describing number of iterations determined from EXIT of DATA->current_loop, or NULL if something goes wrong. */ -static struct tree_niter_desc * +static class tree_niter_desc * niter_for_exit (struct ivopts_data *data, edge exit) { - struct tree_niter_desc *desc; + class tree_niter_desc *desc; tree_niter_desc **slot; if (!data->niters) @@ -995,7 +995,7 @@ niter_for_exit (struct ivopts_data *data, edge exit) /* Try to determine number of iterations. We cannot safely work with ssa names that appear in phi nodes on abnormal edges, so that we do not create overlapping life ranges for them (PR 27283). */ - desc = XNEW (struct tree_niter_desc); + desc = XNEW (class tree_niter_desc); if (!number_of_iterations_exit (data->current_loop, exit, desc, true) || contains_abnormal_ssa_name_p (desc->niter)) @@ -1015,7 +1015,7 @@ niter_for_exit (struct ivopts_data *data, edge exit) single dominating exit of DATA->current_loop, or NULL if something goes wrong. */ -static struct tree_niter_desc * +static class tree_niter_desc * niter_for_single_dom_exit (struct ivopts_data *data) { edge exit = single_dom_exit (data->current_loop); @@ -1246,7 +1246,7 @@ find_bivs (struct ivopts_data *data) affine_iv iv; tree step, type, base, stop; bool found = false; - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; gphi_iterator psi; for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi)) @@ -1304,7 +1304,7 @@ mark_bivs (struct ivopts_data *data) gimple *def; tree var; struct iv *iv, *incr_iv; - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; basic_block incr_bb; gphi_iterator psi; @@ -1351,7 +1351,7 @@ static bool find_givs_in_stmt_scev (struct ivopts_data *data, gimple *stmt, affine_iv *iv) { tree lhs, stop; - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; iv->base = NULL_TREE; iv->step = NULL_TREE; @@ -1415,7 +1415,7 @@ find_givs_in_bb (struct ivopts_data *data, basic_block bb) static void find_givs (struct ivopts_data *data) { - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; basic_block *body = get_loop_body_in_dom_order (loop); unsigned i; @@ -1441,7 +1441,7 @@ find_induction_variables (struct ivopts_data *data) if (dump_file && (dump_flags & TDF_DETAILS)) { - struct tree_niter_desc *niter = niter_for_single_dom_exit (data); + class tree_niter_desc *niter = niter_for_single_dom_exit (data); if (niter) { @@ -1741,8 +1741,8 @@ find_interesting_uses_cond (struct ivopts_data *data, gimple *stmt) outside of the returned loop. Returns NULL if EXPR is not even obviously invariant in LOOP. */ -struct loop * -outermost_invariant_loop_for_expr (struct loop *loop, tree expr) +class loop * +outermost_invariant_loop_for_expr (class loop *loop, tree expr) { basic_block def_bb; unsigned i, len; @@ -1771,7 +1771,7 @@ outermost_invariant_loop_for_expr (struct loop *loop, tree expr) len = TREE_OPERAND_LENGTH (expr); for (i = 0; i < len; i++) { - struct loop *ivloop; + class loop *ivloop; if (!TREE_OPERAND (expr, i)) continue; @@ -1789,7 +1789,7 @@ outermost_invariant_loop_for_expr (struct loop *loop, tree expr) should not be the function body. */ bool -expr_invariant_in_loop_p (struct loop *loop, tree expr) +expr_invariant_in_loop_p (class loop *loop, tree expr) { basic_block def_bb; unsigned i, len; @@ -1982,7 +1982,7 @@ idx_find_step (tree base, tree *idx, void *data) struct iv *iv; bool use_overflow_semantics = false; tree step, iv_base, iv_step, lbound, off; - struct loop *loop = dta->ivopts_data->current_loop; + class loop *loop = dta->ivopts_data->current_loop; /* If base is a component ref, require that the offset of the reference be invariant. */ @@ -3140,7 +3140,7 @@ add_candidate_1 (struct ivopts_data *data, is already nonempty. */ static bool -allow_ip_end_pos_p (struct loop *loop) +allow_ip_end_pos_p (class loop *loop) { if (!ip_normal_pos (loop)) return true; @@ -3331,8 +3331,8 @@ static void record_common_cand (struct ivopts_data *data, tree base, tree step, struct iv_use *use) { - struct iv_common_cand ent; - struct iv_common_cand **slot; + class iv_common_cand ent; + class iv_common_cand **slot; ent.base = base; ent.step = step; @@ -3361,10 +3361,10 @@ static int common_cand_cmp (const void *p1, const void *p2) { unsigned n1, n2; - const struct iv_common_cand *const *const ccand1 - = (const struct iv_common_cand *const *)p1; - const struct iv_common_cand *const *const ccand2 - = (const struct iv_common_cand *const *)p2; + const class iv_common_cand *const *const ccand1 + = (const class iv_common_cand *const *)p1; + const class iv_common_cand *const *const ccand2 + = (const class iv_common_cand *const *)p2; n1 = (*ccand1)->uses.length (); n2 = (*ccand2)->uses.length (); @@ -3382,7 +3382,7 @@ add_iv_candidate_derived_from_uses (struct ivopts_data *data) data->iv_common_cands.qsort (common_cand_cmp); for (i = 0; i < data->iv_common_cands.length (); i++) { - struct iv_common_cand *ptr = data->iv_common_cands[i]; + class iv_common_cand *ptr = data->iv_common_cands[i]; /* Only add IV candidate if it's derived from multiple uses. */ if (ptr->uses.length () <= 1) @@ -3558,7 +3558,7 @@ alloc_use_cost_map (struct ivopts_data *data) } group->n_map_members = size; - group->cost_map = XCNEWVEC (struct cost_pair, size); + group->cost_map = XCNEWVEC (class cost_pair, size); } } @@ -3614,12 +3614,12 @@ found: /* Gets cost of (GROUP, CAND) pair. */ -static struct cost_pair * +static class cost_pair * get_group_iv_cost (struct ivopts_data *data, struct iv_group *group, struct iv_cand *cand) { unsigned i, s; - struct cost_pair *ret; + class cost_pair *ret; if (!cand) return NULL; @@ -3753,7 +3753,7 @@ prepare_decl_rtl (tree *expr_p, int *ws, void *data) static bool ATTRIBUTE_UNUSED generic_predict_doloop_p (struct ivopts_data *data) { - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; /* Call target hook for target dependent checks. */ if (!targetm.predict_doloop_p (loop)) @@ -3768,7 +3768,7 @@ generic_predict_doloop_p (struct ivopts_data *data) suitable or not. Keep it as simple as possible, feel free to extend it if you find any multiple exits cases matter. */ edge exit = single_dom_exit (loop); - struct tree_niter_desc *niter_desc; + class tree_niter_desc *niter_desc; if (!exit || !(niter_desc = niter_for_exit (data, exit))) { if (dump_file && (dump_flags & TDF_DETAILS)) @@ -3832,7 +3832,7 @@ computation_cost (tree expr, bool speed) /* Returns variable containing the value of candidate CAND at statement AT. */ static tree -var_at_stmt (struct loop *loop, struct iv_cand *cand, gimple *stmt) +var_at_stmt (class loop *loop, struct iv_cand *cand, gimple *stmt) { if (stmt_after_increment (loop, cand, stmt)) return cand->var_after; @@ -3883,9 +3883,9 @@ determine_common_wider_type (tree *a, tree *b) non-null. Returns false if USE cannot be expressed using CAND. */ static bool -get_computation_aff_1 (struct loop *loop, gimple *at, struct iv_use *use, - struct iv_cand *cand, struct aff_tree *aff_inv, - struct aff_tree *aff_var, widest_int *prat = NULL) +get_computation_aff_1 (class loop *loop, gimple *at, struct iv_use *use, + struct iv_cand *cand, class aff_tree *aff_inv, + class aff_tree *aff_var, widest_int *prat = NULL) { tree ubase = use->iv->base, ustep = use->iv->step; tree cbase = cand->iv->base, cstep = cand->iv->step; @@ -3989,8 +3989,8 @@ get_computation_aff_1 (struct loop *loop, gimple *at, struct iv_use *use, form into AFF. Returns false if USE cannot be expressed using CAND. */ static bool -get_computation_aff (struct loop *loop, gimple *at, struct iv_use *use, - struct iv_cand *cand, struct aff_tree *aff) +get_computation_aff (class loop *loop, gimple *at, struct iv_use *use, + struct iv_cand *cand, class aff_tree *aff) { aff_tree aff_var; @@ -4027,7 +4027,7 @@ get_use_type (struct iv_use *use) CAND at statement AT in LOOP. The computation is unshared. */ static tree -get_computation_at (struct loop *loop, gimple *at, +get_computation_at (class loop *loop, gimple *at, struct iv_use *use, struct iv_cand *cand) { aff_tree aff; @@ -4809,7 +4809,7 @@ determine_group_iv_cost_address (struct ivopts_data *data, stores it to VAL. */ static void -cand_value_at (struct loop *loop, struct iv_cand *cand, gimple *at, tree niter, +cand_value_at (class loop *loop, struct iv_cand *cand, gimple *at, tree niter, aff_tree *val) { aff_tree step, delta, nit; @@ -4868,7 +4868,7 @@ iv_period (struct iv *iv) static enum tree_code iv_elimination_compare (struct ivopts_data *data, struct iv_use *use) { - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; basic_block ex_bb; edge exit; @@ -4992,10 +4992,10 @@ difference_cannot_overflow_p (struct ivopts_data *data, tree base, tree offset) static bool iv_elimination_compare_lt (struct ivopts_data *data, struct iv_cand *cand, enum tree_code *comp_p, - struct tree_niter_desc *niter) + class tree_niter_desc *niter) { tree cand_type, a, b, mbz, nit_type = TREE_TYPE (niter->niter), offset; - struct aff_tree nit, tmpa, tmpb; + class aff_tree nit, tmpa, tmpb; enum tree_code comp; HOST_WIDE_INT step; @@ -5094,9 +5094,9 @@ may_eliminate_iv (struct ivopts_data *data, basic_block ex_bb; edge exit; tree period; - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; aff_tree bnd; - struct tree_niter_desc *desc = NULL; + class tree_niter_desc *desc = NULL; if (TREE_CODE (cand->iv->step) != INTEGER_CST) return false; @@ -5704,7 +5704,7 @@ determine_set_costs (struct ivopts_data *data) gphi *phi; gphi_iterator psi; tree op; - struct loop *loop = data->current_loop; + class loop *loop = data->current_loop; bitmap_iterator bi; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -5761,7 +5761,7 @@ determine_set_costs (struct ivopts_data *data) /* Returns true if A is a cheaper cost pair than B. */ static bool -cheaper_cost_pair (struct cost_pair *a, struct cost_pair *b) +cheaper_cost_pair (class cost_pair *a, class cost_pair *b) { if (!a) return false; @@ -5786,7 +5786,7 @@ cheaper_cost_pair (struct cost_pair *a, struct cost_pair *b) for more expensive, equal and cheaper respectively. */ static int -compare_cost_pair (struct cost_pair *a, struct cost_pair *b) +compare_cost_pair (class cost_pair *a, class cost_pair *b) { if (cheaper_cost_pair (a, b)) return -1; @@ -5798,8 +5798,8 @@ compare_cost_pair (struct cost_pair *a, struct cost_pair *b) /* Returns candidate by that USE is expressed in IVS. */ -static struct cost_pair * -iv_ca_cand_for_group (struct iv_ca *ivs, struct iv_group *group) +static class cost_pair * +iv_ca_cand_for_group (class iv_ca *ivs, struct iv_group *group) { return ivs->cand_for_group[group->id]; } @@ -5807,7 +5807,7 @@ iv_ca_cand_for_group (struct iv_ca *ivs, struct iv_group *group) /* Computes the cost field of IVS structure. */ static void -iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs) +iv_ca_recount_cost (struct ivopts_data *data, class iv_ca *ivs) { comp_cost cost = ivs->cand_use_cost; @@ -5820,7 +5820,7 @@ iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs) and IVS. */ static void -iv_ca_set_remove_invs (struct iv_ca *ivs, bitmap invs, unsigned *n_inv_uses) +iv_ca_set_remove_invs (class iv_ca *ivs, bitmap invs, unsigned *n_inv_uses) { bitmap_iterator bi; unsigned iid; @@ -5840,11 +5840,11 @@ iv_ca_set_remove_invs (struct iv_ca *ivs, bitmap invs, unsigned *n_inv_uses) /* Set USE not to be expressed by any candidate in IVS. */ static void -iv_ca_set_no_cp (struct ivopts_data *data, struct iv_ca *ivs, +iv_ca_set_no_cp (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group) { unsigned gid = group->id, cid; - struct cost_pair *cp; + class cost_pair *cp; cp = ivs->cand_for_group[gid]; if (!cp) @@ -5874,7 +5874,7 @@ iv_ca_set_no_cp (struct ivopts_data *data, struct iv_ca *ivs, IVS. */ static void -iv_ca_set_add_invs (struct iv_ca *ivs, bitmap invs, unsigned *n_inv_uses) +iv_ca_set_add_invs (class iv_ca *ivs, bitmap invs, unsigned *n_inv_uses) { bitmap_iterator bi; unsigned iid; @@ -5894,8 +5894,8 @@ iv_ca_set_add_invs (struct iv_ca *ivs, bitmap invs, unsigned *n_inv_uses) /* Set cost pair for GROUP in set IVS to CP. */ static void -iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs, - struct iv_group *group, struct cost_pair *cp) +iv_ca_set_cp (struct ivopts_data *data, class iv_ca *ivs, + struct iv_group *group, class cost_pair *cp) { unsigned gid = group->id, cid; @@ -5933,10 +5933,10 @@ iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs, set IVS don't give any result. */ static void -iv_ca_add_group (struct ivopts_data *data, struct iv_ca *ivs, +iv_ca_add_group (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group) { - struct cost_pair *best_cp = NULL, *cp; + class cost_pair *best_cp = NULL, *cp; bitmap_iterator bi; unsigned i; struct iv_cand *cand; @@ -5970,7 +5970,7 @@ iv_ca_add_group (struct ivopts_data *data, struct iv_ca *ivs, /* Get cost for assignment IVS. */ static comp_cost -iv_ca_cost (struct iv_ca *ivs) +iv_ca_cost (class iv_ca *ivs) { /* This was a conditional expression but it triggered a bug in Sun C 5.5. */ @@ -5985,9 +5985,9 @@ iv_ca_cost (struct iv_ca *ivs) respectively. */ static int -iv_ca_compare_deps (struct ivopts_data *data, struct iv_ca *ivs, - struct iv_group *group, struct cost_pair *old_cp, - struct cost_pair *new_cp) +iv_ca_compare_deps (struct ivopts_data *data, class iv_ca *ivs, + struct iv_group *group, class cost_pair *old_cp, + class cost_pair *new_cp) { gcc_assert (old_cp && new_cp && old_cp != new_cp); unsigned old_n_invs = ivs->n_invs; @@ -6002,8 +6002,8 @@ iv_ca_compare_deps (struct ivopts_data *data, struct iv_ca *ivs, it before NEXT. */ static struct iv_ca_delta * -iv_ca_delta_add (struct iv_group *group, struct cost_pair *old_cp, - struct cost_pair *new_cp, struct iv_ca_delta *next) +iv_ca_delta_add (struct iv_group *group, class cost_pair *old_cp, + class cost_pair *new_cp, struct iv_ca_delta *next) { struct iv_ca_delta *change = XNEW (struct iv_ca_delta); @@ -6059,10 +6059,10 @@ iv_ca_delta_reverse (struct iv_ca_delta *delta) reverted instead. */ static void -iv_ca_delta_commit (struct ivopts_data *data, struct iv_ca *ivs, +iv_ca_delta_commit (struct ivopts_data *data, class iv_ca *ivs, struct iv_ca_delta *delta, bool forward) { - struct cost_pair *from, *to; + class cost_pair *from, *to; struct iv_ca_delta *act; if (!forward) @@ -6083,7 +6083,7 @@ iv_ca_delta_commit (struct ivopts_data *data, struct iv_ca *ivs, /* Returns true if CAND is used in IVS. */ static bool -iv_ca_cand_used_p (struct iv_ca *ivs, struct iv_cand *cand) +iv_ca_cand_used_p (class iv_ca *ivs, struct iv_cand *cand) { return ivs->n_cand_uses[cand->id] > 0; } @@ -6091,7 +6091,7 @@ iv_ca_cand_used_p (struct iv_ca *ivs, struct iv_cand *cand) /* Returns number of induction variable candidates in the set IVS. */ static unsigned -iv_ca_n_cands (struct iv_ca *ivs) +iv_ca_n_cands (class iv_ca *ivs) { return ivs->n_cands; } @@ -6114,14 +6114,14 @@ iv_ca_delta_free (struct iv_ca_delta **delta) /* Allocates new iv candidates assignment. */ -static struct iv_ca * +static class iv_ca * iv_ca_new (struct ivopts_data *data) { - struct iv_ca *nw = XNEW (struct iv_ca); + class iv_ca *nw = XNEW (class iv_ca); nw->upto = 0; nw->bad_groups = 0; - nw->cand_for_group = XCNEWVEC (struct cost_pair *, + nw->cand_for_group = XCNEWVEC (class cost_pair *, data->vgroups.length ()); nw->n_cand_uses = XCNEWVEC (unsigned, data->vcands.length ()); nw->cands = BITMAP_ALLOC (NULL); @@ -6139,7 +6139,7 @@ iv_ca_new (struct ivopts_data *data) /* Free memory occupied by the set IVS. */ static void -iv_ca_free (struct iv_ca **ivs) +iv_ca_free (class iv_ca **ivs) { free ((*ivs)->cand_for_group); free ((*ivs)->n_cand_uses); @@ -6153,7 +6153,7 @@ iv_ca_free (struct iv_ca **ivs) /* Dumps IVS to FILE. */ static void -iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs) +iv_ca_dump (struct ivopts_data *data, FILE *file, class iv_ca *ivs) { unsigned i; comp_cost cost = iv_ca_cost (ivs); @@ -6168,7 +6168,7 @@ iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs) for (i = 0; i < ivs->upto; i++) { struct iv_group *group = data->vgroups[i]; - struct cost_pair *cp = iv_ca_cand_for_group (ivs, group); + class cost_pair *cp = iv_ca_cand_for_group (ivs, group); if (cp) fprintf (file, " group:%d --> iv_cand:%d, cost=(" "%" PRId64 ",%d)\n", group->id, cp->cand->id, @@ -6204,14 +6204,14 @@ iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs) the function will try to find a solution with mimimal iv candidates. */ static comp_cost -iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs, +iv_ca_extend (struct ivopts_data *data, class iv_ca *ivs, struct iv_cand *cand, struct iv_ca_delta **delta, unsigned *n_ivs, bool min_ncand) { unsigned i; comp_cost cost; struct iv_group *group; - struct cost_pair *old_cp, *new_cp; + class cost_pair *old_cp, *new_cp; *delta = NULL; for (i = 0; i < ivs->upto; i++) @@ -6257,13 +6257,13 @@ iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs, the candidate with which we start narrowing. */ static comp_cost -iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs, +iv_ca_narrow (struct ivopts_data *data, class iv_ca *ivs, struct iv_cand *cand, struct iv_cand *start, struct iv_ca_delta **delta) { unsigned i, ci; struct iv_group *group; - struct cost_pair *old_cp, *new_cp, *cp; + class cost_pair *old_cp, *new_cp, *cp; bitmap_iterator bi; struct iv_cand *cnd; comp_cost cost, best_cost, acost; @@ -6351,7 +6351,7 @@ iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs, differences in DELTA. */ static comp_cost -iv_ca_prune (struct ivopts_data *data, struct iv_ca *ivs, +iv_ca_prune (struct ivopts_data *data, class iv_ca *ivs, struct iv_cand *except_cand, struct iv_ca_delta **delta) { bitmap_iterator bi; @@ -6400,13 +6400,13 @@ iv_ca_prune (struct ivopts_data *data, struct iv_ca *ivs, cheaper local cost for GROUP than BEST_CP. Return pointer to the corresponding cost_pair, otherwise just return BEST_CP. */ -static struct cost_pair* +static class cost_pair* cheaper_cost_with_cand (struct ivopts_data *data, struct iv_group *group, unsigned int cand_idx, struct iv_cand *old_cand, - struct cost_pair *best_cp) + class cost_pair *best_cp) { struct iv_cand *cand; - struct cost_pair *cp; + class cost_pair *cp; gcc_assert (old_cand != NULL && best_cp != NULL); if (cand_idx == old_cand->id) @@ -6428,7 +6428,7 @@ cheaper_cost_with_cand (struct ivopts_data *data, struct iv_group *group, candidate replacement in list DELTA. */ static comp_cost -iv_ca_replace (struct ivopts_data *data, struct iv_ca *ivs, +iv_ca_replace (struct ivopts_data *data, class iv_ca *ivs, struct iv_ca_delta **delta) { bitmap_iterator bi, bj; @@ -6436,7 +6436,7 @@ iv_ca_replace (struct ivopts_data *data, struct iv_ca *ivs, struct iv_cand *cand; comp_cost orig_cost, acost; struct iv_ca_delta *act_delta, *tmp_delta; - struct cost_pair *old_cp, *best_cp = NULL; + class cost_pair *old_cp, *best_cp = NULL; *delta = NULL; orig_cost = iv_ca_cost (ivs); @@ -6503,7 +6503,7 @@ iv_ca_replace (struct ivopts_data *data, struct iv_ca *ivs, based on any memory object. */ static bool -try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs, +try_add_cand_for (struct ivopts_data *data, class iv_ca *ivs, struct iv_group *group, bool originalp) { comp_cost best_cost, act_cost; @@ -6511,7 +6511,7 @@ try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs, bitmap_iterator bi; struct iv_cand *cand; struct iv_ca_delta *best_delta = NULL, *act_delta; - struct cost_pair *cp; + class cost_pair *cp; iv_ca_add_group (data, ivs, group); best_cost = iv_ca_cost (ivs); @@ -6615,11 +6615,11 @@ try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs, /* Finds an initial assignment of candidates to uses. */ -static struct iv_ca * +static class iv_ca * get_initial_solution (struct ivopts_data *data, bool originalp) { unsigned i; - struct iv_ca *ivs = iv_ca_new (data); + class iv_ca *ivs = iv_ca_new (data); for (i = 0; i < data->vgroups.length (); i++) if (!try_add_cand_for (data, ivs, data->vgroups[i], originalp)) @@ -6637,7 +6637,7 @@ get_initial_solution (struct ivopts_data *data, bool originalp) static bool try_improve_iv_set (struct ivopts_data *data, - struct iv_ca *ivs, bool *try_replace_p) + class iv_ca *ivs, bool *try_replace_p) { unsigned i, n_ivs; comp_cost acost, best_cost = iv_ca_cost (ivs); @@ -6708,10 +6708,10 @@ try_improve_iv_set (struct ivopts_data *data, greedy heuristic -- we try to replace at most one candidate in the selected solution and remove the unused ivs while this improves the cost. */ -static struct iv_ca * +static class iv_ca * find_optimal_iv_set_1 (struct ivopts_data *data, bool originalp) { - struct iv_ca *set; + class iv_ca *set; bool try_replace_p = true; /* Get the initial solution. */ @@ -6749,12 +6749,12 @@ find_optimal_iv_set_1 (struct ivopts_data *data, bool originalp) return set; } -static struct iv_ca * +static class iv_ca * find_optimal_iv_set (struct ivopts_data *data) { unsigned i; comp_cost cost, origcost; - struct iv_ca *set, *origset; + class iv_ca *set, *origset; /* Determine the cost based on a strategy that starts with original IVs, and try again using a strategy that prefers candidates not based @@ -6850,7 +6850,7 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand) /* Creates new induction variables described in SET. */ static void -create_new_ivs (struct ivopts_data *data, struct iv_ca *set) +create_new_ivs (struct ivopts_data *data, class iv_ca *set) { unsigned i; struct iv_cand *cand; @@ -7204,7 +7204,7 @@ rewrite_use_compare (struct ivopts_data *data, gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt); enum tree_code compare; struct iv_group *group = data->vgroups[use->group_id]; - struct cost_pair *cp = get_group_iv_cost (data, group, cand); + class cost_pair *cp = get_group_iv_cost (data, group, cand); bound = cp->value; if (bound) @@ -7416,7 +7416,7 @@ remove_unused_ivs (struct ivopts_data *data, bitmap toremove) } } -/* Frees memory occupied by struct tree_niter_desc in *VALUE. Callback +/* Frees memory occupied by class tree_niter_desc in *VALUE. Callback for hash_map::traverse. */ bool @@ -7599,11 +7599,11 @@ determine_scaling_factor (struct ivopts_data *data, basic_block *body) /* Optimizes the LOOP. Returns true if anything changed. */ static bool -tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop, +tree_ssa_iv_optimize_loop (struct ivopts_data *data, class loop *loop, bitmap toremove) { bool changed = false; - struct iv_ca *iv_ca; + class iv_ca *iv_ca; edge exit = single_dom_exit (loop); basic_block *body; @@ -7689,7 +7689,7 @@ finish: void tree_ssa_iv_optimize (void) { - struct loop *loop; + class loop *loop; struct ivopts_data data; auto_bitmap toremove; diff --git a/gcc/tree-ssa-loop-ivopts.h b/gcc/tree-ssa-loop-ivopts.h index 6f21e63..1ad4a77 100644 --- a/gcc/tree-ssa-loop-ivopts.h +++ b/gcc/tree-ssa-loop-ivopts.h @@ -20,18 +20,18 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_SSA_LOOP_IVOPTS_H #define GCC_TREE_SSA_LOOP_IVOPTS_H -extern edge single_dom_exit (struct loop *); +extern edge single_dom_exit (class loop *); extern void dump_iv (FILE *, struct iv *); extern void dump_use (FILE *, struct iv_use *); extern void dump_uses (FILE *, struct ivopts_data *); extern void dump_cand (FILE *, struct iv_cand *); extern bool contains_abnormal_ssa_name_p (tree); -extern struct loop *outermost_invariant_loop_for_expr (struct loop *, tree); -extern bool expr_invariant_in_loop_p (struct loop *, tree); +extern class loop *outermost_invariant_loop_for_expr (class loop *, tree); +extern bool expr_invariant_in_loop_p (class loop *, tree); extern tree strip_offset (tree, poly_uint64_pod *); bool may_be_nonaddressable_p (tree expr); void tree_ssa_iv_optimize (void); -void create_canonical_iv (struct loop *, edge, tree, +void create_canonical_iv (class loop *, edge, tree, tree * = NULL, tree * = NULL); #endif /* GCC_TREE_SSA_LOOP_IVOPTS_H */ diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index ecbe212..6a1bbaa 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -58,7 +58,7 @@ static bitmap_obstack loop_renamer_obstack; VAR_AFTER (unless they are NULL). */ void -create_iv (tree base, tree step, tree var, struct loop *loop, +create_iv (tree base, tree step, tree var, class loop *loop, gimple_stmt_iterator *incr_pos, bool after, tree *var_before, tree *var_after) { @@ -156,8 +156,8 @@ create_iv (tree base, tree step, tree var, struct loop *loop, /* Return the innermost superloop LOOP of USE_LOOP that is a superloop of both DEF_LOOP and USE_LOOP. */ -static inline struct loop * -find_sibling_superloop (struct loop *use_loop, struct loop *def_loop) +static inline class loop * +find_sibling_superloop (class loop *use_loop, class loop *def_loop) { unsigned ud = loop_depth (use_loop); unsigned dd = loop_depth (def_loop); @@ -196,7 +196,7 @@ compute_live_loop_exits (bitmap live_exits, bitmap use_blocks, { unsigned i; bitmap_iterator bi; - struct loop *def_loop = def_bb->loop_father; + class loop *def_loop = def_bb->loop_father; unsigned def_loop_depth = loop_depth (def_loop); bitmap def_loop_exits; @@ -208,7 +208,7 @@ compute_live_loop_exits (bitmap live_exits, bitmap use_blocks, EXECUTE_IF_SET_IN_BITMAP (use_blocks, 0, i, bi) { basic_block use_bb = BASIC_BLOCK_FOR_FN (cfun, i); - struct loop *use_loop = use_bb->loop_father; + class loop *use_loop = use_bb->loop_father; gcc_checking_assert (def_loop != use_loop && ! flow_loop_nested_p (def_loop, use_loop)); if (! flow_loop_nested_p (use_loop, def_loop)) @@ -234,7 +234,7 @@ compute_live_loop_exits (bitmap live_exits, bitmap use_blocks, FOR_EACH_EDGE (e, ei, bb->preds) { basic_block pred = e->src; - struct loop *pred_loop = pred->loop_father; + class loop *pred_loop = pred->loop_father; unsigned pred_loop_depth = loop_depth (pred_loop); bool pred_visited; @@ -268,7 +268,7 @@ compute_live_loop_exits (bitmap live_exits, bitmap use_blocks, } def_loop_exits = BITMAP_ALLOC (&loop_renamer_obstack); - for (struct loop *loop = def_loop; + for (class loop *loop = def_loop; loop != current_loops->tree_root; loop = loop_outer (loop)) bitmap_ior_into (def_loop_exits, loop_exits[loop->num]); @@ -293,7 +293,7 @@ add_exit_phi (basic_block exit, tree var) basic_block def_bb = gimple_bb (def_stmt); FOR_EACH_EDGE (e, ei, exit->preds) { - struct loop *aloop = find_common_loop (def_bb->loop_father, + class loop *aloop = find_common_loop (def_bb->loop_father, e->src->loop_father); if (!flow_bb_inside_loop_p (aloop, e->dest)) break; @@ -357,7 +357,7 @@ add_exit_phis (bitmap names_to_rename, bitmap *use_blocks, bitmap *loop_exits) static void get_loops_exits (bitmap *loop_exits) { - struct loop *loop; + class loop *loop; unsigned j; edge e; @@ -383,7 +383,7 @@ find_uses_to_rename_use (basic_block bb, tree use, bitmap *use_blocks, { unsigned ver; basic_block def_bb; - struct loop *def_loop; + class loop *def_loop; if (TREE_CODE (use) != SSA_NAME) return; @@ -532,7 +532,7 @@ find_uses_to_rename_def (tree def, bitmap *use_blocks, bitmap need_phis) USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */ static void -find_uses_to_rename_in_loop (struct loop *loop, bitmap *use_blocks, +find_uses_to_rename_in_loop (class loop *loop, bitmap *use_blocks, bitmap need_phis, int use_flags) { bool do_virtuals = (use_flags & SSA_OP_VIRTUAL_USES) != 0; @@ -624,7 +624,7 @@ find_uses_to_rename_in_loop (struct loop *loop, bitmap *use_blocks, void rewrite_into_loop_closed_ssa_1 (bitmap changed_bbs, unsigned update_flag, - int use_flags, struct loop *loop) + int use_flags, class loop *loop) { bitmap *use_blocks; bitmap names_to_rename; @@ -698,7 +698,7 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) form. */ void -rewrite_virtuals_into_loop_closed_ssa (struct loop *loop) +rewrite_virtuals_into_loop_closed_ssa (class loop *loop) { rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_VIRTUAL_USES, loop); } @@ -754,7 +754,7 @@ check_loop_closed_ssa_bb (basic_block bb) if LOOP is NULL, otherwise, only LOOP is checked. */ DEBUG_FUNCTION void -verify_loop_closed_ssa (bool verify_ssa_p, struct loop *loop) +verify_loop_closed_ssa (bool verify_ssa_p, class loop *loop) { if (number_of_loops (cfun) <= 1) return; @@ -830,7 +830,7 @@ split_loop_exit_edge (edge exit, bool copy_constants_p) variables incremented at the end of the LOOP. */ basic_block -ip_end_pos (struct loop *loop) +ip_end_pos (class loop *loop) { return loop->latch; } @@ -839,7 +839,7 @@ ip_end_pos (struct loop *loop) variables incremented just before exit condition of a LOOP. */ basic_block -ip_normal_pos (struct loop *loop) +ip_normal_pos (class loop *loop) { gimple *last; basic_block bb; @@ -870,7 +870,7 @@ ip_normal_pos (struct loop *loop) the increment should be inserted after *BSI. */ void -standard_iv_increment_position (struct loop *loop, gimple_stmt_iterator *bsi, +standard_iv_increment_position (class loop *loop, gimple_stmt_iterator *bsi, bool *insert_after) { basic_block bb = ip_normal_pos (loop), latch = ip_end_pos (loop); @@ -918,7 +918,7 @@ copy_phi_node_args (unsigned first_new_block) after the loop has been duplicated. */ bool -gimple_duplicate_loop_to_header_edge (struct loop *loop, edge e, +gimple_duplicate_loop_to_header_edge (class loop *loop, edge e, unsigned int ndupl, sbitmap wont_exit, edge orig, vec *to_remove, int flags) @@ -950,8 +950,8 @@ gimple_duplicate_loop_to_header_edge (struct loop *loop, edge e, of iterations of the loop is returned in NITER. */ bool -can_unroll_loop_p (struct loop *loop, unsigned factor, - struct tree_niter_desc *niter) +can_unroll_loop_p (class loop *loop, unsigned factor, + class tree_niter_desc *niter) { edge exit; @@ -997,7 +997,7 @@ can_unroll_loop_p (struct loop *loop, unsigned factor, how the exit from the unrolled loop should be controlled. */ static void -determine_exit_conditions (struct loop *loop, struct tree_niter_desc *desc, +determine_exit_conditions (class loop *loop, class tree_niter_desc *desc, unsigned factor, tree *enter_cond, tree *exit_base, tree *exit_step, enum tree_code *exit_cmp, tree *exit_bound) @@ -1106,7 +1106,7 @@ determine_exit_conditions (struct loop *loop, struct tree_niter_desc *desc, dominated by BB by NUM/DEN. */ static void -scale_dominated_blocks_in_loop (struct loop *loop, basic_block bb, +scale_dominated_blocks_in_loop (class loop *loop, basic_block bb, profile_count num, profile_count den) { basic_block son; @@ -1128,7 +1128,7 @@ scale_dominated_blocks_in_loop (struct loop *loop, basic_block bb, /* Return estimated niter for LOOP after unrolling by FACTOR times. */ gcov_type -niter_for_unrolled_loop (struct loop *loop, unsigned factor) +niter_for_unrolled_loop (class loop *loop, unsigned factor) { gcc_assert (factor != 0); bool profile_p = false; @@ -1225,8 +1225,8 @@ niter_for_unrolled_loop (struct loop *loop, unsigned factor) #define PROB_UNROLLED_LOOP_ENTERED 90 void -tree_transform_and_unroll_loop (struct loop *loop, unsigned factor, - edge exit, struct tree_niter_desc *desc, +tree_transform_and_unroll_loop (class loop *loop, unsigned factor, + edge exit, class tree_niter_desc *desc, transform_callback transform, void *data) { @@ -1237,7 +1237,7 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor, gphi *phi_old_loop, *phi_new_loop, *phi_rest; gphi_iterator psi_old_loop, psi_new_loop; tree init, next, new_init; - struct loop *new_loop; + class loop *new_loop; basic_block rest, exit_bb; edge old_entry, new_entry, old_latch, precond_edge, new_exit; edge new_nonexit, e; @@ -1435,8 +1435,8 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor, of the arguments is the same as for tree_transform_and_unroll_loop. */ void -tree_unroll_loop (struct loop *loop, unsigned factor, - edge exit, struct tree_niter_desc *desc) +tree_unroll_loop (class loop *loop, unsigned factor, + edge exit, class tree_niter_desc *desc) { tree_transform_and_unroll_loop (loop, factor, exit, desc, NULL, NULL); @@ -1518,7 +1518,7 @@ rewrite_all_phi_nodes_with_iv (loop_p loop, tree main_iv) created. */ tree -canonicalize_loop_ivs (struct loop *loop, tree *nit, bool bump_in_latch) +canonicalize_loop_ivs (class loop *loop, tree *nit, bool bump_in_latch) { unsigned precision = TYPE_PRECISION (TREE_TYPE (*nit)); unsigned original_precision = precision; diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h index 0020659..8263a67 100644 --- a/gcc/tree-ssa-loop-manip.h +++ b/gcc/tree-ssa-loop-manip.h @@ -20,41 +20,41 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_SSA_LOOP_MANIP_H #define GCC_TREE_SSA_LOOP_MANIP_H -typedef void (*transform_callback)(struct loop *, void *); +typedef void (*transform_callback)(class loop *, void *); -extern void create_iv (tree, tree, tree, struct loop *, gimple_stmt_iterator *, +extern void create_iv (tree, tree, tree, class loop *, gimple_stmt_iterator *, bool, tree *, tree *); extern void rewrite_into_loop_closed_ssa_1 (bitmap, unsigned, int, - struct loop *); + class loop *); extern void rewrite_into_loop_closed_ssa (bitmap, unsigned); -extern void rewrite_virtuals_into_loop_closed_ssa (struct loop *); -extern void verify_loop_closed_ssa (bool, struct loop * = NULL); +extern void rewrite_virtuals_into_loop_closed_ssa (class loop *); +extern void verify_loop_closed_ssa (bool, class loop * = NULL); static inline void -checking_verify_loop_closed_ssa (bool verify_ssa_p, struct loop *loop = NULL) +checking_verify_loop_closed_ssa (bool verify_ssa_p, class loop *loop = NULL) { if (flag_checking) verify_loop_closed_ssa (verify_ssa_p, loop); } extern basic_block split_loop_exit_edge (edge, bool = false); -extern basic_block ip_end_pos (struct loop *); -extern basic_block ip_normal_pos (struct loop *); -extern void standard_iv_increment_position (struct loop *, +extern basic_block ip_end_pos (class loop *); +extern basic_block ip_normal_pos (class loop *); +extern void standard_iv_increment_position (class loop *, gimple_stmt_iterator *, bool *); -extern bool gimple_duplicate_loop_to_header_edge (struct loop *, edge, +extern bool gimple_duplicate_loop_to_header_edge (class loop *, edge, unsigned int, sbitmap, edge, vec *, int); -extern bool can_unroll_loop_p (struct loop *loop, unsigned factor, - struct tree_niter_desc *niter); -extern gcov_type niter_for_unrolled_loop (struct loop *, unsigned); -extern void tree_transform_and_unroll_loop (struct loop *, unsigned, - edge, struct tree_niter_desc *, +extern bool can_unroll_loop_p (class loop *loop, unsigned factor, + class tree_niter_desc *niter); +extern gcov_type niter_for_unrolled_loop (class loop *, unsigned); +extern void tree_transform_and_unroll_loop (class loop *, unsigned, + edge, class tree_niter_desc *, transform_callback, void *); -extern void tree_unroll_loop (struct loop *, unsigned, - edge, struct tree_niter_desc *); -extern tree canonicalize_loop_ivs (struct loop *, tree *, bool); +extern void tree_unroll_loop (class loop *, unsigned, + edge, class tree_niter_desc *); +extern tree canonicalize_loop_ivs (class loop *, tree *, bool); diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 5e75a41..cd2ced3 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -65,7 +65,7 @@ struct bounds static bool number_of_iterations_popcount (loop_p loop, edge exit, enum tree_code code, - struct tree_niter_desc *niter); + class tree_niter_desc *niter); /* Splits expression EXPR to a variable part VAR and constant OFFSET. */ @@ -346,7 +346,7 @@ end: in TYPE to MIN and MAX. */ static void -determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, +determine_value_range (class loop *loop, tree type, tree var, mpz_t off, mpz_t min, mpz_t max) { int cnt = 0; @@ -704,7 +704,7 @@ end: comparisons before the loop (usually created by loop header copying). */ static void -bound_difference (struct loop *loop, tree x, tree y, bounds *bnds) +bound_difference (class loop *loop, tree x, tree y, bounds *bnds) { tree type = TREE_TYPE (x); tree varx, vary; @@ -964,8 +964,8 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s, bounds on the difference FINAL - IV->base. */ static bool -number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv, - tree final, struct tree_niter_desc *niter, +number_of_iterations_ne (class loop *loop, tree type, affine_iv *iv, + tree final, class tree_niter_desc *niter, bool exit_must_be_taken, bounds *bnds) { tree niter_type = unsigned_type_for (type); @@ -1149,7 +1149,7 @@ number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv, static bool number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, - struct tree_niter_desc *niter, + class tree_niter_desc *niter, tree *delta, tree step, bool exit_must_be_taken, bounds *bnds) { @@ -1268,7 +1268,7 @@ end: static bool assert_no_overflow_lt (tree type, affine_iv *iv0, affine_iv *iv1, - struct tree_niter_desc *niter, tree step) + class tree_niter_desc *niter, tree step) { tree bound, d, assumption, diff; tree niter_type = TREE_TYPE (step); @@ -1337,7 +1337,7 @@ assert_no_overflow_lt (tree type, affine_iv *iv0, affine_iv *iv1, static void assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1, - struct tree_niter_desc *niter, bounds *bnds) + class tree_niter_desc *niter, bounds *bnds) { tree assumption = boolean_true_node, bound, diff; tree mbz, mbzl, mbzr, type1; @@ -1463,8 +1463,8 @@ assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1, that the exit must be taken eventually. */ static bool -number_of_iterations_lt (struct loop *loop, tree type, affine_iv *iv0, - affine_iv *iv1, struct tree_niter_desc *niter, +number_of_iterations_lt (class loop *loop, tree type, affine_iv *iv0, + affine_iv *iv1, class tree_niter_desc *niter, bool exit_must_be_taken, bounds *bnds) { tree niter_type = unsigned_type_for (type); @@ -1576,8 +1576,8 @@ number_of_iterations_lt (struct loop *loop, tree type, affine_iv *iv0, is the case). BNDS bounds the difference IV1->base - IV0->base. */ static bool -number_of_iterations_le (struct loop *loop, tree type, affine_iv *iv0, - affine_iv *iv1, struct tree_niter_desc *niter, +number_of_iterations_le (class loop *loop, tree type, affine_iv *iv0, + affine_iv *iv1, class tree_niter_desc *niter, bool exit_must_be_taken, bounds *bnds) { tree assumption; @@ -1721,14 +1721,14 @@ adjust_cond_for_loop_until_wrap (tree type, affine_iv *iv0, tree_code *code, if EVERY_ITERATION is true, we know the test is executed on every iteration. The results (number of iterations and assumptions as described in - comments at struct tree_niter_desc in tree-ssa-loop.h) are stored to NITER. + comments at class tree_niter_desc in tree-ssa-loop.h) are stored to NITER. Returns false if it fails to determine number of iterations, true if it was determined (possibly with some assumptions). */ static bool -number_of_iterations_cond (struct loop *loop, +number_of_iterations_cond (class loop *loop, tree type, affine_iv *iv0, enum tree_code code, - affine_iv *iv1, struct tree_niter_desc *niter, + affine_iv *iv1, class tree_niter_desc *niter, bool only_exit, bool every_iteration) { bool exit_must_be_taken = false, ret; @@ -2263,7 +2263,7 @@ tree_simplify_using_condition (tree cond, tree expr) simplification was possible). */ tree -simplify_using_initial_conditions (struct loop *loop, tree expr) +simplify_using_initial_conditions (class loop *loop, tree expr) { edge e; basic_block bb; @@ -2315,7 +2315,7 @@ simplify_using_initial_conditions (struct loop *loop, tree expr) (or EXPR unchanged, if no simplification was possible). */ static tree -simplify_using_outer_evolutions (struct loop *loop, tree expr) +simplify_using_outer_evolutions (class loop *loop, tree expr) { enum tree_code code = TREE_CODE (expr); bool changed; @@ -2368,7 +2368,7 @@ simplify_using_outer_evolutions (struct loop *loop, tree expr) /* Returns true if EXIT is the only possible exit from LOOP. */ bool -loop_only_exit_p (const struct loop *loop, const_edge exit) +loop_only_exit_p (const class loop *loop, const_edge exit) { basic_block *body; gimple_stmt_iterator bsi; @@ -2395,15 +2395,15 @@ loop_only_exit_p (const struct loop *loop, const_edge exit) /* Stores description of number of iterations of LOOP derived from EXIT (an exit edge of the LOOP) in NITER. Returns true if some useful information could be derived (and fields of NITER have meaning described - in comments at struct tree_niter_desc declaration), false otherwise. + in comments at class tree_niter_desc declaration), false otherwise. When EVERY_ITERATION is true, only tests that are known to be executed every iteration are considered (i.e. only test that alone bounds the loop). If AT_STMT is not NULL, this function stores LOOP's condition statement in it when returning true. */ bool -number_of_iterations_exit_assumptions (struct loop *loop, edge exit, - struct tree_niter_desc *niter, +number_of_iterations_exit_assumptions (class loop *loop, edge exit, + class tree_niter_desc *niter, gcond **at_stmt, bool every_iteration) { gimple *last; @@ -2598,7 +2598,7 @@ ssa_defined_by_minus_one_stmt_p (tree op, tree val) static bool number_of_iterations_popcount (loop_p loop, edge exit, enum tree_code code, - struct tree_niter_desc *niter) + class tree_niter_desc *niter) { bool adjust = true; tree iter; @@ -2720,8 +2720,8 @@ number_of_iterations_popcount (loop_p loop, edge exit, the niter information holds unconditionally. */ bool -number_of_iterations_exit (struct loop *loop, edge exit, - struct tree_niter_desc *niter, +number_of_iterations_exit (class loop *loop, edge exit, + class tree_niter_desc *niter, bool warn, bool every_iteration) { gcond *stmt; @@ -2746,13 +2746,13 @@ number_of_iterations_exit (struct loop *loop, edge exit, chrec_dont_know is returned. */ tree -find_loop_niter (struct loop *loop, edge *exit) +find_loop_niter (class loop *loop, edge *exit) { unsigned i; vec exits = get_loop_exit_edges (loop); edge ex; tree niter = NULL_TREE, aniter; - struct tree_niter_desc desc; + class tree_niter_desc desc; *exit = NULL; FOR_EACH_VEC_ELT (exits, i, ex) @@ -2808,7 +2808,7 @@ find_loop_niter (struct loop *loop, edge *exit) /* Return true if loop is known to have bounded number of iterations. */ bool -finite_loop_p (struct loop *loop) +finite_loop_p (class loop *loop) { widest_int nit; int flags; @@ -2870,7 +2870,7 @@ finite_loop_p (struct loop *loop) operands are constants. */ static gphi * -chain_of_csts_start (struct loop *loop, tree x) +chain_of_csts_start (class loop *loop, tree x) { gimple *stmt = SSA_NAME_DEF_STMT (x); tree use; @@ -2919,7 +2919,7 @@ chain_of_csts_start (struct loop *loop, tree x) If such phi node exists, it is returned, otherwise NULL is returned. */ static gphi * -get_base_for (struct loop *loop, tree x) +get_base_for (class loop *loop, tree x) { gphi *phi; tree init, next; @@ -3007,7 +3007,7 @@ get_val_for (tree x, tree base) of the iterations of LOOP if successful, chrec_dont_know otherwise. */ tree -loop_niter_by_eval (struct loop *loop, edge exit) +loop_niter_by_eval (class loop *loop, edge exit) { tree acnd; tree op[2], val[2], next[2], aval[2]; @@ -3108,7 +3108,7 @@ loop_niter_by_eval (struct loop *loop, edge exit) determines the number of iterations, chrec_dont_know is returned. */ tree -find_loop_niter_by_eval (struct loop *loop, edge *exit) +find_loop_niter_by_eval (class loop *loop, edge *exit) { unsigned i; vec exits = get_loop_exit_edges (loop); @@ -3325,7 +3325,7 @@ derive_constant_upper_bound_ops (tree type, tree op0, /* Emit a -Waggressive-loop-optimizations warning if needed. */ static void -do_warn_aggressive_loop_optimizations (struct loop *loop, +do_warn_aggressive_loop_optimizations (class loop *loop, widest_int i_bound, gimple *stmt) { /* Don't warn if the loop doesn't have known constant bound. */ @@ -3367,7 +3367,7 @@ do_warn_aggressive_loop_optimizations (struct loop *loop, BOUND times. I_BOUND is a widest_int upper estimate on BOUND. */ static void -record_estimate (struct loop *loop, tree bound, const widest_int &i_bound, +record_estimate (class loop *loop, tree bound, const widest_int &i_bound, gimple *at_stmt, bool is_exit, bool realistic, bool upper) { widest_int delta; @@ -3399,7 +3399,7 @@ record_estimate (struct loop *loop, tree bound, const widest_int &i_bound, || loop->nb_iterations == NULL_TREE || TREE_CODE (loop->nb_iterations) != INTEGER_CST)) { - struct nb_iter_bound *elt = ggc_alloc (); + class nb_iter_bound *elt = ggc_alloc (); elt->bound = i_bound; elt->stmt = at_stmt; @@ -3436,7 +3436,7 @@ record_estimate (struct loop *loop, tree bound, const widest_int &i_bound, and doesn't overflow. */ static void -record_control_iv (struct loop *loop, struct tree_niter_desc *niter) +record_control_iv (class loop *loop, class tree_niter_desc *niter) { struct control_iv *iv; @@ -3470,7 +3470,7 @@ get_cst_init_from_scev (tree var, wide_int *init, bool is_min) return false; gimple *def_stmt = SSA_NAME_DEF_STMT (var); - struct loop *loop = loop_containing_stmt (def_stmt); + class loop *loop = loop_containing_stmt (def_stmt); if (loop == NULL) return false; @@ -3499,7 +3499,7 @@ get_cst_init_from_scev (tree var, wide_int *init, bool is_min) UPPER is true if we are sure the induction variable does not wrap. */ static void -record_nonwrapping_iv (struct loop *loop, tree base, tree step, gimple *stmt, +record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt, tree low, tree high, bool realistic, bool upper) { tree niter_bound, extreme, delta; @@ -3576,7 +3576,7 @@ record_nonwrapping_iv (struct loop *loop, tree base, tree step, gimple *stmt, struct ilb_data { - struct loop *loop; + class loop *loop; gimple *stmt; }; @@ -3587,7 +3587,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta) tree ev, init, step; tree low, high, type, next; bool sign, upper = true, at_end = false; - struct loop *loop = data->loop; + class loop *loop = data->loop; if (TREE_CODE (base) != ARRAY_REF) return true; @@ -3601,7 +3601,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta) upper = false; } - struct loop *dloop = loop_containing_stmt (data->stmt); + class loop *dloop = loop_containing_stmt (data->stmt); if (!dloop) return true; @@ -3676,7 +3676,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta) STMT is guaranteed to be executed in every iteration of LOOP.*/ static void -infer_loop_bounds_from_ref (struct loop *loop, gimple *stmt, tree ref) +infer_loop_bounds_from_ref (class loop *loop, gimple *stmt, tree ref) { struct ilb_data data; @@ -3690,7 +3690,7 @@ infer_loop_bounds_from_ref (struct loop *loop, gimple *stmt, tree ref) executed in every iteration of LOOP. */ static void -infer_loop_bounds_from_array (struct loop *loop, gimple *stmt) +infer_loop_bounds_from_array (class loop *loop, gimple *stmt) { if (is_gimple_assign (stmt)) { @@ -3727,7 +3727,7 @@ infer_loop_bounds_from_array (struct loop *loop, gimple *stmt) that pointer arithmetics in STMT does not overflow. */ static void -infer_loop_bounds_from_pointer_arith (struct loop *loop, gimple *stmt) +infer_loop_bounds_from_pointer_arith (class loop *loop, gimple *stmt) { tree def, base, step, scev, type, low, high; tree var, ptr; @@ -3752,7 +3752,7 @@ infer_loop_bounds_from_pointer_arith (struct loop *loop, gimple *stmt) if (TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (var))) return; - struct loop *uloop = loop_containing_stmt (stmt); + class loop *uloop = loop_containing_stmt (stmt); scev = instantiate_parameters (loop, analyze_scalar_evolution (uloop, def)); if (chrec_contains_undetermined (scev)) return; @@ -3786,7 +3786,7 @@ infer_loop_bounds_from_pointer_arith (struct loop *loop, gimple *stmt) that signed arithmetics in STMT does not overflow. */ static void -infer_loop_bounds_from_signedness (struct loop *loop, gimple *stmt) +infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt) { tree def, base, step, scev, type, low, high; @@ -3838,7 +3838,7 @@ infer_loop_bounds_from_signedness (struct loop *loop, gimple *stmt) */ static void -infer_loop_bounds_from_undefined (struct loop *loop) +infer_loop_bounds_from_undefined (class loop *loop) { unsigned i; basic_block *bbs; @@ -3918,9 +3918,9 @@ bound_index (vec bounds, const widest_int &bound) some bounded statement. */ static void -discover_iteration_bound_by_body_walk (struct loop *loop) +discover_iteration_bound_by_body_walk (class loop *loop) { - struct nb_iter_bound *elt; + class nb_iter_bound *elt; auto_vec bounds; vec > queues = vNULL; vec queue = vNULL; @@ -4083,10 +4083,10 @@ discover_iteration_bound_by_body_walk (struct loop *loop) count by 1. */ static void -maybe_lower_iteration_bound (struct loop *loop) +maybe_lower_iteration_bound (class loop *loop) { hash_set *not_executed_last_iteration = NULL; - struct nb_iter_bound *elt; + class nb_iter_bound *elt; bool found_exit = false; auto_vec queue; bitmap visited; @@ -4236,12 +4236,12 @@ get_upper_bound_based_on_builtin_expr_with_prob (gcond *cond) is true also use estimates derived from undefined behavior. */ void -estimate_numbers_of_iterations (struct loop *loop) +estimate_numbers_of_iterations (class loop *loop) { vec exits; tree niter, type; unsigned i; - struct tree_niter_desc niter_desc; + class tree_niter_desc niter_desc; edge ex; widest_int bound; edge likely_exit; @@ -4337,7 +4337,7 @@ estimate_numbers_of_iterations (struct loop *loop) the function returns false, otherwise returns true. */ bool -estimated_loop_iterations (struct loop *loop, widest_int *nit) +estimated_loop_iterations (class loop *loop, widest_int *nit) { /* When SCEV information is available, try to update loop iterations estimate. Otherwise just return whatever we recorded earlier. */ @@ -4352,7 +4352,7 @@ estimated_loop_iterations (struct loop *loop, widest_int *nit) on the number of iterations of LOOP could not be derived, returns -1. */ HOST_WIDE_INT -estimated_loop_iterations_int (struct loop *loop) +estimated_loop_iterations_int (class loop *loop) { widest_int nit; HOST_WIDE_INT hwi_nit; @@ -4373,7 +4373,7 @@ estimated_loop_iterations_int (struct loop *loop) false, otherwise returns true. */ bool -max_loop_iterations (struct loop *loop, widest_int *nit) +max_loop_iterations (class loop *loop, widest_int *nit) { /* When SCEV information is available, try to update loop iterations estimate. Otherwise just return whatever we recorded earlier. */ @@ -4388,7 +4388,7 @@ max_loop_iterations (struct loop *loop, widest_int *nit) on the number of iterations of LOOP could not be derived, returns -1. */ HOST_WIDE_INT -max_loop_iterations_int (struct loop *loop) +max_loop_iterations_int (class loop *loop) { widest_int nit; HOST_WIDE_INT hwi_nit; @@ -4408,7 +4408,7 @@ max_loop_iterations_int (struct loop *loop) false, otherwise returns true. */ bool -likely_max_loop_iterations (struct loop *loop, widest_int *nit) +likely_max_loop_iterations (class loop *loop, widest_int *nit) { /* When SCEV information is available, try to update loop iterations estimate. Otherwise just return whatever we recorded earlier. */ @@ -4423,7 +4423,7 @@ likely_max_loop_iterations (struct loop *loop, widest_int *nit) on the number of iterations of LOOP could not be derived, returns -1. */ HOST_WIDE_INT -likely_max_loop_iterations_int (struct loop *loop) +likely_max_loop_iterations_int (class loop *loop) { widest_int nit; HOST_WIDE_INT hwi_nit; @@ -4443,7 +4443,7 @@ likely_max_loop_iterations_int (struct loop *loop) the number of execution of the latch by one. */ HOST_WIDE_INT -estimated_stmt_executions_int (struct loop *loop) +estimated_stmt_executions_int (class loop *loop) { HOST_WIDE_INT nit = estimated_loop_iterations_int (loop); HOST_WIDE_INT snit; @@ -4462,7 +4462,7 @@ estimated_stmt_executions_int (struct loop *loop) false, otherwise returns true. */ bool -max_stmt_executions (struct loop *loop, widest_int *nit) +max_stmt_executions (class loop *loop, widest_int *nit) { widest_int nit_minus_one; @@ -4481,7 +4481,7 @@ max_stmt_executions (struct loop *loop, widest_int *nit) false, otherwise returns true. */ bool -likely_max_stmt_executions (struct loop *loop, widest_int *nit) +likely_max_stmt_executions (class loop *loop, widest_int *nit) { widest_int nit_minus_one; @@ -4500,7 +4500,7 @@ likely_max_stmt_executions (struct loop *loop, widest_int *nit) false, otherwise returns true. */ bool -estimated_stmt_executions (struct loop *loop, widest_int *nit) +estimated_stmt_executions (class loop *loop, widest_int *nit) { widest_int nit_minus_one; @@ -4519,7 +4519,7 @@ estimated_stmt_executions (struct loop *loop, widest_int *nit) void estimate_numbers_of_iterations (function *fn) { - struct loop *loop; + class loop *loop; /* We don't want to issue signed overflow warnings while getting loop iteration estimates. */ @@ -4577,7 +4577,7 @@ stmt_dominates_stmt_p (gimple *s1, gimple *s2) static bool n_of_executions_at_most (gimple *stmt, - struct nb_iter_bound *niter_bound, + class nb_iter_bound *niter_bound, tree niter) { widest_int bound = niter_bound->bound; @@ -4664,11 +4664,11 @@ nowrap_type_p (tree type) static bool loop_exits_before_overflow (tree base, tree step, - gimple *at_stmt, struct loop *loop) + gimple *at_stmt, class loop *loop) { widest_int niter; struct control_iv *civ; - struct nb_iter_bound *bound; + class nb_iter_bound *bound; tree e, delta, step_abs, unsigned_base; tree type = TREE_TYPE (step); tree unsigned_type, valid_niter; @@ -4856,7 +4856,7 @@ loop_exits_before_overflow (tree base, tree step, (4294967295, 4294967296, ...). */ static bool -scev_var_range_cant_overflow (tree var, tree step, struct loop *loop) +scev_var_range_cant_overflow (tree var, tree step, class loop *loop) { tree type; wide_int minv, maxv, diff, step_wi; @@ -4910,7 +4910,7 @@ scev_var_range_cant_overflow (tree var, tree step, struct loop *loop) bool scev_probably_wraps_p (tree var, tree base, tree step, - gimple *at_stmt, struct loop *loop, + gimple *at_stmt, class loop *loop, bool use_overflow_semantics) { /* FIXME: We really need something like @@ -4962,16 +4962,16 @@ scev_probably_wraps_p (tree var, tree base, tree step, /* Frees the information on upper bounds on numbers of iterations of LOOP. */ void -free_numbers_of_iterations_estimates (struct loop *loop) +free_numbers_of_iterations_estimates (class loop *loop) { struct control_iv *civ; - struct nb_iter_bound *bound; + class nb_iter_bound *bound; loop->nb_iterations = NULL; loop->estimate_state = EST_NOT_COMPUTED; for (bound = loop->bounds; bound;) { - struct nb_iter_bound *next = bound->next; + class nb_iter_bound *next = bound->next; ggc_free (bound); bound = next; } @@ -4991,7 +4991,7 @@ free_numbers_of_iterations_estimates (struct loop *loop) void free_numbers_of_iterations_estimates (function *fn) { - struct loop *loop; + class loop *loop; FOR_EACH_LOOP_FN (fn, loop, 0) free_numbers_of_iterations_estimates (loop); @@ -5001,7 +5001,7 @@ free_numbers_of_iterations_estimates (function *fn) at LOOP. */ void -substitute_in_loop_info (struct loop *loop, tree name, tree val) +substitute_in_loop_info (class loop *loop, tree name, tree val) { loop->nb_iterations = simplify_replace_tree (loop->nb_iterations, name, val); } diff --git a/gcc/tree-ssa-loop-niter.h b/gcc/tree-ssa-loop-niter.h index dc11648..4454c1a 100644 --- a/gcc/tree-ssa-loop-niter.h +++ b/gcc/tree-ssa-loop-niter.h @@ -21,39 +21,39 @@ along with GCC; see the file COPYING3. If not see #define GCC_TREE_SSA_LOOP_NITER_H extern tree expand_simple_operations (tree, tree = NULL); -extern tree simplify_using_initial_conditions (struct loop *, tree); -extern bool loop_only_exit_p (const struct loop *, const_edge); -extern bool number_of_iterations_exit (struct loop *, edge, - struct tree_niter_desc *niter, bool, +extern tree simplify_using_initial_conditions (class loop *, tree); +extern bool loop_only_exit_p (const class loop *, const_edge); +extern bool number_of_iterations_exit (class loop *, edge, + class tree_niter_desc *niter, bool, bool every_iteration = true); -extern bool number_of_iterations_exit_assumptions (struct loop *, edge, - struct tree_niter_desc *, +extern bool number_of_iterations_exit_assumptions (class loop *, edge, + class tree_niter_desc *, gcond **, bool = true); -extern tree find_loop_niter (struct loop *, edge *); -extern bool finite_loop_p (struct loop *); -extern tree loop_niter_by_eval (struct loop *, edge); -extern tree find_loop_niter_by_eval (struct loop *, edge *); -extern bool estimated_loop_iterations (struct loop *, widest_int *); -extern HOST_WIDE_INT estimated_loop_iterations_int (struct loop *); -extern bool max_loop_iterations (struct loop *, widest_int *); -extern HOST_WIDE_INT max_loop_iterations_int (struct loop *); -extern bool likely_max_loop_iterations (struct loop *, widest_int *); -extern HOST_WIDE_INT likely_max_loop_iterations_int (struct loop *); -extern HOST_WIDE_INT max_stmt_executions_int (struct loop *); -extern HOST_WIDE_INT likely_max_stmt_executions_int (struct loop *); -extern HOST_WIDE_INT estimated_stmt_executions_int (struct loop *); -extern bool max_stmt_executions (struct loop *, widest_int *); -extern bool likely_max_stmt_executions (struct loop *, widest_int *); -extern bool estimated_stmt_executions (struct loop *, widest_int *); +extern tree find_loop_niter (class loop *, edge *); +extern bool finite_loop_p (class loop *); +extern tree loop_niter_by_eval (class loop *, edge); +extern tree find_loop_niter_by_eval (class loop *, edge *); +extern bool estimated_loop_iterations (class loop *, widest_int *); +extern HOST_WIDE_INT estimated_loop_iterations_int (class loop *); +extern bool max_loop_iterations (class loop *, widest_int *); +extern HOST_WIDE_INT max_loop_iterations_int (class loop *); +extern bool likely_max_loop_iterations (class loop *, widest_int *); +extern HOST_WIDE_INT likely_max_loop_iterations_int (class loop *); +extern HOST_WIDE_INT max_stmt_executions_int (class loop *); +extern HOST_WIDE_INT likely_max_stmt_executions_int (class loop *); +extern HOST_WIDE_INT estimated_stmt_executions_int (class loop *); +extern bool max_stmt_executions (class loop *, widest_int *); +extern bool likely_max_stmt_executions (class loop *, widest_int *); +extern bool estimated_stmt_executions (class loop *, widest_int *); extern void estimate_numbers_of_iterations (function *); -extern void estimate_numbers_of_iterations (struct loop *); +extern void estimate_numbers_of_iterations (class loop *); extern bool stmt_dominates_stmt_p (gimple *, gimple *); extern bool nowrap_type_p (tree); extern bool scev_probably_wraps_p (tree, tree, tree, gimple *, - struct loop *, bool); -extern void free_numbers_of_iterations_estimates (struct loop *); + class loop *, bool); +extern void free_numbers_of_iterations_estimates (class loop *); extern void free_numbers_of_iterations_estimates (function *); extern tree simplify_replace_tree (tree, tree, tree, tree (*)(tree) = NULL); -extern void substitute_in_loop_info (struct loop *, tree, tree); +extern void substitute_in_loop_info (class loop *, tree, tree); #endif /* GCC_TREE_SSA_LOOP_NITER_H */ diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index 7afd85f..04ff524 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -421,7 +421,7 @@ release_mem_refs (struct mem_ref_group *groups) struct ar_data { - struct loop *loop; /* Loop of the reference. */ + class loop *loop; /* Loop of the reference. */ gimple *stmt; /* Statement of the reference. */ tree *step; /* Step of the memory reference. */ HOST_WIDE_INT *delta; /* Offset of the memory reference. */ @@ -486,7 +486,7 @@ idx_analyze_ref (tree base, tree *index, void *data) references from REF_P. */ static bool -analyze_ref (struct loop *loop, tree *ref_p, tree *base, +analyze_ref (class loop *loop, tree *ref_p, tree *base, tree *step, HOST_WIDE_INT *delta, gimple *stmt) { @@ -535,7 +535,7 @@ analyze_ref (struct loop *loop, tree *ref_p, tree *base, reference was recorded, false otherwise. */ static bool -gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs, +gather_memory_references_ref (class loop *loop, struct mem_ref_group **refs, tree ref, bool write_p, gimple *stmt) { tree base, step; @@ -606,7 +606,7 @@ gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs, true if there are no other memory references inside the loop. */ static struct mem_ref_group * -gather_memory_references (struct loop *loop, bool *no_other_refs, unsigned *ref_count) +gather_memory_references (class loop *loop, bool *no_other_refs, unsigned *ref_count) { basic_block *body = get_loop_body_in_dom_order (loop); basic_block bb; @@ -1286,7 +1286,7 @@ mark_nontemporal_store (struct mem_ref *ref) /* Issue a memory fence instruction after LOOP. */ static void -emit_mfence_after_loop (struct loop *loop) +emit_mfence_after_loop (class loop *loop) { vec exits = get_loop_exit_edges (loop); edge exit; @@ -1315,7 +1315,7 @@ emit_mfence_after_loop (struct loop *loop) /* Returns true if we can use storent in loop, false otherwise. */ static bool -may_use_storent_in_loop_p (struct loop *loop) +may_use_storent_in_loop_p (class loop *loop) { bool ret = true; @@ -1345,7 +1345,7 @@ may_use_storent_in_loop_p (struct loop *loop) references in the loop. */ static void -mark_nontemporal_stores (struct loop *loop, struct mem_ref_group *groups) +mark_nontemporal_stores (class loop *loop, struct mem_ref_group *groups) { struct mem_ref *ref; bool any = false; @@ -1366,7 +1366,7 @@ mark_nontemporal_stores (struct loop *loop, struct mem_ref_group *groups) iterations. */ static bool -should_unroll_loop_p (struct loop *loop, struct tree_niter_desc *desc, +should_unroll_loop_p (class loop *loop, class tree_niter_desc *desc, unsigned factor) { if (!can_unroll_loop_p (loop, factor, desc)) @@ -1390,8 +1390,8 @@ should_unroll_loop_p (struct loop *loop, struct tree_niter_desc *desc, the loop, or -1 if no estimate is available. */ static unsigned -determine_unroll_factor (struct loop *loop, struct mem_ref_group *refs, - unsigned ninsns, struct tree_niter_desc *desc, +determine_unroll_factor (class loop *loop, struct mem_ref_group *refs, + unsigned ninsns, class tree_niter_desc *desc, HOST_WIDE_INT est_niter) { unsigned upper_bound; @@ -1493,9 +1493,9 @@ volume_of_dist_vector (lambda_vector vec, unsigned *loop_sizes, unsigned n) static void add_subscript_strides (tree access_fn, unsigned stride, - HOST_WIDE_INT *strides, unsigned n, struct loop *loop) + HOST_WIDE_INT *strides, unsigned n, class loop *loop) { - struct loop *aloop; + class loop *aloop; tree step; HOST_WIDE_INT astep; unsigned min_depth = loop_depth (loop) - n; @@ -1526,7 +1526,7 @@ add_subscript_strides (tree access_fn, unsigned stride, static unsigned self_reuse_distance (data_reference_p dr, unsigned *loop_sizes, unsigned n, - struct loop *loop) + class loop *loop) { tree stride, access_fn; HOST_WIDE_INT *strides, astride; @@ -1596,10 +1596,10 @@ self_reuse_distance (data_reference_p dr, unsigned *loop_sizes, unsigned n, memory references in the loop. Return false if the analysis fails. */ static bool -determine_loop_nest_reuse (struct loop *loop, struct mem_ref_group *refs, +determine_loop_nest_reuse (class loop *loop, struct mem_ref_group *refs, bool no_other_refs) { - struct loop *nest, *aloop; + class loop *nest, *aloop; vec datarefs = vNULL; vec dependences = vNULL; struct mem_ref_group *gr; @@ -1879,12 +1879,12 @@ insn_to_prefetch_ratio_too_small_p (unsigned ninsns, unsigned prefetch_count, true if the LOOP was unrolled. */ static bool -loop_prefetch_arrays (struct loop *loop) +loop_prefetch_arrays (class loop *loop) { struct mem_ref_group *refs; unsigned ahead, ninsns, time, unroll_factor; HOST_WIDE_INT est_niter; - struct tree_niter_desc desc; + class tree_niter_desc desc; bool unrolled = false, no_other_refs; unsigned prefetch_count; unsigned mem_ref_count; @@ -1982,7 +1982,7 @@ fail: unsigned int tree_ssa_prefetch_arrays (void) { - struct loop *loop; + class loop *loop; bool unrolled = false; int todo_flags = 0; diff --git a/gcc/tree-ssa-loop-split.c b/gcc/tree-ssa-loop-split.c index 999c9a3..f5f0833 100644 --- a/gcc/tree-ssa-loop-split.c +++ b/gcc/tree-ssa-loop-split.c @@ -70,7 +70,7 @@ along with GCC; see the file COPYING3. If not see point in *BORDER and the comparison induction variable in IV. */ static tree -split_at_bb_p (struct loop *loop, basic_block bb, tree *border, affine_iv *iv) +split_at_bb_p (class loop *loop, basic_block bb, tree *border, affine_iv *iv) { gimple *last; gcond *stmt; @@ -102,7 +102,7 @@ split_at_bb_p (struct loop *loop, basic_block bb, tree *border, affine_iv *iv) tree op0 = gimple_cond_lhs (stmt); tree op1 = gimple_cond_rhs (stmt); - struct loop *useloop = loop_containing_stmt (stmt); + class loop *useloop = loop_containing_stmt (stmt); if (!simple_iv (loop, useloop, op0, iv, false)) return NULL_TREE; @@ -150,7 +150,7 @@ split_at_bb_p (struct loop *loop, basic_block bb, tree *border, affine_iv *iv) also be true/false in the next iteration. */ static void -patch_loop_exit (struct loop *loop, gcond *guard, tree nextval, tree newbound, +patch_loop_exit (class loop *loop, gcond *guard, tree nextval, tree newbound, bool initial_true) { edge exit = single_exit (loop); @@ -181,7 +181,7 @@ patch_loop_exit (struct loop *loop, gcond *guard, tree nextval, tree newbound, such phi node. Return that phi node. */ static gphi * -find_or_create_guard_phi (struct loop *loop, tree guard_iv, affine_iv * /*iv*/) +find_or_create_guard_phi (class loop *loop, tree guard_iv, affine_iv * /*iv*/) { gimple *def = SSA_NAME_DEF_STMT (guard_iv); gphi *phi; @@ -197,7 +197,7 @@ find_or_create_guard_phi (struct loop *loop, tree guard_iv, affine_iv * /*iv*/) determined easily (i.e. that connect_loop_phis can determine them). */ static bool -easy_exit_values (struct loop *loop) +easy_exit_values (class loop *loop) { edge exit = single_exit (loop); edge latch = loop_latch_edge (loop); @@ -229,7 +229,7 @@ easy_exit_values (struct loop *loop) this. The loops need to fulfill easy_exit_values(). */ static void -connect_loop_phis (struct loop *loop1, struct loop *loop2, edge new_e) +connect_loop_phis (class loop *loop1, class loop *loop2, edge new_e) { basic_block rest = loop_preheader_edge (loop2)->src; gcc_assert (new_e->dest == rest); @@ -323,7 +323,7 @@ connect_loop_phis (struct loop *loop1, struct loop *loop2, edge new_e) This doesn't update the SSA form, see connect_loop_phis for that. */ static edge -connect_loops (struct loop *loop1, struct loop *loop2) +connect_loops (class loop *loop1, class loop *loop2) { edge exit = single_exit (loop1); basic_block skip_bb = split_edge (exit); @@ -387,7 +387,7 @@ connect_loops (struct loop *loop1, struct loop *loop2) and add or subtract 1. This routine computes newend above. */ static tree -compute_new_first_bound (gimple_seq *stmts, struct tree_niter_desc *niter, +compute_new_first_bound (gimple_seq *stmts, class tree_niter_desc *niter, tree border, enum tree_code guard_code, tree guard_init) { @@ -487,7 +487,7 @@ compute_new_first_bound (gimple_seq *stmts, struct tree_niter_desc *niter, single exit of LOOP. */ static bool -split_loop (struct loop *loop1, struct tree_niter_desc *niter) +split_loop (class loop *loop1, class tree_niter_desc *niter) { basic_block *bbs; unsigned i; @@ -557,7 +557,7 @@ split_loop (struct loop *loop1, struct tree_niter_desc *niter) initialize_original_copy_tables (); basic_block cond_bb; - struct loop *loop2 = loop_version (loop1, cond, &cond_bb, + class loop *loop2 = loop_version (loop1, cond, &cond_bb, profile_probability::always (), profile_probability::always (), profile_probability::always (), @@ -617,7 +617,7 @@ split_loop (struct loop *loop1, struct tree_niter_desc *niter) static unsigned int tree_ssa_split_loops (void) { - struct loop *loop; + class loop *loop; bool changed = false; gcc_assert (scev_initialized_p ()); @@ -627,7 +627,7 @@ tree_ssa_split_loops (void) /* Go through all loops starting from innermost. */ FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) { - struct tree_niter_desc niter; + class tree_niter_desc niter; if (loop->aux) { /* If any of our inner loops was split, don't split us, diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c index 30a2a9d..e60019d 100644 --- a/gcc/tree-ssa-loop-unswitch.c +++ b/gcc/tree-ssa-loop-unswitch.c @@ -75,23 +75,23 @@ along with GCC; see the file COPYING3. If not see tree-ssa-loop-im.c ensures that all the suitable conditions are in this shape. */ -static struct loop *tree_unswitch_loop (struct loop *, basic_block, tree); -static bool tree_unswitch_single_loop (struct loop *, int); -static tree tree_may_unswitch_on (basic_block, struct loop *); -static bool tree_unswitch_outer_loop (struct loop *); -static edge find_loop_guard (struct loop *); -static bool empty_bb_without_guard_p (struct loop *, basic_block); -static bool used_outside_loop_p (struct loop *, tree); -static void hoist_guard (struct loop *, edge); -static bool check_exit_phi (struct loop *); -static tree get_vop_from_header (struct loop *); +static class loop *tree_unswitch_loop (class loop *, basic_block, tree); +static bool tree_unswitch_single_loop (class loop *, int); +static tree tree_may_unswitch_on (basic_block, class loop *); +static bool tree_unswitch_outer_loop (class loop *); +static edge find_loop_guard (class loop *); +static bool empty_bb_without_guard_p (class loop *, basic_block); +static bool used_outside_loop_p (class loop *, tree); +static void hoist_guard (class loop *, edge); +static bool check_exit_phi (class loop *); +static tree get_vop_from_header (class loop *); /* Main entry point. Perform loop unswitching on all suitable loops. */ unsigned int tree_ssa_unswitch_loops (void) { - struct loop *loop; + class loop *loop; bool changed = false; /* Go through all loops starting from innermost. */ @@ -114,7 +114,7 @@ tree_ssa_unswitch_loops (void) considering for unswitching and LOOP is the loop it appears in. */ static bool -is_maybe_undefined (const tree name, gimple *stmt, struct loop *loop) +is_maybe_undefined (const tree name, gimple *stmt, class loop *loop) { /* The loop header is the only block we can trivially determine that will always be executed. If the comparison is in the loop @@ -187,7 +187,7 @@ is_maybe_undefined (const tree name, gimple *stmt, struct loop *loop) basic blocks (for what it means see comments below). */ static tree -tree_may_unswitch_on (basic_block bb, struct loop *loop) +tree_may_unswitch_on (basic_block bb, class loop *loop) { gimple *last, *def; gcond *stmt; @@ -232,7 +232,7 @@ tree_may_unswitch_on (basic_block bb, struct loop *loop) unnecessarily). */ static tree -simplify_using_entry_checks (struct loop *loop, tree cond) +simplify_using_entry_checks (class loop *loop, tree cond) { edge e = loop_preheader_edge (loop); gimple *stmt; @@ -265,10 +265,10 @@ simplify_using_entry_checks (struct loop *loop, tree cond) grow exponentially. */ static bool -tree_unswitch_single_loop (struct loop *loop, int num) +tree_unswitch_single_loop (class loop *loop, int num) { basic_block *bbs; - struct loop *nloop; + class loop *nloop; unsigned i, found; tree cond = NULL_TREE; gimple *stmt; @@ -476,8 +476,8 @@ tree_unswitch_single_loop (struct loop *loop, int num) loop is entered -- the new loop is entered if COND is true. Returns NULL if impossible, new loop otherwise. */ -static struct loop * -tree_unswitch_loop (struct loop *loop, +static class loop * +tree_unswitch_loop (class loop *loop, basic_block unswitch_on, tree cond) { profile_probability prob_true; @@ -500,7 +500,7 @@ tree_unswitch_loop (struct loop *loop, /* Unswitch outer loops by hoisting invariant guard on inner loop without code duplication. */ static bool -tree_unswitch_outer_loop (struct loop *loop) +tree_unswitch_outer_loop (class loop *loop) { edge exit, guard; HOST_WIDE_INT iterations; @@ -544,7 +544,7 @@ tree_unswitch_outer_loop (struct loop *loop) otherwise returns NULL. */ static edge -find_loop_guard (struct loop *loop) +find_loop_guard (class loop *loop) { basic_block header = loop->header; edge guard_edge, te, fe; @@ -701,7 +701,7 @@ end: are invariant or not. */ static bool -empty_bb_without_guard_p (struct loop *loop, basic_block bb) +empty_bb_without_guard_p (class loop *loop, basic_block bb) { basic_block exit_bb = single_exit (loop)->src; bool may_be_used_outside = (bb == exit_bb @@ -749,7 +749,7 @@ empty_bb_without_guard_p (struct loop *loop, basic_block bb) /* Return true if NAME is used outside of LOOP. */ static bool -used_outside_loop_p (struct loop *loop, tree name) +used_outside_loop_p (class loop *loop, tree name) { imm_use_iterator it; use_operand_p use; @@ -767,7 +767,7 @@ used_outside_loop_p (struct loop *loop, tree name) /* Return argument for loop preheader edge in header virtual phi if any. */ static tree -get_vop_from_header (struct loop *loop) +get_vop_from_header (class loop *loop) { for (gphi_iterator gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -783,7 +783,7 @@ get_vop_from_header (struct loop *loop) /* Move the check of GUARD outside of LOOP. */ static void -hoist_guard (struct loop *loop, edge guard) +hoist_guard (class loop *loop, edge guard) { edge exit = single_exit (loop); edge preh = loop_preheader_edge (loop); @@ -934,7 +934,7 @@ hoist_guard (struct loop *loop, edge guard) for edge around loop. */ static bool -check_exit_phi (struct loop *loop) +check_exit_phi (class loop *loop) { edge exit = single_exit (loop); basic_block pre_header = loop_preheader_edge (loop)->src; diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index 208c583..fc9f083 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -157,7 +157,7 @@ gate_oacc_kernels (function *fn) if (!lookup_attribute ("oacc kernels", DECL_ATTRIBUTES (fn->decl))) return false; - struct loop *loop; + class loop *loop; FOR_EACH_LOOP (loop, 0) if (loop->in_oacc_kernels_region) return true; @@ -455,7 +455,7 @@ public: unsigned pass_scev_cprop::execute (function *) { - struct loop *loop; + class loop *loop; bool any = false; /* Perform final value replacement in loops, in case the replacement @@ -776,7 +776,7 @@ get_lsm_tmp_name (tree ref, unsigned n, const char *suffix) /* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */ unsigned -tree_num_loop_insns (struct loop *loop, eni_weights *weights) +tree_num_loop_insns (class loop *loop, eni_weights *weights) { basic_block *body = get_loop_body (loop); gimple_stmt_iterator gsi; diff --git a/gcc/tree-ssa-loop.h b/gcc/tree-ssa-loop.h index 24fad0f..e523de2 100644 --- a/gcc/tree-ssa-loop.h +++ b/gcc/tree-ssa-loop.h @@ -66,11 +66,11 @@ public: extern bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *); extern char *get_lsm_tmp_name (tree ref, unsigned n, const char *suffix = NULL); -extern unsigned tree_num_loop_insns (struct loop *, struct eni_weights *); +extern unsigned tree_num_loop_insns (class loop *, struct eni_weights *); /* Returns the loop of the statement STMT. */ -static inline struct loop * +static inline class loop * loop_containing_stmt (gimple *stmt) { basic_block bb = gimple_bb (stmt); diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 9c1a9a6..635fc93 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -270,7 +270,7 @@ static long phi_rank (gimple *stmt) { basic_block bb = gimple_bb (stmt); - struct loop *father = bb->loop_father; + class loop *father = bb->loop_father; tree res; unsigned i; use_operand_p use; @@ -603,7 +603,7 @@ add_repeat_to_ops_vec (vec *ops, tree op, operation with tree code CODE, and is inside LOOP. */ static bool -is_reassociable_op (gimple *stmt, enum tree_code code, struct loop *loop) +is_reassociable_op (gimple *stmt, enum tree_code code, class loop *loop) { basic_block bb = gimple_bb (stmt); @@ -1560,7 +1560,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode) static bool undistribute_ops_list (enum tree_code opcode, - vec *ops, struct loop *loop) + vec *ops, class loop *loop) { unsigned int length = ops->length (); operand_entry *oe1; @@ -3861,7 +3861,7 @@ no_side_effect_bb (basic_block bb) static bool get_ops (tree var, enum tree_code code, vec *ops, - struct loop *loop) + class loop *loop) { gimple *stmt = SSA_NAME_DEF_STMT (var); tree rhs[2]; @@ -3896,7 +3896,7 @@ get_ops (tree var, enum tree_code code, vec *ops, static tree update_ops (tree var, enum tree_code code, vec ops, - unsigned int *pidx, struct loop *loop) + unsigned int *pidx, class loop *loop) { gimple *stmt = SSA_NAME_DEF_STMT (var); tree rhs[4]; @@ -4834,7 +4834,7 @@ linearize_expr (gimple *stmt) gimple *oldbinrhs = binrhs; enum tree_code rhscode = gimple_assign_rhs_code (stmt); gimple *newbinrhs = NULL; - struct loop *loop = loop_containing_stmt (stmt); + class loop *loop = loop_containing_stmt (stmt); tree lhs = gimple_assign_lhs (stmt); gcc_assert (is_reassociable_op (binlhs, rhscode, loop) @@ -4968,7 +4968,7 @@ should_break_up_subtract (gimple *stmt) tree binlhs = gimple_assign_rhs1 (stmt); tree binrhs = gimple_assign_rhs2 (stmt); gimple *immusestmt; - struct loop *loop = loop_containing_stmt (stmt); + class loop *loop = loop_containing_stmt (stmt); if (TREE_CODE (binlhs) == SSA_NAME && is_reassociable_op (SSA_NAME_DEF_STMT (binlhs), PLUS_EXPR, loop)) @@ -5123,7 +5123,7 @@ linearize_expr_tree (vec *ops, gimple *stmt, bool binlhsisreassoc = false; bool binrhsisreassoc = false; enum tree_code rhscode = gimple_assign_rhs_code (stmt); - struct loop *loop = loop_containing_stmt (stmt); + class loop *loop = loop_containing_stmt (stmt); if (set_visited) gimple_set_visited (stmt, true); diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c index 838cf8f..574bc30 100644 --- a/gcc/tree-ssa-scopedtables.c +++ b/gcc/tree-ssa-scopedtables.c @@ -1028,9 +1028,9 @@ bool expr_elt_hasher::equal (const value_type &p1, const compare_type &p2) { const struct hashable_expr *expr1 = p1->expr (); - const struct expr_hash_elt *stamp1 = p1->stamp (); + const class expr_hash_elt *stamp1 = p1->stamp (); const struct hashable_expr *expr2 = p2->expr (); - const struct expr_hash_elt *stamp2 = p2->stamp (); + const class expr_hash_elt *stamp2 = p2->stamp (); /* This case should apply only when removing entries from the table. */ if (stamp1 == stamp2) diff --git a/gcc/tree-ssa-scopedtables.h b/gcc/tree-ssa-scopedtables.h index 2328d1c..4818500 100644 --- a/gcc/tree-ssa-scopedtables.h +++ b/gcc/tree-ssa-scopedtables.h @@ -96,7 +96,7 @@ class expr_hash_elt /* A unique stamp, typically the address of the hash element itself, used in removing entries from the table. */ - struct expr_hash_elt *m_stamp; + class expr_hash_elt *m_stamp; /* We should never be making assignments between objects in this class. Though it might allow us to exploit C++11 move semantics if we diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index f470f31..f8962d6 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -1420,7 +1420,7 @@ public: number 1, pages 9-14. */ static void -scc_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n) +scc_visit (constraint_graph_t graph, class scc_info *si, unsigned int n) { unsigned int i; bitmap_iterator bi; @@ -2023,7 +2023,7 @@ static int location_equiv_class; and label it's nodes with DFS numbers. */ static void -condense_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n) +condense_visit (constraint_graph_t graph, class scc_info *si, unsigned int n) { unsigned int i; bitmap_iterator bi; @@ -2128,7 +2128,7 @@ condense_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n) 3. Hashable. */ static void -label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n) +label_visit (constraint_graph_t graph, class scc_info *si, unsigned int n) { unsigned int i, first_pred; bitmap_iterator bi; @@ -2215,7 +2215,7 @@ label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n) /* Print the pred graph in dot format. */ static void -dump_pred_graph (struct scc_info *si, FILE *file) +dump_pred_graph (class scc_info *si, FILE *file) { unsigned int i; @@ -2290,7 +2290,7 @@ dump_pred_graph (struct scc_info *si, FILE *file) /* Perform offline variable substitution, discovering equivalence classes, and eliminating non-pointer variables. */ -static struct scc_info * +static class scc_info * perform_var_substitution (constraint_graph_t graph) { unsigned int i; @@ -2424,7 +2424,7 @@ perform_var_substitution (constraint_graph_t graph) substitution. */ static void -free_var_substitution_info (struct scc_info *si) +free_var_substitution_info (class scc_info *si) { delete si; free (graph->pointer_label); @@ -2548,7 +2548,7 @@ move_complex_constraints (constraint_graph_t graph) static void rewrite_constraints (constraint_graph_t graph, - struct scc_info *si) + class scc_info *si) { int i; constraint_t c; @@ -7184,7 +7184,7 @@ remove_preds_and_fake_succs (constraint_graph_t graph) static void solve_constraints (void) { - struct scc_info *si; + class scc_info *si; /* Sort varinfos so that ones that cannot be pointed to are last. This makes bitmaps more efficient. */ diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index a56ccfb..51a316a 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -1556,7 +1556,7 @@ dbds_continue_enumeration_p (const_basic_block bb, const void *stop) returns the state. */ enum bb_dom_status -determine_bb_domination_status (struct loop *loop, basic_block bb) +determine_bb_domination_status (class loop *loop, basic_block bb) { basic_block *bblocks; unsigned nblocks, i; @@ -1614,7 +1614,7 @@ determine_bb_domination_status (struct loop *loop, basic_block bb) to the inside of the loop. */ static bool -thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers) +thread_through_loop_header (class loop *loop, bool may_peel_loop_headers) { basic_block header = loop->header; edge e, tgt_edge, latch = loop_latch_edge (loop); @@ -2317,7 +2317,7 @@ duplicate_thread_path (edge entry, edge exit, basic_block *region, unsigned n_region, unsigned current_path_no) { unsigned i; - struct loop *loop = entry->dest->loop_father; + class loop *loop = entry->dest->loop_father; edge exit_copy; edge redirected; profile_count curr_count; @@ -2517,7 +2517,7 @@ thread_through_all_blocks (bool may_peel_loop_headers) { bool retval = false; unsigned int i; - struct loop *loop; + class loop *loop; auto_bitmap threaded_blocks; hash_set visited_starting_edges; diff --git a/gcc/tree-ssa-threadupdate.h b/gcc/tree-ssa-threadupdate.h index d66e8e0..dc6de2f 100644 --- a/gcc/tree-ssa-threadupdate.h +++ b/gcc/tree-ssa-threadupdate.h @@ -59,6 +59,6 @@ enum bb_dom_status DOMST_DOMINATING }; -enum bb_dom_status determine_bb_domination_status (struct loop *, basic_block); +enum bb_dom_status determine_bb_domination_status (class loop *, basic_block); #endif diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c index 35b3e98..dc8bbf8 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see block IB. */ tree -streamer_read_string_cst (struct data_in *data_in, struct lto_input_block *ib) +streamer_read_string_cst (class data_in *data_in, class lto_input_block *ib) { unsigned int len; const char * ptr; @@ -57,7 +57,7 @@ streamer_read_string_cst (struct data_in *data_in, struct lto_input_block *ib) block IB. */ static tree -input_identifier (struct data_in *data_in, struct lto_input_block *ib) +input_identifier (class data_in *data_in, class lto_input_block *ib) { unsigned int len; const char *ptr; @@ -73,7 +73,7 @@ input_identifier (struct data_in *data_in, struct lto_input_block *ib) tables and descriptors for the file being read. */ tree -streamer_read_chain (struct lto_input_block *ib, struct data_in *data_in) +streamer_read_chain (class lto_input_block *ib, class data_in *data_in) { tree first, prev, curr; @@ -404,7 +404,7 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) of expression EXPR from bitpack BP. */ static void -unpack_ts_block_value_fields (struct data_in *data_in, +unpack_ts_block_value_fields (class data_in *data_in, struct bitpack_d *bp, tree expr) { /* BLOCK_NUMBER is recomputed. */ @@ -415,7 +415,7 @@ unpack_ts_block_value_fields (struct data_in *data_in, structure of expression EXPR from bitpack BP. */ static void -unpack_ts_translation_unit_decl_value_fields (struct data_in *data_in, +unpack_ts_translation_unit_decl_value_fields (class data_in *data_in, struct bitpack_d *bp, tree expr) { TRANSLATION_UNIT_LANGUAGE (expr) = xstrdup (bp_unpack_string (data_in, bp)); @@ -427,7 +427,7 @@ unpack_ts_translation_unit_decl_value_fields (struct data_in *data_in, structure of expression EXPR from bitpack BP. */ static void -unpack_ts_omp_clause_value_fields (struct data_in *data_in, +unpack_ts_omp_clause_value_fields (class data_in *data_in, struct bitpack_d *bp, tree expr) { stream_input_location (&OMP_CLAUSE_LOCATION (expr), bp, data_in); @@ -473,8 +473,8 @@ unpack_ts_omp_clause_value_fields (struct data_in *data_in, bitfield values that the writer may have written. */ void -streamer_read_tree_bitfields (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +streamer_read_tree_bitfields (class lto_input_block *ib, + class data_in *data_in, tree expr) { enum tree_code code; struct bitpack_d bp; @@ -570,7 +570,7 @@ streamer_read_tree_bitfields (struct lto_input_block *ib, *IX_P the index into the reader cache where the new tree is stored. */ tree -streamer_alloc_tree (struct lto_input_block *ib, struct data_in *data_in, +streamer_alloc_tree (class lto_input_block *ib, class data_in *data_in, enum LTO_tags tag) { enum tree_code code; @@ -640,8 +640,8 @@ streamer_alloc_tree (struct lto_input_block *ib, struct data_in *data_in, static void -lto_input_ts_common_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_common_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { if (TREE_CODE (expr) != IDENTIFIER_NODE) TREE_TYPE (expr) = stream_read_tree (ib, data_in); @@ -653,8 +653,8 @@ lto_input_ts_common_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_vector_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_vector_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { unsigned int count = vector_cst_encoded_nelts (expr); for (unsigned int i = 0; i < count; ++i) @@ -667,8 +667,8 @@ lto_input_ts_vector_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_poly_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_poly_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) POLY_INT_CST_COEFF (expr, i) = stream_read_tree (ib, data_in); @@ -680,8 +680,8 @@ lto_input_ts_poly_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_complex_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_complex_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { TREE_REALPART (expr) = stream_read_tree (ib, data_in); TREE_IMAGPART (expr) = stream_read_tree (ib, data_in); @@ -693,8 +693,8 @@ lto_input_ts_complex_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_decl_minimal_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_decl_minimal_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { DECL_NAME (expr) = stream_read_tree (ib, data_in); DECL_CONTEXT (expr) = stream_read_tree (ib, data_in); @@ -706,8 +706,8 @@ lto_input_ts_decl_minimal_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_decl_common_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { DECL_SIZE (expr) = stream_read_tree (ib, data_in); DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in); @@ -733,8 +733,8 @@ lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_decl_non_common_tree_pointers (struct lto_input_block *, - struct data_in *, tree) +lto_input_ts_decl_non_common_tree_pointers (class lto_input_block *, + class data_in *, tree) { } @@ -744,8 +744,8 @@ lto_input_ts_decl_non_common_tree_pointers (struct lto_input_block *, file being read. */ static void -lto_input_ts_decl_with_vis_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_decl_with_vis_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { tree id; @@ -763,8 +763,8 @@ lto_input_ts_decl_with_vis_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_field_decl_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_field_decl_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { DECL_FIELD_OFFSET (expr) = stream_read_tree (ib, data_in); DECL_BIT_FIELD_TYPE (expr) = stream_read_tree (ib, data_in); @@ -778,8 +778,8 @@ lto_input_ts_field_decl_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_function_decl_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_function_decl_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { /* DECL_STRUCT_FUNCTION is loaded on demand by cgraph_get_body. */ DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree (ib, data_in); @@ -816,8 +816,8 @@ lto_input_ts_function_decl_tree_pointers (struct lto_input_block *ib, being read. */ static void -lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_type_common_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { TYPE_SIZE (expr) = stream_read_tree (ib, data_in); TYPE_SIZE_UNIT (expr) = stream_read_tree (ib, data_in); @@ -838,8 +838,8 @@ lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_type_non_common_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, +lto_input_ts_type_non_common_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { if (TREE_CODE (expr) == ENUMERAL_TYPE) @@ -863,8 +863,8 @@ lto_input_ts_type_non_common_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_list_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_list_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { TREE_PURPOSE (expr) = stream_read_tree (ib, data_in); TREE_VALUE (expr) = stream_read_tree (ib, data_in); @@ -877,8 +877,8 @@ lto_input_ts_list_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_vec_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_vec_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { int i; @@ -895,8 +895,8 @@ lto_input_ts_vec_tree_pointers (struct lto_input_block *ib, static void -lto_input_ts_exp_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_exp_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { int i; tree block; @@ -921,8 +921,8 @@ lto_input_ts_exp_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_block_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_block_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { BLOCK_VARS (expr) = streamer_read_chain (ib, data_in); @@ -967,8 +967,8 @@ lto_input_ts_block_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_binfo_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_binfo_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { tree t; @@ -999,8 +999,8 @@ lto_input_ts_binfo_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_constructor_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_constructor_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { unsigned i; @@ -1019,8 +1019,8 @@ lto_input_ts_constructor_tree_pointers (struct lto_input_block *ib, file being read. */ static void -lto_input_ts_omp_clause_tree_pointers (struct lto_input_block *ib, - struct data_in *data_in, tree expr) +lto_input_ts_omp_clause_tree_pointers (class lto_input_block *ib, + class data_in *data_in, tree expr) { int i; @@ -1034,7 +1034,7 @@ lto_input_ts_omp_clause_tree_pointers (struct lto_input_block *ib, contains tables and descriptors for the file being read. */ void -streamer_read_tree_body (struct lto_input_block *ib, struct data_in *data_in, +streamer_read_tree_body (class lto_input_block *ib, class data_in *data_in, tree expr) { enum tree_code code; @@ -1104,7 +1104,7 @@ streamer_read_tree_body (struct lto_input_block *ib, struct data_in *data_in, DATA_IN->FILE_DATA->GLOBALS_INDEX[IX]. */ tree -streamer_get_pickled_tree (struct lto_input_block *ib, struct data_in *data_in) +streamer_get_pickled_tree (class lto_input_block *ib, class data_in *data_in) { unsigned HOST_WIDE_INT ix; tree result; diff --git a/gcc/tree-streamer.h b/gcc/tree-streamer.h index 2972861..01ddd63 100644 --- a/gcc/tree-streamer.h +++ b/gcc/tree-streamer.h @@ -58,14 +58,14 @@ struct streamer_tree_cache_d }; /* In tree-streamer-in.c. */ -tree streamer_read_string_cst (struct data_in *, struct lto_input_block *); -tree streamer_read_chain (struct lto_input_block *, struct data_in *); -tree streamer_alloc_tree (struct lto_input_block *, struct data_in *, +tree streamer_read_string_cst (class data_in *, class lto_input_block *); +tree streamer_read_chain (class lto_input_block *, class data_in *); +tree streamer_alloc_tree (class lto_input_block *, class data_in *, enum LTO_tags); -void streamer_read_tree_body (struct lto_input_block *, struct data_in *, tree); -tree streamer_get_pickled_tree (struct lto_input_block *, struct data_in *); -void streamer_read_tree_bitfields (struct lto_input_block *, - struct data_in *, tree); +void streamer_read_tree_body (class lto_input_block *, class data_in *, tree); +tree streamer_get_pickled_tree (class lto_input_block *, class data_in *); +void streamer_read_tree_bitfields (class lto_input_block *, + class data_in *, tree); /* In tree-streamer-out.c. */ void streamer_write_string_cst (struct output_block *, @@ -117,7 +117,7 @@ static inline machine_mode bp_unpack_machine_mode (struct bitpack_d *bp) { return (machine_mode) - ((struct lto_input_block *) + ((class lto_input_block *) bp->stream)->mode_table[bp_unpack_enum (bp, machine_mode, 1 << 8)]; } diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 5f8ed46..776db77 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -1448,8 +1448,8 @@ bit_test_cluster::is_beneficial (const vec &clusters, int case_bit_test::cmp (const void *p1, const void *p2) { - const struct case_bit_test *const d1 = (const struct case_bit_test *) p1; - const struct case_bit_test *const d2 = (const struct case_bit_test *) p2; + const case_bit_test *const d1 = (const case_bit_test *) p1; + const case_bit_test *const d2 = (const case_bit_test *) p2; if (d2->bits != d1->bits) return d2->bits - d1->bits; @@ -1480,7 +1480,7 @@ void bit_test_cluster::emit (tree index_expr, tree index_type, tree, basic_block default_bb) { - struct case_bit_test test[m_max_case_bit_tests] = { {} }; + case_bit_test test[m_max_case_bit_tests] = { {} }; unsigned int i, j, k; unsigned int count; diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 1af36d8..6390b19 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -183,7 +183,7 @@ vect_get_smallest_scalar_type (stmt_vec_info stmt_info, static opt_result vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); if ((unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS) == 0) return opt_result::failure_at (vect_location, @@ -306,7 +306,7 @@ vect_analyze_possibly_independent_ddr (data_dependence_relation *ddr, loop_vec_info loop_vinfo, int loop_depth, unsigned int *max_vf) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); lambda_vector dist_v; unsigned int i; FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v) @@ -363,7 +363,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, unsigned int *max_vf) { unsigned int i; - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct data_reference *dra = DDR_A (ddr); struct data_reference *drb = DDR_B (ddr); dr_vec_info *dr_info_a = loop_vinfo->lookup_dr (dra); @@ -867,7 +867,7 @@ void vect_record_base_alignments (vec_info *vinfo) { loop_vec_info loop_vinfo = dyn_cast (vinfo); - struct loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL; + class loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL; data_reference *dr; unsigned int i; FOR_EACH_VEC_ELT (vinfo->shared->datarefs, i, dr) @@ -914,7 +914,7 @@ vect_compute_data_ref_alignment (dr_vec_info *dr_info) stmt_vec_info stmt_info = dr_info->stmt; vec_base_alignments *base_alignments = &stmt_info->vinfo->base_alignments; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = NULL; + class loop *loop = NULL; tree ref = DR_REF (dr_info->dr); tree vectype = STMT_VINFO_VECTYPE (stmt_info); @@ -1659,7 +1659,7 @@ opt_result vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) { vec datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); enum dr_alignment_support supportable_dr_alignment; dr_vec_info *first_store = NULL; dr_vec_info *dr0_info = NULL; @@ -1822,7 +1822,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) computation will be invariant in the outermost loop. */ else if (same_align_drs_max == same_align_drs) { - struct loop *ivloop0, *ivloop; + class loop *ivloop0, *ivloop; ivloop0 = outermost_invariant_loop_for_expr (loop, DR_BASE_ADDRESS (dr0_info->dr)); ivloop = outermost_invariant_loop_for_expr @@ -2710,7 +2710,7 @@ vect_analyze_data_ref_access (dr_vec_info *dr_info) tree scalar_type = TREE_TYPE (DR_REF (dr)); stmt_vec_info stmt_info = dr_info->stmt; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = NULL; + class loop *loop = NULL; if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)) return true; @@ -3730,7 +3730,7 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, { HOST_WIDE_INT scale = 1; poly_int64 pbitpos, pbitsize; - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); tree offtype = NULL_TREE; tree decl = NULL_TREE, base, off; @@ -4162,7 +4162,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt, opt_result vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf, bool *fatal) { - struct loop *loop = NULL; + class loop *loop = NULL; unsigned int i; struct data_reference *dr; tree scalar_type; @@ -4673,16 +4673,16 @@ vect_create_addr_base_for_vector_ref (stmt_vec_info stmt_info, tree vect_create_data_ref_ptr (stmt_vec_info stmt_info, tree aggr_type, - struct loop *at_loop, tree offset, + class loop *at_loop, tree offset, tree *initial_address, gimple_stmt_iterator *gsi, gimple **ptr_incr, bool only_init, tree byte_offset, tree iv_step) { const char *base_name; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = NULL; + class loop *loop = NULL; bool nested_in_vect_loop = false; - struct loop *containing_loop = NULL; + class loop *containing_loop = NULL; tree aggr_ptr_type; tree aggr_ptr; tree new_temp; @@ -5427,13 +5427,13 @@ vect_setup_realignment (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, tree *realignment_token, enum dr_alignment_support alignment_support_scheme, tree init_addr, - struct loop **at_loop) + class loop **at_loop) { tree vectype = STMT_VINFO_VECTYPE (stmt_info); loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); struct data_reference *dr = dr_info->dr; - struct loop *loop = NULL; + class loop *loop = NULL; edge pe = NULL; tree scalar_dest = gimple_assign_lhs (stmt_info->stmt); tree vec_dest; @@ -5448,8 +5448,8 @@ vect_setup_realignment (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, gimple_seq stmts = NULL; bool compute_in_loop = false; bool nested_in_vect_loop = false; - struct loop *containing_loop = (gimple_bb (stmt_info->stmt))->loop_father; - struct loop *loop_for_initial_load = NULL; + class loop *containing_loop = (gimple_bb (stmt_info->stmt))->loop_father; + class loop *loop_for_initial_load = NULL; if (loop_vinfo) { @@ -6459,7 +6459,7 @@ vect_supportable_dr_alignment (dr_vec_info *dr_info, tree vectype = STMT_VINFO_VECTYPE (stmt_info); machine_mode mode = TYPE_MODE (vectype); loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *vect_loop = NULL; + class loop *vect_loop = NULL; bool nested_in_vect_loop = false; if (aligned_access_p (dr_info) && !check_aligned_accesses) diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index bd8fffb..5c25441 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -89,8 +89,8 @@ rename_variables_in_bb (basic_block bb, bool rename_from_outer_loop) ssa_op_iter iter; edge e; edge_iterator ei; - struct loop *loop = bb->loop_father; - struct loop *outer_loop = NULL; + class loop *loop = bb->loop_father; + class loop *outer_loop = NULL; if (rename_from_outer_loop) { @@ -258,7 +258,7 @@ adjust_phi_and_debug_stmts (gimple *update_phi, edge e, tree new_def) value that it should have on subsequent iterations. */ static void -vect_set_loop_mask (struct loop *loop, tree mask, tree init_mask, +vect_set_loop_mask (class loop *loop, tree mask, tree init_mask, tree next_mask) { gphi *phi = create_phi_node (mask, loop->header); @@ -269,7 +269,7 @@ vect_set_loop_mask (struct loop *loop, tree mask, tree init_mask, /* Add SEQ to the end of LOOP's preheader block. */ static void -add_preheader_seq (struct loop *loop, gimple_seq seq) +add_preheader_seq (class loop *loop, gimple_seq seq) { if (seq) { @@ -282,7 +282,7 @@ add_preheader_seq (struct loop *loop, gimple_seq seq) /* Add SEQ to the beginning of LOOP's header block. */ static void -add_header_seq (struct loop *loop, gimple_seq seq) +add_header_seq (class loop *loop, gimple_seq seq) { if (seq) { @@ -406,7 +406,7 @@ vect_maybe_permute_loop_masks (gimple_seq *seq, rgroup_masks *dest_rgm, would ever hit a value that produces a set of all-false masks for RGM. */ static tree -vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo, +vect_set_loop_masks_directly (class loop *loop, loop_vec_info loop_vinfo, gimple_seq *preheader_seq, gimple_stmt_iterator loop_cond_gsi, rgroup_masks *rgm, tree niters, tree niters_skip, @@ -635,7 +635,7 @@ vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo, final gcond. */ static gcond * -vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo, +vect_set_loop_condition_masked (class loop *loop, loop_vec_info loop_vinfo, tree niters, tree final_iv, bool niters_maybe_zero, gimple_stmt_iterator loop_cond_gsi) @@ -743,7 +743,7 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo, are no loop masks. */ static gcond * -vect_set_loop_condition_unmasked (struct loop *loop, tree niters, +vect_set_loop_condition_unmasked (class loop *loop, tree niters, tree step, tree final_iv, bool niters_maybe_zero, gimple_stmt_iterator loop_cond_gsi) @@ -896,7 +896,7 @@ vect_set_loop_condition_unmasked (struct loop *loop, tree niters, Assumption: the exit-condition of LOOP is the last stmt in the loop. */ void -vect_set_loop_condition (struct loop *loop, loop_vec_info loop_vinfo, +vect_set_loop_condition (class loop *loop, loop_vec_info loop_vinfo, tree niters, tree step, tree final_iv, bool niters_maybe_zero) { @@ -985,11 +985,11 @@ slpeel_duplicate_current_defs_from_edges (edge from, edge to) basic blocks from SCALAR_LOOP instead of LOOP, but to either the entry or exit of LOOP. */ -struct loop * -slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, - struct loop *scalar_loop, edge e) +class loop * +slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop, + class loop *scalar_loop, edge e) { - struct loop *new_loop; + class loop *new_loop; basic_block *new_bbs, *bbs, *pbbs; bool at_exit; bool was_imm_dom; @@ -1214,7 +1214,7 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, */ bool -slpeel_can_duplicate_loop_p (const struct loop *loop, const_edge e) +slpeel_can_duplicate_loop_p (const class loop *loop, const_edge e) { edge exit_e = single_exit (loop); edge entry_e = loop_preheader_edge (loop); @@ -1244,7 +1244,7 @@ slpeel_can_duplicate_loop_p (const struct loop *loop, const_edge e) uses should be renamed. */ static void -create_lcssa_for_virtual_phi (struct loop *loop) +create_lcssa_for_virtual_phi (class loop *loop) { gphi_iterator gsi; edge exit_e = single_exit (loop); @@ -1289,7 +1289,7 @@ create_lcssa_for_virtual_phi (struct loop *loop) Return the loop location if succeed and NULL if not. */ dump_user_location_t -find_loop_location (struct loop *loop) +find_loop_location (class loop *loop) { gimple *stmt = NULL; basic_block bb; @@ -1351,7 +1351,7 @@ iv_phi_p (stmt_vec_info stmt_info) bool vect_can_advance_ivs_p (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block bb = loop->header; gphi_iterator gsi; @@ -1465,7 +1465,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters, edge update_e) { gphi_iterator gsi, gsi1; - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block update_bb = update_e->dest; basic_block exit_bb = single_exit (loop)->dest; @@ -1991,7 +1991,7 @@ vect_gen_vector_loop_niters_mult_vf (loop_vec_info loop_vinfo, { /* We should be using a step_vector of VF if VF is variable. */ int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo).to_constant (); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); tree type = TREE_TYPE (niters_vector); tree log_vf = build_int_cst (type, exact_log2 (vf)); basic_block exit_bb = single_exit (loop)->dest; @@ -2059,11 +2059,11 @@ vect_gen_vector_loop_niters_mult_vf (loop_vec_info loop_vinfo, static void slpeel_update_phi_nodes_for_loops (loop_vec_info loop_vinfo, - struct loop *first, struct loop *second, + class loop *first, class loop *second, bool create_lcssa_for_iv_phis) { gphi_iterator gsi_update, gsi_orig; - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); edge first_latch_e = EDGE_SUCC (first->latch, 0); edge second_preheader_e = loop_preheader_edge (second); @@ -2147,8 +2147,8 @@ slpeel_update_phi_nodes_for_loops (loop_vec_info loop_vinfo, in the update_loop's PHI node with the result of new PHI result. */ static void -slpeel_update_phi_nodes_for_guard1 (struct loop *skip_loop, - struct loop *update_loop, +slpeel_update_phi_nodes_for_guard1 (class loop *skip_loop, + class loop *update_loop, edge guard_edge, edge merge_edge) { location_t merge_loc, guard_loc; @@ -2188,7 +2188,7 @@ slpeel_update_phi_nodes_for_guard1 (struct loop *skip_loop, NULL. */ static tree -find_guard_arg (struct loop *loop, struct loop *epilog ATTRIBUTE_UNUSED, +find_guard_arg (class loop *loop, class loop *epilog ATTRIBUTE_UNUSED, gphi *lcssa_phi) { gphi_iterator gsi; @@ -2259,7 +2259,7 @@ find_guard_arg (struct loop *loop, struct loop *epilog ATTRIBUTE_UNUSED, in exit_bb will also be updated. */ static void -slpeel_update_phi_nodes_for_guard2 (struct loop *loop, struct loop *epilog, +slpeel_update_phi_nodes_for_guard2 (class loop *loop, class loop *epilog, edge guard_edge, edge merge_edge) { gphi_iterator gsi; @@ -2308,7 +2308,7 @@ slpeel_update_phi_nodes_for_guard2 (struct loop *loop, struct loop *epilog, the arg of its loop closed ssa PHI needs to be updated. */ static void -slpeel_update_phi_nodes_for_lcssa (struct loop *epilog) +slpeel_update_phi_nodes_for_lcssa (class loop *epilog) { gphi_iterator gsi; basic_block exit_bb = single_exit (epilog)->dest; @@ -2397,7 +2397,7 @@ slpeel_update_phi_nodes_for_lcssa (struct loop *epilog) versioning conditions if loop versioning is needed. */ -struct loop * +class loop * vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, tree *niters_vector, tree *step_vector, tree *niters_vector_mult_vf_var, int th, @@ -2439,8 +2439,8 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, prob_prolog = prob_epilog = profile_probability::guessed_always () .apply_scale (estimated_vf - 1, estimated_vf); - struct loop *prolog, *epilog = NULL, *loop = LOOP_VINFO_LOOP (loop_vinfo); - struct loop *first_loop = loop; + class loop *prolog, *epilog = NULL, *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *first_loop = loop; bool irred_flag = loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP; create_lcssa_for_virtual_phi (loop); update_ssa (TODO_update_ssa_only_virtuals); @@ -2503,7 +2503,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, } dump_user_location_t loop_loc = find_loop_location (loop); - struct loop *scalar_loop = LOOP_VINFO_SCALAR_LOOP (loop_vinfo); + class loop *scalar_loop = LOOP_VINFO_SCALAR_LOOP (loop_vinfo); if (prolog_peeling) { e = loop_preheader_edge (loop); @@ -2965,13 +2965,13 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr) The versioning precondition(s) are placed in *COND_EXPR and *COND_EXPR_STMT_LIST. */ -struct loop * +class loop * vect_loop_versioning (loop_vec_info loop_vinfo, unsigned int th, bool check_profitability, poly_uint64 versioning_threshold) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo), *nloop; - struct loop *scalar_loop = LOOP_VINFO_SCALAR_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo), *nloop; + class loop *scalar_loop = LOOP_VINFO_SCALAR_LOOP (loop_vinfo); basic_block condition_bb; gphi_iterator gsi; gimple_stmt_iterator cond_exp_gsi; @@ -3058,7 +3058,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo, /* Compute the outermost loop cond_expr and cond_expr_stmt_list are invariant in. */ - struct loop *outermost = outermost_invariant_loop_for_expr (loop, cond_expr); + class loop *outermost = outermost_invariant_loop_for_expr (loop, cond_expr); for (gimple_stmt_iterator gsi = gsi_start (cond_expr_stmt_list); !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -3075,7 +3075,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo, /* Search for the outermost loop we can version. Avoid versioning of non-perfect nests but allow if-conversion versioned loops inside. */ - struct loop *loop_to_version = loop; + class loop *loop_to_version = loop; if (flow_loop_nested_p (outermost, loop)) { if (dump_enabled_p ()) @@ -3148,7 +3148,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo, /* Kill off IFN_LOOP_VECTORIZED_CALL in the copy, nobody will reap those otherwise; they also refer to the original loops. */ - struct loop *l = loop; + class loop *l = loop; while (gimple *call = vect_loop_vectorized_call (l)) { call = SSA_NAME_DEF_STMT (get_current_def (gimple_call_lhs (call))); diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index b49ab15..b0cbbac 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -286,7 +286,7 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf, static opt_result vect_determine_vectorization_factor (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); unsigned nbbs = loop->num_nodes; poly_uint64 vectorization_factor = 1; @@ -481,7 +481,7 @@ vect_inner_phi_in_double_reduction_p (stmt_vec_info stmt_info, gphi *phi) enclosing LOOP). */ static void -vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop) +vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, class loop *loop) { basic_block bb = loop->header; tree init, step; @@ -633,7 +633,7 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop) static void vect_analyze_scalar_cycles (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); vect_analyze_scalar_cycles_1 (loop_vinfo, loop); @@ -714,11 +714,11 @@ vect_fixup_scalar_cycles_with_patterns (loop_vec_info loop_vinfo) static gcond * -vect_get_loop_niters (struct loop *loop, tree *assumptions, +vect_get_loop_niters (class loop *loop, tree *assumptions, tree *number_of_iterations, tree *number_of_iterationsm1) { edge exit = single_exit (loop); - struct tree_niter_desc niter_desc; + class tree_niter_desc niter_desc; tree niter_assumptions, niter, may_be_zero; gcond *cond = get_loop_exit_condition (loop); @@ -793,7 +793,7 @@ vect_get_loop_niters (struct loop *loop, tree *assumptions, static bool bb_in_loop_p (const_basic_block bb, const void *data) { - const struct loop *const loop = (const struct loop *)data; + const class loop *const loop = (const class loop *)data; if (flow_bb_inside_loop_p (loop, bb)) return true; return false; @@ -803,7 +803,7 @@ bb_in_loop_p (const_basic_block bb, const void *data) /* Create and initialize a new loop_vec_info struct for LOOP_IN, as well as stmt_vec_info structs for all the stmts in LOOP_IN. */ -_loop_vec_info::_loop_vec_info (struct loop *loop_in, vec_info_shared *shared) +_loop_vec_info::_loop_vec_info (class loop *loop_in, vec_info_shared *shared) : vec_info (vec_info::loop, init_cost (loop_in), shared), loop (loop_in), bbs (XCNEWVEC (basic_block, loop->num_nodes)), @@ -1029,7 +1029,7 @@ vect_get_max_nscalars_per_iter (loop_vec_info loop_vinfo) static bool vect_verify_full_masking (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); unsigned int min_ni_width; unsigned int max_nscalars_per_iter = vect_get_max_nscalars_per_iter (loop_vinfo); @@ -1122,7 +1122,7 @@ vect_verify_full_masking (loop_vec_info loop_vinfo) static void vect_compute_single_scalar_iteration_cost (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); int nbbs = loop->num_nodes, factor; int innerloop_iters, i; @@ -1204,7 +1204,7 @@ vect_compute_single_scalar_iteration_cost (loop_vec_info loop_vinfo) niter could be analyzed under some assumptions. */ opt_result -vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, +vect_analyze_loop_form_1 (class loop *loop, gcond **loop_cond, tree *assumptions, tree *number_of_iterationsm1, tree *number_of_iterations, gcond **inner_loop_cond) { @@ -1239,7 +1239,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, } else { - struct loop *innerloop = loop->inner; + class loop *innerloop = loop->inner; edge entryedge; /* Nested loop. We currently require that the loop is doubly-nested, @@ -1356,7 +1356,7 @@ vect_analyze_loop_form_1 (struct loop *loop, gcond **loop_cond, /* Analyze LOOP form and return a loop_vec_info if it is of suitable form. */ opt_loop_vec_info -vect_analyze_loop_form (struct loop *loop, vec_info_shared *shared) +vect_analyze_loop_form (class loop *loop, vec_info_shared *shared) { tree assumptions, number_of_iterations, number_of_iterationsm1; gcond *loop_cond, *inner_loop_cond = NULL; @@ -1419,7 +1419,7 @@ vect_analyze_loop_form (struct loop *loop, vec_info_shared *shared) static void vect_update_vf_for_slp (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); int nbbs = loop->num_nodes; poly_uint64 vectorization_factor; @@ -1515,7 +1515,7 @@ vect_active_double_reduction_p (stmt_vec_info stmt_info) static opt_result vect_analyze_loop_operations (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); int nbbs = loop->num_nodes; int i; @@ -1661,7 +1661,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) static int vect_analyze_loop_costing (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); unsigned int assumed_vf = vect_vf_for_cost (loop_vinfo); /* Only fully-masked loops can have iteration counts less than the @@ -2328,7 +2328,7 @@ again: loop_vec_info struct. If ORIG_LOOP_VINFO is not NULL epilogue must be vectorized. */ opt_loop_vec_info -vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo, +vect_analyze_loop (class loop *loop, loop_vec_info orig_loop_vinfo, vec_info_shared *shared) { auto_vector_sizes vector_sizes; @@ -2532,7 +2532,7 @@ neutral_op_for_slp_reduction (slp_tree slp_node, tree_code code, stmt_vec_info stmt_vinfo = stmts[0]; tree vector_type = STMT_VINFO_VECTYPE (stmt_vinfo); tree scalar_type = TREE_TYPE (vector_type); - struct loop *loop = gimple_bb (stmt_vinfo->stmt)->loop_father; + class loop *loop = gimple_bb (stmt_vinfo->stmt)->loop_father; gcc_assert (loop); switch (code) @@ -2611,8 +2611,8 @@ static bool vect_is_slp_reduction (loop_vec_info loop_info, gimple *phi, gimple *first_stmt) { - struct loop *loop = (gimple_bb (phi))->loop_father; - struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info); + class loop *loop = (gimple_bb (phi))->loop_father; + class loop *vect_loop = LOOP_VINFO_LOOP (loop_info); enum tree_code code; gimple *loop_use_stmt = NULL; stmt_vec_info use_stmt_info; @@ -2951,8 +2951,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, enum vect_reduction_type *v_reduc_type) { gphi *phi = as_a (phi_info->stmt); - struct loop *loop = (gimple_bb (phi))->loop_father; - struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info); + class loop *loop = (gimple_bb (phi))->loop_father; + class loop *vect_loop = LOOP_VINFO_LOOP (loop_info); bool nested_in_vect_loop = flow_loop_nested_p (vect_loop, loop); gimple *phi_use_stmt = NULL; enum tree_code orig_code, code; @@ -3977,7 +3977,7 @@ vect_model_reduction_cost (stmt_vec_info stmt_info, internal_fn reduc_fn, tree vectype; machine_mode mode; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = NULL; + class loop *loop = NULL; if (loop_vinfo) loop = LOOP_VINFO_LOOP (loop_vinfo); @@ -4208,7 +4208,7 @@ get_initial_def_for_reduction (stmt_vec_info stmt_vinfo, tree init_val, tree *adjustment_def) { loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); tree scalar_type = TREE_TYPE (init_val); tree vectype = get_vectype_for_scalar_type (scalar_type); enum tree_code code = gimple_assign_rhs_code (stmt_vinfo->stmt); @@ -4329,7 +4329,7 @@ get_initial_defs_for_reduction (slp_tree slp_node, tree vector_type; unsigned int group_size = stmts.length (); unsigned int i; - struct loop *loop; + class loop *loop; vector_type = STMT_VINFO_VECTYPE (stmt_vinfo); @@ -4517,7 +4517,7 @@ vect_create_epilog_for_reduction (vec vect_defs, tree vectype; machine_mode mode; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo), *outer_loop = NULL; + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo), *outer_loop = NULL; basic_block exit_bb; tree scalar_dest; tree scalar_type; @@ -5955,7 +5955,7 @@ vectorize_fold_left_reduction (stmt_vec_info stmt_info, int reduc_index, vec_loop_masks *masks) { loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); tree vectype_out = STMT_VINFO_VECTYPE (stmt_info); stmt_vec_info new_stmt_info = NULL; internal_fn mask_reduc_fn = get_masked_reduction_fn (reduc_fn, vectype_in); @@ -6098,7 +6098,7 @@ vectorize_fold_left_reduction (stmt_vec_info stmt_info, does not cause overflow. */ static bool -is_nonwrapping_integer_induction (stmt_vec_info stmt_vinfo, struct loop *loop) +is_nonwrapping_integer_induction (stmt_vec_info stmt_vinfo, class loop *loop) { gphi *phi = as_a (stmt_vinfo->stmt); tree base = STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED (stmt_vinfo); @@ -6256,7 +6256,7 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, tree vectype_out = STMT_VINFO_VECTYPE (stmt_info); tree vectype_in = NULL_TREE; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); enum tree_code code, orig_code; internal_fn reduc_fn; machine_mode vec_mode; @@ -6280,7 +6280,7 @@ vectorizable_reduction (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, bool nested_cycle = false, found_nested_cycle_def = false; bool double_reduc = false; basic_block def_bb; - struct loop * def_stmt_loop; + class loop * def_stmt_loop; tree def_arg; auto_vec vec_oprnds0; auto_vec vec_oprnds1; @@ -7468,10 +7468,10 @@ vectorizable_induction (stmt_vec_info stmt_info, stmt_vector_for_cost *cost_vec) { loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); unsigned ncopies; bool nested_in_vect_loop = false; - struct loop *iv_loop; + class loop *iv_loop; tree vec_def; edge pe = loop_preheader_edge (loop); basic_block new_bb; @@ -8012,7 +8012,7 @@ vectorizable_live_operation (stmt_vec_info stmt_info, stmt_vector_for_cost *) { loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); imm_use_iterator imm_iter; tree lhs, lhs_type, bitsize, vec_bitsize; tree vectype = STMT_VINFO_VECTYPE (stmt_info); @@ -8220,7 +8220,7 @@ vectorizable_live_operation (stmt_vec_info stmt_info, /* Kill any debug uses outside LOOP of SSA names defined in STMT_INFO. */ static void -vect_loop_kill_debug_uses (struct loop *loop, stmt_vec_info stmt_info) +vect_loop_kill_debug_uses (class loop *loop, stmt_vec_info stmt_info) { ssa_op_iter op_iter; imm_use_iterator imm_iter; @@ -8276,7 +8276,7 @@ loop_niters_no_overflow (loop_vec_info loop_vinfo) } widest_int max; - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); /* Check the upper bound of loop niters. */ if (get_max_loop_iterations (loop, &max)) { @@ -8384,7 +8384,7 @@ vect_get_loop_mask (gimple_stmt_iterator *gsi, vec_loop_masks *masks, by factor VF. */ static void -scale_profile_for_vect_loop (struct loop *loop, unsigned vf) +scale_profile_for_vect_loop (class loop *loop, unsigned vf) { edge preheader = loop_preheader_edge (loop); /* Reduce loop iterations by the vectorization factor. */ @@ -8422,7 +8422,7 @@ static void vect_transform_loop_stmt (loop_vec_info loop_vinfo, stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, stmt_vec_info *seen_store) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo); if (dump_enabled_p ()) @@ -8467,11 +8467,11 @@ vect_transform_loop_stmt (loop_vec_info loop_vinfo, stmt_vec_info stmt_info, stmts in the loop, and update the loop exit condition. Returns scalar epilogue loop if any. */ -struct loop * +class loop * vect_transform_loop (loop_vec_info loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); - struct loop *epilogue = NULL; + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *epilogue = NULL; basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); int nbbs = loop->num_nodes; int i; @@ -8528,7 +8528,7 @@ vect_transform_loop (loop_vec_info loop_vinfo) versioning_threshold); check_profitability = false; } - struct loop *sloop + class loop *sloop = vect_loop_versioning (loop_vinfo, th, check_profitability, versioning_threshold); sloop->force_vectorize = false; @@ -8894,13 +8894,13 @@ vect_transform_loop (loop_vec_info loop_vinfo) */ void -optimize_mask_stores (struct loop *loop) +optimize_mask_stores (class loop *loop) { basic_block *bbs = get_loop_body (loop); unsigned nbbs = loop->num_nodes; unsigned i; basic_block bb; - struct loop *bb_loop; + class loop *bb_loop; gimple_stmt_iterator gsi; gimple *stmt; auto_vec worklist; @@ -9089,7 +9089,7 @@ widest_int vect_iv_limit_for_full_masking (loop_vec_info loop_vinfo) { tree niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); unsigned HOST_WIDE_INT max_vf = vect_max_vf (loop_vinfo); /* Calculate the value that the induction variable must be able diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 0157ba4..8430c98 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -859,7 +859,7 @@ vect_reassociating_reduction_p (stmt_vec_info stmt_info, tree_code code, /* We don't allow changing the order of the computation in the inner-loop when doing outer-loop vectorization. */ - struct loop *loop = LOOP_VINFO_LOOP (loop_info); + class loop *loop = LOOP_VINFO_LOOP (loop_info); if (loop && nested_in_vect_loop_p (loop, stmt_info)) return false; @@ -4664,7 +4664,7 @@ vect_determine_precisions (vec_info *vinfo) if (loop_vec_info loop_vinfo = dyn_cast (vinfo)) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); unsigned int nbbs = loop->num_nodes; @@ -4954,7 +4954,7 @@ vect_pattern_recog_1 (vect_recog_func *recog_func, stmt_vec_info stmt_info) void vect_pattern_recog (vec_info *vinfo) { - struct loop *loop; + class loop *loop; basic_block *bbs; unsigned int nbbs; gimple_stmt_iterator si; diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 1aaf10e..d172c3a 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -2019,7 +2019,7 @@ vect_analyze_slp_instance (vec_info *vinfo, else { /* Create a new SLP instance. */ - new_instance = XNEW (struct _slp_instance); + new_instance = XNEW (class _slp_instance); SLP_INSTANCE_TREE (new_instance) = node; SLP_INSTANCE_GROUP_SIZE (new_instance) = group_size; SLP_INSTANCE_UNROLLING_FACTOR (new_instance) = unrolling_factor; diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 10ce2a2..e921225 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -62,7 +62,7 @@ along with GCC; see the file COPYING3. If not see /* Return the vectorized type for the given statement. */ tree -stmt_vectype (struct _stmt_vec_info *stmt_info) +stmt_vectype (class _stmt_vec_info *stmt_info) { return STMT_VINFO_VECTYPE (stmt_info); } @@ -70,12 +70,12 @@ stmt_vectype (struct _stmt_vec_info *stmt_info) /* Return TRUE iff the given statement is in an inner loop relative to the loop being vectorized. */ bool -stmt_in_inner_loop_p (struct _stmt_vec_info *stmt_info) +stmt_in_inner_loop_p (class _stmt_vec_info *stmt_info) { gimple *stmt = STMT_VINFO_STMT (stmt_info); basic_block bb = gimple_bb (stmt); loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop* loop; + class loop* loop; if (!loop_vinfo) return false; @@ -297,7 +297,7 @@ static bool vect_stmt_relevant_p (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, enum vect_relevant *relevant, bool *live_p) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); ssa_op_iter op_iter; imm_use_iterator imm_iter; use_operand_p use_p; @@ -610,7 +610,7 @@ process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo, opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo, bool *fatal) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); unsigned int nbbs = loop->num_nodes; gimple_stmt_iterator si; @@ -1415,7 +1415,7 @@ vect_init_vector_1 (stmt_vec_info stmt_vinfo, gimple *new_stmt, if (loop_vinfo) { - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block new_bb; edge pe; @@ -2041,7 +2041,7 @@ vect_truncate_gather_scatter_offset (stmt_vec_info stmt_info, unsigned HOST_WIDE_INT count = vect_max_vf (loop_vinfo) - 1; /* Try lowering COUNT to the number of scalar latch iterations. */ - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); widest_int max_iters; if (max_loop_iterations (loop, &max_iters) && max_iters < count) @@ -2209,7 +2209,7 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp, { vec_info *vinfo = stmt_info->vinfo; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL; + class loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL; stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info); dr_vec_info *first_dr_info = STMT_VINFO_DR_INFO (first_stmt_info); unsigned int group_size = DR_GROUP_SIZE (first_stmt_info); @@ -2727,7 +2727,7 @@ vect_build_gather_load_calls (stmt_vec_info stmt_info, tree mask) { loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); tree vectype = STMT_VINFO_VECTYPE (stmt_info); poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype); int ncopies = vect_get_num_copies (loop_vinfo, vectype); @@ -2969,7 +2969,7 @@ vect_build_gather_load_calls (stmt_vec_info stmt_info, containing loop. */ static void -vect_get_gather_scatter_ops (struct loop *loop, stmt_vec_info stmt_info, +vect_get_gather_scatter_ops (class loop *loop, stmt_vec_info stmt_info, gather_scatter_info *gs_info, tree *dataref_ptr, tree *vec_offset) { @@ -3004,7 +3004,7 @@ vect_get_strided_load_store_ops (stmt_vec_info stmt_info, tree *dataref_bump, tree *vec_offset) { struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); - struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); tree vectype = STMT_VINFO_VECTYPE (stmt_info); gimple_seq stmts; @@ -3759,7 +3759,7 @@ struct simd_call_arg_info *ARGINFO. */ static void -vect_simd_lane_linear (tree op, struct loop *loop, +vect_simd_lane_linear (tree op, class loop *loop, struct simd_call_arg_info *arginfo) { gimple *def_stmt = SSA_NAME_DEF_STMT (op); @@ -3856,7 +3856,7 @@ vectorizable_simd_clone_call (stmt_vec_info stmt_info, loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info); vec_info *vinfo = stmt_info->vinfo; - struct loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL; + class loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL; tree fndecl, new_temp; int ncopies, j; auto_vec arginfo; @@ -7200,7 +7200,7 @@ vectorizable_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, tree vec_oprnd = NULL_TREE; tree elem_type; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = NULL; + class loop *loop = NULL; machine_mode vec_mode; tree dummy; enum dr_alignment_support alignment_support_scheme; @@ -8349,7 +8349,7 @@ permute_vec_elements (tree x, tree y, tree mask_vec, stmt_vec_info stmt_info, otherwise returns false. */ static bool -hoist_defs_of_uses (stmt_vec_info stmt_info, struct loop *loop) +hoist_defs_of_uses (stmt_vec_info stmt_info, class loop *loop) { ssa_op_iter i; tree op; @@ -8417,8 +8417,8 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, tree data_ref = NULL; stmt_vec_info prev_stmt_info; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *loop = NULL; - struct loop *containing_loop = gimple_bb (stmt_info->stmt)->loop_father; + class loop *loop = NULL; + class loop *containing_loop = gimple_bb (stmt_info->stmt)->loop_father; bool nested_in_vect_loop = false; tree elem_type; tree new_temp; @@ -8442,7 +8442,7 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, stmt_vec_info first_stmt_info; stmt_vec_info first_stmt_info_for_drptr = NULL; bool compute_in_loop = false; - struct loop *at_loop; + class loop *at_loop; int vec_num; bool slp = (slp_node != NULL); bool slp_perm = false; @@ -10811,7 +10811,7 @@ vect_transform_stmt (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, || STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_outer_by_reduction)) { - struct loop *innerloop = LOOP_VINFO_LOOP ( + class loop *innerloop = LOOP_VINFO_LOOP ( STMT_VINFO_LOOP_VINFO (stmt_info))->inner; imm_use_iterator imm_iter; use_operand_p use_p; @@ -11203,7 +11203,7 @@ supportable_widening_operation (enum tree_code code, stmt_vec_info stmt_info, vec *interm_types) { loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_info); - struct loop *vect_loop = NULL; + class loop *vect_loop = NULL; machine_mode vec_mode; enum insn_code icode1, icode2; optab optab1, optab2; diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 868dc5c..173e6b5 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -633,7 +633,7 @@ vec_info::replace_stmt (gimple_stmt_iterator *gsi, stmt_vec_info stmt_info, stmt_vec_info vec_info::new_stmt_vec_info (gimple *stmt) { - stmt_vec_info res = XCNEW (struct _stmt_vec_info); + stmt_vec_info res = XCNEW (class _stmt_vec_info); res->vinfo = this; res->stmt = stmt; @@ -714,7 +714,7 @@ vec_info::free_stmt_vec_info (stmt_vec_info stmt_info) clear loop constraint LOOP_C_FINITE. */ void -vect_free_loop_info_assumptions (struct loop *loop) +vect_free_loop_info_assumptions (class loop *loop) { scev_reset_htab (); /* We need to explicitly reset upper bound information since they are @@ -729,7 +729,7 @@ vect_free_loop_info_assumptions (struct loop *loop) guarding it. */ gimple * -vect_loop_vectorized_call (struct loop *loop, gcond **cond) +vect_loop_vectorized_call (class loop *loop, gcond **cond) { basic_block bb = loop_preheader_edge (loop)->src; gimple *g; @@ -765,11 +765,11 @@ vect_loop_vectorized_call (struct loop *loop, gcond **cond) internal call. */ static gimple * -vect_loop_dist_alias_call (struct loop *loop) +vect_loop_dist_alias_call (class loop *loop) { basic_block bb; basic_block entry; - struct loop *outer, *orig; + class loop *outer, *orig; gimple_stmt_iterator gsi; gimple *g; @@ -824,7 +824,7 @@ set_uid_loop_bbs (loop_vec_info loop_vinfo, gimple *loop_vectorized_call) tree arg = gimple_call_arg (loop_vectorized_call, 1); basic_block *bbs; unsigned int i; - struct loop *scalar_loop = get_loop (cfun, tree_to_shwi (arg)); + class loop *scalar_loop = get_loop (cfun, tree_to_shwi (arg)); LOOP_VINFO_SCALAR_LOOP (loop_vinfo) = scalar_loop; gcc_checking_assert (vect_loop_vectorized_call (scalar_loop) @@ -1047,7 +1047,7 @@ vectorize_loops (void) unsigned int i; unsigned int num_vectorized_loops = 0; unsigned int vect_loops_num; - struct loop *loop; + class loop *loop; hash_table *simduid_to_vf_htab = NULL; hash_table *simd_array_to_simduid_htab = NULL; bool any_ifcvt_loops = false; @@ -1098,7 +1098,7 @@ vectorize_loops (void) && vect_loop_vectorized_call (loop->inner)) { tree arg = gimple_call_arg (loop_vectorized_call, 0); - struct loop *vector_loop + class loop *vector_loop = get_loop (cfun, tree_to_shwi (arg)); if (vector_loop && vector_loop != loop) { diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 6e76b7e..1456cde 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -21,7 +21,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_VECTORIZER_H #define GCC_TREE_VECTORIZER_H -typedef struct _stmt_vec_info *stmt_vec_info; +typedef class _stmt_vec_info *stmt_vec_info; #include "tree-data-ref.h" #include "tree-hash-traits.h" @@ -227,7 +227,7 @@ public: stmt_vec_info lookup_stmt (gimple *); stmt_vec_info lookup_def (tree); stmt_vec_info lookup_single_use (tree); - struct dr_vec_info *lookup_dr (data_reference *); + class dr_vec_info *lookup_dr (data_reference *); void move_dr (stmt_vec_info, stmt_vec_info); void remove_stmt (stmt_vec_info); void replace_stmt (gimple_stmt_iterator *, stmt_vec_info, gimple *); @@ -262,8 +262,8 @@ private: void free_stmt_vec_info (stmt_vec_info); }; -struct _loop_vec_info; -struct _bb_vec_info; +class _loop_vec_info; +class _bb_vec_info; template<> template<> @@ -383,11 +383,11 @@ typedef auto_vec vec_loop_masks; /*-----------------------------------------------------------------*/ typedef class _loop_vec_info : public vec_info { public: - _loop_vec_info (struct loop *, vec_info_shared *); + _loop_vec_info (class loop *, vec_info_shared *); ~_loop_vec_info (); /* The loop to which this info struct refers to. */ - struct loop *loop; + class loop *loop; /* The loop basic blocks. */ basic_block *bbs; @@ -445,7 +445,7 @@ public: tree iv_type; /* Unknown DRs according to which loop was peeled. */ - struct dr_vec_info *unaligned_dr; + class dr_vec_info *unaligned_dr; /* peeling_for_alignment indicates whether peeling for alignment will take place, and what the peeling factor should be: @@ -558,7 +558,7 @@ public: /* If if-conversion versioned this loop before conversion, this is the loop version without if-conversion. */ - struct loop *scalar_loop; + class loop *scalar_loop; /* For loops being epilogues of already vectorized loops this points to the original vectorized loop. Otherwise NULL. */ @@ -650,7 +650,7 @@ public: typedef opt_pointer_wrapper opt_loop_vec_info; static inline loop_vec_info -loop_vec_info_for_loop (struct loop *loop) +loop_vec_info_for_loop (class loop *loop) { return (loop_vec_info) loop->aux; } @@ -1112,7 +1112,7 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo) && TYPE_UNSIGNED (TYPE))) static inline bool -nested_in_vect_loop_p (struct loop *loop, stmt_vec_info stmt_info) +nested_in_vect_loop_p (class loop *loop, stmt_vec_info stmt_info) { return (loop->inner && (loop->inner == (gimple_bb (stmt_info->stmt))->loop_father)); @@ -1206,7 +1206,7 @@ int vect_get_stmt_cost (enum vect_cost_for_stmt type_of_cost) /* Alias targetm.vectorize.init_cost. */ static inline void * -init_cost (struct loop *loop_info) +init_cost (class loop *loop_info) { return targetm.vectorize.init_cost (loop_info); } @@ -1475,17 +1475,17 @@ class auto_purge_vect_location /* Simple loop peeling and versioning utilities for vectorizer's purposes - in tree-vect-loop-manip.c. */ -extern void vect_set_loop_condition (struct loop *, loop_vec_info, +extern void vect_set_loop_condition (class loop *, loop_vec_info, tree, tree, tree, bool); -extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge); -struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *, - struct loop *, edge); -struct loop *vect_loop_versioning (loop_vec_info, unsigned int, bool, +extern bool slpeel_can_duplicate_loop_p (const class loop *, const_edge); +class loop *slpeel_tree_duplicate_loop_to_edge_cfg (class loop *, + class loop *, edge); +class loop *vect_loop_versioning (loop_vec_info, unsigned int, bool, poly_uint64); -extern struct loop *vect_do_peeling (loop_vec_info, tree, tree, +extern class loop *vect_do_peeling (loop_vec_info, tree, tree, tree *, tree *, tree *, int, bool, bool); extern void vect_prepare_for_masked_peels (loop_vec_info); -extern dump_user_location_t find_loop_location (struct loop *); +extern dump_user_location_t find_loop_location (class loop *); extern bool vect_can_advance_ivs_p (loop_vec_info); /* In tree-vect-stmts.c. */ @@ -1544,7 +1544,7 @@ extern void vect_get_store_cost (stmt_vec_info, int, extern bool vect_supportable_shift (enum tree_code, tree); extern tree vect_gen_perm_mask_any (tree, const vec_perm_indices &); extern tree vect_gen_perm_mask_checked (tree, const vec_perm_indices &); -extern void optimize_mask_stores (struct loop*); +extern void optimize_mask_stores (class loop*); extern gcall *vect_gen_while (tree, tree, tree); extern tree vect_gen_while_not (gimple_seq *, tree, tree, tree); extern opt_result vect_get_vector_types_for_stmt (stmt_vec_info, tree *, @@ -1573,7 +1573,7 @@ extern opt_result vect_find_stmt_data_reference (loop_p, gimple *, vec *); extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *); extern void vect_record_base_alignments (vec_info *); -extern tree vect_create_data_ref_ptr (stmt_vec_info, tree, struct loop *, tree, +extern tree vect_create_data_ref_ptr (stmt_vec_info, tree, class loop *, tree, tree *, gimple_stmt_iterator *, gimple **, bool, tree = NULL_TREE, tree = NULL_TREE); @@ -1589,7 +1589,7 @@ extern void vect_permute_store_chain (vec ,unsigned int, stmt_vec_info, gimple_stmt_iterator *, vec *); extern tree vect_setup_realignment (stmt_vec_info, gimple_stmt_iterator *, tree *, enum dr_alignment_support, tree, - struct loop **); + class loop **); extern void vect_transform_grouped_load (stmt_vec_info, vec , int, gimple_stmt_iterator *); extern void vect_record_grouped_load_vectors (stmt_vec_info, vec); @@ -1608,7 +1608,7 @@ extern widest_int vect_iv_limit_for_full_masking (loop_vec_info loop_vinfo); extern bool check_reduction_path (dump_user_location_t, loop_p, gphi *, tree, enum tree_code); /* Drive for loop analysis stage. */ -extern opt_loop_vec_info vect_analyze_loop (struct loop *, +extern opt_loop_vec_info vect_analyze_loop (class loop *, loop_vec_info, vec_info_shared *); extern tree vect_build_loop_niters (loop_vec_info, bool * = NULL); @@ -1622,8 +1622,8 @@ extern tree vect_get_loop_mask (gimple_stmt_iterator *, vec_loop_masks *, unsigned int, tree, unsigned int); /* Drive for loop transformation stage. */ -extern struct loop *vect_transform_loop (loop_vec_info); -extern opt_loop_vec_info vect_analyze_loop_form (struct loop *, +extern class loop *vect_transform_loop (loop_vec_info); +extern opt_loop_vec_info vect_analyze_loop_form (class loop *, vec_info_shared *); extern bool vectorizable_live_operation (stmt_vec_info, gimple_stmt_iterator *, slp_tree, int, stmt_vec_info *, @@ -1671,8 +1671,8 @@ void vect_pattern_recog (vec_info *); /* In tree-vectorizer.c. */ unsigned vectorize_loops (void); -void vect_free_loop_info_assumptions (struct loop *); -gimple *vect_loop_vectorized_call (struct loop *, gcond **cond = NULL); +void vect_free_loop_info_assumptions (class loop *); +gimple *vect_loop_vectorized_call (class loop *, gcond **cond = NULL); #endif /* GCC_TREE_VECTORIZER_H */ diff --git a/gcc/tree.c b/gcc/tree.c index 7892c20..a609963 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -5130,7 +5130,7 @@ public: language data removed. The lists are held inside FLD. */ static void -add_tree_to_fld_list (tree t, struct free_lang_data_d *fld) +add_tree_to_fld_list (tree t, class free_lang_data_d *fld) { if (DECL_P (t)) fld->decls.safe_push (t); @@ -5143,7 +5143,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld) /* Push tree node T into FLD->WORKLIST. */ static inline void -fld_worklist_push (tree t, struct free_lang_data_d *fld) +fld_worklist_push (tree t, class free_lang_data_d *fld) { if (t && !is_lang_specific (t) && !fld->pset.contains (t)) fld->worklist.safe_push ((t)); @@ -5197,7 +5197,7 @@ fld_type_variant_equal_p (tree t, tree v, tree inner_type) Set TREE_TYPE to INNER_TYPE if non-NULL. */ static tree -fld_type_variant (tree first, tree t, struct free_lang_data_d *fld, +fld_type_variant (tree first, tree t, class free_lang_data_d *fld, tree inner_type = NULL) { if (first == TYPE_MAIN_VARIANT (t)) @@ -5242,7 +5242,7 @@ static hash_map *fld_simplified_types; static tree fld_process_array_type (tree t, tree t2, hash_map *map, - struct free_lang_data_d *fld) + class free_lang_data_d *fld) { if (TREE_TYPE (t) == t2) return t; @@ -5291,7 +5291,7 @@ fld_decl_context (tree ctx) Return T if no simplification is possible. */ static tree -fld_incomplete_type_of (tree t, struct free_lang_data_d *fld) +fld_incomplete_type_of (tree t, class free_lang_data_d *fld) { if (!t) return NULL; @@ -5383,7 +5383,7 @@ fld_incomplete_type_of (tree t, struct free_lang_data_d *fld) types. */ static tree -fld_simplified_type (tree t, struct free_lang_data_d *fld) +fld_simplified_type (tree t, class free_lang_data_d *fld) { if (!t) return t; @@ -5441,7 +5441,7 @@ free_lang_data_in_binfo (tree binfo) /* Reset all language specific information still present in TYPE. */ static void -free_lang_data_in_type (tree type, struct free_lang_data_d *fld) +free_lang_data_in_type (tree type, class free_lang_data_d *fld) { gcc_assert (TYPE_P (type)); @@ -5657,7 +5657,7 @@ need_assembler_name_p (tree decl) DECL. */ static void -free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld) +free_lang_data_in_decl (tree decl, class free_lang_data_d *fld) { gcc_assert (DECL_P (decl)); @@ -5821,7 +5821,7 @@ static tree find_decls_types_r (tree *tp, int *ws, void *data) { tree t = *tp; - struct free_lang_data_d *fld = (struct free_lang_data_d *) data; + class free_lang_data_d *fld = (class free_lang_data_d *) data; if (TREE_CODE (t) == TREE_LIST) return NULL_TREE; @@ -5977,7 +5977,7 @@ find_decls_types_r (tree *tp, int *ws, void *data) /* Find decls and types in T. */ static void -find_decls_types (tree t, struct free_lang_data_d *fld) +find_decls_types (tree t, class free_lang_data_d *fld) { while (1) { @@ -6019,7 +6019,7 @@ get_eh_types_for_runtime (tree list) FLD->DECLS and FLD->TYPES. */ static void -find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld) +find_decls_types_in_eh_region (eh_region r, class free_lang_data_d *fld) { switch (r->type) { @@ -6062,7 +6062,7 @@ find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld) NAMESPACE_DECLs, etc). */ static void -find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) +find_decls_types_in_node (struct cgraph_node *n, class free_lang_data_d *fld) { basic_block bb; struct function *fn; @@ -6131,7 +6131,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) NAMESPACE_DECLs, etc). */ static void -find_decls_types_in_var (varpool_node *v, struct free_lang_data_d *fld) +find_decls_types_in_var (varpool_node *v, class free_lang_data_d *fld) { find_decls_types (v->decl, fld); } @@ -6182,7 +6182,7 @@ assign_assembler_name_if_needed (tree t) been set up. */ static void -free_lang_data_in_cgraph (struct free_lang_data_d *fld) +free_lang_data_in_cgraph (class free_lang_data_d *fld) { struct cgraph_node *n; varpool_node *v; @@ -6223,7 +6223,7 @@ static unsigned free_lang_data (void) { unsigned i; - struct free_lang_data_d fld; + class free_lang_data_d fld; /* If we are the LTO frontend we have freed lang-specific data already. */ if (in_lto_p diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 66c4bba..32e6ddd 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -345,7 +345,7 @@ stream_out_histogram_value (struct output_block *ob, histogram_value hist) /* Dump information about HIST to DUMP_FILE. */ void -stream_in_histogram_value (struct lto_input_block *ib, gimple *stmt) +stream_in_histogram_value (class lto_input_block *ib, gimple *stmt) { enum hist_type type; unsigned int ncounters = 0; diff --git a/gcc/value-prof.h b/gcc/value-prof.h index 9f69d7d..ca846d0 100644 --- a/gcc/value-prof.h +++ b/gcc/value-prof.h @@ -108,7 +108,7 @@ extern void gimple_gen_time_profiler (unsigned, unsigned); extern void gimple_gen_average_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_ior_profiler (histogram_value, unsigned, unsigned); extern void stream_out_histogram_value (struct output_block *, histogram_value); -extern void stream_in_histogram_value (struct lto_input_block *, gimple *); +extern void stream_in_histogram_value (class lto_input_block *, gimple *); extern struct cgraph_node* find_func_by_profile_id (int func_id); diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 65df25d..67f25c1 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -1031,7 +1031,7 @@ use_narrower_mode (rtx x, scalar_int_mode mode, scalar_int_mode wmode) static rtx adjust_mems (rtx loc, const_rtx old_rtx, void *data) { - struct adjust_mem_data *amd = (struct adjust_mem_data *) data; + class adjust_mem_data *amd = (class adjust_mem_data *) data; rtx mem, addr = loc, tem; machine_mode mem_mode_save; bool store_save; @@ -6389,7 +6389,7 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn) if (!frame_pointer_needed) { - struct adjust_mem_data amd; + class adjust_mem_data amd; amd.mem_mode = VOIDmode; amd.stack_adjust = -VTI (bb)->out.stack_adjust; amd.store = true; @@ -8330,8 +8330,8 @@ static inline rtx vt_expand_var_loc_chain (variable *var, bitmap regs, void *data, bool *pendrecp) { - struct expand_loc_callback_data *elcd - = (struct expand_loc_callback_data *) data; + class expand_loc_callback_data *elcd + = (class expand_loc_callback_data *) data; location_chain *loc, *next; rtx result = NULL; int first_child, result_first_child, last_child; @@ -8469,8 +8469,8 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth ATTRIBUTE_UNUSED, void *data) { - struct expand_loc_callback_data *elcd - = (struct expand_loc_callback_data *) data; + class expand_loc_callback_data *elcd + = (class expand_loc_callback_data *) data; decl_or_value dv; variable *var; rtx result, subreg; @@ -8627,7 +8627,7 @@ resolve_expansions_pending_recursion (vec *pending) static rtx vt_expand_loc (rtx loc, variable_table_type *vars) { - struct expand_loc_callback_data data; + class expand_loc_callback_data data; rtx result; if (!MAY_HAVE_DEBUG_BIND_INSNS) @@ -8649,7 +8649,7 @@ vt_expand_loc (rtx loc, variable_table_type *vars) static rtx vt_expand_1pvar (variable *var, variable_table_type *vars) { - struct expand_loc_callback_data data; + class expand_loc_callback_data data; rtx loc; gcc_checking_assert (var->onepart && var->n_var_parts == 1); diff --git a/gcc/varasm.c b/gcc/varasm.c index 827a370..e886cdc 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -68,8 +68,8 @@ extern GTY(()) const char *weak_global_object_name; const char *first_global_object_name; const char *weak_global_object_name; -struct addr_const; -struct constant_descriptor_rtx; +class addr_const; +class constant_descriptor_rtx; struct rtx_constant_pool; #define n_deferred_constants (crtl->varasm.deferred_constants) @@ -105,7 +105,7 @@ static int contains_pointers_p (tree); #ifdef ASM_OUTPUT_EXTERNAL static bool incorporeal_function_p (tree); #endif -static void decode_addr_const (tree, struct addr_const *); +static void decode_addr_const (tree, class addr_const *); static hashval_t const_hash_1 (const tree); static int compare_constant (const tree, const tree); static void output_constant_def_contents (rtx); @@ -2906,7 +2906,7 @@ public: }; static void -decode_addr_const (tree exp, struct addr_const *value) +decode_addr_const (tree exp, class addr_const *value) { tree target = TREE_OPERAND (exp, 0); poly_int64 offset = 0; @@ -3076,7 +3076,7 @@ const_hash_1 (const tree exp) /* Fallthru. */ case FDESC_EXPR: { - struct addr_const value; + class addr_const value; decode_addr_const (exp, &value); switch (GET_CODE (value.base)) @@ -3272,7 +3272,7 @@ compare_constant (const tree t1, const tree t2) case ADDR_EXPR: case FDESC_EXPR: { - struct addr_const value1, value2; + class addr_const value1, value2; enum rtx_code code; int ret; @@ -3624,7 +3624,7 @@ tree_output_constant_def (tree exp) class GTY((chain_next ("%h.next"), for_user)) constant_descriptor_rtx { public: - struct constant_descriptor_rtx *next; + class constant_descriptor_rtx *next; rtx mem; rtx sym; rtx constant; @@ -3651,8 +3651,8 @@ struct const_rtx_desc_hasher : ggc_ptr_hash struct GTY(()) rtx_constant_pool { /* Pointers to first and last constant in pool, as ordered by offset. */ - struct constant_descriptor_rtx *first; - struct constant_descriptor_rtx *last; + class constant_descriptor_rtx *first; + class constant_descriptor_rtx *last; /* Hash facility for making memory-constants from constant rtl-expressions. It is used on RISC machines where immediate integer arguments and @@ -3812,7 +3812,7 @@ simplify_subtraction (rtx x) rtx force_const_mem (machine_mode in_mode, rtx x) { - struct constant_descriptor_rtx *desc, tmp; + class constant_descriptor_rtx *desc, tmp; struct rtx_constant_pool *pool; char label[256]; rtx def, symbol; @@ -3920,7 +3920,7 @@ get_pool_constant (const_rtx addr) rtx get_pool_constant_mark (rtx addr, bool *pmarked) { - struct constant_descriptor_rtx *desc; + class constant_descriptor_rtx *desc; desc = SYMBOL_REF_CONSTANT (addr); *pmarked = (desc->mark != 0); @@ -4028,7 +4028,7 @@ output_constant_pool_2 (fixed_size_mode mode, rtx x, unsigned int align) giving it ALIGN bits of alignment. */ static void -output_constant_pool_1 (struct constant_descriptor_rtx *desc, +output_constant_pool_1 (class constant_descriptor_rtx *desc, unsigned int align) { rtx x, tmp; @@ -4105,7 +4105,7 @@ output_constant_pool_1 (struct constant_descriptor_rtx *desc, static void recompute_pool_offsets (struct rtx_constant_pool *pool) { - struct constant_descriptor_rtx *desc; + class constant_descriptor_rtx *desc; pool->offset = 0; for (desc = pool->first; desc ; desc = desc->next) @@ -4134,7 +4134,7 @@ mark_constants_in_pattern (rtx insn) { if (CONSTANT_POOL_ADDRESS_P (x)) { - struct constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x); + class constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x); if (desc->mark == 0) { desc->mark = 1; @@ -4203,7 +4203,7 @@ mark_constant_pool (void) static void output_constant_pool_contents (struct rtx_constant_pool *pool) { - struct constant_descriptor_rtx *desc; + class constant_descriptor_rtx *desc; for (desc = pool->first; desc ; desc = desc->next) if (desc->mark) @@ -7452,7 +7452,7 @@ void place_block_symbol (rtx symbol) { unsigned HOST_WIDE_INT size, mask, offset; - struct constant_descriptor_rtx *desc; + class constant_descriptor_rtx *desc; unsigned int alignment; struct object_block *block; tree decl; @@ -7614,7 +7614,7 @@ get_section_anchor (struct object_block *block, HOST_WIDE_INT offset, static void output_object_block (struct object_block *block) { - struct constant_descriptor_rtx *desc; + class constant_descriptor_rtx *desc; unsigned int i; HOST_WIDE_INT offset; tree decl; diff --git a/gcc/vr-values.c b/gcc/vr-values.c index 3f20c1a..9a4aea0 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -1711,7 +1711,7 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val, for VAR. If so, update VR with the new limits. */ void -vr_values::adjust_range_with_scev (value_range *vr, struct loop *loop, +vr_values::adjust_range_with_scev (value_range *vr, class loop *loop, gimple *stmt, tree var) { tree init, step, chrec, tmin, tmax, min, max, type, tem; @@ -2806,7 +2806,7 @@ vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result) value_range *lhs_vr = get_value_range (lhs); bool first = true; int edges, old_edges; - struct loop *l; + class loop *l; if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git a/gcc/vr-values.h b/gcc/vr-values.h index bd67f73..3856da1 100644 --- a/gcc/vr-values.h +++ b/gcc/vr-values.h @@ -46,7 +46,7 @@ class vr_values void set_defs_to_varying (gimple *); bool update_value_range (const_tree, value_range *); tree op_with_constant_singleton_value_range (tree); - void adjust_range_with_scev (value_range *, struct loop *, gimple *, tree); + void adjust_range_with_scev (value_range *, class loop *, gimple *, tree); tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *); void dump_all_value_ranges (FILE *); diff --git a/gcc/web.c b/gcc/web.c index 4a9bec0..dcc15ca 100644 --- a/gcc/web.c +++ b/gcc/web.c @@ -74,7 +74,7 @@ unionfind_union (web_entry_base *first, web_entry_base *second) return false; } -class web_entry : public web_entry_base +struct web_entry : public web_entry_base { private: rtx reg_pvt; diff --git a/gcc/wide-int.h b/gcc/wide-int.h index 18e76b7..bb8ced1 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -329,7 +329,7 @@ typedef generic_wide_int < fixed_wide_int_storage > /* wi::storage_ref can be a reference to a primitive type, so this is the conservatively-correct setting. */ template -struct wide_int_ref_storage; +class wide_int_ref_storage; typedef generic_wide_int > wide_int_ref; -- cgit v1.1 From 4faba5c3bc37c0bfceec6b254d76c5d0b3e2fe8b Mon Sep 17 00:00:00 2001 From: John Darrington Date: Tue, 9 Jul 2019 19:11:27 +0000 Subject: simplify-rtx.c (simplify_unary_operation_1): Use GET_MODE_PRECISION rather than GET_MODE_BITSIZE to better handle partial... 2019-07-09 John Darrington * simplify-rtx.c (simplify_unary_operation_1): Use GET_MODE_PRECISION rather than GET_MODE_BITSIZE to better handle partial integer modes. From-SVN: r273312 --- gcc/ChangeLog | 5 +++++ gcc/simplify-rtx.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3872b6d..2061c1b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 John Darrington + + * simplify-rtx.c (simplify_unary_operation_1): Use GET_MODE_PRECISION + rather than GET_MODE_BITSIZE to better handle partial integer modes. + 2019-07-09 Michael Meissner * config/rs6000/rs6000-internal.h (create_TOC_reference): Delete. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index dd2acd4..4892c49 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1504,12 +1504,12 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) && CONST_INT_P (XEXP (op, 1)) && XEXP (XEXP (op, 0), 1) == XEXP (op, 1) && (op_mode = as_a (GET_MODE (op)), - GET_MODE_BITSIZE (op_mode) > INTVAL (XEXP (op, 1)))) + GET_MODE_PRECISION (op_mode) > INTVAL (XEXP (op, 1)))) { scalar_int_mode tmode; - gcc_assert (GET_MODE_BITSIZE (int_mode) - > GET_MODE_BITSIZE (op_mode)); - if (int_mode_for_size (GET_MODE_BITSIZE (op_mode) + gcc_assert (GET_MODE_PRECISION (int_mode) + > GET_MODE_PRECISION (op_mode)); + if (int_mode_for_size (GET_MODE_PRECISION (op_mode) - INTVAL (XEXP (op, 1)), 1).exists (&tmode)) { rtx inner = -- cgit v1.1 From 4b1a1d981869346f5b98f78fa1f31acb58535932 Mon Sep 17 00:00:00 2001 From: Dragan Mladjenovic Date: Tue, 9 Jul 2019 21:20:57 +0000 Subject: cfgcleanup.c (old_insns_match_p): Check if used hard regs set is equal for both call instructions. 2019-07-09 Dragan Mladjenovic * cfgcleanup.c (old_insns_match_p): Check if used hard regs set is equal for both call instructions. 2019-07-09 Dragan Mladjenovic * gcc.target/mips/cfgcleanup-jalr1.c: New test. * gcc.target/mips/cfgcleanup-jalr2.c: New test. * gcc.target/mips/cfgcleanup-jalr3.c: New test. From-SVN: r273314 --- gcc/ChangeLog | 5 +++++ gcc/cfgcleanup.c | 9 +++++++++ gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.target/mips/cfgcleanup-jalr1.c | 19 +++++++++++++++++++ gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c | 23 +++++++++++++++++++++++ gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c | 23 +++++++++++++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 gcc/testsuite/gcc.target/mips/cfgcleanup-jalr1.c create mode 100644 gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c create mode 100644 gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2061c1b..71569bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Dragan Mladjenovic + + * cfgcleanup.c (old_insns_match_p): Check if used hard regs set is equal + for both call instructions. + 2019-07-09 John Darrington * simplify-rtx.c (simplify_unary_operation_1): Use GET_MODE_PRECISION diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 992912c..fca3a08 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "dce.h" #include "dbgcnt.h" #include "rtl-iter.h" +#include "regs.h" #define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK) @@ -1224,6 +1225,14 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx_insn *i1, rtx_insn *i2) } } } + + HARD_REG_SET i1_used, i2_used; + + get_call_reg_set_usage (i1, &i1_used, call_used_reg_set); + get_call_reg_set_usage (i2, &i2_used, call_used_reg_set); + + if (!hard_reg_set_equal_p (i1_used, i2_used)) + return dir_none; } /* If both i1 and i2 are frame related, verify all the CFA notes diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31e8a83..bf7c992 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Dragan Mladjenovic + + * gcc.target/mips/cfgcleanup-jalr1.c: New test. + * gcc.target/mips/cfgcleanup-jalr2.c: New test. + * gcc.target/mips/cfgcleanup-jalr3.c: New test. + 2019-07-09 Richard Biener PR tree-optimization/91114 diff --git a/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr1.c b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr1.c new file mode 100644 index 0000000..24c1826 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-mabicalls -fpic -mno-mips16 -mno-micromips" } */ +/* { dg-skip-if "needs codesize optimization" { *-*-* } { "-O0" "-O1" "-O2" "-O3" } { "" } } */ + +extern void foo (void*); + +extern void bar (void*); + +void +test (void* p) +{ + if (!p) + foo(p); + else + bar(p); +} + +/* { dg-final { scan-assembler-not "\\\.reloc\t1f,R_MIPS_JALR,foo" } } */ +/* { dg-final { scan-assembler-not "\\\.reloc\t1f,R_MIPS_JALR,bar" } } */ diff --git a/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c new file mode 100644 index 0000000..9fd75c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr2.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-mabicalls -fpic -mno-mips16 -mno-micromips" } */ +/* { dg-additional-options "-fno-inline -fipa-ra -mcompact-branches=never" } */ +/* { dg-skip-if "needs codesize optimization" { *-*-* } { "-O0" "-O1" "-O2" "-O3" } { "" } } */ + +static int foo (void* p) { __asm__ (""::"r"(p):"$t0"); return 0; } + +static int bar (void* p) { return 1; } + +int +test (void* p) +{ + int res = !p ? foo(p) : bar(p); + + register int tmp __asm__("$t0") = -1; + __asm__ (""::"r"(tmp)); + + return res; +} + +/* { dg-final { scan-assembler "\\\.reloc\t1f,R_MIPS_JALR,foo" } } */ +/* { dg-final { scan-assembler "\\\.reloc\t1f,R_MIPS_JALR,bar" } } */ +/* { dg-final { scan-assembler-not "\\.set\tnomacro\n\tjalr\t\\\$25" } } */ diff --git a/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c new file mode 100644 index 0000000..580c6ec --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/cfgcleanup-jalr3.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-mabicalls -fpic -mno-mips16 -mno-micromips" } */ +/* { dg-additional-options "-fno-inline -fipa-ra -mcompact-branches=never" } */ +/* { dg-skip-if "needs codesize optimization" { *-*-* } { "-O0" "-O1" "-O2" "-O3" } { "" } } */ + +static int foo (void* p) { return 0; } + +static int bar (void* p) { return 1; } + +int +test (void* p) +{ + int res = !p ? foo(p) : bar(p); + + register int tmp __asm__("$t0") = -1; + __asm__ (""::"r"(tmp)); + + return res; +} + +/* { dg-final { scan-assembler-not "\\\.reloc\t1f,R_MIPS_JALR,foo" } } */ +/* { dg-final { scan-assembler-not "\\\.reloc\t1f,R_MIPS_JALR,bar" } } */ +/* { dg-final { scan-assembler "\\.set\tnomacro\n\tjalr\t\\\$25" } } */ -- cgit v1.1 From a0aeb7fb93da156b64fd08391c79ff35a69af7ba Mon Sep 17 00:00:00 2001 From: Joern Rennecke Date: Tue, 9 Jul 2019 21:55:31 +0000 Subject: tree-vect-stmts.c (vectorizable_comparison): Swap operands only once. * tree-vect-stmts.c (vectorizable_comparison) : Swap operands only once. From-SVN: r273316 --- gcc/ChangeLog | 5 +++++ gcc/tree-vect-stmts.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 71569bf..4ae2fd8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Joern Rennecke + + * tree-vect-stmts.c (vectorizable_comparison) : + Swap operands only once. + 2019-07-09 Dragan Mladjenovic * cfgcleanup.c (old_insns_match_p): Check if used hard regs set is equal diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index e921225..601a6f5 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -10369,7 +10369,7 @@ vectorizable_comparison (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, if (!slp_node) { - if (swap_p) + if (swap_p && j == 0) std::swap (vec_rhs1, vec_rhs2); vec_oprnds0.quick_push (vec_rhs1); vec_oprnds1.quick_push (vec_rhs2); -- cgit v1.1 From c2e8bd51418b927c2b31f48aa9cd630d94a59b3a Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 9 Jul 2019 23:29:33 +0000 Subject: PR tree-optimization gcc/ChangeLog: PR tree-optimization * tree-ssa-strlen.c (handle_char_store): Constrain a single character optimization to just single character stores. gcc/testsuite/ChangeLog: PR tree-optimization * gcc.dg/strlenopt-26.c: Exit with test result status. * gcc.dg/strlenopt-67.c: New test. From-SVN: r273317 --- gcc/ChangeLog | 6 +++ gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/gcc.dg/strlenopt-26.c | 3 +- gcc/testsuite/gcc.dg/strlenopt-67.c | 104 ++++++++++++++++++++++++++++++++++++ gcc/tree-ssa-strlen.c | 52 +++++++++--------- 5 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/strlenopt-67.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4ae2fd8..f37b1f06 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Martin Sebor + + PR tree-optimization/90989 + * tree-ssa-strlen.c (handle_char_store): Constrain a single character + optimization to just single character stores. + 2019-07-09 Joern Rennecke * tree-vect-stmts.c (vectorizable_comparison) : diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bf7c992..b025521 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Martin Sebor + + PR tree-optimization/90989 + * gcc.dg/strlenopt-26.c: Exit with test result status. + * gcc.dg/strlenopt-67.c: New test. + 2019-07-09 Dragan Mladjenovic * gcc.target/mips/cfgcleanup-jalr1.c: New test. diff --git a/gcc/testsuite/gcc.dg/strlenopt-26.c b/gcc/testsuite/gcc.dg/strlenopt-26.c index da2f465..6bb0263 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-26.c +++ b/gcc/testsuite/gcc.dg/strlenopt-26.c @@ -17,8 +17,7 @@ main (void) { char p[] = "foobar"; const char *volatile q = "xyzzy"; - fn1 (p, q); - return 0; + return fn1 (p, q); } /* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-67.c b/gcc/testsuite/gcc.dg/strlenopt-67.c new file mode 100644 index 0000000..a2bcfba --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-67.c @@ -0,0 +1,104 @@ +/* PR tree-optimization/90989 - incorrrect strlen result after second strcpy + into the same destination. + { dg-do compile } + { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + +// #include "strlenopt.h" + +char a[4]; + +int f4 (void) +{ + char b[4]; + __builtin_strcpy (b, "12"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "123"); + if (__builtin_strlen (b) != 3) + __builtin_abort (); + + return i; +} + +int f6 (void) +{ + char b[6]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "12345"); + if (__builtin_strlen (b) != 5) + __builtin_abort (); + + return i; +} + +int f8 (void) +{ + char b[8]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "1234567"); + if (__builtin_strlen (b) != 7) + __builtin_abort (); + + return i; +} + +/* { dg-final { scan-tree-dump-times "abort|strlen" 0 "optimized" } } */ +/* PR tree-optimization/ - incorrrect strlen result after second strcpy + into the same destination. + { dg-do compile } + { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + +// #include "strlenopt.h" + +char a[4]; + +int f4 (void) +{ + char b[4]; + __builtin_strcpy (b, "12"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "123"); + if (__builtin_strlen (b) != 3) + __builtin_abort (); + + return i; +} + +int f6 (void) +{ + char b[6]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "12345"); + if (__builtin_strlen (b) != 5) + __builtin_abort (); + + return i; +} + +int f8 (void) +{ + char b[8]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "1234567"); + if (__builtin_strlen (b) != 7) + __builtin_abort (); + + return i; +} + +/* { dg-final { scan-tree-dump-times "abort|strlen" 0 "optimized" } } */ diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 74cd6c4..88b6bd7 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -3462,34 +3462,38 @@ handle_char_store (gimple_stmt_iterator *gsi) return false; } } - /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0', - and if we aren't storing '\0', we know that the length of the - string and any other zero terminated string in memory remains - the same. In that case we move to the next gimple statement and - return to signal the caller that it shouldn't invalidate anything. - - This is benefical for cases like: - - char p[20]; - void foo (char *q) - { - strcpy (p, "foobar"); - size_t len = strlen (p); // This can be optimized into 6 - size_t len2 = strlen (q); // This has to be computed - p[0] = 'X'; - size_t len3 = strlen (p); // This can be optimized into 6 - size_t len4 = strlen (q); // This can be optimized into len2 - bar (len, len2, len3, len4); - } - */ - else if (storing_nonzero_p && cmp > 0) + + if (cmp > 0 + && storing_nonzero_p + && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE) { + /* Handle a single non-nul character store. + If si->nonzero_chars > OFFSET, we aren't overwriting '\0', + and if we aren't storing '\0', we know that the length of the + string and any other zero terminated string in memory remains + the same. In that case we move to the next gimple statement and + return to signal the caller that it shouldn't invalidate anything. + + This is benefical for cases like: + + char p[20]; + void foo (char *q) + { + strcpy (p, "foobar"); + size_t len = strlen (p); // can be folded to 6 + size_t len2 = strlen (q); // has to be computed + p[0] = 'X'; + size_t len3 = strlen (p); // can be folded to 6 + size_t len4 = strlen (q); // can be folded to len2 + bar (len, len2, len3, len4); + } */ gsi_next (gsi); return false; } - else if (storing_all_zeros_p - || storing_nonzero_p - || (offset != 0 && cmp > 0)) + + if (storing_all_zeros_p + || storing_nonzero_p + || (offset != 0 && cmp > 0)) { /* When STORING_NONZERO_P, we know that the string will start with at least OFFSET + 1 nonzero characters. If storing -- cgit v1.1 From 1d00272bf2d32c13e3d9d5a100b956074f1e0320 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 10 Jul 2019 00:16:19 +0000 Subject: Daily bump. From-SVN: r273321 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 02c3d86..c3e1766 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190709 +20190710 -- cgit v1.1 From caa0705cb68fa63e5b2cce9d9fe3561f1ba23e58 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 10 Jul 2019 08:08:29 +0200 Subject: tree-ssa-alias.c (nonoverlapping_component_refs_p_1): Break out from ...; work also on duplicated types. * tree-ssa-alias.c (nonoverlapping_component_refs_p_1): Break out from ...; work also on duplicated types. (nonoverlapping_component_refs_since_match): ... here (ncr_type_uid): Break out from ... (ncr_compar): ... here; look for TYPE_UID of canonical type if available. (nonoverlapping_component_refs_p): Use same_type_for_tbaa to match the types and nonoverlapping_component_refs_p_1 to disambiguate. * g++.dg/lto/alias-3_0.C: New file. * g++.dg/lto/alias-3_1.c: New file. From-SVN: r273322 --- gcc/ChangeLog | 11 ++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/lto/alias-3_0.C | 27 +++++ gcc/testsuite/g++.dg/lto/alias-3_1.c | 20 ++++ gcc/tree-ssa-alias.c | 206 +++++++++++++++++++++++++---------- 5 files changed, 210 insertions(+), 59 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lto/alias-3_0.C create mode 100644 gcc/testsuite/g++.dg/lto/alias-3_1.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f37b1f06..2f98633 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2019-07-09 Jan Hubicka + + * tree-ssa-alias.c (nonoverlapping_component_refs_p_1): Break out + from ...; work also on duplicated types. + (nonoverlapping_component_refs_since_match): ... here + (ncr_type_uid): Break out from ... + (ncr_compar): ... here; look for TYPE_UID of canonical type if + available. + (nonoverlapping_component_refs_p): Use same_type_for_tbaa to match + the types and nonoverlapping_component_refs_p_1 to disambiguate. + 2019-07-09 Martin Sebor PR tree-optimization/90989 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b025521..c9fa127 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-09 Jan Hubicka + + * g++.dg/lto/alias-3_0.C: New file. + * g++.dg/lto/alias-3_1.c: New file. + 2019-07-09 Martin Sebor PR tree-optimization/90989 diff --git a/gcc/testsuite/g++.dg/lto/alias-3_0.C b/gcc/testsuite/g++.dg/lto/alias-3_0.C new file mode 100644 index 0000000..facba59 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/alias-3_0.C @@ -0,0 +1,27 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */ + +struct a +{ + int foo,bar; +}; +struct b +{ + struct a a[10]; +}; + +__attribute__ ((used)) struct b b, *bptr=&b, *bptr2=&b; +__attribute__ ((used)) int i,j; + +extern "C" void inline_me_late (void); + +int +main (void) +{ + int jj=j; + bptr2->a[jj].bar = 0; + inline_me_late (); + if (!__builtin_constant_p (bptr2->a[jj].bar == 0)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/lto/alias-3_1.c b/gcc/testsuite/g++.dg/lto/alias-3_1.c new file mode 100644 index 0000000..11b0268 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/alias-3_1.c @@ -0,0 +1,20 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */ +struct a +{ + int foo,bar; +}; +struct b +{ + struct a a[10]; +}; + +extern struct b *bptr; +extern int i; + +void +inline_me_late (void) +{ + bptr->a[i].foo=1; +} + diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index b5e980d..54e3a54 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1128,6 +1128,94 @@ aliasing_component_refs_p (tree ref1, return false; } +/* FIELD1 and FIELD2 are two fields of component refs. We assume + that bases of both component refs are either equivalent or nonoverlapping. + We do not assume that the containers of FIELD1 and FIELD2 are of the + same type or size. + + Return 0 in case the base address of component_refs are same then + FIELD1 and FIELD2 have same address. Note that FIELD1 and FIELD2 + may not be of same type or size. + + Return 1 if FIELD1 and FIELD2 are non-overlapping. + + Return -1 otherwise. + + Main difference between 0 and -1 is to let + nonoverlapping_component_refs_since_match_p discover the semantically + equivalent part of the access path. + + Note that this function is used even with -fno-strict-aliasing + and makes use of no TBAA assumptions. */ + +static int +nonoverlapping_component_refs_p_1 (const_tree field1, const_tree field2) +{ + /* If both fields are of the same type, we could save hard work of + comparing offsets. */ + tree type1 = DECL_CONTEXT (field1); + tree type2 = DECL_CONTEXT (field2); + + if (TREE_CODE (type1) == RECORD_TYPE + && DECL_BIT_FIELD_REPRESENTATIVE (field1)) + field1 = DECL_BIT_FIELD_REPRESENTATIVE (field1); + if (TREE_CODE (type2) == RECORD_TYPE + && DECL_BIT_FIELD_REPRESENTATIVE (field2)) + field2 = DECL_BIT_FIELD_REPRESENTATIVE (field2); + + /* ??? Bitfields can overlap at RTL level so punt on them. + FIXME: RTL expansion should be fixed by adjusting the access path + when producing MEM_ATTRs for MEMs which are wider than + the bitfields similarly as done in set_mem_attrs_minus_bitpos. */ + if (DECL_BIT_FIELD (field1) && DECL_BIT_FIELD (field2)) + return -1; + + /* Assume that different FIELD_DECLs never overlap within a RECORD_TYPE. */ + if (type1 == type2 && TREE_CODE (type1) == RECORD_TYPE) + return field1 != field2; + + /* In common case the offsets and bit offsets will be the same. + However if frontends do not agree on the alignment, they may be + different even if they actually represent same address. + Try the common case first and if that fails calcualte the + actual bit offset. */ + if (tree_int_cst_equal (DECL_FIELD_OFFSET (field1), + DECL_FIELD_OFFSET (field2)) + && tree_int_cst_equal (DECL_FIELD_BIT_OFFSET (field1), + DECL_FIELD_BIT_OFFSET (field2))) + return 0; + + /* Note that it may be possible to use component_ref_field_offset + which would provide offsets as trees. However constructing and folding + trees is expensive and does not seem to be worth the compile time + cost. */ + + poly_uint64 offset1, offset2; + poly_uint64 bit_offset1, bit_offset2; + + if (poly_int_tree_p (DECL_FIELD_OFFSET (field1), &offset1) + && poly_int_tree_p (DECL_FIELD_OFFSET (field2), &offset2) + && poly_int_tree_p (DECL_FIELD_BIT_OFFSET (field1), &bit_offset1) + && poly_int_tree_p (DECL_FIELD_BIT_OFFSET (field2), &bit_offset2)) + { + offset1 = (offset1 << LOG2_BITS_PER_UNIT) + bit_offset1; + offset2 = (offset2 << LOG2_BITS_PER_UNIT) + bit_offset2; + + if (known_eq (offset1, offset2)) + return 0; + + poly_uint64 size1, size2; + + if (poly_int_tree_p (DECL_SIZE (field1), &size1) + && poly_int_tree_p (DECL_SIZE (field2), &size2) + && !ranges_maybe_overlap_p (offset1, size1, offset2, size2)) + return 1; + } + /* Resort to slower overlap checking by looking for matching types in + the middle of access path. */ + return -1; +} + /* Try to disambiguate REF1 and REF2 under the assumption that MATCH1 and MATCH2 either point to the same address or are disjoint. MATCH1 and MATCH2 are assumed to be ref in the access path of REF1 and REF2 @@ -1224,6 +1312,7 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, case the return value will precisely be false. */ while (true) { + bool seen_noncomponent_ref_p = false; do { if (component_refs1.is_empty ()) @@ -1233,6 +1322,8 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, return 0; } ref1 = component_refs1.pop (); + if (TREE_CODE (ref1) != COMPONENT_REF) + seen_noncomponent_ref_p = true; } while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref1, 0)))); @@ -1245,17 +1336,15 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, return 0; } ref2 = component_refs2.pop (); + if (TREE_CODE (ref2) != COMPONENT_REF) + seen_noncomponent_ref_p = true; } while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref2, 0)))); - /* Beware of BIT_FIELD_REF. */ - if (TREE_CODE (ref1) != COMPONENT_REF - || TREE_CODE (ref2) != COMPONENT_REF) - { - ++alias_stats - .nonoverlapping_component_refs_since_match_p_may_alias; - return -1; - } + /* BIT_FIELD_REF and VIEW_CONVERT_EXPR are taken off the vectors + earlier. */ + gcc_checking_assert (TREE_CODE (ref1) == COMPONENT_REF + && TREE_CODE (ref2) == COMPONENT_REF); tree field1 = TREE_OPERAND (ref1, 1); tree field2 = TREE_OPERAND (ref2, 1); @@ -1266,33 +1355,27 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, tree type1 = DECL_CONTEXT (field1); tree type2 = DECL_CONTEXT (field2); - /* We cannot disambiguate fields in a union or qualified union. */ - if (type1 != type2 || TREE_CODE (type1) != RECORD_TYPE) + /* If we skipped array refs on type of different sizes, we can + no longer be sure that there are not partial overlaps. */ + if (seen_noncomponent_ref_p + && !operand_equal_p (TYPE_SIZE (type1), TYPE_SIZE (type2), 0)) { - ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias; + ++alias_stats + .nonoverlapping_component_refs_since_match_p_may_alias; return -1; } - if (field1 != field2) + int cmp = nonoverlapping_component_refs_p_1 (field1, field2); + if (cmp == -1) { - /* A field and its representative need to be considered the - same. */ - if (DECL_BIT_FIELD_REPRESENTATIVE (field1) == field2 - || DECL_BIT_FIELD_REPRESENTATIVE (field2) == field1) - { - ++alias_stats - .nonoverlapping_component_refs_since_match_p_must_overlap; - return 0; - } - /* Different fields of the same record type cannot overlap. - ??? Bitfields can overlap at RTL level so punt on them. */ - if (DECL_BIT_FIELD (field1) && DECL_BIT_FIELD (field2)) - { - ++alias_stats - .nonoverlapping_component_refs_since_match_p_must_overlap; - return 0; - } - ++alias_stats.nonoverlapping_component_refs_since_match_p_no_alias; + ++alias_stats + .nonoverlapping_component_refs_since_match_p_may_alias; + return -1; + } + else if (cmp == 1) + { + ++alias_stats + .nonoverlapping_component_refs_since_match_p_no_alias; return 1; } } @@ -1301,6 +1384,24 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, return 0; } +/* Return TYPE_UID which can be used to match record types we consider + same for TBAA purposes. */ + +static inline int +ncr_type_uid (const_tree field) +{ + /* ??? We cannot simply use the type of operand #0 of the refs here + as the Fortran compiler smuggles type punning into COMPONENT_REFs + for common blocks instead of using unions like everyone else. */ + tree type = DECL_FIELD_CONTEXT (field); + /* With LTO types considered same_type_for_tbaa_p + from different translation unit may not have same + main variant. They however have same TYPE_CANONICAL. */ + if (TYPE_CANONICAL (type)) + return TYPE_UID (TYPE_CANONICAL (type)); + return TYPE_UID (type); +} + /* qsort compare function to sort FIELD_DECLs after their DECL_FIELD_CONTEXT TYPE_UID. */ @@ -1309,8 +1410,9 @@ ncr_compar (const void *field1_, const void *field2_) { const_tree field1 = *(const_tree *) const_cast (field1_); const_tree field2 = *(const_tree *) const_cast (field2_); - unsigned int uid1 = TYPE_UID (DECL_FIELD_CONTEXT (field1)); - unsigned int uid2 = TYPE_UID (DECL_FIELD_CONTEXT (field2)); + unsigned int uid1 = ncr_type_uid (field1); + unsigned int uid2 = ncr_type_uid (field2); + if (uid1 < uid2) return -1; else if (uid1 > uid2) @@ -1377,10 +1479,9 @@ nonoverlapping_component_refs_p (const_tree x, const_tree y) if (fieldsx.length () == 1 && fieldsy.length () == 1) { - if ((DECL_FIELD_CONTEXT (fieldsx[0]) - == DECL_FIELD_CONTEXT (fieldsy[0])) - && fieldsx[0] != fieldsy[0] - && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0]))) + if (same_type_for_tbaa (DECL_FIELD_CONTEXT (fieldsx[0]), + DECL_FIELD_CONTEXT (fieldsy[0])) == 1 + && nonoverlapping_component_refs_p_1 (fieldsx[0], fieldsy[0]) == 1) { ++alias_stats.nonoverlapping_component_refs_p_no_alias; return true; @@ -1413,31 +1514,18 @@ nonoverlapping_component_refs_p (const_tree x, const_tree y) { const_tree fieldx = fieldsx[i]; const_tree fieldy = fieldsy[j]; - tree typex = DECL_FIELD_CONTEXT (fieldx); - tree typey = DECL_FIELD_CONTEXT (fieldy); - if (typex == typey) + + /* We're left with accessing different fields of a structure, + no possible overlap. */ + if (same_type_for_tbaa (DECL_FIELD_CONTEXT (fieldx), + DECL_FIELD_CONTEXT (fieldy)) == 1 + && nonoverlapping_component_refs_p_1 (fieldx, fieldy) == 1) { - /* We're left with accessing different fields of a structure, - no possible overlap. */ - if (fieldx != fieldy) - { - /* A field and its representative need to be considered the - same. */ - if (DECL_BIT_FIELD_REPRESENTATIVE (fieldx) == fieldy - || DECL_BIT_FIELD_REPRESENTATIVE (fieldy) == fieldx) - ; - /* Different fields of the same record type cannot overlap. - ??? Bitfields can overlap at RTL level so punt on them. */ - else if (DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy)) - ; - else - { - ++alias_stats.nonoverlapping_component_refs_p_no_alias; - return true; - } - } + ++alias_stats.nonoverlapping_component_refs_p_no_alias; + return true; } - if (TYPE_UID (typex) < TYPE_UID (typey)) + + if (ncr_type_uid (fieldx) < ncr_type_uid (fieldy)) { i++; if (i == fieldsx.length ()) -- cgit v1.1 From a620ef15027baace38d591709474f1a9519ba657 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Wed, 10 Jul 2019 08:24:54 +0000 Subject: decl.c (get_type_quals, [...]): New. /cp 2019-07-10 Paolo Carlini * decl.c (get_type_quals, smallest_type_location (const cp_decl_specifier_seq*)): New. (check_tag_decl): Use smallest_type_location in error_at about multiple types in one declaration. (grokdeclarator): Use locations[ds_complex] in error_at about complex invalid; use locations[ds_storage_class] in error_at about static cdtor; use id_loc in error_at about flexible array member in union; use get_type_quals. /testsuite 2019-07-10 Paolo Carlini * g++.dg/diagnostic/complex-invalid-1.C: New. * g++.dg/diagnostic/static-cdtor-1.C: Likewise. * g++.dg/cpp1z/has-unique-obj-representations2.C: Test location too. * g++.dg/other/anon-union3.C: Adjust expected location. * g++.dg/parse/error8.C: Likewise. From-SVN: r273323 --- gcc/cp/ChangeLog | 11 +++++ gcc/cp/decl.c | 52 ++++++++++++++++------ gcc/testsuite/ChangeLog | 9 ++++ .../g++.dg/cpp1z/has-unique-obj-representations2.C | 2 +- .../g++.dg/diagnostic/complex-invalid-1.C | 1 + gcc/testsuite/g++.dg/diagnostic/static-cdtor-1.C | 5 +++ gcc/testsuite/g++.dg/other/anon-union3.C | 4 +- gcc/testsuite/g++.dg/parse/error8.C | 2 +- 8 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/complex-invalid-1.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/static-cdtor-1.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7609b20..bc788c1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2019-07-10 Paolo Carlini + + * decl.c (get_type_quals, + smallest_type_location (const cp_decl_specifier_seq*)): New. + (check_tag_decl): Use smallest_type_location in error_at about + multiple types in one declaration. + (grokdeclarator): Use locations[ds_complex] in error_at about + complex invalid; use locations[ds_storage_class] in error_at + about static cdtor; use id_loc in error_at about flexible + array member in union; use get_type_quals. + 2019-07-09 Martin Sebor PR c++/61339 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a178b22..dbcf681 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -100,6 +100,7 @@ static tree build_cp_library_fn (tree, enum tree_code, tree, int); static void store_parm_decls (tree); static void initialize_local_var (tree, tree); static void expand_static_init (tree, tree); +static location_t smallest_type_location (const cp_decl_specifier_seq*); /* The following symbols are subsumed in the cp_global_trees array, and listed here individually for documentation purposes. @@ -4802,6 +4803,24 @@ warn_misplaced_attr_for_class_type (location_t location, class_type, class_key_or_enum_as_string (class_type)); } +/* Returns the cv-qualifiers that apply to the type specified + by the DECLSPECS. */ + +static int +get_type_quals (const cp_decl_specifier_seq *declspecs) +{ + int type_quals = TYPE_UNQUALIFIED; + + if (decl_spec_seq_has_spec_p (declspecs, ds_const)) + type_quals |= TYPE_QUAL_CONST; + if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) + type_quals |= TYPE_QUAL_VOLATILE; + if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) + type_quals |= TYPE_QUAL_RESTRICT; + + return type_quals; +} + /* Make sure that a declaration with no declarator is well-formed, i.e. just declares a tagged type or anonymous union. @@ -4821,7 +4840,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs, bool error_p = false; if (declspecs->multiple_types_p) - error ("multiple types in one declaration"); + error_at (smallest_type_location (declspecs), + "multiple types in one declaration"); else if (declspecs->redefined_builtin_type) { if (!in_system_header_at (input_location)) @@ -10142,6 +10162,13 @@ smallest_type_location (int type_quals, const location_t* locations) return min_location (loc, locations[ds_type_spec]); } +static location_t +smallest_type_location (const cp_decl_specifier_seq *declspecs) +{ + int type_quals = get_type_quals (declspecs); + return smallest_type_location (type_quals, declspecs->locations); +} + /* Check that it's OK to declare a function with the indicated TYPE and TYPE_QUALS. SFK indicates the kind of special function (if any) that this function is. OPTYPE is the type given in a conversion @@ -10407,7 +10434,7 @@ grokdeclarator (const cp_declarator *declarator, a member function. */ cp_ref_qualifier rqual = REF_QUAL_NONE; /* cv-qualifiers that apply to the type specified by the DECLSPECS. */ - int type_quals = TYPE_UNQUALIFIED; + int type_quals = get_type_quals (declspecs); tree raises = NULL_TREE; int template_count = 0; tree returned_attrs = NULL_TREE; @@ -10454,13 +10481,6 @@ grokdeclarator (const cp_declarator *declarator, if (concept_p) constexpr_p = true; - if (decl_spec_seq_has_spec_p (declspecs, ds_const)) - type_quals |= TYPE_QUAL_CONST; - if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) - type_quals |= TYPE_QUAL_VOLATILE; - if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) - type_quals |= TYPE_QUAL_RESTRICT; - if (decl_context == FUNCDEF) funcdef_flag = true, decl_context = NORMAL; else if (decl_context == MEMFUNCDEF) @@ -10999,7 +11019,8 @@ grokdeclarator (const cp_declarator *declarator, if (decl_spec_seq_has_spec_p (declspecs, ds_complex)) { if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) - error ("complex invalid for %qs", name); + error_at (declspecs->locations[ds_complex], + "complex invalid for %qs", name); /* If a modifier is specified, the resulting complex is the complex form of TYPE. E.g, "complex short" is "complex short int". */ else if (type == integer_type_node) @@ -11578,9 +11599,12 @@ grokdeclarator (const cp_declarator *declarator, virtual. A constructor may not be static. A constructor may not be declared with ref-qualifier. */ if (staticp == 2) - error ((flags == DTOR_FLAG) - ? G_("destructor cannot be static member function") - : G_("constructor cannot be static member function")); + error_at (declspecs->locations[ds_storage_class], + (flags == DTOR_FLAG) + ? G_("destructor cannot be static member " + "function") + : G_("constructor cannot be static member " + "function")); if (memfn_quals) { error ((flags == DTOR_FLAG) @@ -12438,7 +12462,7 @@ grokdeclarator (const cp_declarator *declarator, && (TREE_CODE (ctype) == UNION_TYPE || TREE_CODE (ctype) == QUAL_UNION_TYPE)) { - error ("flexible array member in union"); + error_at (id_loc, "flexible array member in union"); type = error_mark_node; } else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c9fa127..430c508 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2019-07-10 Paolo Carlini + + * g++.dg/diagnostic/complex-invalid-1.C: New. + * g++.dg/diagnostic/static-cdtor-1.C: Likewise. + * g++.dg/cpp1z/has-unique-obj-representations2.C: Test location + too. + * g++.dg/other/anon-union3.C: Adjust expected location. + * g++.dg/parse/error8.C: Likewise. + 2019-07-09 Jan Hubicka * g++.dg/lto/alias-3_0.C: New file. diff --git a/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C index c4ae555..f1f3388 100644 --- a/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C +++ b/gcc/testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C @@ -1,7 +1,7 @@ struct S; struct T { S t; }; // { dg-error "incomplete type" } struct U { int u[sizeof (S)]; }; // { dg-error "incomplete type" } -union V { char c; char d[]; }; // { dg-error "flexible array member in union" } +union V { char c; char d[]; }; // { dg-error "24:flexible array member in union" } bool a = __has_unique_object_representations (S); // { dg-error "incomplete type" } bool b = __has_unique_object_representations (T); bool c = __has_unique_object_representations (U); diff --git a/gcc/testsuite/g++.dg/diagnostic/complex-invalid-1.C b/gcc/testsuite/g++.dg/diagnostic/complex-invalid-1.C new file mode 100644 index 0000000..5a61765 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/complex-invalid-1.C @@ -0,0 +1 @@ +__complex__ bool b; // { dg-error "1:complex invalid" } diff --git a/gcc/testsuite/g++.dg/diagnostic/static-cdtor-1.C b/gcc/testsuite/g++.dg/diagnostic/static-cdtor-1.C new file mode 100644 index 0000000..ae3fd56 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/static-cdtor-1.C @@ -0,0 +1,5 @@ +struct S +{ + static S(); // { dg-error "3:constructor" } + static ~S(); // { dg-error "3:destructor" } +}; diff --git a/gcc/testsuite/g++.dg/other/anon-union3.C b/gcc/testsuite/g++.dg/other/anon-union3.C index ca59d02..6f2946b 100644 --- a/gcc/testsuite/g++.dg/other/anon-union3.C +++ b/gcc/testsuite/g++.dg/other/anon-union3.C @@ -3,9 +3,9 @@ class C { auto union // { dg-error "storage class" "" { target { ! c++11 } } } - { // { dg-error "auto" "" { target c++11 } .-1 } + { // { dg-error "auto|multiple types" "" { target c++11 } .-1 } int a; - }; // { dg-error "multiple types" "" { target c++11 } } + }; register union // { dg-error "storage class" } { int b; diff --git a/gcc/testsuite/g++.dg/parse/error8.C b/gcc/testsuite/g++.dg/parse/error8.C index 61e42e0..135f078 100644 --- a/gcc/testsuite/g++.dg/parse/error8.C +++ b/gcc/testsuite/g++.dg/parse/error8.C @@ -5,5 +5,5 @@ struct A { friend typename struct B; }; // { dg-error "28:expected nested-name-specifier before 'struct'" "expected" { target *-*-* } 4 } -// { dg-error "35:multiple types in one declaration" "multiple" { target *-*-* } 4 } +// { dg-error "19:multiple types in one declaration" "multiple" { target *-*-* } 4 } // { dg-error "12:friend declaration does not name a class or function" "friend decl" { target *-*-* } 4 } -- cgit v1.1 From e9427de1bf3eb46ba1651a8fd2ce1feb7e8d63f1 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 10 Jul 2019 08:59:33 +0000 Subject: [Ada] Use renamings in GNATprove mode for side-effects extraction In the GNATprove mode for formal verification, prefer renamings over declaration of a constant to extract side-effects from expressions, whenever the constant could be of an owning type, as declaring a constant of an owning type has an effect on ownership which is undesirable. There is no impact on compilation. 2019-07-10 Yannick Moy gcc/ada/ * exp_util.adb (Remove_Side_Effects): Prefer renamings for objects of possible owning type in GNATprove mode. From-SVN: r273324 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_util.adb | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cb2acf3..db33d64 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Yannick Moy + + * exp_util.adb (Remove_Side_Effects): Prefer renamings for + objects of possible owning type in GNATprove mode. + 2019-07-09 Ed Schonberg * sem_ch3.adb (Analyze_Object_Declaration): If the object type diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index f131080..2d88ee9 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -11333,7 +11333,17 @@ package body Exp_Util is -- Generate: -- Rnn : Exp_Type renames Expr; - if Renaming_Req then + -- In GNATprove mode, we prefer to use renamings for intermediate + -- variables to definition of constants, due to the implicit move + -- operation that such a constant definition causes as part of the + -- support in GNATprove for ownership pointers. Hence we generate + -- a renaming for a reference to an object of a non-scalar type. + + if Renaming_Req + or else (GNATprove_Mode + and then Is_Object_Reference (Exp) + and then not Is_Scalar_Type (Exp_Type)) + then E := Make_Object_Renaming_Declaration (Loc, Defining_Identifier => Def_Id, -- cgit v1.1 From 3f833dc291c4ece5b7419e9dacf08b0831782693 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Wed, 10 Jul 2019 08:59:38 +0000 Subject: [Ada] Minor reformatting 2019-07-10 Gary Dismukes gcc/ada/ * exp_util.adb: Reformatting and a typo fix. From-SVN: r273325 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/exp_util.adb | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index db33d64..4aa59b6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-10 Gary Dismukes + + * exp_util.adb: Reformatting and a typo fix. + 2019-07-10 Yannick Moy * exp_util.adb (Remove_Side_Effects): Prefer renamings for diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 2d88ee9..e4fbd8b 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -343,7 +343,7 @@ package body Exp_Util is return; end if; - -- Case of zero/non-zero semantics or non-standard enumeration + -- Case of zero/nonzero semantics or nonstandard enumeration -- representation. In each case, we rewrite the node as: -- ityp!(N) /= False'Enum_Rep @@ -5618,7 +5618,7 @@ package body Exp_Util is -- We can retrieve primitive operations by name if it is an internal -- name. For equality we must check that both of its operands have -- the same type, to avoid confusion with user-defined equalities - -- than may have a non-symmetric signature. + -- than may have a asymmetric signature. exit when Chars (Op) = Name and then @@ -6822,8 +6822,8 @@ package body Exp_Util is N := Assoc_Node; P := Parent (Assoc_Node); - -- Non-subexpression case. Note that N is initially Empty in this case - -- (N is only guaranteed Non-Empty in the subexpr case). + -- Nonsubexpression case. Note that N is initially Empty in this case + -- (N is only guaranteed non-Empty in the subexpr case). else N := Empty; @@ -8345,7 +8345,7 @@ package body Exp_Util is S : Nat; begin - -- If component reference is for an array with non-static bounds, + -- If component reference is for an array with nonstatic bounds, -- then it is always aligned: we can only process unaligned arrays -- with static bounds (more precisely compile time known bounds). @@ -9067,7 +9067,7 @@ package body Exp_Util is then Constr_Root := Root_Typ; - -- At this point in the expansion, non-limited view of the type + -- At this point in the expansion, nonlimited view of the type -- must be available, otherwise the error will be reported later. if From_Limited_With (Constr_Root) @@ -9840,7 +9840,7 @@ package body Exp_Util is -- in the derivation chain starting from parent type Par_Typ leading to -- derived type Deriv_Typ. The returned value is one of the following: -- - -- * An entity which is either a discriminant or a non-discriminant + -- * An entity which is either a discriminant or a nondiscriminant -- name, and renames/constraints Discr. -- -- * An expression which constraints Discr @@ -11336,8 +11336,8 @@ package body Exp_Util is -- In GNATprove mode, we prefer to use renamings for intermediate -- variables to definition of constants, due to the implicit move -- operation that such a constant definition causes as part of the - -- support in GNATprove for ownership pointers. Hence we generate - -- a renaming for a reference to an object of a non-scalar type. + -- support in GNATprove for ownership pointers. Hence, we generate + -- a renaming for a reference to an object of a nonscalar type. if Renaming_Req or else (GNATprove_Mode @@ -11465,7 +11465,7 @@ package body Exp_Util is -- For expressions that denote names, we can use a renaming scheme. -- This is needed for correctness in the case of a volatile object of - -- a non-volatile type because the Make_Reference call of the "default" + -- a nonvolatile type because the Make_Reference call of the "default" -- approach would generate an illegal access value (an access value -- cannot designate such an object - see Analyze_Reference). @@ -11487,7 +11487,7 @@ package body Exp_Util is Name => Relocate_Node (Exp))); -- If this is a packed reference, or a selected component with - -- a non-standard representation, a reference to the temporary + -- a nonstandard representation, a reference to the temporary -- will be replaced by a copy of the original expression (see -- Exp_Ch2.Expand_Renaming). Otherwise the temporary must be -- elaborated by gigi, and is of course not to be replaced in-line @@ -12097,7 +12097,7 @@ package body Exp_Util is and then Nkind_In (N, N_Package_Body, N_Package_Specification); -- N is at the library level if the top-most context is a package and - -- the path taken to reach N does not inlcude non-package constructs. + -- the path taken to reach N does not include nonpackage constructs. begin case Nkind (N) is @@ -12784,7 +12784,7 @@ package body Exp_Util is -- Mark the assignment statement as elaboration code. This allows -- the early call region mechanism (see Sem_Elab) to properly - -- ignore such assignments even though they are non-preelaborable + -- ignore such assignments even though they are nonpreelaborable -- code. Set_Is_Elaboration_Code (Asn); -- cgit v1.1 From 19448640ac04e980ef665ae72bc3f106b4e5b6e0 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Wed, 10 Jul 2019 08:59:46 +0000 Subject: [Ada] Elaboration order v4.0 and linker switches This patch adds a missing functionality with respect to elaboration order v3.0. Units carry an attribute called Elab_Position which among other things controls the sorting of linker switches by gnatbind. Setting the proper position ensures the gnatbind will output the linker switches in an order compatible with what gnatlink expects. No simple test available as this requires a Windows cross-compiler. 2019-07-10 Hristian Kirtchev gcc/ada/ * bindo-elaborators.adb (Elaborate_Units): Set attribute Elab_Position of all elaborated units. (Set_Unit_Elaboration_Positions): New routine. From-SVN: r273326 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/bindo-elaborators.adb | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4aa59b6..0973593 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-10 Hristian Kirtchev + + * bindo-elaborators.adb (Elaborate_Units): Set attribute + Elab_Position of all elaborated units. + (Set_Unit_Elaboration_Positions): New routine. + 2019-07-10 Gary Dismukes * exp_util.adb: Reformatting and a typo fix. diff --git a/gcc/ada/bindo-elaborators.adb b/gcc/ada/bindo-elaborators.adb index 6d3a1e24..0d9f207 100644 --- a/gcc/ada/bindo-elaborators.adb +++ b/gcc/ada/bindo-elaborators.adb @@ -274,6 +274,10 @@ package body Bindo.Elaborators is -- Determine whether vertex Vertex of library graph G is suitable for -- weak elaboration. + procedure Set_Unit_Elaboration_Positions (Order : Unit_Id_Table); + pragma Inline (Set_Unit_Elaboration_Positions); + -- Set the ALI.Units positions of all elaboration units in order Order + procedure Trace_Component (G : Library_Graph; Comp : Component_Id; @@ -750,6 +754,11 @@ package body Bindo.Elaborators is if Status = Order_OK then Validate_Elaboration_Order (Order); + -- Set attribute Elab_Position of table ALI.Units for all units in + -- the elaboration order. + + Set_Unit_Elaboration_Positions (Order); + -- Output the dependencies among units when switch -e (output -- complete list of elaboration order dependencies) is active. @@ -1304,6 +1313,23 @@ package body Bindo.Elaborators is and then Is_Weakly_Elaborable_Vertex (G, Vertex); end Is_Suitable_Weakly_Elaborable_Vertex; + ------------------------------------ + -- Set_Unit_Elaboration_Positions -- + ------------------------------------ + + procedure Set_Unit_Elaboration_Positions (Order : Unit_Id_Table) is + U_Id : Unit_Id; + + begin + for Position in Unit_Id_Tables.First .. + Unit_Id_Tables.Last (Order) + loop + U_Id := Order.Table (Position); + + ALI.Units.Table (U_Id).Elab_Position := Position; + end loop; + end Set_Unit_Elaboration_Positions; + --------------------- -- Trace_Component -- --------------------- -- cgit v1.1 From ff3ee5e5ef8c91d94a0ff6236a46dc46a670f1c3 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Wed, 10 Jul 2019 08:59:55 +0000 Subject: [Ada] Spurious error on overloaded equality in postcondition This patch fixes a spurious error in a postcondition in a nested instantiation when the expression includes an inherited equality and checks are enabled. 2019-07-10 Ed Schonberg gcc/ada/ * sem_res.adb (Resolve_Equality_Op): Do not replace the resolved operator by its alias if expander is not active, because the operand type may not be frozen yet and its inherited operations have not yet been created. gcc/testsuite/ * gnat.dg/equal8.adb, gnat.dg/equal8.ads, gnat.dg/equal8_pkg.ads: New testcase. From-SVN: r273327 --- gcc/ada/ChangeLog | 7 +++++ gcc/ada/sem_res.adb | 9 +++++- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gnat.dg/equal8.adb | 6 ++++ gcc/testsuite/gnat.dg/equal8.ads | 36 ++++++++++++++++++++++ gcc/testsuite/gnat.dg/equal8_pkg.ads | 58 ++++++++++++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/equal8.adb create mode 100644 gcc/testsuite/gnat.dg/equal8.ads create mode 100644 gcc/testsuite/gnat.dg/equal8_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0973593..762db94 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-10 Ed Schonberg + + * sem_res.adb (Resolve_Equality_Op): Do not replace the resolved + operator by its alias if expander is not active, because the + operand type may not be frozen yet and its inherited operations + have not yet been created. + 2019-07-10 Hristian Kirtchev * bindo-elaborators.adb (Elaborate_Units): Set attribute diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index d505bc5..4f56c53 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -8471,7 +8471,14 @@ package body Sem_Res is Get_Next_Interp (I, It); end loop; - if Present (Alias (Entity (N))) then + -- If expansion is active and this is wn inherited operation, + -- replace it with its ancestor. This must not be done during + -- preanalysis because the type nay not be frozen yet, as when + -- the context is a pre/post condition. + + if Present (Alias (Entity (N))) + and then Expander_Active + then Set_Entity (N, Alias (Entity (N))); end if; end; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 430c508..5c247f16 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Ed Schonberg + + * gnat.dg/equal8.adb, gnat.dg/equal8.ads, + gnat.dg/equal8_pkg.ads: New testcase. + 2019-07-10 Paolo Carlini * g++.dg/diagnostic/complex-invalid-1.C: New. diff --git a/gcc/testsuite/gnat.dg/equal8.adb b/gcc/testsuite/gnat.dg/equal8.adb new file mode 100644 index 0000000..9424abc --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal8.adb @@ -0,0 +1,6 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +package body Equal8 is + procedure Foo is null; +end Equal8; diff --git a/gcc/testsuite/gnat.dg/equal8.ads b/gcc/testsuite/gnat.dg/equal8.ads new file mode 100644 index 0000000..9b6694d --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal8.ads @@ -0,0 +1,36 @@ +with Ada.Containers.Formal_Hashed_Sets; +with Ada.Strings.Hash; + +-- with Dynamic_Strings; use Dynamic_Strings; +-- with Bounded_Dynamic_Strings; + +with Equal8_Pkg; + +package Equal8 is + + package Dynamic_Strings is + -- pragma SPARK_Mode (On); + + package Bounded_Dynamic_Strings is new Equal8_Pkg + (Component => Character, + List_Index => Positive, + List => String, + Default_Value => ' '); + type Dynamic_String is new Bounded_Dynamic_Strings.Sequence; + + end Dynamic_Strings; + use Dynamic_Strings; + + subtype Subscription_Address is Dynamic_String (Capacity => 255); + + function Hashed_Subscription_Address (Element : Subscription_Address) + return Ada.Containers.Hash_Type is + (Ada.Strings.Hash (Value (Element))); + + package Subscription_Addresses is new Ada.Containers.Formal_Hashed_Sets + (Element_Type => Subscription_Address, + Hash => Hashed_Subscription_Address, + Equivalent_Elements => "="); + + procedure Foo; +end Equal8; diff --git a/gcc/testsuite/gnat.dg/equal8_pkg.ads b/gcc/testsuite/gnat.dg/equal8_pkg.ads new file mode 100644 index 0000000..b454a2c --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal8_pkg.ads @@ -0,0 +1,58 @@ +generic + type Component is private; + type List_Index is range <>; + type List is array (List_Index range <>) of Component; + Default_Value : Component; + -- with function "=" (Left, Right : List) return Boolean is <>; + +package Equal8_Pkg is + + pragma Pure; + + Maximum_Length : constant List_Index := List_Index'Last; + + subtype Natural_Index is List_Index'Base range 0 .. Maximum_Length; + type Sequence (Capacity : Natural_Index) is private; + -- from zero to Capacity. + + function Value (This : Sequence) return List; + -- Returns the content of this sequence. The value returned is the + -- "logical" value in that only that slice which is currently assigned + -- is returned, as opposed to the entire physical representation. + + overriding + function "=" (Left, Right : Sequence) return Boolean with + Inline; + + function "=" (Left : Sequence; Right : List) return Boolean with + Inline; + +private + type Sequence (Capacity : Natural_Index) is record + Current_Length : Natural_Index := 0; + Content : List (1 .. Capacity) := (others => Default_Value); + end record; + + ----------- + -- Value -- + ----------- + + function Value (This : Sequence) return List is + (This.Content (1 .. This.Current_Length)); + + --------- + -- "=" -- + --------- + + overriding + function "=" (Left, Right : Sequence) return Boolean is + (Value (Left) = Value (Right)); + + --------- + -- "=" -- + --------- + + function "=" (Left : Sequence; Right : List) return Boolean is + (Value (Left) = Right); +end Equal8_Pkg; + -- cgit v1.1 From 5a6446841aa17a717f2f04ec22e507c86c864355 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Wed, 10 Jul 2019 09:00:16 +0000 Subject: [Ada] Missing implicit interface type conversion The compiler skips adding an implicit type conversion when the interface type is visible through a limited-with clause. No small reproducer available. 2019-07-10 Javier Miranda gcc/ada/ * exp_ch6.adb (Is_Class_Wide_Interface_Type): New subprogram. (Expand_Call_Helper): Handle non-limited views when we check if any formal is a class-wide interface type. * exp_disp.adb (Expand_Interface_Actuals): Handle non-limited views when we look for interface type formals to force "this" displacement. From-SVN: r273328 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/exp_ch6.adb | 40 +++++++++++++++++++++++++++++++--------- gcc/ada/exp_disp.adb | 16 ++++++++++++++++ 3 files changed, 56 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 762db94..389a12d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-10 Javier Miranda + + * exp_ch6.adb (Is_Class_Wide_Interface_Type): New subprogram. + (Expand_Call_Helper): Handle non-limited views when we check if + any formal is a class-wide interface type. + * exp_disp.adb (Expand_Interface_Actuals): Handle non-limited + views when we look for interface type formals to force "this" + displacement. + 2019-07-10 Ed Schonberg * sem_res.adb (Resolve_Equality_Op): Do not replace the resolved diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 364acd9..448f981 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -2331,6 +2331,10 @@ package body Exp_Ch6 is function In_Unfrozen_Instance (E : Entity_Id) return Boolean; -- Return true if E comes from an instance that is not yet frozen + function Is_Class_Wide_Interface_Type (E : Entity_Id) return Boolean; + -- Return True when E is a class-wide interface type or an access to + -- a class-wide interface type. + function Is_Direct_Deep_Call (Subp : Entity_Id) return Boolean; -- Determine if Subp denotes a non-dispatching call to a Deep routine @@ -2585,6 +2589,32 @@ package body Exp_Ch6 is return False; end In_Unfrozen_Instance; + ---------------------------------- + -- Is_Class_Wide_Interface_Type -- + ---------------------------------- + + function Is_Class_Wide_Interface_Type (E : Entity_Id) return Boolean is + Typ : Entity_Id := E; + DDT : Entity_Id; + + begin + if Has_Non_Limited_View (Typ) then + Typ := Non_Limited_View (Typ); + end if; + + if Ekind (Typ) = E_Anonymous_Access_Type then + DDT := Directly_Designated_Type (Typ); + + if Has_Non_Limited_View (DDT) then + DDT := Non_Limited_View (DDT); + end if; + + return Is_Class_Wide_Type (DDT) and then Is_Interface (DDT); + else + return Is_Class_Wide_Type (Typ) and then Is_Interface (Typ); + end if; + end Is_Class_Wide_Interface_Type; + ------------------------- -- Is_Direct_Deep_Call -- ------------------------- @@ -2919,15 +2949,7 @@ package body Exp_Ch6 is CW_Interface_Formals_Present := CW_Interface_Formals_Present - or else - (Is_Class_Wide_Type (Etype (Formal)) - and then Is_Interface (Etype (Etype (Formal)))) - or else - (Ekind (Etype (Formal)) = E_Anonymous_Access_Type - and then Is_Class_Wide_Type (Directly_Designated_Type - (Etype (Etype (Formal)))) - and then Is_Interface (Directly_Designated_Type - (Etype (Etype (Formal))))); + or else Is_Class_Wide_Interface_Type (Etype (Formal)); -- Create possible extra actual for constrained case. Usually, the -- extra actual is of the form actual'constrained, but since this diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index a659594..4fae37c 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -1682,18 +1682,34 @@ package body Exp_Disp is while Present (Formal) loop Formal_Typ := Etype (Formal); + if Has_Non_Limited_View (Formal_Typ) then + Formal_Typ := Non_Limited_View (Formal_Typ); + end if; + if Ekind (Formal_Typ) = E_Record_Type_With_Private then Formal_Typ := Full_View (Formal_Typ); end if; if Is_Access_Type (Formal_Typ) then Formal_DDT := Directly_Designated_Type (Formal_Typ); + + if Has_Non_Limited_View (Formal_DDT) then + Formal_DDT := Non_Limited_View (Formal_DDT); + end if; end if; Actual_Typ := Etype (Actual); + if Has_Non_Limited_View (Actual_Typ) then + Actual_Typ := Non_Limited_View (Actual_Typ); + end if; + if Is_Access_Type (Actual_Typ) then Actual_DDT := Directly_Designated_Type (Actual_Typ); + + if Has_Non_Limited_View (Actual_DDT) then + Actual_DDT := Non_Limited_View (Actual_DDT); + end if; end if; if Is_Interface (Formal_Typ) -- cgit v1.1 From 74b96685bb00766f8931c95d45d6e2c4d719cf1a Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 10 Jul 2019 09:00:48 +0000 Subject: [Ada] Fix crashes on ownership checking in SPARK Code that violates the conditions for ownership checking should lead to error messages pointing to the violations instead of crashes. There is no impact on compilation, only GNATprove. 2019-07-10 Yannick Moy gcc/ada/ * sem_spark.adb (Get_Root_Object): Replace precondition by error message. (Read_Indexes): Replace precondition by error message. (Check_Callable_Body): Check only traversal function returns an anonymous access type. (Check_Expression): Issue error on unexpected expression as path. * sem_util.adb (First_Global): Fix access to global on entry/task. From-SVN: r273329 --- gcc/ada/ChangeLog | 12 ++++++++++++ gcc/ada/sem_spark.adb | 26 +++++++++++++++++++++++--- gcc/ada/sem_util.adb | 19 ++++++++++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 389a12d..a5ba513 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,15 @@ +2019-07-10 Yannick Moy + + * sem_spark.adb (Get_Root_Object): Replace precondition by error + message. + (Read_Indexes): Replace precondition by error message. + (Check_Callable_Body): Check only traversal function returns an + anonymous access type. + (Check_Expression): Issue error on unexpected expression as + path. + * sem_util.adb (First_Global): Fix access to global on + entry/task. + 2019-07-10 Javier Miranda * exp_ch6.adb (Is_Class_Wide_Interface_Type): New subprogram. diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 70953b5..af7dcd5 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -714,7 +714,6 @@ package body Sem_SPARK is function Get_Root_Object (Expr : Node_Id; Through_Traversal : Boolean := True) return Entity_Id; - pragma Precondition (Is_Path_Expression (Expr)); -- Return the root of the path expression Expr, or Empty for an allocator, -- NULL, or a function call. Through_Traversal is True if it should follow -- through calls to traversal functions. @@ -1311,6 +1310,15 @@ package body Sem_SPARK is Inside_Elaboration := False; + if Ekind (Spec_Id) = E_Function + and then Is_Anonymous_Access_Type (Etype (Spec_Id)) + and then not Is_Traversal_Function (Spec_Id) + then + Error_Msg_N ("anonymous access type for result only allowed for " + & "traveral functions", Spec_Id); + return; + end if; + -- Save environment and put a new one in place Move_Env (Current_Perm_Env, Saved_Env); @@ -1451,7 +1459,6 @@ package body Sem_SPARK is -- Call Read_Expression on every expression in the list L procedure Read_Indexes (Expr : Node_Id); - pragma Precondition (Is_Path_Expression (Expr)); -- When processing a path, the index expressions and function call -- arguments occurring on the path should be analyzed in Read mode. @@ -1562,6 +1569,11 @@ package body Sem_SPARK is -- Start of processing for Read_Indexes begin + if not Is_Path_Expression (Expr) then + Error_Msg_N ("name expected here for move/borrow/observe", Expr); + return; + end if; + case N_Subexpr'(Nkind (Expr)) is when N_Identifier | N_Expanded_Name @@ -1710,7 +1722,10 @@ package body Sem_SPARK is -- Expressions that are not path expressions should only be analyzed in -- Read mode. - pragma Assert (Mode = Read); + if Mode /= Read then + Error_Msg_N ("name expected here for move/borrow/observe", Expr); + return; + end if; -- Special handling for nodes that may contain evaluated expressions in -- the form of constraints. @@ -3484,6 +3499,11 @@ package body Sem_SPARK is Through_Traversal : Boolean := True) return Entity_Id is begin + if not Is_Path_Expression (Expr) then + Error_Msg_N ("name expected here for path", Expr); + return Empty; + end if; + case Nkind (Expr) is when N_Expanded_Name | N_Identifier diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 19e0026..1c26634 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -8713,7 +8713,24 @@ package body Sem_Util is -- case, it can only be located on the body entity. if Refined then - Body_Id := Subprogram_Body_Entity (Subp); + if Is_Subprogram_Or_Generic_Subprogram (Subp) then + Body_Id := Subprogram_Body_Entity (Subp); + + elsif Is_Entry (Subp) + or else Is_Task_Type (Subp) + then + Body_Id := Corresponding_Body (Parent (Subp)); + + -- ??? It should be possible to retrieve the Refined_Global on the + -- task body associated to the task object. This is not yet possible. + + elsif Is_Single_Task_Object (Subp) then + Body_Id := Empty; + + else + Body_Id := Empty; + end if; + if Present (Body_Id) then Global := Get_Pragma (Body_Id, Pragma_Refined_Global); end if; -- cgit v1.1 From 9098d477ba81e9fba2c41611513bbd643f5caab1 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Wed, 10 Jul 2019 09:00:59 +0000 Subject: [Ada] Elaboration order v4.0 and cycle detection This patch introduces a new cycle detection algorithm which is based on Tarjan's "Enumeration of the Elementary Circuits of a Directed Graph" algorithm, with several ideas borrowed from Jonson's "Finding all the Elementary Circuits of a Directed Graph" algorithm. No need for a test because the new algorithm improves the performance of cycle detection only. 2019-07-10 Hristian Kirtchev gcc/ada/ * bindo.adb: Update the section on switches. * bindo-graphs.adb (Add_Cycle, Add_Vertex_And_Complement): Remove. (Create): The graph no longer needs a set of recorded cycles because the cycles are not rediscovered in permuted forms. (Cycle_End_Vertices): New routine. (Destroy): The graph no longer needs a set of recorded cycles because the cycles are not rediscovered in permuted forms. (Destroy_Library_Graph_Vertex): Move to the library level. (Find_All_Cycles_Through_Vertex, Find_All_Cycles_With_Edge): Remove. (Find_Cycles_From_Successor, Find_Cycles_From_Vertex, Find_Cycles_In_Component, Has_Elaborate_All_Edge): New routines. (Insert_And_Sort): Remove. (Is_Elaborate_Body_Edge): Use predicate Is_Vertex_With_Elaborate_Body. (Is_Recorded_Cycle): Remove. (Is_Vertex_With_Elaborate_Body): New routine. (Normalize_And_Add_Cycle): Remove. (Precedence): Rename to xxx_Precedence, where xxx relates to the input. These versions better reflect the desired input precedence. (Record_Cycle): New routine. (Remove_Vertex_And_Complement, Set_Is_Recorded_Cycle): Remove. (Trace_xxx): Update all versions to use debug switch -d_t. (Trace_Component): New routine. (Trace_Eol): Removed. (Trace_Vertex): Do not output the component as this information is already available when the component is traced. (Unvisit, Visit): New routine. * bindo-graphs.ads: Add new instance LGV_Lists. Remove instance RC_Sets. Update the structure of type Library_Graph_Attributes to remove the set of recorded cycles. (Destroy_Library_Graph_Vertex): Move to the library level. * bindo-writers.adb (Write_Component_Vertices): Output information about the number of vertices. * debug.adb: Document the use of binder switch -d_t. Update the use of binder switch -d_T. From-SVN: r273330 --- gcc/ada/ChangeLog | 41 + gcc/ada/bindo-graphs.adb | 2160 +++++++++++++++++++++++++++------------------ gcc/ada/bindo-graphs.ads | 28 +- gcc/ada/bindo-writers.adb | 35 +- gcc/ada/bindo.adb | 11 +- gcc/ada/debug.adb | 12 +- 6 files changed, 1402 insertions(+), 885 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a5ba513..ecbee09 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,44 @@ +2019-07-10 Hristian Kirtchev + + * bindo.adb: Update the section on switches. + * bindo-graphs.adb + (Add_Cycle, Add_Vertex_And_Complement): Remove. + (Create): The graph no longer needs a set of recorded cycles + because the cycles are not rediscovered in permuted forms. + (Cycle_End_Vertices): New routine. + (Destroy): The graph no longer needs a set of recorded cycles + because the cycles are not rediscovered in permuted forms. + (Destroy_Library_Graph_Vertex): Move to the library level. + (Find_All_Cycles_Through_Vertex, Find_All_Cycles_With_Edge): + Remove. + (Find_Cycles_From_Successor, Find_Cycles_From_Vertex, + Find_Cycles_In_Component, Has_Elaborate_All_Edge): New routines. + (Insert_And_Sort): Remove. + (Is_Elaborate_Body_Edge): Use predicate + Is_Vertex_With_Elaborate_Body. + (Is_Recorded_Cycle): Remove. + (Is_Vertex_With_Elaborate_Body): New routine. + (Normalize_And_Add_Cycle): Remove. + (Precedence): Rename to xxx_Precedence, where xxx relates to the + input. These versions better reflect the desired input + precedence. + (Record_Cycle): New routine. + (Remove_Vertex_And_Complement, Set_Is_Recorded_Cycle): Remove. + (Trace_xxx): Update all versions to use debug switch -d_t. + (Trace_Component): New routine. + (Trace_Eol): Removed. + (Trace_Vertex): Do not output the component as this information + is already available when the component is traced. + (Unvisit, Visit): New routine. + * bindo-graphs.ads: Add new instance LGV_Lists. Remove instance + RC_Sets. Update the structure of type Library_Graph_Attributes + to remove the set of recorded cycles. + (Destroy_Library_Graph_Vertex): Move to the library level. + * bindo-writers.adb (Write_Component_Vertices): Output + information about the number of vertices. + * debug.adb: Document the use of binder switch -d_t. Update the + use of binder switch -d_T. + 2019-07-10 Yannick Moy * sem_spark.adb (Get_Root_Object): Replace precondition by error diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index c3ae738..f1bfe47 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -94,6 +94,18 @@ package body Bindo.Graphs is null; end Destroy_Library_Graph_Edge; + ---------------------------------- + -- Destroy_Library_Graph_Vertex -- + ---------------------------------- + + procedure Destroy_Library_Graph_Vertex + (Vertex : in out Library_Graph_Vertex_Id) + is + pragma Unreferenced (Vertex); + begin + null; + end Destroy_Library_Graph_Vertex; + -------------------------------- -- Hash_Invocation_Graph_Edge -- -------------------------------- @@ -1047,16 +1059,6 @@ package body Bindo.Graphs is -- corresponding specs or bodies, where the body is a predecessor -- and the spec is a successor. Add all edges to list Edges. - procedure Add_Cycle - (G : Library_Graph; - Attrs : Library_Graph_Cycle_Attributes; - Indent : Indentation_Level); - pragma Inline (Add_Cycle); - -- Store a cycle described by attributes Attrs in library graph G, - -- unless a prior rotation of it already exists. The edges of the cycle - -- must be in normalized form. Indent is the desired indentation level - -- for tracing. - function Add_Edge_With_Return (G : Library_Graph; Pred : Library_Graph_Vertex_Id; @@ -1070,16 +1072,6 @@ package body Bindo.Graphs is -- involves a task activation. If Pred and Succ are already related, -- no edge is created and No_Library_Graph_Edge is returned. - procedure Add_Vertex_And_Complement - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Do_Complement : Boolean); - pragma Inline (Add_Vertex_And_Complement); - -- Add vertex Vertex of library graph G to set Set. If the vertex is - -- part of an Elaborate_Body pair, or flag Do_Complement is set, add - -- the complementary vertex to the set. - function At_Least_One_Edge_Satisfies (G : Library_Graph; Cycle : Library_Graph_Cycle_Id; @@ -1094,6 +1086,18 @@ package body Bindo.Graphs is pragma Inline (Copy_Cycle_Path); -- Create a deep copy of list Cycle_Path + function Cycle_End_Vertices + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean) return LGV_Sets.Membership_Set; + pragma Inline (Cycle_End_Vertices); + -- Part of Tarjan's enumeration of the elementary circuits of a directed + -- graph algorithm. Collect the vertices that terminate a cycle starting + -- from vertex Vertex of library graph G in a set. This is usually the + -- vertex itself, unless the vertex is part of an Elaborate_Body pair, + -- or flag Elaborate_All_Active is set. In that case the complementary + -- vertex is also added to the set. + function Cycle_Kind_Of (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Library_Graph_Cycle_Kind; @@ -1101,6 +1105,29 @@ package body Bindo.Graphs is -- Determine the cycle kind of edge Edge of library graph G if the edge -- participated in a circuit. + function Cycle_Kind_Precedence + (Kind : Library_Graph_Cycle_Kind; + Compared_To : Library_Graph_Cycle_Kind) return Precedence_Kind; + pragma Inline (Cycle_Kind_Precedence); + -- Determine the precedence of cycle kind Kind compared to cycle kind + -- Compared_To. + + function Cycle_Path_Precedence + (G : Library_Graph; + Path : LGE_Lists.Doubly_Linked_List; + Compared_To : LGE_Lists.Doubly_Linked_List) return Precedence_Kind; + pragma Inline (Cycle_Path_Precedence); + -- Determine the precedence of cycle path Path of library graph G + -- compared to path Compared_To. + + function Cycle_Precedence + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Compared_To : Library_Graph_Cycle_Id) return Precedence_Kind; + pragma Inline (Cycle_Precedence); + -- Determine the precedence of cycle Cycle of library graph G compared + -- to cycle Compared_To. + procedure Decrement_Library_Graph_Edge_Count (G : Library_Graph; Kind : Library_Graph_Edge_Kind); @@ -1121,40 +1148,133 @@ package body Bindo.Graphs is pragma Inline (Delete_Edge); -- Delete edge Edge from library graph G - procedure Find_All_Cycles_Through_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - End_Vertices : LGV_Sets.Membership_Set; - Most_Significant_Edge : Library_Graph_Edge_Id; - Invocation_Edge_Count : Natural; - Spec_And_Body_Together : Boolean; - Cycle_Path : LGE_Lists.Doubly_Linked_List; - Visited_Vertices : LGV_Sets.Membership_Set; - Indent : Indentation_Level); - pragma Inline (Find_All_Cycles_Through_Vertex); - -- Explore all edges to successors of vertex Vertex of library graph G - -- in an attempt to find a cycle. A cycle is considered closed when the - -- Vertex appears in set End_Vertices. Most_Significant_Edge denotes the - -- edge with the highest significance along the candidate cycle path. - -- Invocation_Edge_Count denotes the number of invocation edges along - -- the candidate cycle path. Spec_And_Body_Together should be set when - -- spec and body vertices must be treated as one vertex. Cycle_Path is - -- the candidate cycle path. Visited_Vertices denotes the set of visited - -- vertices so far. Indent is the desired indentation level for tracing. - - procedure Find_All_Cycles_With_Edge - (G : Library_Graph; - Initial_Edge : Library_Graph_Edge_Id; - Spec_And_Body_Together : Boolean; - Cycle_Path : LGE_Lists.Doubly_Linked_List; - Visited_Vertices : LGV_Sets.Membership_Set; - Indent : Indentation_Level); - pragma Inline (Find_All_Cycles_With_Edge); - -- Find all cycles which contain edge Initial_Edge of library graph G. - -- Spec_And_Body_Together should be set when spec and body vertices must - -- be treated as one vertex. Cycle_Path is the candidate cycle path. - -- Visited_Vertices is the set of visited vertices so far. Indent is - -- the desired indentation level for tracing. + function Edge_Precedence + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Compared_To : Library_Graph_Edge_Id) return Precedence_Kind; + pragma Inline (Edge_Precedence); + -- Determine the precedence of edge Edge of library graph G compared to + -- edge Compared_To. + + procedure Find_Cycles_From_Successor + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + End_Vertices : LGV_Sets.Membership_Set; + Deleted_Vertices : LGV_Sets.Membership_Set; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path_Stack : LGE_Lists.Doubly_Linked_List; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List; + Cycle_Count : in out Natural; + Cycle_Limit : Natural; + Elaborate_All_Active : Boolean; + Has_Cycle : out Boolean; + Indent : Indentation_Level); + pragma Inline (Find_Cycles_From_Successor); + -- Part of Tarjan's enumeration of the elementary circuits of a directed + -- graph algorithm. Find all cycles from the successor indicated by edge + -- Edge of library graph G. If at least one cycle exists, set Has_Cycle + -- to True. The remaining parameters are as follows: + -- + -- * End vertices is the set of vertices that terminate a potential + -- cycle. + -- + -- * Deleted vertices is the set of vertices that have been expended + -- during previous depth-first searches and should not be visited + -- for the rest of the algorithm. + -- + -- * Most_Significant_Edge is the current highest precedence edge on + -- the path of the potential cycle. + -- + -- * Invocation_Edge_Count is the number of invocation edges on the + -- path of the potential cycle. + -- + -- * Cycle_Path_Stack is the path of the potential cycle. + -- + -- * Visited_Set is the set of vertices that have been visited during + -- the current depth-first search. + -- + -- * Visited_Stack maintains the vertices of Visited_Set in a stack + -- for later unvisiting. + -- + -- * Cycle_Count is the number of cycles discovered so far. + -- + -- * Cycle_Limit is the upper bound of the number of cycles to be + -- discovered. + -- + -- * Elaborate_All_Active should be set when the component currently + -- being examined for cycles contains an Elaborate_All edge. + -- + -- * Indent in the desired indentation level for tracing. + + procedure Find_Cycles_From_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + End_Vertices : LGV_Sets.Membership_Set; + Deleted_Vertices : LGV_Sets.Membership_Set; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path_Stack : LGE_Lists.Doubly_Linked_List; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List; + Cycle_Count : in out Natural; + Cycle_Limit : Natural; + Elaborate_All_Active : Boolean; + Is_Start_Vertex : Boolean; + Has_Cycle : out Boolean; + Indent : Indentation_Level); + pragma Inline (Find_Cycles_From_Vertex); + -- Part of Tarjan's enumeration of the elementary circuits of a directed + -- graph algorithm. Find all cycles from vertex Vertex of library graph + -- G. If at least one cycle exists, set Has_Cycle to True. The remaining + -- parameters are as follows: + -- + -- * End_Vertices is the set of vertices that terminate a potential + -- cycle. + -- + -- * Deleted_Vertices is the set of vertices that have been expended + -- during previous depth-first searches and should not be visited + -- for the rest of the algorithm. + -- + -- * Most_Significant_Edge is the current highest precedence edge on + -- the path of the potential cycle. + -- + -- * Invocation_Edge_Count is the number of invocation edges on the + -- path of the potential cycle. + -- + -- * Cycle_Path_Stack is the path of the potential cycle. + -- + -- * Visited_Set is the set of vertices that have been visited during + -- the current depth-first search. + -- + -- * Visited_Stack maintains the vertices of Visited_Set in a stack + -- for later unvisiting. + -- + -- * Cycle_Count is the number of cycles discovered so far. + -- + -- * Cycle_Limit is the upper bound of the number of cycles to be + -- discovered. + -- + -- * Elaborate_All_Active should be set when the component currently + -- being examined for cycles contains an Elaborate_All edge. + -- + -- * Indent in the desired indentation level for tracing. + + procedure Find_Cycles_In_Component + (G : Library_Graph; + Comp : Component_Id; + Cycle_Count : in out Natural; + Cycle_Limit : Natural); + pragma Inline (Find_Cycles_In_Component); + -- Part of Tarjan's enumeration of the elementary circuits of a directed + -- graph algorithm. Find all cycles in component Comp of library graph + -- G. The remaining parameters are as follows: + -- + -- * Cycle_Count is the number of cycles discovered so far. + -- + -- * Cycle_Limit is the upper bound of the number of cycles to be + -- discovered. function Find_First_Lower_Precedence_Cycle (G : Library_Graph; @@ -1201,6 +1321,21 @@ package body Bindo.Graphs is -- Determine whether vertex Vertex of library graph G is subject to -- pragma Elaborate_Body. + function Has_Elaborate_All_Edge + (G : Library_Graph; + Comp : Component_Id) return Boolean; + pragma Inline (Has_Elaborate_All_Edge); + -- Determine whether component Comp of library graph G contains an + -- Elaborate_All edge that links two vertices in the same component. + + function Has_Elaborate_All_Edge + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Has_Elaborate_All_Edge); + -- Determine whether vertex Vertex of library graph G contains an + -- Elaborate_All edge to a successor where both the vertex and the + -- successor reside in the same component. + function Highest_Precedence_Edge (G : Library_Graph; Left : Library_Graph_Edge_Id; @@ -1238,13 +1373,6 @@ package body Bindo.Graphs is -- Initialize on the initial call or re-initialize on subsequent calls -- all components of library graph G. - procedure Insert_And_Sort - (G : Library_Graph; - Cycle : Library_Graph_Cycle_Id); - pragma Inline (Insert_And_Sort); - -- Insert cycle Cycle in library graph G and sort it based on its - -- precedence relative to all recorded cycles. - function Is_Cycle_Initiating_Edge (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Boolean; @@ -1302,13 +1430,6 @@ package body Bindo.Graphs is -- cycle and is the result of a with dependency between its successor -- and predecessor. - function Is_Recorded_Cycle - (G : Library_Graph; - Attrs : Library_Graph_Cycle_Attributes) return Boolean; - pragma Inline (Is_Recorded_Cycle); - -- Determine whether a cycle described by its attributes Attrs has - -- has already been recorded in library graph G. - function Is_Recorded_Edge (G : Library_Graph; Rel : Predecessor_Successor_Relation) return Boolean; @@ -1323,6 +1444,14 @@ package body Bindo.Graphs is -- Determine whether the successor of invocation edge Edge represents a -- unit that was compiled with the static model. + function Is_Vertex_With_Elaborate_Body + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean; + pragma Inline (Is_Vertex_With_Elaborate_Body); + -- Determine whether vertex Vertex of library graph G denotes a spec + -- subject to pragma Elaborate_Body or the completing body of such a + -- spec. + function Links_Vertices_In_Same_Component (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Boolean; @@ -1338,19 +1467,6 @@ package body Bindo.Graphs is -- Determine whether edge Edge of library graph G is an invocation edge, -- and if it is return Count + 1, otherwise return Count. - procedure Normalize_And_Add_Cycle - (G : Library_Graph; - Most_Significant_Edge : Library_Graph_Edge_Id; - Invocation_Edge_Count : Natural; - Cycle_Path : LGE_Lists.Doubly_Linked_List; - Indent : Indentation_Level); - pragma Inline (Normalize_And_Add_Cycle); - -- Normalize a cycle described by its path Cycle_Path and add it to - -- library graph G. Most_Significant_Edge denotes the edge with the - -- highest significance along the cycle path. Invocation_Edge_Count - -- denotes the number of invocation edges along the cycle path. Indent - -- is the desired indentation level for tracing. - procedure Normalize_Cycle_Path (Cycle_Path : LGE_Lists.Doubly_Linked_List; Most_Significant_Edge : Library_Graph_Edge_Id); @@ -1358,6 +1474,13 @@ package body Bindo.Graphs is -- Normalize cycle path Path by rotating it until its starting edge is -- Sig_Edge. + procedure Order_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id); + pragma Inline (Order_Cycle); + -- Insert cycle Cycle in library graph G and sort it based on its + -- precedence relative to all recorded cycles. + function Path (G : Library_Graph; Cycle : Library_Graph_Cycle_Id) return LGE_Lists.Doubly_Linked_List; @@ -1365,46 +1488,18 @@ package body Bindo.Graphs is -- Obtain the path of edges which comprises cycle Cycle of library -- graph G. - function Precedence - (G : Library_Graph; - Cycle : Library_Graph_Cycle_Id; - Compared_To : Library_Graph_Cycle_Id) return Precedence_Kind; - pragma Inline (Precedence); - -- Determine the precedence of cycle Cycle of library graph G compared - -- to cycle Compared_To. - - function Precedence - (Kind : Library_Graph_Cycle_Kind; - Compared_To : Library_Graph_Cycle_Kind) return Precedence_Kind; - pragma Inline (Precedence); - -- Determine the precedence of cycle kind Kind compared to cycle kind - -- Compared_To. - - function Precedence - (G : Library_Graph; - Edge : Library_Graph_Edge_Id; - Compared_To : Library_Graph_Edge_Id) return Precedence_Kind; - pragma Inline (Precedence); - -- Determine the precedence of edge Edge of library graph G compared to - -- edge Compared_To. - - function Precedence - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; - pragma Inline (Precedence); - -- Determine the precedence of vertex Vertex of library graph G compared - -- to vertex Compared_To. - - procedure Remove_Vertex_And_Complement - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Do_Complement : Boolean); - pragma Inline (Remove_Vertex_And_Complement); - -- Remove vertex Vertex of library graph G from set Set. If the vertex - -- is part of an Elaborate_Body pair, or Do_Complement is set, remove - -- the complementary vertex from the set. + procedure Record_Cycle + (G : Library_Graph; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Indent : Indentation_Level); + pragma Inline (Record_Cycle); + -- Normalize a cycle described by its path Cycle_Path and add it to + -- library graph G. Most_Significant_Edge denotes the edge with the + -- highest significance along the cycle path. Invocation_Edge_Count + -- is the number of invocation edges along the cycle path. Indent is + -- the desired indentation level for tracing. procedure Set_Component_Attributes (G : Library_Graph; @@ -1420,14 +1515,6 @@ package body Bindo.Graphs is pragma Inline (Set_Corresponding_Vertex); -- Associate vertex Val of library graph G with unit U_Id - procedure Set_Is_Recorded_Cycle - (G : Library_Graph; - Attrs : Library_Graph_Cycle_Attributes; - Val : Boolean := True); - pragma Inline (Set_Is_Recorded_Cycle); - -- Mark a cycle described by its attributes Attrs as recorded in library - -- graph G depending on value Val. - procedure Set_Is_Recorded_Edge (G : Library_Graph; Rel : Predecessor_Successor_Relation; @@ -1457,6 +1544,14 @@ package body Bindo.Graphs is pragma Inline (Set_LGV_Attributes); -- Set the attributes of vertex Vertex of library graph G to value Val + procedure Trace_Component + (G : Library_Graph; + Comp : Component_Id; + Indent : Indentation_Level); + pragma Inline (Trace_Component); + -- Write the contents of component Comp of library graph G to standard + -- output. Indent is the desired indentation level for tracing. + procedure Trace_Cycle (G : Library_Graph; Cycle : Library_Graph_Cycle_Id; @@ -1473,10 +1568,6 @@ package body Bindo.Graphs is -- Write the contents of edge Edge of library graph G to standard -- output. Indent is the desired indentation level for tracing. - procedure Trace_Eol; - pragma Inline (Trace_Eol); - -- Write an end-of-line to standard output - procedure Trace_Vertex (G : Library_Graph; Vertex : Library_Graph_Vertex_Id; @@ -1485,6 +1576,15 @@ package body Bindo.Graphs is -- Write the contents of vertex Vertex of library graph G to standard -- output. Indent is the desired indentation level for tracing. + procedure Unvisit + (Vertex : Library_Graph_Vertex_Id; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List); + pragma Inline (Unvisit); + -- Part of Tarjan's enumeration of the elementary circuits of a directed + -- graph algorithm. Unwind the Visited_Stack by removing the top vertex + -- from set Visited_Set until vertex Vertex is reached, inclusive. + procedure Update_Pending_Predecessors (Strong_Predecessors : in out Natural; Weak_Predecessors : in out Natural; @@ -1508,6 +1608,23 @@ package body Bindo.Graphs is -- LGE_Is's successor vertex of library graph G must wait on before -- it can be elaborated. + function Vertex_Precedence + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind; + pragma Inline (Vertex_Precedence); + -- Determine the precedence of vertex Vertex of library graph G compared + -- to vertex Compared_To. + + procedure Visit + (Vertex : Library_Graph_Vertex_Id; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List); + pragma Inline (Visit); + -- Part of Tarjan's enumeration of the elementary circuits of a directed + -- graph algorithm. Push vertex Vertex on the Visited_Stack and add it + -- to set Visited_Set. + -------------------- -- Activates_Task -- -------------------- @@ -1616,44 +1733,6 @@ package body Bindo.Graphs is end loop; end Add_Body_Before_Spec_Edges; - --------------- - -- Add_Cycle -- - --------------- - - procedure Add_Cycle - (G : Library_Graph; - Attrs : Library_Graph_Cycle_Attributes; - Indent : Indentation_Level) - is - Cycle : Library_Graph_Cycle_Id; - - begin - pragma Assert (Present (G)); - - -- Nothing to do when the cycle has already been recorded, possibly - -- in a rotated form. - - if Is_Recorded_Cycle (G, Attrs) then - return; - end if; - - -- Mark the cycle as recorded. This prevents further attempts to add - -- rotations of the same cycle. - - Set_Is_Recorded_Cycle (G, Attrs); - - -- Save the attributes of the cycle - - Cycle := Sequence_Next_Cycle; - Set_LGC_Attributes (G, Cycle, Attrs); - - Trace_Cycle (G, Cycle, Indent); - - -- Insert the cycle in the list of all cycle based on its precedence - - Insert_And_Sort (G, Cycle); - end Add_Cycle; - -------------- -- Add_Edge -- -------------- @@ -1799,34 +1878,6 @@ package body Bindo.Graphs is Set_Corresponding_Vertex (G, U_Id, Vertex); end Add_Vertex; - ------------------------------- - -- Add_Vertex_And_Complement -- - ------------------------------- - - procedure Add_Vertex_And_Complement - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Do_Complement : Boolean) - is - pragma Assert (Present (G)); - pragma Assert (Present (Vertex)); - pragma Assert (LGV_Sets.Present (Set)); - - Complement : constant Library_Graph_Vertex_Id := - Complementary_Vertex - (G => G, - Vertex => Vertex, - Force_Complement => Do_Complement); - - begin - LGV_Sets.Insert (Set, Vertex); - - if Present (Complement) then - LGV_Sets.Insert (Set, Complement); - end if; - end Add_Vertex_And_Complement; - --------------------------------- -- At_Least_One_Edge_Satisfies -- --------------------------------- @@ -2051,7 +2102,6 @@ package body Bindo.Graphs is DG.Create (Initial_Vertices => Initial_Vertices, Initial_Edges => Initial_Edges); - G.Recorded_Cycles := RC_Sets.Create (Initial_Vertices); G.Recorded_Edges := RE_Sets.Create (Initial_Edges); G.Unit_To_Vertex := Unit_Tables.Create (Initial_Vertices); G.Vertex_Attributes := LGV_Tables.Create (Initial_Vertices); @@ -2059,6 +2109,49 @@ package body Bindo.Graphs is return G; end Create; + ------------------------ + -- Cycle_End_Vertices -- + ------------------------ + + function Cycle_End_Vertices + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Elaborate_All_Active : Boolean) return LGV_Sets.Membership_Set + is + Complement : Library_Graph_Vertex_Id; + End_Vertices : LGV_Sets.Membership_Set := LGV_Sets.Nil; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + End_Vertices := LGV_Sets.Create (2); + + -- The input vertex always terminates a cycle path + + LGV_Sets.Insert (End_Vertices, Vertex); + + -- Add the complementary vertex to the set of cycle terminating + -- vertices when either Elaborate_All is in effect, or the input + -- vertex is part of an Elaborat_Body pair. + + if Elaborate_All_Active + or else Is_Vertex_With_Elaborate_Body (G, Vertex) + then + Complement := + Complementary_Vertex + (G => G, + Vertex => Vertex, + Force_Complement => Elaborate_All_Active); + + if Present (Complement) then + LGV_Sets.Insert (End_Vertices, Complement); + end if; + end if; + + return End_Vertices; + end Cycle_End_Vertices; + ------------------- -- Cycle_Kind_Of -- ------------------- @@ -2091,84 +2184,252 @@ package body Bindo.Graphs is end if; end Cycle_Kind_Of; - ---------------------------------------- - -- Decrement_Library_Graph_Edge_Count -- - ---------------------------------------- + --------------------------- + -- Cycle_Kind_Precedence -- + --------------------------- - procedure Decrement_Library_Graph_Edge_Count - (G : Library_Graph; - Kind : Library_Graph_Edge_Kind) + function Cycle_Kind_Precedence + (Kind : Library_Graph_Cycle_Kind; + Compared_To : Library_Graph_Cycle_Kind) return Precedence_Kind is - pragma Assert (Present (G)); - - Count : Natural renames G.Counts (Kind); + Comp_Pos : constant Integer := + Library_Graph_Cycle_Kind'Pos (Compared_To); + Kind_Pos : constant Integer := Library_Graph_Cycle_Kind'Pos (Kind); begin - Count := Count - 1; - end Decrement_Library_Graph_Edge_Count; + -- A lower ordinal indicates a higher precedence - ------------------------------------ - -- Decrement_Pending_Predecessors -- - ------------------------------------ + if Kind_Pos < Comp_Pos then + return Higher_Precedence; - procedure Decrement_Pending_Predecessors - (G : Library_Graph; - Comp : Component_Id; - Edge : Library_Graph_Edge_Id) - is - Attrs : Component_Attributes; + elsif Kind_Pos > Comp_Pos then + return Lower_Precedence; - begin - pragma Assert (Present (G)); - pragma Assert (Present (Comp)); + else + return Equal_Precedence; + end if; + end Cycle_Kind_Precedence; - Attrs := Get_Component_Attributes (G, Comp); + --------------------------- + -- Cycle_Path_Precedence -- + --------------------------- - Update_Pending_Predecessors - (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, - Weak_Predecessors => Attrs.Pending_Weak_Predecessors, - Update_Weak => Is_Invocation_Edge (G, Edge), - Value => -1); + function Cycle_Path_Precedence + (G : Library_Graph; + Path : LGE_Lists.Doubly_Linked_List; + Compared_To : LGE_Lists.Doubly_Linked_List) return Precedence_Kind + is + procedure Next_Available + (Iter : in out LGE_Lists.Iterator; + Edge : out Library_Graph_Edge_Id); + pragma Inline (Next_Available); + -- Obtain the next edge available through iterator Iter, or return + -- No_Library_Graph_Edge if the iterator has been exhausted. + + -------------------- + -- Next_Available -- + -------------------- + + procedure Next_Available + (Iter : in out LGE_Lists.Iterator; + Edge : out Library_Graph_Edge_Id) + is + begin + -- Assume that the iterator has been exhausted + + Edge := No_Library_Graph_Edge; + + if LGE_Lists.Has_Next (Iter) then + LGE_Lists.Next (Iter, Edge); + end if; + end Next_Available; - Set_Component_Attributes (G, Comp, Attrs); - end Decrement_Pending_Predecessors; + -- Local variables - ------------------------------------ - -- Decrement_Pending_Predecessors -- - ------------------------------------ + Comp_Edge : Library_Graph_Edge_Id; + Comp_Iter : LGE_Lists.Iterator; + Path_Edge : Library_Graph_Edge_Id; + Path_Iter : LGE_Lists.Iterator; + Prec : Precedence_Kind; - procedure Decrement_Pending_Predecessors - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Edge : Library_Graph_Edge_Id) - is - Attrs : Library_Graph_Vertex_Attributes; + -- Start of processing for Cycle_Path_Precedence begin pragma Assert (Present (G)); - pragma Assert (Present (Vertex)); + pragma Assert (LGE_Lists.Present (Path)); + pragma Assert (LGE_Lists.Present (Compared_To)); - Attrs := Get_LGV_Attributes (G, Vertex); + -- Assume that the paths have equal precedence - Update_Pending_Predecessors - (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, - Weak_Predecessors => Attrs.Pending_Weak_Predecessors, - Update_Weak => Is_Invocation_Edge (G, Edge), - Value => -1); + Prec := Equal_Precedence; - Set_LGV_Attributes (G, Vertex, Attrs); - end Decrement_Pending_Predecessors; + Comp_Iter := LGE_Lists.Iterate (Compared_To); + Path_Iter := LGE_Lists.Iterate (Path); - ----------------------------------- - -- Delete_Body_Before_Spec_Edges -- - ----------------------------------- + Next_Available (Comp_Iter, Comp_Edge); + Next_Available (Path_Iter, Path_Edge); - procedure Delete_Body_Before_Spec_Edges - (G : Library_Graph; - Edges : LGE_Lists.Doubly_Linked_List) - is - Edge : Library_Graph_Edge_Id; - Iter : LGE_Lists.Iterator; + -- IMPORTANT: + -- + -- * The iteration must run to completion in order to unlock the + -- edges of both paths. + + while Present (Comp_Edge) or else Present (Path_Edge) loop + if Prec = Equal_Precedence + and then Present (Comp_Edge) + and then Present (Path_Edge) + then + Prec := + Edge_Precedence + (G => G, + Edge => Path_Edge, + Compared_To => Comp_Edge); + end if; + + Next_Available (Comp_Iter, Comp_Edge); + Next_Available (Path_Iter, Path_Edge); + end loop; + + return Prec; + end Cycle_Path_Precedence; + + ---------------------- + -- Cycle_Precedence -- + ---------------------- + + function Cycle_Precedence + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id; + Compared_To : Library_Graph_Cycle_Id) return Precedence_Kind + is + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + pragma Assert (Present (Compared_To)); + + Comp_Invs : constant Natural := + Invocation_Edge_Count (G, Compared_To); + Comp_Len : constant Natural := Length (G, Compared_To); + Cycle_Invs : constant Natural := Invocation_Edge_Count (G, Cycle); + Cycle_Len : constant Natural := Length (G, Cycle); + Kind_Prec : constant Precedence_Kind := + Cycle_Kind_Precedence + (Kind => Kind (G, Cycle), + Compared_To => Kind (G, Compared_To)); + + begin + -- Prefer a cycle with higher precedence based on its kind + + if Kind_Prec = Higher_Precedence + or else + Kind_Prec = Lower_Precedence + then + return Kind_Prec; + + -- Prefer a shorter cycle + + elsif Cycle_Len < Comp_Len then + return Higher_Precedence; + + elsif Cycle_Len > Comp_Len then + return Lower_Precedence; + + -- Prefer a cycle wih fewer invocation edges + + elsif Cycle_Invs < Comp_Invs then + return Higher_Precedence; + + elsif Cycle_Invs > Comp_Invs then + return Lower_Precedence; + + -- Prever a cycle with a higher path precedence + + else + return + Cycle_Path_Precedence + (G => G, + Path => Path (G, Cycle), + Compared_To => Path (G, Compared_To)); + end if; + end Cycle_Precedence; + + ---------------------------------------- + -- Decrement_Library_Graph_Edge_Count -- + ---------------------------------------- + + procedure Decrement_Library_Graph_Edge_Count + (G : Library_Graph; + Kind : Library_Graph_Edge_Kind) + is + pragma Assert (Present (G)); + + Count : Natural renames G.Counts (Kind); + + begin + Count := Count - 1; + end Decrement_Library_Graph_Edge_Count; + + ------------------------------------ + -- Decrement_Pending_Predecessors -- + ------------------------------------ + + procedure Decrement_Pending_Predecessors + (G : Library_Graph; + Comp : Component_Id; + Edge : Library_Graph_Edge_Id) + is + Attrs : Component_Attributes; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Comp)); + + Attrs := Get_Component_Attributes (G, Comp); + + Update_Pending_Predecessors + (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, + Weak_Predecessors => Attrs.Pending_Weak_Predecessors, + Update_Weak => Is_Invocation_Edge (G, Edge), + Value => -1); + + Set_Component_Attributes (G, Comp, Attrs); + end Decrement_Pending_Predecessors; + + ------------------------------------ + -- Decrement_Pending_Predecessors -- + ------------------------------------ + + procedure Decrement_Pending_Predecessors + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Edge : Library_Graph_Edge_Id) + is + Attrs : Library_Graph_Vertex_Attributes; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + Attrs := Get_LGV_Attributes (G, Vertex); + + Update_Pending_Predecessors + (Strong_Predecessors => Attrs.Pending_Strong_Predecessors, + Weak_Predecessors => Attrs.Pending_Weak_Predecessors, + Update_Weak => Is_Invocation_Edge (G, Edge), + Value => -1); + + Set_LGV_Attributes (G, Vertex, Attrs); + end Decrement_Pending_Predecessors; + + ----------------------------------- + -- Delete_Body_Before_Spec_Edges -- + ----------------------------------- + + procedure Delete_Body_Before_Spec_Edges + (G : Library_Graph; + Edges : LGE_Lists.Doubly_Linked_List) + is + Edge : Library_Graph_Edge_Id; + Iter : LGE_Lists.Iterator; begin pragma Assert (Present (G)); @@ -2240,7 +2501,6 @@ package body Bindo.Graphs is LGC_Lists.Destroy (G.Cycles); LGE_Tables.Destroy (G.Edge_Attributes); DG.Destroy (G.Graph); - RC_Sets.Destroy (G.Recorded_Cycles); RE_Sets.Destroy (G.Recorded_Edges); Unit_Tables.Destroy (G.Unit_To_Vertex); LGV_Tables.Destroy (G.Vertex_Attributes); @@ -2283,18 +2543,6 @@ package body Bindo.Graphs is null; end Destroy_Library_Graph_Edge_Attributes; - ---------------------------------- - -- Destroy_Library_Graph_Vertex -- - ---------------------------------- - - procedure Destroy_Library_Graph_Vertex - (Vertex : in out Library_Graph_Vertex_Id) - is - pragma Unreferenced (Vertex); - begin - null; - end Destroy_Library_Graph_Vertex; - --------------------------------------------- -- Destroy_Library_Graph_Vertex_Attributes -- --------------------------------------------- @@ -2307,6 +2555,62 @@ package body Bindo.Graphs is null; end Destroy_Library_Graph_Vertex_Attributes; + --------------------- + -- Edge_Precedence -- + --------------------- + + function Edge_Precedence + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + Compared_To : Library_Graph_Edge_Id) return Precedence_Kind + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + pragma Assert (Present (Compared_To)); + + Comp_Succ : constant Library_Graph_Vertex_Id := + Successor (G, Compared_To); + Edge_Succ : constant Library_Graph_Vertex_Id := + Successor (G, Edge); + Kind_Prec : constant Precedence_Kind := + Cycle_Kind_Precedence + (Kind => Cycle_Kind_Of (G, Edge), + Compared_To => Cycle_Kind_Of (G, Compared_To)); + Succ_Prec : constant Precedence_Kind := + Vertex_Precedence + (G => G, + Vertex => Edge_Succ, + Compared_To => Comp_Succ); + + begin + -- Prefer an edge with a higher cycle kind precedence + + if Kind_Prec = Higher_Precedence + or else + Kind_Prec = Lower_Precedence + then + return Kind_Prec; + + -- Prefer an edge whose successor has a higher precedence + + elsif Comp_Succ /= Edge_Succ + and then (Succ_Prec = Higher_Precedence + or else + Succ_Prec = Lower_Precedence) + then + return Succ_Prec; + + -- Prefer an edge whose predecessor has a higher precedence + + else + return + Vertex_Precedence + (G => G, + Vertex => Predecessor (G, Edge), + Compared_To => Predecessor (G, Compared_To)); + end if; + end Edge_Precedence; + --------------- -- File_Name -- --------------- @@ -2322,320 +2626,512 @@ package body Bindo.Graphs is return File_Name (Unit (G, Vertex)); end File_Name; - ------------------------------------ - -- Find_All_Cycles_Through_Vertex -- - ------------------------------------ + --------------------- + -- Find_Components -- + --------------------- - procedure Find_All_Cycles_Through_Vertex - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - End_Vertices : LGV_Sets.Membership_Set; - Most_Significant_Edge : Library_Graph_Edge_Id; - Invocation_Edge_Count : Natural; - Spec_And_Body_Together : Boolean; - Cycle_Path : LGE_Lists.Doubly_Linked_List; - Visited_Vertices : LGV_Sets.Membership_Set; - Indent : Indentation_Level) - is - Edge_Indent : constant Indentation_Level := - Indent + Nested_Indentation; + procedure Find_Components (G : Library_Graph) is + Edges : LGE_Lists.Doubly_Linked_List; + + begin + pragma Assert (Present (G)); + + -- Initialize or reinitialize the components of the graph + + Initialize_Components (G); + + -- Create a set of special edges that link a predecessor body with a + -- successor spec. This is an illegal dependency, however using such + -- edges eliminates the need to create yet another graph, where both + -- spec and body are collapsed into a single vertex. + + Edges := LGE_Lists.Create; + Add_Body_Before_Spec_Edges (G, Edges); + + DG.Find_Components (G.Graph); + + -- Remove the special edges that link a predecessor body with a + -- successor spec because they cause unresolvable circularities. - Iter : Edges_To_Successors_Iterator; - Next_Edge : Library_Graph_Edge_Id; + Delete_Body_Before_Spec_Edges (G, Edges); + LGE_Lists.Destroy (Edges); + + -- Update the number of predecessors various components must wait on + -- before they can be elaborated. + + Update_Pending_Predecessors_Of_Components (G); + end Find_Components; + + ----------------- + -- Find_Cycles -- + ----------------- + + procedure Find_Cycles (G : Library_Graph) is + All_Cycle_Limit : constant Natural := 64; + -- The performance of Tarjan's algorithm may degrate to exponential + -- when pragma Elaborate_All is in effect, or some vertex is part of + -- an Elaborate_Body pair. In this case the algorithm discovers all + -- combinations of edges that close a circuit starting and ending on + -- some start vertex while going through different vertices. Use a + -- limit on the total number of cycles within a component to guard + -- against such degradation. + + Comp : Component_Id; + Cycle_Count : Natural; + Iter : Component_Iterator; begin pragma Assert (Present (G)); - pragma Assert (LGV_Sets.Present (End_Vertices)); - pragma Assert (Present (Most_Significant_Edge)); - pragma Assert (LGE_Lists.Present (Cycle_Path)); - pragma Assert (LGV_Sets.Present (Visited_Vertices)); - -- Nothing to do when there is no vertex + -- The cycles of graph G are discovered using Tarjan's enumeration + -- of the elementary circuits of a directed graph algorithm. Do not + -- modify this code unless you intimately understand the algorithm. + -- + -- The logic of the algorithm is split among the following routines: + -- + -- Cycle_End_Vertices + -- Find_Cycles_From_Successor + -- Find_Cycles_From_Vertex + -- Find_Cycles_In_Component + -- Unvisit + -- Visit + -- + -- The original algorithm has been significantly modified in order to + -- + -- * Accomodate the semantics of Elaborate_All and Elaborate_Body. + -- + -- * Capture cycle paths as edges rather than vertices. + -- + -- * Take advantage of graph components. - if not Present (Vertex) then - return; - end if; + -- Assume that the graph does not contain a cycle - -- The current vertex denotes the end vertex of the cycle and closes - -- the circuit. Normalize the cycle such that it is rotated with its - -- most significant edge first, and record it for diagnostics. + Cycle_Count := 0; - if LGV_Sets.Contains (End_Vertices, Vertex) then - Trace_Vertex (G, Vertex, Indent); + -- Run the modified version of the algorithm on each component of the + -- graph. - Normalize_And_Add_Cycle - (G => G, - Most_Significant_Edge => Most_Significant_Edge, - Invocation_Edge_Count => Invocation_Edge_Count, - Cycle_Path => Cycle_Path, - Indent => Indent + Nested_Indentation); + Iter := Iterate_Components (G); + while Has_Next (Iter) loop + Next (Iter, Comp); - -- Otherwise extend the search for a cycle only when the vertex has - -- not been visited yet. + Find_Cycles_In_Component + (G => G, + Comp => Comp, + Cycle_Count => Cycle_Count, + Cycle_Limit => All_Cycle_Limit); + end loop; + end Find_Cycles; - elsif not LGV_Sets.Contains (Visited_Vertices, Vertex) then - Trace_Vertex (G, Vertex, Indent); + -------------------------------- + -- Find_Cycles_From_Successor -- + -------------------------------- + + procedure Find_Cycles_From_Successor + (G : Library_Graph; + Edge : Library_Graph_Edge_Id; + End_Vertices : LGV_Sets.Membership_Set; + Deleted_Vertices : LGV_Sets.Membership_Set; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path_Stack : LGE_Lists.Doubly_Linked_List; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List; + Cycle_Count : in out Natural; + Cycle_Limit : Natural; + Elaborate_All_Active : Boolean; + Has_Cycle : out Boolean; + Indent : Indentation_Level) + is + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + pragma Assert (LGV_Sets.Present (End_Vertices)); + pragma Assert (LGV_Sets.Present (Deleted_Vertices)); + pragma Assert (LGE_Lists.Present (Cycle_Path_Stack)); + pragma Assert (LGV_Sets.Present (Visited_Set)); + pragma Assert (LGV_Lists.Present (Visited_Stack)); + + Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); + Succ_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + + begin + -- Assume that the successor reached via the edge does not result in + -- a cycle. + + Has_Cycle := False; + + -- Nothing to do when the edge connects two vertices residing in two + -- different components. + + if not Is_Cyclic_Edge (G, Edge) then + return; + end if; - -- Prepare for vertex backtracking + Trace_Edge (G, Edge, Indent); + + -- The modified version does not place vertices on the "point stack", + -- but instead collects the edges comprising the cycle. Prepare the + -- edge for backtracking. + + LGE_Lists.Prepend (Cycle_Path_Stack, Edge); + + Find_Cycles_From_Vertex + (G => G, + Vertex => Succ, + End_Vertices => End_Vertices, + Deleted_Vertices => Deleted_Vertices, + Most_Significant_Edge => Most_Significant_Edge, + Invocation_Edge_Count => Invocation_Edge_Count, + Cycle_Path_Stack => Cycle_Path_Stack, + Visited_Set => Visited_Set, + Visited_Stack => Visited_Stack, + Cycle_Count => Cycle_Count, + Cycle_Limit => Cycle_Limit, + Elaborate_All_Active => Elaborate_All_Active, + Is_Start_Vertex => False, + Has_Cycle => Has_Cycle, + Indent => Succ_Indent); + + -- The modified version does not place vertices on the "point stack", + -- but instead collects the edges comprising the cycle. Backtrack the + -- edge. - LGV_Sets.Insert (Visited_Vertices, Vertex); + LGE_Lists.Delete_First (Cycle_Path_Stack); + end Find_Cycles_From_Successor; - -- Extend the search via all edges to successors of the vertex + ----------------------------- + -- Find_Cycles_From_Vertex -- + ----------------------------- - Iter := Iterate_Edges_To_Successors (G, Vertex); - while Has_Next (Iter) loop - Next (Iter, Next_Edge); + procedure Find_Cycles_From_Vertex + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + End_Vertices : LGV_Sets.Membership_Set; + Deleted_Vertices : LGV_Sets.Membership_Set; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path_Stack : LGE_Lists.Doubly_Linked_List; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List; + Cycle_Count : in out Natural; + Cycle_Limit : Natural; + Elaborate_All_Active : Boolean; + Is_Start_Vertex : Boolean; + Has_Cycle : out Boolean; + Indent : Indentation_Level) + is + Edge_Indent : constant Indentation_Level := + Indent + Nested_Indentation; + + Complement : Library_Graph_Vertex_Id; + Edge : Library_Graph_Edge_Id; + Iter : Edges_To_Successors_Iterator; - if Is_Cyclic_Edge (G, Next_Edge) then - Trace_Edge (G, Next_Edge, Edge_Indent); + Complement_Has_Cycle : Boolean; + -- This flag is set when either Elaborate_All is in effect or the + -- current vertex is part of an Elaborate_Body pair, and visiting + -- the "complementary" vertex resulted in a cycle. - -- Prepare for edge backtracking. Prepending ensures that - -- final ordering of edges can be traversed from successor - -- to predecessor. + Successor_Has_Cycle : Boolean; + -- This flag is set when visiting at least once successor of the + -- current vertex resulted in a cycle. - LGE_Lists.Prepend (Cycle_Path, Next_Edge); + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + pragma Assert (LGV_Sets.Present (End_Vertices)); + pragma Assert (LGV_Sets.Present (Deleted_Vertices)); + pragma Assert (LGE_Lists.Present (Cycle_Path_Stack)); + pragma Assert (LGV_Sets.Present (Visited_Set)); + pragma Assert (LGV_Lists.Present (Visited_Stack)); - -- Extend the search via the successor of the next edge + -- Assume that the vertex does not close a circuit - Find_All_Cycles_Through_Vertex - (G => G, - Vertex => Successor (G, Next_Edge), - End_Vertices => End_Vertices, + Has_Cycle := False; - -- The next edge may be more important than the current - -- most important edge, thus "upgrading" the nature of - -- the cycle, and shifting its point of normalization. + -- Nothing to do when the limit on the number of saved cycles has + -- been reached. This protects against a combinatorial explostion + -- in components with Elaborate_All cycles. - Most_Significant_Edge => - Highest_Precedence_Edge - (G => G, - Left => Next_Edge, - Right => Most_Significant_Edge), + if Cycle_Count >= Cycle_Limit then + return; - -- The next edge may be an invocation edge, in which case - -- the count of invocation edges increases by one. + -- The vertex closes the circuit, thus resulting in a cycle. Save + -- the cycle for later diagnostics. The initial invocation of the + -- routine always ignores the starting vertex to prevent a spurious + -- self cycle. - Invocation_Edge_Count => - Maximum_Invocation_Edge_Count - (G => G, - Edge => Next_Edge, - Count => Invocation_Edge_Count), - Spec_And_Body_Together => Spec_And_Body_Together, - Cycle_Path => Cycle_Path, - Visited_Vertices => Visited_Vertices, - Indent => Indent); + elsif not Is_Start_Vertex + and then LGV_Sets.Contains (End_Vertices, Vertex) + then + Trace_Vertex (G, Vertex, Indent); - -- Backtrack the edge + Record_Cycle + (G => G, + Most_Significant_Edge => Most_Significant_Edge, + Invocation_Edge_Count => Invocation_Edge_Count, + Cycle_Path => Cycle_Path_Stack, + Indent => Indent); - LGE_Lists.Delete_First (Cycle_Path); - end if; - end loop; + Has_Cycle := True; + Cycle_Count := Cycle_Count + 1; + return; - -- Extend the search via the complementary vertex when the current - -- vertex is part of an Elaborate_Body pair, or the initial edge - -- is an Elaborate_All edge. + -- Nothing to do when the vertex has already been deleted. This + -- indicates that all available cycles involving the vertex have + -- been discovered, and the vertex cannot contribute further to + -- the depth-first search. - Find_All_Cycles_Through_Vertex - (G => G, - Vertex => - Complementary_Vertex - (G => G, - Vertex => Vertex, - Force_Complement => Spec_And_Body_Together), - End_Vertices => End_Vertices, - Most_Significant_Edge => Most_Significant_Edge, - Invocation_Edge_Count => Invocation_Edge_Count, - Spec_And_Body_Together => Spec_And_Body_Together, - Cycle_Path => Cycle_Path, - Visited_Vertices => Visited_Vertices, - Indent => Indent); + elsif LGV_Sets.Contains (Deleted_Vertices, Vertex) then + return; - -- Backtrack the vertex + -- Nothing to do when the vertex has already been visited. This + -- indicates that the depth-first search initiated from some start + -- vertex already encountered this vertex, and the visited stack has + -- not been unrolled yet. - LGV_Sets.Delete (Visited_Vertices, Vertex); + elsif LGV_Sets.Contains (Visited_Set, Vertex) then + return; end if; - end Find_All_Cycles_Through_Vertex; - ------------------------------- - -- Find_All_Cycles_With_Edge -- - ------------------------------- - - procedure Find_All_Cycles_With_Edge - (G : Library_Graph; - Initial_Edge : Library_Graph_Edge_Id; - Spec_And_Body_Together : Boolean; - Cycle_Path : LGE_Lists.Doubly_Linked_List; - Visited_Vertices : LGV_Sets.Membership_Set; - Indent : Indentation_Level) - is - pragma Assert (Present (G)); - pragma Assert (Present (Initial_Edge)); - pragma Assert (LGE_Lists.Present (Cycle_Path)); - pragma Assert (LGV_Sets.Present (Visited_Vertices)); + Trace_Vertex (G, Vertex, Indent); - Pred : constant Library_Graph_Vertex_Id := - Predecessor (G, Initial_Edge); - Succ : constant Library_Graph_Vertex_Id := - Successor (G, Initial_Edge); + -- Mark the vertex as visited - End_Vertices : LGV_Sets.Membership_Set; + Visit + (Vertex => Vertex, + Visited_Set => Visited_Set, + Visited_Stack => Visited_Stack); - begin - Trace_Edge (G, Initial_Edge, Indent); + -- Extend the depth-first search via all the edges to successors - -- Use a set to represent the end vertices of the cycle. The set is - -- needed to accommodate the Elaborate_All and Elaborate_Body cases - -- where a cycle may terminate on either a spec or a body vertex. + Iter := Iterate_Edges_To_Successors (G, Vertex); + while Has_Next (Iter) loop + Next (Iter, Edge); - End_Vertices := LGV_Sets.Create (2); - Add_Vertex_And_Complement - (G => G, - Vertex => Pred, - Set => End_Vertices, - Do_Complement => Spec_And_Body_Together); + Find_Cycles_From_Successor + (G => G, + Edge => Edge, + End_Vertices => End_Vertices, + Deleted_Vertices => Deleted_Vertices, + + -- The edge may be more important than the most important edge + -- up to this point, thus "upgrading" the nature of the cycle, + -- and shifting its point of normalization. + + Most_Significant_Edge => + Highest_Precedence_Edge + (G => G, + Left => Edge, + Right => Most_Significant_Edge), + + -- The edge may be an invocation edge, in which case the count + -- of invocation edges increases by one. + + Invocation_Edge_Count => + Maximum_Invocation_Edge_Count + (G => G, + Edge => Edge, + Count => Invocation_Edge_Count), + + Cycle_Path_Stack => Cycle_Path_Stack, + Visited_Set => Visited_Set, + Visited_Stack => Visited_Stack, + Cycle_Count => Cycle_Count, + Cycle_Limit => Cycle_Limit, + Elaborate_All_Active => Elaborate_All_Active, + Has_Cycle => Successor_Has_Cycle, + Indent => Edge_Indent); + + Has_Cycle := Has_Cycle or Successor_Has_Cycle; + end loop; - -- Prepare for edge backtracking - -- - -- The initial edge starts the path. During the traversal, edges with - -- higher precedence may be discovered, in which case they supersede - -- the initial edge in terms of significance. Prepending to the cycle - -- path ensures that the vertices can be visited in the proper order - -- for diagnostics. + -- Visit the complementary vertex of the current vertex when pragma + -- Elaborate_All is in effect, or the current vertex is part of an + -- Elaborate_Body pair. - LGE_Lists.Prepend (Cycle_Path, Initial_Edge); + if Elaborate_All_Active + or else Is_Vertex_With_Elaborate_Body (G, Vertex) + then + Complement := + Complementary_Vertex + (G => G, + Vertex => Vertex, + Force_Complement => Elaborate_All_Active); + + if Present (Complement) then + Find_Cycles_From_Vertex + (G => G, + Vertex => Complement, + End_Vertices => End_Vertices, + Deleted_Vertices => Deleted_Vertices, + Most_Significant_Edge => Most_Significant_Edge, + Invocation_Edge_Count => Invocation_Edge_Count, + Cycle_Path_Stack => Cycle_Path_Stack, + Visited_Set => Visited_Set, + Visited_Stack => Visited_Stack, + Cycle_Count => Cycle_Count, + Cycle_Limit => Cycle_Limit, + Elaborate_All_Active => Elaborate_All_Active, + Is_Start_Vertex => Is_Start_Vertex, + Has_Cycle => Complement_Has_Cycle, + Indent => Indent); + + Has_Cycle := Has_Cycle or Complement_Has_Cycle; + end if; + end if; - -- Prepare for vertex backtracking + -- The original algorithm clears the "marked stack" in two places: -- - -- The predecessor is considered the terminator of the path. Add it - -- to the set of visited vertices along with its complement vertex - -- in the Elaborate_All and Elaborate_Body cases to prevent infinite - -- recursion. - - Add_Vertex_And_Complement - (G => G, - Vertex => Pred, - Set => Visited_Vertices, - Do_Complement => Spec_And_Body_Together); - - -- Traverse a potential cycle by continuously visiting successors - -- until either the predecessor of the initial edge is reached, or - -- no more successors are available. - - Find_All_Cycles_Through_Vertex - (G => G, - Vertex => Succ, - End_Vertices => End_Vertices, - Most_Significant_Edge => Initial_Edge, - Invocation_Edge_Count => - Maximum_Invocation_Edge_Count - (G => G, - Edge => Initial_Edge, - Count => 0), - Spec_And_Body_Together => Spec_And_Body_Together, - Cycle_Path => Cycle_Path, - Visited_Vertices => Visited_Vertices, - Indent => Indent + Nested_Indentation); - - -- Backtrack the edge - - LGE_Lists.Delete_First (Cycle_Path); - - -- Backtrack the predecessor, along with the complement vertex in the - -- Elaborate_All and Elaborate_Body cases. - - Remove_Vertex_And_Complement - (G => G, - Vertex => Pred, - Set => Visited_Vertices, - Do_Complement => Spec_And_Body_Together); - - LGV_Sets.Destroy (End_Vertices); - end Find_All_Cycles_With_Edge; - - --------------------- - -- Find_Components -- - --------------------- + -- * When the depth-first search starting from the current vertex + -- discovers at least one cycle, and + -- + -- * When the depth-first search initiated from a start vertex + -- completes. + -- + -- The modified version handles both cases in one place. - procedure Find_Components (G : Library_Graph) is - Edges : LGE_Lists.Doubly_Linked_List; + if Has_Cycle or else Is_Start_Vertex then + Unvisit + (Vertex => Vertex, + Visited_Set => Visited_Set, + Visited_Stack => Visited_Stack); + end if; - begin - pragma Assert (Present (G)); + -- Delete a start vertex from the graph once its depth-first search + -- completes. This action preserves the invariant where a cycle is + -- not rediscovered "later" in some permuted form. - -- Initialize or reinitialize the components of the graph + if Is_Start_Vertex then + LGV_Sets.Insert (Deleted_Vertices, Vertex); + end if; + end Find_Cycles_From_Vertex; - Initialize_Components (G); + ------------------------------ + -- Find_Cycles_In_Component -- + ------------------------------ - -- Create a set of special edges that link a predecessor body with a - -- successor spec. This is an illegal dependency, however using such - -- edges eliminates the need to create yet another graph, where both - -- spec and body are collapsed into a single vertex. + procedure Find_Cycles_In_Component + (G : Library_Graph; + Comp : Component_Id; + Cycle_Count : in out Natural; + Cycle_Limit : Natural) + is + pragma Assert (Present (G)); + pragma Assert (Present (Comp)); - Edges := LGE_Lists.Create; - Add_Body_Before_Spec_Edges (G, Edges); + Num_Of_Vertices : constant Natural := + Number_Of_Component_Vertices (G, Comp); - DG.Find_Components (G.Graph); + Elaborate_All_Active : constant Boolean := + Has_Elaborate_All_Edge (G, Comp); + -- The presence of an Elaborate_All edge within a component causes + -- all spec-body pairs to be treated as one vertex. - -- Remove the special edges that link a predecessor body with a - -- successor spec because they cause unresolvable circularities. + Has_Cycle : Boolean; + Iter : Component_Vertex_Iterator; + Vertex : Library_Graph_Vertex_Id; - Delete_Body_Before_Spec_Edges (G, Edges); - LGE_Lists.Destroy (Edges); + Cycle_Path_Stack : LGE_Lists.Doubly_Linked_List := LGE_Lists.Nil; + -- The "point stack" of Tarjan's algorithm. The original maintains + -- a stack of vertices, however for diagnostic purposes using edges + -- is preferable. - -- Update the number of predecessors various components must wait on - -- before they can be elaborated. + Deleted_Vertices : LGV_Sets.Membership_Set := LGV_Sets.Nil; + -- The original algorithm alters the graph by deleting vertices with + -- lower ordinals compared to some starting vertex. Since the graph + -- must remain intact for diagnostic purposes, vertices are instead + -- inserted in this set and treated as "deleted". - Update_Pending_Predecessors_Of_Components (G); - end Find_Components; + End_Vertices : LGV_Sets.Membership_Set := LGV_Sets.Nil; + -- The original algorithm uses a single vertex to indicate the start + -- and end vertex of a cycle. The semantics of pragmas Elaborate_All + -- and Elaborate_Body increase this number by one. The end vertices + -- are added to this set and treated as "cycle-terminating". - ----------------- - -- Find_Cycles -- - ----------------- + Visited_Set : LGV_Sets.Membership_Set := LGV_Sets.Nil; + -- The "mark" array of Tarjan's algorithm. Since the original visits + -- all vertices in increasing ordinal number 1 .. N, the array offers + -- a one to one mapping between a vertex and its "marked" state. The + -- modified version however visits vertices within components, where + -- their ordinals are not contiguous. Vertices are added to this set + -- and treated as "marked". - procedure Find_Cycles (G : Library_Graph) is - Cycle_Path : LGE_Lists.Doubly_Linked_List; - Edge : Library_Graph_Edge_Id; - Iter : All_Edge_Iterator; - Visited_Vertices : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List := LGV_Lists.Nil; + -- The "marked stack" of Tarjan's algorithm begin - pragma Assert (Present (G)); + Trace_Component (G, Comp, No_Indentation); - -- Use a list of edges to describe the path of a cycle + -- Initialize all component-level data structures - Cycle_Path := LGE_Lists.Create; + Cycle_Path_Stack := LGE_Lists.Create; + Deleted_Vertices := LGV_Sets.Create (Num_Of_Vertices); + Visited_Set := LGV_Sets.Create (Num_Of_Vertices); + Visited_Stack := LGV_Lists.Create; - -- Use a set of visited vertices to prevent infinite traversal of the - -- graph. - - Visited_Vertices := LGV_Sets.Create (Number_Of_Vertices (G)); + -- The modified version does not use ordinals to visit vertices in + -- 1 .. N fashion. To preserve the invariant of the original, this + -- version deletes a vertex after its depth-first search completes. + -- The timing of the deletion is sound because all cycles through + -- that vertex have already been discovered, thus the vertex cannot + -- contribute to any cycles discovered "later" in the algorithm. - -- Inspect all edges, trying to find an edge that links two vertices - -- in the same component. - - Iter := Iterate_All_Edges (G); + Iter := Iterate_Component_Vertices (G, Comp); while Has_Next (Iter) loop - Next (Iter, Edge); - - -- Find all cycles involving the current edge. Duplicate cycles in - -- the forms of rotations are not saved for diagnostic purposes. - - if Is_Cycle_Initiating_Edge (G, Edge) then - Find_All_Cycles_With_Edge - (G => G, - Initial_Edge => Edge, - Spec_And_Body_Together => Is_Elaborate_All_Edge (G, Edge), - Cycle_Path => Cycle_Path, - Visited_Vertices => Visited_Vertices, - Indent => No_Indentation); - - Trace_Eol; - end if; + Next (Iter, Vertex); + + -- Construct the set of vertices (at most 2) that terminates a + -- potential cycle that starts from the current vertex. + + End_Vertices := + Cycle_End_Vertices + (G => G, + Vertex => Vertex, + Elaborate_All_Active => Elaborate_All_Active); + + -- The modified version maintans two addition attributes while + -- performing the depth-first search: + -- + -- * The most significant edge of the current potential cycle. + -- + -- * The number of invocation edges encountered along the path + -- of the current potential cycle. + -- + -- Both attributes are used in the heuristic which determines the + -- importance of cycles. + + Find_Cycles_From_Vertex + (G => G, + Vertex => Vertex, + End_Vertices => End_Vertices, + Deleted_Vertices => Deleted_Vertices, + Most_Significant_Edge => No_Library_Graph_Edge, + Invocation_Edge_Count => 0, + Cycle_Path_Stack => Cycle_Path_Stack, + Visited_Set => Visited_Set, + Visited_Stack => Visited_Stack, + Cycle_Count => Cycle_Count, + Cycle_Limit => Cycle_Limit, + Elaborate_All_Active => Elaborate_All_Active, + Is_Start_Vertex => True, + Has_Cycle => Has_Cycle, + Indent => Nested_Indentation); + + -- Destroy the cycle-terminating vertices because a new set must + -- be constructed for the next vertex. + + LGV_Sets.Destroy (End_Vertices); end loop; - LGE_Lists.Destroy (Cycle_Path); - LGV_Sets.Destroy (Visited_Vertices); - end Find_Cycles; + -- Destroy all component-level data structures + + LGE_Lists.Destroy (Cycle_Path_Stack); + LGV_Sets.Destroy (Deleted_Vertices); + LGV_Sets.Destroy (Visited_Set); + LGV_Lists.Destroy (Visited_Stack); + end Find_Cycles_In_Component; --------------------------------------- -- Find_First_Lower_Precedence_Cycle -- @@ -2670,7 +3166,7 @@ package body Bindo.Graphs is Next (Iter, Current_Cycle); if not Present (Lesser_Cycle) - and then Precedence + and then Cycle_Precedence (G => G, Cycle => Cycle, Compared_To => Current_Cycle) = Higher_Precedence @@ -2776,6 +3272,77 @@ package body Bindo.Graphs is return Seen; end Has_Elaborate_All_Cycle; + ---------------------------- + -- Has_Elaborate_All_Edge -- + ---------------------------- + + function Has_Elaborate_All_Edge + (G : Library_Graph; + Comp : Component_Id) return Boolean + is + Has_Edge : Boolean; + Iter : Component_Vertex_Iterator; + Vertex : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Comp)); + + -- Assume that there is no Elaborate_All edge + + Has_Edge := False; + + -- IMPORTANT: + -- + -- * The iteration must run to completion in order to unlock the + -- component vertices. + + Iter := Iterate_Component_Vertices (G, Comp); + while Has_Next (Iter) loop + Next (Iter, Vertex); + + Has_Edge := Has_Edge or else Has_Elaborate_All_Edge (G, Vertex); + end loop; + + return Has_Edge; + end Has_Elaborate_All_Edge; + + ---------------------------- + -- Has_Elaborate_All_Edge -- + ---------------------------- + + function Has_Elaborate_All_Edge + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is + Edge : Library_Graph_Edge_Id; + Has_Edge : Boolean; + Iter : Edges_To_Successors_Iterator; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + -- Assume that there is no Elaborate_All edge + + Has_Edge := False; + + -- IMPORTANT: + -- + -- * The iteration must run to completion in order to unlock the + -- edges to successors. + + Iter := Iterate_Edges_To_Successors (G, Vertex); + while Has_Next (Iter) loop + Next (Iter, Edge); + + Has_Edge := + Has_Edge or else Is_Cyclic_Elaborate_All_Edge (G, Edge); + end loop; + + return Has_Edge; + end Has_Elaborate_All_Edge; + ------------------------ -- Has_Elaborate_Body -- ------------------------ @@ -2961,7 +3528,7 @@ package body Bindo.Graphs is if Present (Left) and then Present (Right) then Edge_Prec := - Precedence + Edge_Precedence (G => G, Edge => Left, Compared_To => Right); @@ -3109,50 +3676,6 @@ package body Bindo.Graphs is end if; end Initialize_Components; - --------------------- - -- Insert_And_Sort -- - --------------------- - - procedure Insert_And_Sort - (G : Library_Graph; - Cycle : Library_Graph_Cycle_Id) - is - Lesser_Cycle : Library_Graph_Cycle_Id; - - begin - pragma Assert (Present (G)); - pragma Assert (Present (Cycle)); - pragma Assert (LGC_Lists.Present (G.Cycles)); - - -- The input cycle is the first to be inserted - - if LGC_Lists.Is_Empty (G.Cycles) then - LGC_Lists.Prepend (G.Cycles, Cycle); - - -- Otherwise the list of all cycles contains at least one cycle. - -- Insert the input cycle based on its precedence. - - else - Lesser_Cycle := Find_First_Lower_Precedence_Cycle (G, Cycle); - - -- The list contains at least one cycle, and the input cycle has a - -- higher precedence compared to some cycle in the list. - - if Present (Lesser_Cycle) then - LGC_Lists.Insert_Before - (L => G.Cycles, - Before => Lesser_Cycle, - Elem => Cycle); - - -- Otherwise the input cycle has the lowest precedence among all - -- cycles. - - else - LGC_Lists.Append (G.Cycles, Cycle); - end if; - end if; - end Insert_And_Sort; - --------------------------- -- Invocation_Edge_Count -- --------------------------- @@ -3496,17 +4019,13 @@ package body Bindo.Graphs is (G : Library_Graph; Edge : Library_Graph_Edge_Id) return Boolean is + begin pragma Assert (Present (G)); pragma Assert (Present (Edge)); - Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); - - begin return Kind (G, Edge) = With_Edge - and then - (Is_Spec_With_Elaborate_Body (G, Succ) - or else Is_Body_Of_Spec_With_Elaborate_Body (G, Succ)); + and then Is_Vertex_With_Elaborate_Body (G, Successor (G, Edge)); end Is_Elaborate_Body_Edge; ----------------------- @@ -3622,20 +4141,6 @@ package body Bindo.Graphs is return U_Rec.Preelab or else U_Rec.Pure; end Is_Preelaborated_Unit; - ----------------------- - -- Is_Recorded_Cycle -- - ----------------------- - - function Is_Recorded_Cycle - (G : Library_Graph; - Attrs : Library_Graph_Cycle_Attributes) return Boolean - is - begin - pragma Assert (Present (G)); - - return RC_Sets.Contains (G.Recorded_Cycles, Attrs); - end Is_Recorded_Cycle; - ---------------------- -- Is_Recorded_Edge -- ---------------------- @@ -3722,6 +4227,24 @@ package body Bindo.Graphs is and then not Is_Dynamically_Elaborated (G, Successor (G, Edge)); end Is_Static_Successor_Edge; + ----------------------------------- + -- Is_Vertex_With_Elaborate_Body -- + ----------------------------------- + + function Is_Vertex_With_Elaborate_Body + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + + return + Is_Spec_With_Elaborate_Body (G, Vertex) + or else + Is_Body_Of_Spec_With_Elaborate_Body (G, Vertex); + end Is_Vertex_With_Elaborate_Body; + --------------------------------- -- Is_Weakly_Elaborable_Vertex -- ---------------------------------- @@ -4107,50 +4630,6 @@ package body Bindo.Graphs is DG.Next (DG.Component_Vertex_Iterator (Iter), Vertex); end Next; - ----------------------------- - -- Normalize_And_Add_Cycle -- - ----------------------------- - - procedure Normalize_And_Add_Cycle - (G : Library_Graph; - Most_Significant_Edge : Library_Graph_Edge_Id; - Invocation_Edge_Count : Natural; - Cycle_Path : LGE_Lists.Doubly_Linked_List; - Indent : Indentation_Level) - is - Path : LGE_Lists.Doubly_Linked_List; - - begin - pragma Assert (Present (G)); - pragma Assert (Present (Most_Significant_Edge)); - pragma Assert (LGE_Lists.Present (Cycle_Path)); - - -- Replicate the path of the cycle in order to avoid sharing lists - - Path := Copy_Cycle_Path (Cycle_Path); - - -- Normalize the path of the cycle such that its most significant - -- edge is the first in the list of edges. - - Normalize_Cycle_Path - (Cycle_Path => Path, - Most_Significant_Edge => Most_Significant_Edge); - - -- Save the cycle for diagnostic purposes. Its kind is determined by - -- its most significant edge. - - Add_Cycle - (G => G, - Attrs => - (Invocation_Edge_Count => Invocation_Edge_Count, - Kind => - Cycle_Kind_Of - (G => G, - Edge => Most_Significant_Edge), - Path => Path), - Indent => Indent); - end Normalize_And_Add_Cycle; - -------------------------- -- Normalize_Cycle_Path -- -------------------------- @@ -4256,12 +4735,56 @@ package body Bindo.Graphs is -- Number_Of_Vertices -- ------------------------ - function Number_Of_Vertices (G : Library_Graph) return Natural is - begin - pragma Assert (Present (G)); + function Number_Of_Vertices (G : Library_Graph) return Natural is + begin + pragma Assert (Present (G)); + + return DG.Number_Of_Vertices (G.Graph); + end Number_Of_Vertices; + + ----------------- + -- Order_Cycle -- + ----------------- + + procedure Order_Cycle + (G : Library_Graph; + Cycle : Library_Graph_Cycle_Id) + is + Lesser_Cycle : Library_Graph_Cycle_Id; + + begin + pragma Assert (Present (G)); + pragma Assert (Present (Cycle)); + pragma Assert (LGC_Lists.Present (G.Cycles)); + + -- The input cycle is the first to be inserted + + if LGC_Lists.Is_Empty (G.Cycles) then + LGC_Lists.Prepend (G.Cycles, Cycle); + + -- Otherwise the list of all cycles contains at least one cycle. + -- Insert the input cycle based on its precedence. + + else + Lesser_Cycle := Find_First_Lower_Precedence_Cycle (G, Cycle); + + -- The list contains at least one cycle, and the input cycle has a + -- higher precedence compared to some cycle in the list. + + if Present (Lesser_Cycle) then + LGC_Lists.Insert_Before + (L => G.Cycles, + Before => Lesser_Cycle, + Elem => Cycle); + + -- Otherwise the input cycle has the lowest precedence among all + -- cycles. - return DG.Number_Of_Vertices (G.Graph); - end Number_Of_Vertices; + else + LGC_Lists.Append (G.Cycles, Cycle); + end if; + end if; + end Order_Cycle; ---------- -- Path -- @@ -4399,146 +4922,6 @@ package body Bindo.Graphs is return Get_LGV_Attributes (G, Vertex).Pending_Weak_Predecessors; end Pending_Weak_Predecessors; - ---------------- - -- Precedence -- - ---------------- - - function Precedence - (G : Library_Graph; - Cycle : Library_Graph_Cycle_Id; - Compared_To : Library_Graph_Cycle_Id) return Precedence_Kind - is - pragma Assert (Present (G)); - pragma Assert (Present (Cycle)); - pragma Assert (Present (Compared_To)); - - Comp_Invs : constant Natural := - Invocation_Edge_Count (G, Compared_To); - Comp_Len : constant Natural := Length (G, Compared_To); - Cycle_Invs : constant Natural := Invocation_Edge_Count (G, Cycle); - Cycle_Len : constant Natural := Length (G, Cycle); - Kind_Prec : constant Precedence_Kind := - Precedence - (Kind => Kind (G, Cycle), - Compared_To => Kind (G, Compared_To)); - - begin - if Kind_Prec = Higher_Precedence - or else - Kind_Prec = Lower_Precedence - then - return Kind_Prec; - - -- Otherwise both cycles have the same precedence based on their - -- kind. Prefer a cycle with fewer invocation edges. - - elsif Cycle_Invs < Comp_Invs then - return Higher_Precedence; - - elsif Cycle_Invs > Comp_Invs then - return Lower_Precedence; - - -- Otherwise both cycles have the same number of invocation edges. - -- Prefer a cycle with a smaller length. - - elsif Cycle_Len < Comp_Len then - return Higher_Precedence; - - elsif Cycle_Len > Comp_Len then - return Lower_Precedence; - - else - return Equal_Precedence; - end if; - end Precedence; - - ---------------- - -- Precedence -- - ---------------- - - function Precedence - (Kind : Library_Graph_Cycle_Kind; - Compared_To : Library_Graph_Cycle_Kind) return Precedence_Kind - is - Comp_Pos : constant Integer := - Library_Graph_Cycle_Kind'Pos (Compared_To); - Kind_Pos : constant Integer := Library_Graph_Cycle_Kind'Pos (Kind); - - begin - -- A lower ordinal indicates higher precedence - - if Kind_Pos < Comp_Pos then - return Higher_Precedence; - - elsif Kind_Pos > Comp_Pos then - return Lower_Precedence; - - else - return Equal_Precedence; - end if; - end Precedence; - - ---------------- - -- Precedence -- - ---------------- - - function Precedence - (G : Library_Graph; - Edge : Library_Graph_Edge_Id; - Compared_To : Library_Graph_Edge_Id) return Precedence_Kind - is - pragma Assert (Present (G)); - pragma Assert (Present (Edge)); - pragma Assert (Present (Compared_To)); - - Kind_Prec : constant Precedence_Kind := - Precedence - (Kind => Cycle_Kind_Of (G, Edge), - Compared_To => Cycle_Kind_Of (G, Compared_To)); - - begin - if Kind_Prec = Higher_Precedence - or else - Kind_Prec = Lower_Precedence - then - return Kind_Prec; - - -- Otherwise both edges have the same precedence based on their cycle - -- kinds. Prefer an edge whose successor has higher precedence. - - else - return - Precedence - (G => G, - Vertex => Successor (G, Edge), - Compared_To => Successor (G, Compared_To)); - end if; - end Precedence; - - ---------------- - -- Precedence -- - ---------------- - - function Precedence - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind - is - begin - pragma Assert (Present (G)); - pragma Assert (Present (Vertex)); - pragma Assert (Present (Compared_To)); - - -- Use lexicographical order to determine precedence and ensure - -- deterministic behavior. - - if Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then - return Higher_Precedence; - else - return Lower_Precedence; - end if; - end Precedence; - ----------------- -- Predecessor -- ----------------- @@ -4615,33 +4998,59 @@ package body Bindo.Graphs is end if; end Proper_Spec; - ---------------------------------- - -- Remove_Vertex_And_Complement -- - ---------------------------------- + ------------------ + -- Record_Cycle -- + ------------------ - procedure Remove_Vertex_And_Complement - (G : Library_Graph; - Vertex : Library_Graph_Vertex_Id; - Set : LGV_Sets.Membership_Set; - Do_Complement : Boolean) + procedure Record_Cycle + (G : Library_Graph; + Most_Significant_Edge : Library_Graph_Edge_Id; + Invocation_Edge_Count : Natural; + Cycle_Path : LGE_Lists.Doubly_Linked_List; + Indent : Indentation_Level) is + Cycle : Library_Graph_Cycle_Id; + Path : LGE_Lists.Doubly_Linked_List; + + begin pragma Assert (Present (G)); - pragma Assert (Present (Vertex)); - pragma Assert (LGV_Sets.Present (Set)); + pragma Assert (Present (Most_Significant_Edge)); + pragma Assert (LGE_Lists.Present (Cycle_Path)); - Complement : constant Library_Graph_Vertex_Id := - Complementary_Vertex - (G => G, - Vertex => Vertex, - Force_Complement => Do_Complement); + -- Replicate the path of the cycle in order to avoid sharing lists - begin - LGV_Sets.Delete (Set, Vertex); + Path := Copy_Cycle_Path (Cycle_Path); - if Present (Complement) then - LGV_Sets.Delete (Set, Complement); - end if; - end Remove_Vertex_And_Complement; + -- Normalize the path of the cycle such that its most significant + -- edge is the first in the list of edges. + + Normalize_Cycle_Path + (Cycle_Path => Path, + Most_Significant_Edge => Most_Significant_Edge); + + -- Save the cycle for diagnostic purposes. Its kind is determined by + -- its most significant edge. + + Cycle := Sequence_Next_Cycle; + + Set_LGC_Attributes + (G => G, + Cycle => Cycle, + Val => + (Invocation_Edge_Count => Invocation_Edge_Count, + Kind => + Cycle_Kind_Of + (G => G, + Edge => Most_Significant_Edge), + Path => Path)); + + Trace_Cycle (G, Cycle, Indent); + + -- Order the cycle based on its precedence relative to previously + -- discovered cycles. + + Order_Cycle (G, Cycle); + end Record_Cycle; ----------------------------------------- -- Same_Library_Graph_Cycle_Attributes -- @@ -4737,25 +5146,6 @@ package body Bindo.Graphs is Set_LGV_Attributes (G, Vertex, Attrs); end Set_In_Elaboration_Order; - --------------------------- - -- Set_Is_Recorded_Cycle -- - --------------------------- - - procedure Set_Is_Recorded_Cycle - (G : Library_Graph; - Attrs : Library_Graph_Cycle_Attributes; - Val : Boolean := True) - is - begin - pragma Assert (Present (G)); - - if Val then - RC_Sets.Insert (G.Recorded_Cycles, Attrs); - else - RC_Sets.Delete (G.Recorded_Cycles, Attrs); - end if; - end Set_Is_Recorded_Cycle; - -------------------------- -- Set_Is_Recorded_Edge -- -------------------------- @@ -4840,6 +5230,34 @@ package body Bindo.Graphs is return DG.Destination_Vertex (G.Graph, Edge); end Successor; + --------------------- + -- Trace_Component -- + --------------------- + + procedure Trace_Component + (G : Library_Graph; + Comp : Component_Id; + Indent : Indentation_Level) + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Comp)); + + -- Nothing to do when switch -d_t (output cycle detection trace + -- information) is not in effect. + + if not Debug_Flag_Underscore_T then + return; + end if; + + Write_Eol; + Indent_By (Indent); + Write_Str ("component (Comp_"); + Write_Int (Int (Comp)); + Write_Str (")"); + Write_Eol; + end Trace_Component; + ----------------- -- Trace_Cycle -- ----------------- @@ -4861,15 +5279,15 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Cycle)); - -- Nothing to do when switch -d_T (output elaboration order and cycle - -- detection trace information) is not in effect. + -- Nothing to do when switch -d_t (output cycle detection trace + -- information) is not in effect. - if not Debug_Flag_Underscore_TT then + if not Debug_Flag_Underscore_T then return; end if; Indent_By (Indent); - Write_Str ("cycle (Cycle_Id_"); + Write_Str ("cycle (LGC_Id_"); Write_Int (Int (Cycle)); Write_Str (")"); Write_Eol; @@ -4920,10 +5338,10 @@ package body Bindo.Graphs is Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); begin - -- Nothing to do when switch -d_T (output elaboration order and cycle - -- detection trace information) is not in effect. + -- Nothing to do when switch -d_t (output cycle detection trace + -- information) is not in effect. - if not Debug_Flag_Underscore_TT then + if not Debug_Flag_Underscore_T then return; end if; @@ -4953,22 +5371,6 @@ package body Bindo.Graphs is Write_Eol; end Trace_Edge; - --------------- - -- Trace_Eol -- - --------------- - - procedure Trace_Eol is - begin - -- Nothing to do when switch -d_T (output elaboration order and cycle - -- detection trace information) is not in effect. - - if not Debug_Flag_Underscore_TT then - return; - end if; - - Write_Eol; - end Trace_Eol; - ------------------ -- Trace_Vertex -- ------------------ @@ -4985,10 +5387,10 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Vertex)); - -- Nothing to do when switch -d_T (output elaboration order and cycle - -- detection trace information) is not in effect. + -- Nothing to do when switch -d_t (output cycle detection trace + -- information) is not in effect. - if not Debug_Flag_Underscore_TT then + if not Debug_Flag_Underscore_T then return; end if; @@ -4998,12 +5400,6 @@ package body Bindo.Graphs is Write_Str (")"); Write_Eol; - Indent_By (Attr_Indent); - Write_Str ("Component (Comp_Id_"); - Write_Int (Int (Component (G, Vertex))); - Write_Str (")"); - Write_Eol; - Indent_By (Attr_Indent); Write_Str ("Unit (U_Id_"); Write_Int (Int (Unit (G, Vertex))); @@ -5027,6 +5423,32 @@ package body Bindo.Graphs is return Get_LGV_Attributes (G, Vertex).Unit; end Unit; + ------------- + -- Unvisit -- + ------------- + + procedure Unvisit + (Vertex : Library_Graph_Vertex_Id; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List) + is + Current_Vertex : Library_Graph_Vertex_Id; + + begin + pragma Assert (Present (Vertex)); + pragma Assert (LGV_Sets.Present (Visited_Set)); + pragma Assert (LGV_Lists.Present (Visited_Stack)); + + while not LGV_Lists.Is_Empty (Visited_Stack) loop + Current_Vertex := LGV_Lists.First (Visited_Stack); + + LGV_Lists.Delete_First (Visited_Stack); + LGV_Sets.Delete (Visited_Set, Current_Vertex); + + exit when Current_Vertex = Vertex; + end loop; + end Unvisit; + --------------------------------- -- Update_Pending_Predecessors -- --------------------------------- @@ -5097,6 +5519,48 @@ package body Bindo.Graphs is Edge => Edge); end if; end Update_Pending_Predecessors_Of_Components; + + ----------------------- + -- Vertex_Precedence -- + ----------------------- + + function Vertex_Precedence + (G : Library_Graph; + Vertex : Library_Graph_Vertex_Id; + Compared_To : Library_Graph_Vertex_Id) return Precedence_Kind + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Vertex)); + pragma Assert (Present (Compared_To)); + + -- Use lexicographical order to determine precedence and ensure + -- deterministic behavior. + + if Uname_Less (Name (G, Vertex), Name (G, Compared_To)) then + return Higher_Precedence; + else + return Lower_Precedence; + end if; + end Vertex_Precedence; + + ----------- + -- Visit -- + ----------- + + procedure Visit + (Vertex : Library_Graph_Vertex_Id; + Visited_Set : LGV_Sets.Membership_Set; + Visited_Stack : LGV_Lists.Doubly_Linked_List) + is + begin + pragma Assert (Present (Vertex)); + pragma Assert (LGV_Sets.Present (Visited_Set)); + pragma Assert (LGV_Lists.Present (Visited_Stack)); + + LGV_Sets.Insert (Visited_Set, Vertex); + LGV_Lists.Prepend (Visited_Stack, Vertex); + end Visit; end Library_Graphs; ------------- diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads index 86ba823..8323784 100644 --- a/gcc/ada/bindo-graphs.ads +++ b/gcc/ada/bindo-graphs.ads @@ -174,6 +174,11 @@ package Bindo.Graphs is First_Library_Graph_Vertex : constant Library_Graph_Vertex_Id := No_Library_Graph_Vertex + 1; + procedure Destroy_Library_Graph_Vertex + (Vertex : in out Library_Graph_Vertex_Id); + pragma Inline (Destroy_Library_Graph_Vertex); + -- Destroy library graph vertex Vertex + function Hash_Library_Graph_Vertex (Vertex : Library_Graph_Vertex_Id) return Bucket_Range_Type; pragma Inline (Hash_Library_Graph_Vertex); @@ -183,6 +188,11 @@ package Bindo.Graphs is pragma Inline (Present); -- Determine whether library graph vertex Vertex exists + package LGV_Lists is new Doubly_Linked_Lists + (Element_Type => Library_Graph_Vertex_Id, + "=" => "=", + Destroy_Element => Destroy_Library_Graph_Vertex); + package LGV_Sets is new Membership_Sets (Element_Type => Library_Graph_Vertex_Id, "=" => "=", @@ -1406,11 +1416,6 @@ package Bindo.Graphs is -- Vertices -- -------------- - procedure Destroy_Library_Graph_Vertex - (Vertex : in out Library_Graph_Vertex_Id); - pragma Inline (Destroy_Library_Graph_Vertex); - -- Destroy library graph vertex Vertex - -- The following type represents the attributes of a library graph -- vertex. @@ -1593,15 +1598,6 @@ package Bindo.Graphs is Destroy_Value => Destroy_Library_Graph_Cycle_Attributes, Hash => Hash_Library_Graph_Cycle); - --------------------- - -- Recorded cycles -- - --------------------- - - package RC_Sets is new Membership_Sets - (Element_Type => Library_Graph_Cycle_Attributes, - "=" => Same_Library_Graph_Cycle_Attributes, - Hash => Hash_Library_Graph_Cycle_Attributes); - -------------------- -- Recorded edges -- -------------------- @@ -1693,10 +1689,6 @@ package Bindo.Graphs is -- The underlying graph describing the relations between edges and -- vertices. - Recorded_Cycles : RC_Sets.Membership_Set := RC_Sets.Nil; - -- The set of recorded cycles, used to prevent duplicate cycles in - -- the graph. - Recorded_Edges : RE_Sets.Membership_Set := RE_Sets.Nil; -- The set of recorded edges, used to prevent duplicate edges in the -- graph. diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb index 99f93f5..c4784d4 100644 --- a/gcc/ada/bindo-writers.adb +++ b/gcc/ada/bindo-writers.adb @@ -1102,6 +1102,8 @@ package body Bindo.Writers is Write_Eol; Write_Component_Vertices (G, Comp); + + Write_Eol; end Write_Component; ------------------------------ @@ -1112,25 +1114,34 @@ package body Bindo.Writers is (G : Library_Graph; Comp : Component_Id) is + pragma Assert (Present (G)); + pragma Assert (Present (Comp)); + + Num_Of_Vertices : constant Natural := + Number_Of_Component_Vertices (G, Comp); + Iter : Component_Vertex_Iterator; Vertex : Library_Graph_Vertex_Id; begin - pragma Assert (Present (G)); - pragma Assert (Present (Comp)); + Write_Str (" Vertices: "); + Write_Int (Int (Num_Of_Vertices)); + Write_Eol; - Iter := Iterate_Component_Vertices (G, Comp); - while Has_Next (Iter) loop - Next (Iter, Vertex); + if Num_Of_Vertices > 0 then + Iter := Iterate_Component_Vertices (G, Comp); + while Has_Next (Iter) loop + Next (Iter, Vertex); - Write_Str (" library graph vertex (LGV_Id_"); - Write_Int (Int (Vertex)); - Write_Str (") name = "); - Write_Name (Name (G, Vertex)); + Write_Str (" library graph vertex (LGV_Id_"); + Write_Int (Int (Vertex)); + Write_Str (") name = "); + Write_Name (Name (G, Vertex)); + Write_Eol; + end loop; + else Write_Eol; - end loop; - - Write_Eol; + end if; end Write_Component_Vertices; ---------------------- diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index 519887d..c467617 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -322,6 +322,11 @@ package body Bindo is -- In addition, GNATbind does not create an edge to the body of the -- pragma argument. -- + -- -d_t Output cycle detection trace information + -- + -- GNATbind outputs trace information on cycle detection activities + -- to standard output. + -- -- -d_A Output ALI invocation tables -- -- GNATbind outputs the contents of ALI table Invocation_Constructs @@ -352,8 +357,8 @@ package body Bindo is -- -- -d_T Output elaboration-order trace information -- - -- GNATbind outputs trace information on elaboration-order and cycle- - -- detection activities to standard output. + -- GNATbind outputs trace information on elaboration-order detection + -- activities to standard output. -- -- -d_V Validate bindo cycles, graphs, and order -- @@ -395,7 +400,7 @@ package body Bindo is -- number of files in the bind, Bindo may emit anywhere between several MBs -- to several hundred MBs of data to standard output. The switches are: -- - -- -d_A -d_C -d_I -d_L -d_P -d_T -d_V + -- -d_A -d_C -d_I -d_L -d_P -d_t -d_T -d_V -- -- Bindo offers several debugging routines that can be invoked from gdb. -- Those are defined in the body of Bindo.Writers, in sections denoted by diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index a4ff176..89bb7f8 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -368,7 +368,7 @@ package body Debug is -- d_q -- d_r -- d_s - -- d_t + -- d_t Output cycle detection trace information -- d_u -- d_v -- d_w @@ -380,6 +380,7 @@ package body Debug is -- d_B -- d_C Diagnose all cycles -- d_D + -- d_E -- d_F -- d_G -- d_H @@ -394,7 +395,7 @@ package body Debug is -- d_Q -- d_R -- d_S - -- d_T Output elaboration order and cycle detection trace information + -- d_T Output elaboration order trace information -- d_U -- d_V Validate bindo cycles, graphs, and order -- d_W @@ -1149,6 +1150,9 @@ package body Debug is -- elaboration order and no longer creates an implicit dependency on -- the body of the argument. + -- d_t GNATBIND output trace information of cycle detection activities to + -- standard output. + -- d_A GNATBIND output the contents of all ALI invocation-related tables -- in textual format to standard output. @@ -1163,8 +1167,8 @@ package body Debug is -- d_P GNATBIND outputs the cycle paths to standard output - -- d_T GNATBIND outputs trace information of elaboration order and cycle - -- detection activities to standard output. + -- d_T GNATBIND outputs trace information of elaboration order detection + -- activities to standard output. -- d_V GNATBIND validates the invocation graph, library graph along with -- its cycles, and the elaboration order. -- cgit v1.1 From c03c026753c3cfb102435842e53c0a4773aedc75 Mon Sep 17 00:00:00 2001 From: Patrick Bernardi Date: Wed, 10 Jul 2019 09:01:08 +0000 Subject: [Ada] New port for ppc-vx7r2 2019-07-10 Patrick Bernardi gcc/ada/ * Makefile.rtl: Handle vxworks7r2 ppc target From-SVN: r273331 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/Makefile.rtl | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ecbee09..88c25be 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-10 Patrick Bernardi + + * Makefile.rtl: Handle vxworks7r2 ppc target + 2019-07-10 Hristian Kirtchev * bindo.adb: Update the section on switches. diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 8e906a9..9e3d67e 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -867,7 +867,7 @@ GCC_SPEC_FILES= # If what's left is null then it's a match. # PowerPC and e500v2 VxWorks -ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7 vxworks7spe,$(target_cpu) $(target_vendor) $(target_os))),) +ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe,$(target_cpu) $(target_vendor) $(target_os))),) ifeq ($(strip $(filter-out e500%, $(target_alias))),) ARCH_STR=e500 -- cgit v1.1 From 32e0627f99f4212695ec13b6d50ca48d1c29ded3 Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Wed, 10 Jul 2019 09:01:13 +0000 Subject: [Ada] The environ macro is broken on vxworks7r2 SR0610 In SR0610, the TCB is made private, so the task environ field used by the environ macro is no longer visible. Arguably this is a bug, however a more correct approach is to use accessor functions to retrieve this field and not use the environ macro, thus avoiding the problem. 2019-07-10 Doug Rupp gcc/ada/ * env.c (__gnat_environ): Reformulate to also work for vxworks7r2 SR0610. From-SVN: r273332 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/env.c | 32 +++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 88c25be..e4034e4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Doug Rupp + + * env.c (__gnat_environ): Reformulate to also work for + vxworks7r2 SR0610. + 2019-07-10 Patrick Bernardi * Makefile.rtl: Handle vxworks7r2 ppc target diff --git a/gcc/ada/env.c b/gcc/ada/env.c index cf839f5..04e861e 100644 --- a/gcc/ada/env.c +++ b/gcc/ada/env.c @@ -60,6 +60,9 @@ #endif #if defined (__vxworks) + #include + #include + #if defined (__RTP__) /* On VxWorks 6 Real-Time process mode, environ is defined in unistd.h. */ #include @@ -69,14 +72,18 @@ envLib.h on VxWorks MILS and VxWorks 653. */ #include #include - #else - /* This should work for kernel mode on both VxWorks 5 and VxWorks 6. */ + #elif (_WRS_VXWORKS_MAJOR <= 6) #include - - /* In that mode environ is a macro which reference the following symbol. - As the symbol is not defined in any VxWorks include files we declare - it as extern. */ + /* In that mode the following symbol is not defined in any VxWorks + include files, prior to vxWorks 7, so we declare it as extern. */ extern char** ppGlobalEnviron; + #elif (_WRS_VXWORKS_MAJOR >= 7) + /* This should work for kernel mode on VxWorks 7.x. In 7.2 the tcb + is made private, so accessor functions must be used, in 7.0 it + is optional but there is no way to distinguish between 7.2 + and 7.0 since the version.h header file was never updated. */ + #include + #include #endif #endif @@ -223,7 +230,18 @@ __gnat_environ (void) extern char **environ; return environ; #else - return environ; + #if defined (__RTP__) || defined (VTHREADS) || (_WRS_VXWORKS_MAJOR <= 6) + return environ; + #elif (_WRS_VXWORKS_MAJOR >= 7) + char **task_environ; + + task_environ = envGet (taskIdSelf ()); + + if (task_environ == NULL) + return ppGlobalEnviron; + else + return task_environ; + #endif #endif } -- cgit v1.1 From ef8a3d9ef0ace5479d42f7a5382393b5a1a79d96 Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Wed, 10 Jul 2019 09:01:17 +0000 Subject: [Ada] Vxworks7r2 SR0610 coalesced some macro values SR0600 and SR0610 cannot be differentiated by macro testing (arguably an oversight in header file version.h) so: The case statement testing for "file not found" is reformulated into an if/else series of statements to avoid a problem where two cases have identical values in SR0610, but different values in SR0600. 2019-07-10 Doug Rupp gcc/ada/ * sysdep.c (__gnat_is_file_not_found_error): Reformulate to also work for vxworks7r2 SR0610. From-SVN: r273333 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sysdep.c | 38 +++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e4034e4..2c069ab1 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-10 Doug Rupp + * sysdep.c (__gnat_is_file_not_found_error): Reformulate to also + work for vxworks7r2 SR0610. + +2019-07-10 Doug Rupp + * env.c (__gnat_environ): Reformulate to also work for vxworks7r2 SR0610. diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c index 0fbc606..a5f325d 100644 --- a/gcc/ada/sysdep.c +++ b/gcc/ada/sysdep.c @@ -300,7 +300,7 @@ __gnat_set_mode (int handle ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED) } char * -__gnat_ttyname (int filedes) +__gnat_ttyname (int filedes ATTRIBUTE_UNUSED) { #if defined (__vxworks) return ""; @@ -896,30 +896,34 @@ __gnat_get_task_options (void) #endif int -__gnat_is_file_not_found_error (int errno_val) { - switch (errno_val) { - case ENOENT: +__gnat_is_file_not_found_error (int errno_val) + { + /* WARNING: Do not rewrite this as a switch/case statement. + * Some of the "cases" are duplicated in some versions of + * Vxworks, notably VxWorks7r2 SR0610. */ + if (errno_val == ENOENT) + return 1; #ifdef __vxworks - /* In the case of VxWorks, we also have to take into account various - * filesystem-specific variants of this error. - */ + /* In the case of VxWorks, we also have to take into account various + * filesystem-specific variants of this error. + */ #if ! defined (VTHREADS) && (_WRS_VXWORKS_MAJOR < 7) - case S_dosFsLib_FILE_NOT_FOUND: + else if (errno_val == S_dosFsLib_FILE_NOT_FOUND) + return 1; #endif #if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__)) - case S_nfsLib_NFSERR_NOENT: + else if (errno_val == S_nfsLib_NFSERR_NOENT) + return 1; #endif #if defined (__RTP__) - /* An RTP can return an NFS file not found, and the NFS bits must - first be masked on to check the errno. */ - case M_nfsStat | ENOENT: + /* An RTP can return an NFS file not found, and the NFS bits must + first be masked on to check the errno. */ + else if (errno_val == (M_nfsStat | ENOENT)) + return 1; #endif #endif - return 1; - - default: - return 0; - } + else + return 0; } #if defined (__linux__) -- cgit v1.1 From 0b6694b4e41d394df12d159c319be4b1326745ca Mon Sep 17 00:00:00 2001 From: Joffrey Huguet Date: Wed, 10 Jul 2019 09:01:28 +0000 Subject: [Ada] Add contracts to Strings libraries This patch adds contracts to Ada.Strings libraries, in order to remove warnings when using these libraries in SPARK. 2019-07-10 Joffrey Huguet gcc/ada/ * libgnat/a-strbou.ads, libgnat/a-strfix.ads, libgnat/a-strunb.ads, libgnat/a-strunb__shared.ads: Add global contracts, contract cases, preconditions and postconditions to procedures and functions. From-SVN: r273334 --- gcc/ada/ChangeLog | 7 + gcc/ada/libgnat/a-strbou.ads | 521 +++++++++++++++++++++++++++++------ gcc/ada/libgnat/a-strfix.ads | 246 ++++++++++++++--- gcc/ada/libgnat/a-strunb.ads | 403 ++++++++++++++++++++++----- gcc/ada/libgnat/a-strunb__shared.ads | 405 ++++++++++++++++++++++----- 5 files changed, 1328 insertions(+), 254 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2c069ab1..9d99033 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-10 Joffrey Huguet + + * libgnat/a-strbou.ads, libgnat/a-strfix.ads, + libgnat/a-strunb.ads, libgnat/a-strunb__shared.ads: Add global + contracts, contract cases, preconditions and postconditions to + procedures and functions. + 2019-07-10 Doug Rupp * sysdep.c (__gnat_is_file_not_found_error): Reformulate to also diff --git a/gcc/ada/libgnat/a-strbou.ads b/gcc/ada/libgnat/a-strbou.ads index f525ccf..ae61b86 100644 --- a/gcc/ada/libgnat/a-strbou.ads +++ b/gcc/ada/libgnat/a-strbou.ads @@ -33,6 +33,12 @@ -- -- ------------------------------------------------------------------------------ +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. This is enforced by +-- setting the corresponding assertion policy to Ignore. + +pragma Assertion_Policy (Pre => Ignore); + with Ada.Strings.Maps; with Ada.Strings.Superbounded; @@ -43,7 +49,9 @@ package Ada.Strings.Bounded is Max : Positive; -- Maximum length of a Bounded_String - package Generic_Bounded_Length is + package Generic_Bounded_Length with + Initial_Condition => Length (Null_Bounded_String) = 0 + is Max_Length : constant Positive := Max; @@ -54,7 +62,8 @@ package Ada.Strings.Bounded is subtype Length_Range is Natural range 0 .. Max_Length; - function Length (Source : Bounded_String) return Length_Range; + function Length (Source : Bounded_String) return Length_Range with + Global => null; -------------------------------------------------------- -- Conversion, Concatenation, and Selection Functions -- @@ -62,162 +71,302 @@ package Ada.Strings.Bounded is function To_Bounded_String (Source : String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => (if Source'Length > Max_Length then Drop /= Error), + Post => + Length (To_Bounded_String'Result) + = Natural'Min (Max_Length, Source'Length), + Global => null; - function To_String (Source : Bounded_String) return String; + function To_String (Source : Bounded_String) return String with + Post => To_String'Result'Length = Length (Source), + Global => null; procedure Set_Bounded_String (Target : out Bounded_String; Source : String; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => (if Source'Length > Max_Length then Drop /= Error), + Post => Length (Target) = Natural'Min (Max_Length, Source'Length), + Global => null; pragma Ada_05 (Set_Bounded_String); function Append (Left : Bounded_String; Right : Bounded_String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + (if Length (Left) > Max_Length - Length (Right) + then Drop /= Error), + Post => + Length (Append'Result) + = Natural'Min (Max_Length, Length (Left) + Length (Right)), + Global => null; function Append (Left : Bounded_String; Right : String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + (if Right'Length > Max_Length - Length (Left) + then Drop /= Error), + Post => + Length (Append'Result) + = Natural'Min (Max_Length, Length (Left) + Right'Length), + Global => null; function Append (Left : String; Right : Bounded_String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + (if Left'Length > Max_Length - Length (Right) + then Drop /= Error), + Post => + Length (Append'Result) + = Natural'Min (Max_Length, Left'Length + Length (Right)), + Global => null; function Append (Left : Bounded_String; Right : Character; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => (if Length (Left) = Max_Length then Drop /= Error), + Post => + Length (Append'Result) + = Natural'Min (Max_Length, Length (Left) + 1), + Global => null; function Append (Left : Character; Right : Bounded_String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => (if Length (Right) = Max_Length then Drop /= Error), + Post => + Length (Append'Result) + = Natural'Min (Max_Length, 1 + Length (Right)), + Global => null; procedure Append (Source : in out Bounded_String; New_Item : Bounded_String; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => + (if Length (Source) > Max_Length - Length (New_Item) + then Drop /= Error), + Post => + Length (Source) + = Natural'Min (Max_Length, Length (Source)'Old + Length (New_Item)), + Global => null; procedure Append (Source : in out Bounded_String; New_Item : String; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => + (if New_Item'Length > Max_Length - Length (Source) + then Drop /= Error), + Post => + Length (Source) + = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length), + Global => null; procedure Append (Source : in out Bounded_String; New_Item : Character; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => (if Length (Source) = Max_Length then Drop /= Error), + Post => + Length (Source) + = Natural'Min (Max_Length, Length (Source)'Old + 1), + Global => null; function "&" (Left : Bounded_String; - Right : Bounded_String) return Bounded_String; + Right : Bounded_String) return Bounded_String + with + Pre => Length (Left) <= Max_Length - Length (Right), + Post => Length ("&"'Result) = Length (Left) + Length (Right), + Global => null; function "&" (Left : Bounded_String; - Right : String) return Bounded_String; + Right : String) return Bounded_String + with + Pre => Right'Length <= Max_Length - Length (Left), + Post => Length ("&"'Result) = Length (Left) + Right'Length, + Global => null; function "&" (Left : String; - Right : Bounded_String) return Bounded_String; + Right : Bounded_String) return Bounded_String + with + Pre => Left'Length <= Max_Length - Length (Right), + Post => Length ("&"'Result) = Left'Length + Length (Right), + Global => null; function "&" (Left : Bounded_String; - Right : Character) return Bounded_String; + Right : Character) return Bounded_String + with + Pre => Length (Left) < Max_Length, + Post => Length ("&"'Result) = Length (Left) + 1, + Global => null; function "&" (Left : Character; - Right : Bounded_String) return Bounded_String; + Right : Bounded_String) return Bounded_String + with + Pre => Length (Right) < Max_Length, + Post => Length ("&"'Result) = 1 + Length (Right), + Global => null; function Element (Source : Bounded_String; - Index : Positive) return Character; + Index : Positive) return Character + with + Pre => Index <= Length (Source), + Global => null; procedure Replace_Element (Source : in out Bounded_String; Index : Positive; - By : Character); + By : Character) + with + Pre => Index <= Length (Source), + Post => Length (Source) = Length (Source)'Old, + Global => null; function Slice (Source : Bounded_String; Low : Positive; - High : Natural) return String; + High : Natural) return String + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => Slice'Result'Length = Natural'Max (0, High - Low + 1), + Global => null; function Bounded_Slice (Source : Bounded_String; Low : Positive; - High : Natural) return Bounded_String; + High : Natural) return Bounded_String + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => + Length (Bounded_Slice'Result) = Natural'Max (0, High - Low + 1), + Global => null; pragma Ada_05 (Bounded_Slice); procedure Bounded_Slice (Source : Bounded_String; Target : out Bounded_String; Low : Positive; - High : Natural); + High : Natural) + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => Length (Target) = Natural'Max (0, High - Low + 1), + Global => null; pragma Ada_05 (Bounded_Slice); function "=" (Left : Bounded_String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function "=" (Left : Bounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "=" (Left : String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function "<" (Left : Bounded_String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function "<" (Left : Bounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "<" (Left : String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function "<=" (Left : Bounded_String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function "<=" (Left : Bounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "<=" (Left : String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function ">" (Left : Bounded_String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function ">" (Left : Bounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function ">" (Left : String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function ">=" (Left : Bounded_String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; function ">=" (Left : Bounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function ">=" (Left : String; - Right : Bounded_String) return Boolean; + Right : Bounded_String) return Boolean + with + Global => null; ---------------------- -- Search Functions -- @@ -227,26 +376,40 @@ package Ada.Strings.Bounded is (Source : Bounded_String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Index (Source : Bounded_String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Index (Source : Bounded_String; Set : Maps.Character_Set; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; function Index (Source : Bounded_String; Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => + (if Length (Source) /= 0 + then From <= Length (Source)) + and then Pattern'Length /= 0, + Global => null; pragma Ada_05 (Index); function Index @@ -254,7 +417,13 @@ package Ada.Strings.Bounded is Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => + (if Length (Source) /= 0 + then From <= Length (Source)) + and then Pattern'Length /= 0, + Global => null; pragma Ada_05 (Index); function Index @@ -262,32 +431,48 @@ package Ada.Strings.Bounded is Set : Maps.Character_Set; From : Positive; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_05 (Index); function Index_Non_Blank (Source : Bounded_String; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; function Index_Non_Blank (Source : Bounded_String; From : Positive; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_05 (Index_Non_Blank); function Count (Source : Bounded_String; Pattern : String; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Count (Source : Bounded_String; Pattern : String; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Count (Source : Bounded_String; - Set : Maps.Character_Set) return Natural; + Set : Maps.Character_Set) return Natural + with + Global => null; procedure Find_Token (Source : Bounded_String; @@ -295,7 +480,10 @@ package Ada.Strings.Bounded is From : Positive; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_2012 (Find_Token); procedure Find_Token @@ -303,7 +491,9 @@ package Ada.Strings.Bounded is Set : Maps.Character_Set; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Global => null; ------------------------------------ -- String Translation Subprograms -- @@ -311,19 +501,31 @@ package Ada.Strings.Bounded is function Translate (Source : Bounded_String; - Mapping : Maps.Character_Mapping) return Bounded_String; + Mapping : Maps.Character_Mapping) return Bounded_String + with + Post => Length (Translate'Result) = Length (Source), + Global => null; procedure Translate (Source : in out Bounded_String; - Mapping : Maps.Character_Mapping); + Mapping : Maps.Character_Mapping) + with + Post => Length (Source) = Length (Source)'Old, + Global => null; function Translate (Source : Bounded_String; - Mapping : Maps.Character_Mapping_Function) return Bounded_String; + Mapping : Maps.Character_Mapping_Function) return Bounded_String + with + Post => Length (Translate'Result) = Length (Source), + Global => null; procedure Translate (Source : in out Bounded_String; - Mapping : Maps.Character_Mapping_Function); + Mapping : Maps.Character_Mapping_Function) + with + Post => Length (Source) = Length (Source)'Old, + Global => null; --------------------------------------- -- String Transformation Subprograms -- @@ -334,48 +536,149 @@ package Ada.Strings.Bounded is Low : Positive; High : Natural; By : String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + Low - 1 <= Length (Source) + and then + (if Drop = Error + then (if High >= Low + then Low - 1 + <= Max_Length - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Max_Length - By'Length)), + Contract_Cases => + (High >= Low => + Length (Replace_Slice'Result) + = Natural'Min + (Max_Length, + Low - 1 + By'Length + Natural'Max (Length (Source) - High, + 0)), + others => + Length (Replace_Slice'Result) + = Natural'Min (Max_Length, Length (Source) + By'Length)), + Global => null; procedure Replace_Slice (Source : in out Bounded_String; Low : Positive; High : Natural; By : String; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => + Low - 1 <= Length (Source) + and then + (if Drop = Error + then (if High >= Low + then Low - 1 + <= Max_Length - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Max_Length - By'Length)), + Contract_Cases => + (High >= Low => + Length (Source) + = Natural'Min + (Max_Length, + Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, + 0)), + others => + Length (Source) + = Natural'Min (Max_Length, Length (Source)'Old + By'Length)), + Global => null; function Insert (Source : Bounded_String; Before : Positive; New_Item : String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + Before - 1 <= Length (Source) + and then (if New_Item'Length > Max_Length - Length (Source) + then Drop /= Error), + Post => + Length (Insert'Result) + = Natural'Min (Max_Length, Length (Source) + New_Item'Length), + Global => null; procedure Insert (Source : in out Bounded_String; Before : Positive; New_Item : String; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => + Before - 1 <= Length (Source) + and then (if New_Item'Length > Max_Length - Length (Source) + then Drop /= Error), + Post => + Length (Source) + = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length), + Global => null; function Overwrite (Source : Bounded_String; Position : Positive; New_Item : String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + Position - 1 <= Length (Source) + and then (if New_Item'Length > Max_Length - (Position - 1) + then Drop /= Error), + Post => + Length (Overwrite'Result) + = Natural'Max + (Length (Source), + Natural'Min (Max_Length, Position - 1 + New_Item'Length)), + Global => null; procedure Overwrite (Source : in out Bounded_String; Position : Positive; New_Item : String; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => + Position - 1 <= Length (Source) + and then (if New_Item'Length > Max_Length - (Position - 1) + then Drop /= Error), + Post => + Length (Source) + = Natural'Max + (Length (Source)'Old, + Natural'Min (Max_Length, Position - 1 + New_Item'Length)), + Global => null; function Delete (Source : Bounded_String; From : Positive; - Through : Natural) return Bounded_String; + Through : Natural) return Bounded_String + with + Pre => + (if Through <= From then From - 1 <= Length (Source)), + Contract_Cases => + (Through >= From => + Length (Delete'Result) = Length (Source) - (Through - From + 1), + others => + Length (Delete'Result) = Length (Source)), + + Global => null; procedure Delete (Source : in out Bounded_String; From : Positive; - Through : Natural); + Through : Natural) + with + Pre => + (if Through <= From then From - 1 <= Length (Source)), + Contract_Cases => + (Through >= From => + Length (Source) = Length (Source)'Old - (Through - From + 1), + others => + Length (Source) = Length (Source)'Old), + Global => null; --------------------------------- -- String Selector Subprograms -- @@ -383,45 +686,73 @@ package Ada.Strings.Bounded is function Trim (Source : Bounded_String; - Side : Trim_End) return Bounded_String; + Side : Trim_End) return Bounded_String + with + Post => Length (Trim'Result) <= Length (Source), + Global => null; procedure Trim (Source : in out Bounded_String; - Side : Trim_End); + Side : Trim_End) + with + Post => Length (Source) <= Length (Source)'Old, + Global => null; function Trim (Source : Bounded_String; Left : Maps.Character_Set; - Right : Maps.Character_Set) return Bounded_String; + Right : Maps.Character_Set) return Bounded_String + with + Post => Length (Trim'Result) <= Length (Source), + Global => null; procedure Trim (Source : in out Bounded_String; Left : Maps.Character_Set; - Right : Maps.Character_Set); + Right : Maps.Character_Set) + with + Post => Length (Source) <= Length (Source)'Old, + Global => null; function Head (Source : Bounded_String; Count : Natural; Pad : Character := Space; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => (if Count > Max_Length then Drop /= Error), + Post => Length (Head'Result) = Natural'Min (Max_Length, Count), + Global => null; procedure Head (Source : in out Bounded_String; Count : Natural; Pad : Character := Space; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => (if Count > Max_Length then Drop /= Error), + Post => Length (Source) = Natural'Min (Max_Length, Count), + Global => null; function Tail (Source : Bounded_String; Count : Natural; Pad : Character := Space; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => (if Count > Max_Length then Drop /= Error), + Post => Length (Tail'Result) = Natural'Min (Max_Length, Count), + Global => null; procedure Tail (Source : in out Bounded_String; Count : Natural; Pad : Character := Space; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => (if Count > Max_Length then Drop /= Error), + Post => Length (Source) = Natural'Min (Max_Length, Count), + Global => null; ------------------------------------ -- String Constructor Subprograms -- @@ -429,30 +760,66 @@ package Ada.Strings.Bounded is function "*" (Left : Natural; - Right : Character) return Bounded_String; + Right : Character) return Bounded_String + with + Pre => Left <= Max_Length, + Post => Length ("*"'Result) = Left, + Global => null; function "*" (Left : Natural; - Right : String) return Bounded_String; + Right : String) return Bounded_String + with + Pre => (if Left /= 0 then Right'Length <= Max_Length / Left), + Post => Length ("*"'Result) = Left * Right'Length, + Global => null; function "*" (Left : Natural; - Right : Bounded_String) return Bounded_String; + Right : Bounded_String) return Bounded_String + with + Pre => (if Left /= 0 then Length (Right) <= Max_Length / Left), + Post => Length ("*"'Result) = Left * Length (Right), + Global => null; function Replicate (Count : Natural; Item : Character; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => (if Count > Max_Length then Drop /= Error), + Post => + Length (Replicate'Result) + = Natural'Min (Max_Length, Count), + Global => null; function Replicate (Count : Natural; Item : String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + (if Item'Length /= 0 + and then Count > Max_Length / Item'Length + then Drop /= Error), + Post => + Length (Replicate'Result) + = Natural'Min (Max_Length, Count * Item'Length), + Global => null; function Replicate (Count : Natural; Item : Bounded_String; - Drop : Truncation := Error) return Bounded_String; + Drop : Truncation := Error) return Bounded_String + with + Pre => + (if Length (Item) /= 0 + and then Count > Max_Length / Length (Item) + then Drop /= Error), + Post => + Length (Replicate'Result) + = Natural'Min (Max_Length, Count * Length (Item)), + Global => null; private -- Most of the implementation is in the separate non generic package diff --git a/gcc/ada/libgnat/a-strfix.ads b/gcc/ada/libgnat/a-strfix.ads index 1571861..7d6e121 100644 --- a/gcc/ada/libgnat/a-strfix.ads +++ b/gcc/ada/libgnat/a-strfix.ads @@ -13,6 +13,12 @@ -- -- ------------------------------------------------------------------------------ +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. This is enforced by +-- setting the corresponding assertion policy to Ignore. + +pragma Assertion_Policy (Pre => Ignore); + with Ada.Strings.Maps; -- The language-defined package Strings.Fixed provides string-handling @@ -34,7 +40,7 @@ with Ada.Strings.Maps; -- these effects. Similar control is provided by the string transformation -- procedures. -package Ada.Strings.Fixed is +package Ada.Strings.Fixed with SPARK_Mode is pragma Preelaborate; -------------------------------------------------------------- @@ -46,7 +52,12 @@ package Ada.Strings.Fixed is Target : out String; Drop : Truncation := Error; Justify : Alignment := Left; - Pad : Character := Space); + Pad : Character := Space) + with + + -- Incomplete contract + + Global => null; -- The Move procedure copies characters from Source to Target. If Source -- has the same length as Target, then the effect is to assign Source to -- Target. If Source is shorter than Target then: @@ -95,7 +106,12 @@ package Ada.Strings.Fixed is Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => + Pattern'Length /= 0 + and then (if Source'Length /= 0 then From in Source'Range), + Global => null; pragma Ada_05 (Index); function Index @@ -103,7 +119,12 @@ package Ada.Strings.Fixed is Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => + Pattern'Length /= 0 + and then (if Source'Length /= 0 then From in Source'Range), + Global => null; pragma Ada_05 (Index); -- Each Index function searches, starting from From, for a slice of @@ -123,13 +144,19 @@ package Ada.Strings.Fixed is (Source : String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length > 0, + Global => null; function Index (Source : String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; -- If Going = Forward, returns: -- @@ -143,14 +170,19 @@ package Ada.Strings.Fixed is (Source : String; Set : Maps.Character_Set; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; function Index (Source : String; Set : Maps.Character_Set; From : Positive; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Source'Length /= 0 then From in Source'Range), + Global => null; pragma Ada_05 (Index); -- Index searches for the first or last occurrence of any of a set of -- characters (when Test=Inside), or any of the complement of a set of @@ -164,24 +196,35 @@ package Ada.Strings.Fixed is function Index_Non_Blank (Source : String; From : Positive; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Source'Length /= 0 then From in Source'Range), + Global => null; pragma Ada_05 (Index_Non_Blank); -- Returns Index (Source, Maps.To_Set(Space), From, Outside, Going) function Index_Non_Blank (Source : String; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; -- Returns Index (Source, Maps.To_Set(Space), Outside, Going) function Count (Source : String; Pattern : String; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Count (Source : String; Pattern : String; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; -- Returns the maximum number of nonoverlapping slices of Source that match -- Pattern with respect to Mapping. If Pattern is the null string then @@ -189,7 +232,9 @@ package Ada.Strings.Fixed is function Count (Source : String; - Set : Maps.Character_Set) return Natural; + Set : Maps.Character_Set) return Natural + with + Global => null; -- Returns the number of occurrences in Source of characters that are in -- Set. @@ -199,7 +244,10 @@ package Ada.Strings.Fixed is From : Positive; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Pre => (if Source'Length /= 0 then From in Source'Range), + Global => null; pragma Ada_2012 (Find_Token); -- If Source is not the null string and From is not in Source'Range, then -- Index_Error is raised. Otherwise, First is set to the index of the first @@ -214,7 +262,9 @@ package Ada.Strings.Fixed is Set : Maps.Character_Set; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Global => null; -- Equivalent to Find_Token (Source, Set, Source'First, Test, First, Last) ------------------------------------ @@ -223,11 +273,17 @@ package Ada.Strings.Fixed is function Translate (Source : String; - Mapping : Maps.Character_Mapping_Function) return String; + Mapping : Maps.Character_Mapping_Function) return String + with + Post => Translate'Result'Length = Source'Length, + Global => null; function Translate (Source : String; - Mapping : Maps.Character_Mapping) return String; + Mapping : Maps.Character_Mapping) return String + with + Post => Translate'Result'Length = Source'Length, + Global => null; -- Returns the string S whose length is Source'Length and such that S (I) -- is the character to which Mapping maps the corresponding element of @@ -235,11 +291,15 @@ package Ada.Strings.Fixed is procedure Translate (Source : in out String; - Mapping : Maps.Character_Mapping_Function); + Mapping : Maps.Character_Mapping_Function) + with + Global => null; procedure Translate (Source : in out String; - Mapping : Maps.Character_Mapping); + Mapping : Maps.Character_Mapping) + with + Global => null; -- Equivalent to Source := Translate(Source, Mapping) @@ -254,7 +314,15 @@ package Ada.Strings.Fixed is By : String; Drop : Truncation := Error; Justify : Alignment := Left; - Pad : Character := Space); + Pad : Character := Space) + with + Pre => + + -- Incomplete contract + + Low - 1 <= Source'Last + and then High >= Source'First - 1, + Global => null; -- If Low > Source'Last+1, or High < Source'First - 1, then Index_Error is -- propagated. Otherwise: -- @@ -269,7 +337,25 @@ package Ada.Strings.Fixed is (Source : String; Low : Positive; High : Natural; - By : String) return String; + By : String) return String + with + Pre => + Low - 1 <= Source'Last + and then High >= Source'First - 1 + and then (if High >= Low + then Natural'Max (0, Low - Source'First) + <= Natural'Last - By'Length + - Natural'Max (Source'Last - High, 0) + else Source'Length <= Natural'Last - By'Length), + Contract_Cases => + (High >= Low => + Replace_Slice'Result'Length + = Natural'Max (0, Low - Source'First) + + By'Length + + Natural'Max (Source'Last - High, 0), + others => + Replace_Slice'Result'Length = Source'Length + By'Length), + Global => null; -- Equivalent to: -- -- Move (Replace_Slice (Source, Low, High, By), @@ -278,7 +364,13 @@ package Ada.Strings.Fixed is function Insert (Source : String; Before : Positive; - New_Item : String) return String; + New_Item : String) return String + with + Pre => + Before - 1 in Source'First - 1 .. Source'Last + and then Source'Length <= Natural'Last - New_Item'Length, + Post => Insert'Result'Length = Source'Length + New_Item'Length, + Global => null; -- Propagates Index_Error if Before is not in -- Source'First .. Source'Last+1; otherwise, returns -- Source (Source'First .. Before - 1) @@ -288,13 +380,30 @@ package Ada.Strings.Fixed is (Source : in out String; Before : Positive; New_Item : String; - Drop : Truncation := Error); + Drop : Truncation := Error) + with + Pre => Before - 1 in Source'First - 1 .. Source'Last, + + -- Incomplete contract + + Global => null; -- Equivalent to Move (Insert (Source, Before, New_Item), Source, Drop) function Overwrite (Source : String; Position : Positive; - New_Item : String) return String; + New_Item : String) return String + with + Pre => + Position - 1 in Source'First - 1 .. Source'Last + and then + (if Position - Source'First >= Source'Length - New_Item'Length + then Position - Source'First <= Natural'Last - New_Item'Length), + Post => + Overwrite'Result'Length + = Integer'Max (Source'Length, + Position - Source'First + New_Item'Length), + Global => null; -- Propagates Index_Error if Position is not in -- Source'First .. Source'Last + 1; otherwise, returns the string obtained -- from Source by consecutively replacing characters starting at Position @@ -306,13 +415,29 @@ package Ada.Strings.Fixed is (Source : in out String; Position : Positive; New_Item : String; - Drop : Truncation := Right); + Drop : Truncation := Right) + with + Pre => Position - 1 in Source'First - 1 .. Source'Last, + + -- Incomplete contract + + Global => null; -- Equivalent to Move(Overwrite(Source, Position, New_Item), Source, Drop) function Delete (Source : String; From : Positive; - Through : Natural) return String; + Through : Natural) return String + with + Pre => (if From <= Through + then (From in Source'Range + and then Through <= Source'Last)), + Post => + Delete'Result'Length + = Source'Length - (if From <= Through + then Through - From + 1 + else 0), + Global => null; -- If From <= Through, the returned string is -- Replace_Slice(Source, From, Through, ""); otherwise, it is Source with -- lower bound 1. @@ -322,7 +447,15 @@ package Ada.Strings.Fixed is From : Positive; Through : Natural; Justify : Alignment := Left; - Pad : Character := Space); + Pad : Character := Space) + with + Pre => (if From <= Through + then (From in Source'Range + and then Through <= Source'Last)), + + -- Incomplete contract + + Global => null; -- Equivalent to: -- -- Move (Delete (Source, From, Through), @@ -334,7 +467,10 @@ package Ada.Strings.Fixed is function Trim (Source : String; - Side : Trim_End) return String; + Side : Trim_End) return String + with + Post => Trim'Result'Length <= Source'Length, + Global => null; -- Returns the string obtained by removing from Source all leading Space -- characters (if Side = Left), all trailing Space characters (if -- Side = Right), or all leading and trailing Space characters (if @@ -344,7 +480,12 @@ package Ada.Strings.Fixed is (Source : in out String; Side : Trim_End; Justify : Alignment := Left; - Pad : Character := Space); + Pad : Character := Space) + with + + -- Incomplete contract + + Global => null; -- Equivalent to: -- -- Move (Trim (Source, Side), Source, Justify=>Justify, Pad=>Pad). @@ -352,7 +493,10 @@ package Ada.Strings.Fixed is function Trim (Source : String; Left : Maps.Character_Set; - Right : Maps.Character_Set) return String; + Right : Maps.Character_Set) return String + with + Post => Trim'Result'Length <= Source'Length, + Global => null; -- Returns the string obtained by removing from Source all leading -- characters in Left and all trailing characters in Right. @@ -361,7 +505,12 @@ package Ada.Strings.Fixed is Left : Maps.Character_Set; Right : Maps.Character_Set; Justify : Alignment := Strings.Left; - Pad : Character := Space); + Pad : Character := Space) + with + + -- Incomplete contract + + Global => null; -- Equivalent to: -- -- Move (Trim (Source, Left, Right), @@ -370,7 +519,10 @@ package Ada.Strings.Fixed is function Head (Source : String; Count : Natural; - Pad : Character := Space) return String; + Pad : Character := Space) return String + with + Post => Head'Result'Length = Count, + Global => null; -- Returns a string of length Count. If Count <= Source'Length, the string -- comprises the first Count characters of Source. Otherwise, its contents -- are Source concatenated with Count - Source'Length Pad characters. @@ -379,7 +531,12 @@ package Ada.Strings.Fixed is (Source : in out String; Count : Natural; Justify : Alignment := Left; - Pad : Character := Space); + Pad : Character := Space) + with + + -- Incomplete contract + + Global => null; -- Equivalent to: -- -- Move (Head (Source, Count, Pad), @@ -388,7 +545,10 @@ package Ada.Strings.Fixed is function Tail (Source : String; Count : Natural; - Pad : Character := Space) return String; + Pad : Character := Space) return String + with + Post => Tail'Result'Length = Count, + Global => null; -- Returns a string of length Count. If Count <= Source'Length, the string -- comprises the last Count characters of Source. Otherwise, its contents -- are Count-Source'Length Pad characters concatenated with Source. @@ -397,7 +557,12 @@ package Ada.Strings.Fixed is (Source : in out String; Count : Natural; Justify : Alignment := Left; - Pad : Character := Space); + Pad : Character := Space) + with + + -- Incomplete contract + + Global => null; -- Equivalent to: -- -- Move (Tail (Source, Count, Pad), @@ -409,11 +574,18 @@ package Ada.Strings.Fixed is function "*" (Left : Natural; - Right : Character) return String; + Right : Character) return String + with + Post => "*"'Result'Length = Left, + Global => null; function "*" (Left : Natural; - Right : String) return String; + Right : String) return String + with + Pre => (if Right'Length /= 0 then Left <= Natural'Last / Right'Length), + Post => "*"'Result'Length = Left * Right'Length, + Global => null; -- These functions replicate a character or string a specified number of -- times. The first function returns a string whose length is Left and each diff --git a/gcc/ada/libgnat/a-strunb.ads b/gcc/ada/libgnat/a-strunb.ads index c0caf10..e875b5b 100644 --- a/gcc/ada/libgnat/a-strunb.ads +++ b/gcc/ada/libgnat/a-strunb.ads @@ -33,6 +33,12 @@ -- -- ------------------------------------------------------------------------------ +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. This is enforced by +-- setting the corresponding assertion policy to Ignore. + +pragma Assertion_Policy (Pre => Ignore); + with Ada.Strings.Maps; with Ada.Finalization; @@ -45,7 +51,9 @@ with Ada.Finalization; -- length. Since the Unbounded_String type is private, relevant constructor -- and selector operations are provided. -package Ada.Strings.Unbounded is +package Ada.Strings.Unbounded with + Initial_Condition => Length (Null_Unbounded_String) = 0 +is pragma Preelaborate; type Unbounded_String is private; @@ -56,7 +64,8 @@ package Ada.Strings.Unbounded is -- otherwise initialized, it will be initialized to the same value as -- Null_Unbounded_String. - function Length (Source : Unbounded_String) return Natural; + function Length (Source : Unbounded_String) return Natural with + Global => null; -- Returns the length of the String represented by Source type String_Access is access all String; @@ -71,15 +80,25 @@ package Ada.Strings.Unbounded is -------------------------------------------------------- function To_Unbounded_String - (Source : String) return Unbounded_String; + (Source : String) return Unbounded_String + with + Post => Length (To_Unbounded_String'Result) = Source'Length, + Global => null; -- Returns an Unbounded_String that represents Source function To_Unbounded_String - (Length : Natural) return Unbounded_String; + (Length : Natural) return Unbounded_String + with + Post => + Ada.Strings.Unbounded.Length (To_Unbounded_String'Result) + = Length, + Global => null; -- Returns an Unbounded_String that represents an uninitialized String -- whose length is Length. - function To_String (Source : Unbounded_String) return String; + function To_String (Source : Unbounded_String) return String with + Post => To_String'Result'Length = Length (Source), + Global => null; -- Returns the String with lower bound 1 represented by Source -- To_String and To_Unbounded_String are related as follows: @@ -91,21 +110,35 @@ package Ada.Strings.Unbounded is procedure Set_Unbounded_String (Target : out Unbounded_String; - Source : String); + Source : String) + with + Global => null; pragma Ada_05 (Set_Unbounded_String); -- Sets Target to an Unbounded_String that represents Source procedure Append (Source : in out Unbounded_String; - New_Item : Unbounded_String); + New_Item : Unbounded_String) + with + Pre => Length (New_Item) <= Natural'Last - Length (Source), + Post => Length (Source) = Length (Source)'Old + Length (New_Item), + Global => null; procedure Append (Source : in out Unbounded_String; - New_Item : String); + New_Item : String) + with + Pre => New_Item'Length <= Natural'Last - Length (Source), + Post => Length (Source) = Length (Source)'Old + New_Item'Length, + Global => null; procedure Append (Source : in out Unbounded_String; - New_Item : Character); + New_Item : Character) + with + Pre => Length (Source) < Natural'Last, + Post => Length (Source) = Length (Source)'Old + 1, + Global => null; -- For each of the Append procedures, the resulting string represented by -- the Source parameter is given by the concatenation of the original value @@ -113,23 +146,43 @@ package Ada.Strings.Unbounded is function "&" (Left : Unbounded_String; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => Length (Right) <= Natural'Last - Length (Left), + Post => Length ("&"'Result) = Length (Left) + Length (Right), + Global => null; function "&" (Left : Unbounded_String; - Right : String) return Unbounded_String; + Right : String) return Unbounded_String + with + Pre => Right'Length <= Natural'Last - Length (Left), + Post => Length ("&"'Result) = Length (Left) + Right'Length, + Global => null; function "&" (Left : String; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => Left'Length <= Natural'Last - Length (Right), + Post => Length ("&"'Result) = Left'Length + Length (Right), + Global => null; function "&" (Left : Unbounded_String; - Right : Character) return Unbounded_String; + Right : Character) return Unbounded_String + with + Pre => Length (Left) < Natural'Last, + Post => Length ("&"'Result) = Length (Left) + 1, + Global => null; function "&" (Left : Character; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => Length (Right) < Natural'Last, + Post => Length ("&"'Result) = Length (Right) + 1, + Global => null; -- Each of the "&" functions returns an Unbounded_String obtained by -- concatenating the string or character given or represented by one of the @@ -139,14 +192,21 @@ package Ada.Strings.Unbounded is function Element (Source : Unbounded_String; - Index : Positive) return Character; + Index : Positive) return Character + with + Pre => Index <= Length (Source), + Global => null; -- Returns the character at position Index in the string represented by -- Source; propagates Index_Error if Index > Length (Source). procedure Replace_Element (Source : in out Unbounded_String; Index : Positive; - By : Character); + By : Character) + with + Pre => Index <= Length (Source), + Post => Length (Source) = Length (Source)'Old, + Global => null; -- Updates Source such that the character at position Index in the string -- represented by Source is By; propagates Index_Error if -- Index > Length (Source). @@ -154,7 +214,11 @@ package Ada.Strings.Unbounded is function Slice (Source : Unbounded_String; Low : Positive; - High : Natural) return String; + High : Natural) return String + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => Slice'Result'Length = Natural'Max (0, High - Low + 1), + Global => null; -- Returns the slice at positions Low through High in the string -- represented by Source; propagates Index_Error if -- Low > Length (Source) + 1 or High > Length (Source). The bounds of the @@ -163,7 +227,12 @@ package Ada.Strings.Unbounded is function Unbounded_Slice (Source : Unbounded_String; Low : Positive; - High : Natural) return Unbounded_String; + High : Natural) return Unbounded_String + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => + Length (Unbounded_Slice'Result) = Natural'Max (0, High - Low + 1), + Global => null; pragma Ada_05 (Unbounded_Slice); -- Returns the slice at positions Low through High in the string -- represented by Source as an Unbounded_String. This propagates @@ -173,7 +242,11 @@ package Ada.Strings.Unbounded is (Source : Unbounded_String; Target : out Unbounded_String; Low : Positive; - High : Natural); + High : Natural) + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => Length (Target) = Natural'Max (0, High - Low + 1), + Global => null; pragma Ada_05 (Unbounded_Slice); -- Sets Target to the Unbounded_String representing the slice at positions -- Low through High in the string represented by Source. This propagates @@ -181,63 +254,93 @@ package Ada.Strings.Unbounded is function "=" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "=" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "=" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "<" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<=" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<=" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "<=" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function ">" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">=" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">=" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function ">=" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; -- Each of the functions "=", "<", ">", "<=", and ">=" returns the same -- result as the corresponding String operation applied to the String @@ -251,26 +354,38 @@ package Ada.Strings.Unbounded is (Source : Unbounded_String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Index (Source : Unbounded_String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Index (Source : Unbounded_String; Set : Maps.Character_Set; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; function Index (Source : Unbounded_String; Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)) + and then Pattern'Length /= 0, + Global => null; pragma Ada_05 (Index); function Index @@ -278,7 +393,11 @@ package Ada.Strings.Unbounded is Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)) + and then Pattern'Length /= 0, + Global => null; pragma Ada_05 (Index); function Index @@ -286,32 +405,48 @@ package Ada.Strings.Unbounded is Set : Maps.Character_Set; From : Positive; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_05 (Index); function Index_Non_Blank (Source : Unbounded_String; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; function Index_Non_Blank (Source : Unbounded_String; From : Positive; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_05 (Index_Non_Blank); function Count (Source : Unbounded_String; Pattern : String; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Count (Source : Unbounded_String; Pattern : String; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Count (Source : Unbounded_String; - Set : Maps.Character_Set) return Natural; + Set : Maps.Character_Set) return Natural + with + Global => null; procedure Find_Token (Source : Unbounded_String; @@ -319,7 +454,10 @@ package Ada.Strings.Unbounded is From : Positive; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_2012 (Find_Token); procedure Find_Token @@ -327,7 +465,9 @@ package Ada.Strings.Unbounded is Set : Maps.Character_Set; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Global => null; -- Each of the search subprograms (Index, Index_Non_Blank, Count, -- Find_Token) has the same effect as the corresponding subprogram in @@ -340,19 +480,31 @@ package Ada.Strings.Unbounded is function Translate (Source : Unbounded_String; - Mapping : Maps.Character_Mapping) return Unbounded_String; + Mapping : Maps.Character_Mapping) return Unbounded_String + with + Post => Length (Translate'Result) = Length (Source), + Global => null; procedure Translate (Source : in out Unbounded_String; - Mapping : Maps.Character_Mapping); + Mapping : Maps.Character_Mapping) + with + Post => Length (Source) = Length (Source)'Old, + Global => null; function Translate (Source : Unbounded_String; - Mapping : Maps.Character_Mapping_Function) return Unbounded_String; + Mapping : Maps.Character_Mapping_Function) return Unbounded_String + with + Post => Length (Translate'Result) = Length (Source), + Global => null; procedure Translate (Source : in out Unbounded_String; - Mapping : Maps.Character_Mapping_Function); + Mapping : Maps.Character_Mapping_Function) + with + Post => Length (Source) = Length (Source)'Old, + Global => null; -- The Translate function has an analogous effect to the corresponding -- subprogram in Strings.Fixed. The translation is applied to the string @@ -367,93 +519,204 @@ package Ada.Strings.Unbounded is (Source : Unbounded_String; Low : Positive; High : Natural; - By : String) return Unbounded_String; + By : String) return Unbounded_String + with + Pre => + Low - 1 <= Length (Source) + and then (if High >= Low + then Low - 1 + <= Natural'Last - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Natural'Last - By'Length), + Contract_Cases => + (High >= Low => + Length (Replace_Slice'Result) + = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0), + others => + Length (Replace_Slice'Result) = Length (Source)'Old + By'Length), + Global => null; procedure Replace_Slice (Source : in out Unbounded_String; Low : Positive; High : Natural; - By : String); + By : String) + with + Pre => + Low - 1 <= Length (Source) + and then (if High >= Low + then Low - 1 + <= Natural'Last - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Natural'Last - By'Length), + Contract_Cases => + (High >= Low => + Length (Source) + = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0), + others => + Length (Source) = Length (Source)'Old + By'Length), + Global => null; function Insert (Source : Unbounded_String; Before : Positive; - New_Item : String) return Unbounded_String; + New_Item : String) return Unbounded_String + with + Pre => Before - 1 <= Length (Source) + and then New_Item'Length <= Natural'Last - Length (Source), + Post => Length (Insert'Result) = Length (Source) + New_Item'Length, + Global => null; procedure Insert (Source : in out Unbounded_String; Before : Positive; - New_Item : String); + New_Item : String) + with + Pre => Before - 1 <= Length (Source) + and then New_Item'Length <= Natural'Last - Length (Source), + Post => Length (Source) = Length (Source)'Old + New_Item'Length, + Global => null; function Overwrite (Source : Unbounded_String; Position : Positive; - New_Item : String) return Unbounded_String; + New_Item : String) return Unbounded_String + with + Pre => Position - 1 <= Length (Source) + and then (if New_Item'Length /= 0 + then + New_Item'Length <= Natural'Last - (Position - 1)), + Post => + Length (Overwrite'Result) + = Natural'Max (Length (Source), Position - 1 + New_Item'Length), + Global => null; procedure Overwrite (Source : in out Unbounded_String; Position : Positive; - New_Item : String); + New_Item : String) + with + Pre => Position - 1 <= Length (Source) + and then (if New_Item'Length /= 0 + then + New_Item'Length <= Natural'Last - (Position - 1)), + Post => + Length (Source) + = Natural'Max (Length (Source)'Old, Position - 1 + New_Item'Length), + + Global => null; function Delete (Source : Unbounded_String; From : Positive; - Through : Natural) return Unbounded_String; + Through : Natural) return Unbounded_String + with + Pre => (if Through <= From then From - 1 <= Length (Source)), + Contract_Cases => + (Through >= From => + Length (Delete'Result) = Length (Source) - (Through - From + 1), + others => + Length (Delete'Result) = Length (Source)), + Global => null; procedure Delete (Source : in out Unbounded_String; From : Positive; - Through : Natural); + Through : Natural) + with + Pre => (if Through <= From then From - 1 <= Length (Source)), + Contract_Cases => + (Through >= From => + Length (Source) = Length (Source)'Old - (Through - From + 1), + others => + Length (Source) = Length (Source)'Old), + Global => null; function Trim (Source : Unbounded_String; - Side : Trim_End) return Unbounded_String; + Side : Trim_End) return Unbounded_String + with + Post => Length (Trim'Result) <= Length (Source), + Global => null; procedure Trim (Source : in out Unbounded_String; - Side : Trim_End); + Side : Trim_End) + with + Post => Length (Source) <= Length (Source)'Old, + Global => null; function Trim (Source : Unbounded_String; Left : Maps.Character_Set; - Right : Maps.Character_Set) return Unbounded_String; + Right : Maps.Character_Set) return Unbounded_String + with + Post => Length (Trim'Result) <= Length (Source), + Global => null; procedure Trim (Source : in out Unbounded_String; Left : Maps.Character_Set; - Right : Maps.Character_Set); + Right : Maps.Character_Set) + with + Post => Length (Source) <= Length (Source)'Old, + Global => null; function Head (Source : Unbounded_String; Count : Natural; - Pad : Character := Space) return Unbounded_String; + Pad : Character := Space) return Unbounded_String + with + Post => Length (Head'Result) = Count, + Global => null; procedure Head (Source : in out Unbounded_String; Count : Natural; - Pad : Character := Space); + Pad : Character := Space) + with + Post => Length (Source) = Count, + Global => null; function Tail (Source : Unbounded_String; Count : Natural; - Pad : Character := Space) return Unbounded_String; + Pad : Character := Space) return Unbounded_String + with + Post => Length (Tail'Result) = Count, + Global => null; procedure Tail (Source : in out Unbounded_String; Count : Natural; - Pad : Character := Space); + Pad : Character := Space) + with + Post => Length (Source) = Count, + Global => null; function "*" (Left : Natural; - Right : Character) return Unbounded_String; + Right : Character) return Unbounded_String + with + Pre => Left <= Natural'Last, + Post => Length ("*"'Result) = Left, + Global => null; function "*" (Left : Natural; - Right : String) return Unbounded_String; + Right : String) return Unbounded_String + with + Pre => (if Left /= 0 then Right'Length <= Natural'Last / Left), + Post => Length ("*"'Result) = Left * Right'Length, + Global => null; function "*" (Left : Natural; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => (if Left /= 0 then Length (Right) <= Natural'Last / Left), + Post => Length ("*"'Result) = Left * Length (Right), + Global => null; -- Each of the transformation functions (Replace_Slice, Insert, Overwrite, -- Delete), selector functions (Trim, Head, Tail), and constructor diff --git a/gcc/ada/libgnat/a-strunb__shared.ads b/gcc/ada/libgnat/a-strunb__shared.ads index 385a9e6..17acd56 100644 --- a/gcc/ada/libgnat/a-strunb__shared.ads +++ b/gcc/ada/libgnat/a-strunb__shared.ads @@ -33,6 +33,12 @@ -- -- ------------------------------------------------------------------------------ +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. This is enforced by +-- setting the corresponding assertion policy to Ignore. + +pragma Assertion_Policy (Pre => Ignore); + -- This package provides an implementation of Ada.Strings.Unbounded that uses -- reference counts to implement copy on modification (rather than copy on -- assignment). This is significantly more efficient on many targets. @@ -73,7 +79,9 @@ with Ada.Strings.Maps; private with Ada.Finalization; private with System.Atomic_Counters; -package Ada.Strings.Unbounded is +package Ada.Strings.Unbounded with + Initial_Condition => Length (Null_Unbounded_String) = 0 +is pragma Preelaborate; type Unbounded_String is private; @@ -81,7 +89,8 @@ package Ada.Strings.Unbounded is Null_Unbounded_String : constant Unbounded_String; - function Length (Source : Unbounded_String) return Natural; + function Length (Source : Unbounded_String) return Natural with + Global => null; type String_Access is access all String; @@ -92,136 +101,229 @@ package Ada.Strings.Unbounded is -------------------------------------------------------- function To_Unbounded_String - (Source : String) return Unbounded_String; + (Source : String) return Unbounded_String + with + Post => Length (To_Unbounded_String'Result) = Source'Length, + Global => null; function To_Unbounded_String - (Length : Natural) return Unbounded_String; + (Length : Natural) return Unbounded_String + with + Post => + Ada.Strings.Unbounded.Length (To_Unbounded_String'Result) = Length, + Global => null; - function To_String (Source : Unbounded_String) return String; + function To_String (Source : Unbounded_String) return String with + Post => To_String'Result'Length = Length (Source), + Global => null; procedure Set_Unbounded_String (Target : out Unbounded_String; - Source : String); + Source : String) + with + Global => null; pragma Ada_05 (Set_Unbounded_String); procedure Append (Source : in out Unbounded_String; - New_Item : Unbounded_String); + New_Item : Unbounded_String) + with + Pre => Length (New_Item) <= Natural'Last - Length (Source), + Post => Length (Source) = Length (Source)'Old + Length (New_Item), + Global => null; procedure Append (Source : in out Unbounded_String; - New_Item : String); + New_Item : String) + with + Pre => New_Item'Length <= Natural'Last - Length (Source), + Post => Length (Source) = Length (Source)'Old + New_Item'Length, + Global => null; procedure Append (Source : in out Unbounded_String; - New_Item : Character); + New_Item : Character) + with + Pre => Length (Source) < Natural'Last, + Post => Length (Source) = Length (Source)'Old + 1, + Global => null; function "&" (Left : Unbounded_String; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => Length (Right) <= Natural'Last - Length (Left), + Post => Length ("&"'Result) = Length (Left) + Length (Right), + Global => null; function "&" (Left : Unbounded_String; - Right : String) return Unbounded_String; + Right : String) return Unbounded_String + with + Pre => Right'Length <= Natural'Last - Length (Left), + Post => Length ("&"'Result) = Length (Left) + Right'Length, + Global => null; function "&" (Left : String; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => Left'Length <= Natural'Last - Length (Right), + Post => Length ("&"'Result) = Left'Length + Length (Right), + Global => null; function "&" (Left : Unbounded_String; - Right : Character) return Unbounded_String; + Right : Character) return Unbounded_String + with + Pre => Length (Left) < Natural'Last, + Post => Length ("&"'Result) = Length (Left) + 1, + Global => null; function "&" (Left : Character; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => Length (Right) < Natural'Last, + Post => Length ("&"'Result) = Length (Right) + 1, + Global => null; function Element (Source : Unbounded_String; - Index : Positive) return Character; + Index : Positive) return Character + with + Pre => Index <= Length (Source), + Global => null; procedure Replace_Element (Source : in out Unbounded_String; Index : Positive; - By : Character); + By : Character) + with + Pre => Index <= Length (Source), + Post => Length (Source) = Length (Source)'Old, + Global => null; function Slice (Source : Unbounded_String; Low : Positive; - High : Natural) return String; + High : Natural) return String + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => Slice'Result'Length = Natural'Max (0, High - Low + 1), + Global => null; function Unbounded_Slice (Source : Unbounded_String; Low : Positive; - High : Natural) return Unbounded_String; + High : Natural) return Unbounded_String + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => + Length (Unbounded_Slice'Result) = Natural'Max (0, High - Low + 1), + Global => null; pragma Ada_05 (Unbounded_Slice); procedure Unbounded_Slice (Source : Unbounded_String; Target : out Unbounded_String; Low : Positive; - High : Natural); + High : Natural) + with + Pre => Low - 1 <= Length (Source) and then High <= Length (Source), + Post => Length (Target) = Natural'Max (0, High - Low + 1), + Global => null; pragma Ada_05 (Unbounded_Slice); function "=" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "=" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "=" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "<" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<=" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function "<=" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function "<=" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function ">" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">=" (Left : Unbounded_String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; function ">=" (Left : Unbounded_String; - Right : String) return Boolean; + Right : String) return Boolean + with + Global => null; function ">=" (Left : String; - Right : Unbounded_String) return Boolean; + Right : Unbounded_String) return Boolean + with + Global => null; ------------------------ -- Search Subprograms -- @@ -231,26 +333,39 @@ package Ada.Strings.Unbounded is (Source : Unbounded_String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Index (Source : Unbounded_String; Pattern : String; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Index (Source : Unbounded_String; Set : Maps.Character_Set; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; function Index (Source : Unbounded_String; Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => (if Length (Source) /= 0 + then From <= Length (Source)) + and then Pattern'Length /= 0, + Global => null; pragma Ada_05 (Index); function Index @@ -258,7 +373,13 @@ package Ada.Strings.Unbounded is Pattern : String; From : Positive; Going : Direction := Forward; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => (if Length (Source) /= 0 + then From <= Length (Source)) + and then Pattern'Length /= 0, + Global => null; + pragma Ada_05 (Index); function Index @@ -266,32 +387,48 @@ package Ada.Strings.Unbounded is Set : Maps.Character_Set; From : Positive; Test : Membership := Inside; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_05 (Index); function Index_Non_Blank (Source : Unbounded_String; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Global => null; function Index_Non_Blank (Source : Unbounded_String; From : Positive; - Going : Direction := Forward) return Natural; + Going : Direction := Forward) return Natural + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_05 (Index_Non_Blank); function Count (Source : Unbounded_String; Pattern : String; - Mapping : Maps.Character_Mapping := Maps.Identity) return Natural; + Mapping : Maps.Character_Mapping := Maps.Identity) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Count (Source : Unbounded_String; Pattern : String; - Mapping : Maps.Character_Mapping_Function) return Natural; + Mapping : Maps.Character_Mapping_Function) return Natural + with + Pre => Pattern'Length /= 0, + Global => null; function Count (Source : Unbounded_String; - Set : Maps.Character_Set) return Natural; + Set : Maps.Character_Set) return Natural + with + Global => null; procedure Find_Token (Source : Unbounded_String; @@ -299,7 +436,10 @@ package Ada.Strings.Unbounded is From : Positive; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Pre => (if Length (Source) /= 0 then From <= Length (Source)), + Global => null; pragma Ada_2012 (Find_Token); procedure Find_Token @@ -307,7 +447,9 @@ package Ada.Strings.Unbounded is Set : Maps.Character_Set; Test : Membership; First : out Positive; - Last : out Natural); + Last : out Natural) + with + Global => null; ------------------------------------ -- String Translation Subprograms -- @@ -315,19 +457,31 @@ package Ada.Strings.Unbounded is function Translate (Source : Unbounded_String; - Mapping : Maps.Character_Mapping) return Unbounded_String; + Mapping : Maps.Character_Mapping) return Unbounded_String + with + Post => Length (Translate'Result) = Length (Source), + Global => null; procedure Translate (Source : in out Unbounded_String; - Mapping : Maps.Character_Mapping); + Mapping : Maps.Character_Mapping) + with + Post => Length (Source) = Length (Source)'Old, + Global => null; function Translate (Source : Unbounded_String; - Mapping : Maps.Character_Mapping_Function) return Unbounded_String; + Mapping : Maps.Character_Mapping_Function) return Unbounded_String + with + Post => Length (Translate'Result) = Length (Source), + Global => null; procedure Translate (Source : in out Unbounded_String; - Mapping : Maps.Character_Mapping_Function); + Mapping : Maps.Character_Mapping_Function) + with + Post => Length (Source) = Length (Source)'Old, + Global => null; --------------------------------------- -- String Transformation Subprograms -- @@ -337,93 +491,204 @@ package Ada.Strings.Unbounded is (Source : Unbounded_String; Low : Positive; High : Natural; - By : String) return Unbounded_String; + By : String) return Unbounded_String + with + Pre => + Low - 1 <= Length (Source) + and then (if High >= Low + then Low - 1 + <= Natural'Last - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Natural'Last - By'Length), + Contract_Cases => + (High >= Low => + Length (Replace_Slice'Result) + = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0), + others => + Length (Replace_Slice'Result) = Length (Source)'Old + By'Length), + Global => null; procedure Replace_Slice (Source : in out Unbounded_String; Low : Positive; High : Natural; - By : String); + By : String) + with + Pre => + Low - 1 <= Length (Source) + and then (if High >= Low + then Low - 1 + <= Natural'Last - By'Length + - Natural'Max (Length (Source) - High, 0) + else Length (Source) <= Natural'Last - By'Length), + Contract_Cases => + (High >= Low => + Length (Source) + = Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High, 0), + others => + Length (Source) = Length (Source)'Old + By'Length), + Global => null; function Insert (Source : Unbounded_String; Before : Positive; - New_Item : String) return Unbounded_String; + New_Item : String) return Unbounded_String + with + Pre => Before - 1 <= Length (Source) + and then New_Item'Length <= Natural'Last - Length (Source), + Post => Length (Insert'Result) = Length (Source) + New_Item'Length, + Global => null; procedure Insert (Source : in out Unbounded_String; Before : Positive; - New_Item : String); + New_Item : String) + with + Pre => Before - 1 <= Length (Source) + and then New_Item'Length <= Natural'Last - Length (Source), + Post => Length (Source) = Length (Source)'Old + New_Item'Length, + Global => null; function Overwrite (Source : Unbounded_String; Position : Positive; - New_Item : String) return Unbounded_String; + New_Item : String) return Unbounded_String + with + Pre => Position - 1 <= Length (Source) + and then (if New_Item'Length /= 0 + then + New_Item'Length <= Natural'Last - (Position - 1)), + Post => + Length (Overwrite'Result) + = Natural'Max (Length (Source), Position - 1 + New_Item'Length), + Global => null; procedure Overwrite (Source : in out Unbounded_String; Position : Positive; - New_Item : String); + New_Item : String) + with + Pre => Position - 1 <= Length (Source) + and then (if New_Item'Length /= 0 + then + New_Item'Length <= Natural'Last - (Position - 1)), + Post => + Length (Source) + = Natural'Max (Length (Source)'Old, Position - 1 + New_Item'Length), + + Global => null; function Delete (Source : Unbounded_String; From : Positive; - Through : Natural) return Unbounded_String; + Through : Natural) return Unbounded_String + with + Pre => (if Through <= From then From - 1 <= Length (Source)), + Contract_Cases => + (Through >= From => + Length (Delete'Result) = Length (Source) - (Through - From + 1), + others => + Length (Delete'Result) = Length (Source)), + Global => null; procedure Delete (Source : in out Unbounded_String; From : Positive; - Through : Natural); + Through : Natural) + with + Pre => (if Through <= From then From - 1 <= Length (Source)), + Contract_Cases => + (Through >= From => + Length (Source) = Length (Source)'Old - (Through - From + 1), + others => + Length (Source) = Length (Source)'Old), + Global => null; function Trim (Source : Unbounded_String; - Side : Trim_End) return Unbounded_String; + Side : Trim_End) return Unbounded_String + with + Post => Length (Trim'Result) <= Length (Source), + Global => null; procedure Trim (Source : in out Unbounded_String; - Side : Trim_End); + Side : Trim_End) + with + Post => Length (Source) <= Length (Source)'Old, + Global => null; function Trim (Source : Unbounded_String; Left : Maps.Character_Set; - Right : Maps.Character_Set) return Unbounded_String; + Right : Maps.Character_Set) return Unbounded_String + with + Post => Length (Trim'Result) <= Length (Source), + Global => null; procedure Trim (Source : in out Unbounded_String; Left : Maps.Character_Set; - Right : Maps.Character_Set); + Right : Maps.Character_Set) + with + Post => Length (Source) <= Length (Source)'Old, + Global => null; function Head (Source : Unbounded_String; Count : Natural; - Pad : Character := Space) return Unbounded_String; + Pad : Character := Space) return Unbounded_String + with + Post => Length (Head'Result) = Count, + Global => null; procedure Head (Source : in out Unbounded_String; Count : Natural; - Pad : Character := Space); + Pad : Character := Space) + with + Post => Length (Source) = Count, + Global => null; function Tail (Source : Unbounded_String; Count : Natural; - Pad : Character := Space) return Unbounded_String; + Pad : Character := Space) return Unbounded_String + with + Post => Length (Tail'Result) = Count, + Global => null; procedure Tail (Source : in out Unbounded_String; Count : Natural; - Pad : Character := Space); + Pad : Character := Space) + with + Post => Length (Source) = Count, + Global => null; function "*" (Left : Natural; - Right : Character) return Unbounded_String; + Right : Character) return Unbounded_String + with + Pre => Left <= Natural'Last, + Post => Length ("*"'Result) = Left, + Global => null; function "*" (Left : Natural; - Right : String) return Unbounded_String; + Right : String) return Unbounded_String + with + Pre => (if Left /= 0 then Right'Length <= Natural'Last / Left), + Post => Length ("*"'Result) = Left * Right'Length, + Global => null; function "*" (Left : Natural; - Right : Unbounded_String) return Unbounded_String; + Right : Unbounded_String) return Unbounded_String + with + Pre => (if Left /= 0 then Length (Right) <= Natural'Last / Left), + Post => Length ("*"'Result) = Left * Length (Right), + Global => null; private pragma Inline (Length); -- cgit v1.1 From 7f8c1cd3675b0e30817d98e52740b918b4e970b0 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Wed, 10 Jul 2019 09:01:33 +0000 Subject: [Ada] Minor reformatting 2019-07-10 Hristian Kirtchev gcc/ada/ * bindo-graphs.adb, bindo.adb, debug.adb, exp_ch6.adb, sem_ch10.adb, sem_ch13.adb, sem_ch3.adb, sem_ch4.adb, sem_ch6.adb, sem_ch7.adb, sem_res.adb, sem_spark.adb, sem_util.adb, warnsw.ads: Minor reformatting. From-SVN: r273335 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/bindo-graphs.adb | 36 ++++++++++++++++++------------------ gcc/ada/bindo.adb | 4 ++-- gcc/ada/debug.adb | 4 ++-- gcc/ada/exp_ch6.adb | 2 +- gcc/ada/sem_ch10.adb | 4 ++-- gcc/ada/sem_ch13.adb | 10 ++++++++-- gcc/ada/sem_ch3.adb | 5 ++--- gcc/ada/sem_ch4.adb | 22 +++++++++------------- gcc/ada/sem_ch6.adb | 2 +- gcc/ada/sem_ch7.adb | 10 +++++----- gcc/ada/sem_res.adb | 10 ++++------ gcc/ada/sem_spark.adb | 9 ++++----- gcc/ada/sem_util.adb | 4 +--- gcc/ada/warnsw.ads | 4 ++-- 15 files changed, 68 insertions(+), 65 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9d99033..f3f7217 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-10 Hristian Kirtchev + + * bindo-graphs.adb, bindo.adb, debug.adb, exp_ch6.adb, + sem_ch10.adb, sem_ch13.adb, sem_ch3.adb, sem_ch4.adb, + sem_ch6.adb, sem_ch7.adb, sem_res.adb, sem_spark.adb, + sem_util.adb, warnsw.ads: Minor reformatting. + 2019-07-10 Joffrey Huguet * libgnat/a-strbou.ads, libgnat/a-strfix.ads, diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index f1bfe47..d254b1c 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -1180,11 +1180,11 @@ package body Bindo.Graphs is -- * End vertices is the set of vertices that terminate a potential -- cycle. -- - -- * Deleted vertices is the set of vertices that have been expended + -- * Deleted vertices is the set of vertices that have been expanded -- during previous depth-first searches and should not be visited -- for the rest of the algorithm. -- - -- * Most_Significant_Edge is the current highest precedence edge on + -- * Most_Significant_Edge is the current highest-precedence edge on -- the path of the potential cycle. -- -- * Invocation_Edge_Count is the number of invocation edges on the @@ -1233,11 +1233,11 @@ package body Bindo.Graphs is -- * End_Vertices is the set of vertices that terminate a potential -- cycle. -- - -- * Deleted_Vertices is the set of vertices that have been expended + -- * Deleted_Vertices is the set of vertices that have been expanded -- during previous depth-first searches and should not be visited -- for the rest of the algorithm. -- - -- * Most_Significant_Edge is the current highest precedence edge on + -- * Most_Significant_Edge is the current highest-precedence edge on -- the path of the potential cycle. -- -- * Invocation_Edge_Count is the number of invocation edges on the @@ -2341,7 +2341,7 @@ package body Bindo.Graphs is elsif Cycle_Invs > Comp_Invs then return Lower_Precedence; - -- Prever a cycle with a higher path precedence + -- Prefer a cycle with a higher path precedence else return @@ -2684,7 +2684,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); -- The cycles of graph G are discovered using Tarjan's enumeration - -- of the elementary circuits of a directed graph algorithm. Do not + -- of the elementary circuits of a directed-graph algorithm. Do not -- modify this code unless you intimately understand the algorithm. -- -- The logic of the algorithm is split among the following routines: @@ -2698,7 +2698,7 @@ package body Bindo.Graphs is -- -- The original algorithm has been significantly modified in order to -- - -- * Accomodate the semantics of Elaborate_All and Elaborate_Body. + -- * Accommodate the semantics of Elaborate_All and Elaborate_Body. -- -- * Capture cycle paths as edges rather than vertices. -- @@ -2834,7 +2834,7 @@ package body Bindo.Graphs is -- the "complementary" vertex resulted in a cycle. Successor_Has_Cycle : Boolean; - -- This flag is set when visiting at least once successor of the + -- This flag is set when visiting at least one successor of the -- current vertex resulted in a cycle. begin @@ -2851,7 +2851,7 @@ package body Bindo.Graphs is Has_Cycle := False; -- Nothing to do when the limit on the number of saved cycles has - -- been reached. This protects against a combinatorial explostion + -- been reached. This protects against a combinatorial explosion -- in components with Elaborate_All cycles. if Cycle_Count >= Cycle_Limit then @@ -2859,8 +2859,8 @@ package body Bindo.Graphs is -- The vertex closes the circuit, thus resulting in a cycle. Save -- the cycle for later diagnostics. The initial invocation of the - -- routine always ignores the starting vertex to prevent a spurious - -- self cycle. + -- routine always ignores the starting vertex, to prevent a spurious + -- self-cycle. elsif not Is_Start_Vertex and then LGV_Sets.Contains (End_Vertices, Vertex) @@ -3053,7 +3053,7 @@ package body Bindo.Graphs is Visited_Set : LGV_Sets.Membership_Set := LGV_Sets.Nil; -- The "mark" array of Tarjan's algorithm. Since the original visits -- all vertices in increasing ordinal number 1 .. N, the array offers - -- a one to one mapping between a vertex and its "marked" state. The + -- a one-to-one mapping between a vertex and its "marked" state. The -- modified version however visits vertices within components, where -- their ordinals are not contiguous. Vertices are added to this set -- and treated as "marked". @@ -3091,7 +3091,7 @@ package body Bindo.Graphs is Vertex => Vertex, Elaborate_All_Active => Elaborate_All_Active); - -- The modified version maintans two addition attributes while + -- The modified version maintains two additional attributes while -- performing the depth-first search: -- -- * The most significant edge of the current potential cycle. @@ -3099,7 +3099,7 @@ package body Bindo.Graphs is -- * The number of invocation edges encountered along the path -- of the current potential cycle. -- - -- Both attributes are used in the heuristic which determines the + -- Both attributes are used in the heuristic that determines the -- importance of cycles. Find_Cycles_From_Vertex @@ -5243,7 +5243,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Comp)); - -- Nothing to do when switch -d_t (output cycle detection trace + -- Nothing to do when switch -d_t (output cycle-detection trace -- information) is not in effect. if not Debug_Flag_Underscore_T then @@ -5279,7 +5279,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Cycle)); - -- Nothing to do when switch -d_t (output cycle detection trace + -- Nothing to do when switch -d_t (output cycle-detection trace -- information) is not in effect. if not Debug_Flag_Underscore_T then @@ -5338,7 +5338,7 @@ package body Bindo.Graphs is Succ : constant Library_Graph_Vertex_Id := Successor (G, Edge); begin - -- Nothing to do when switch -d_t (output cycle detection trace + -- Nothing to do when switch -d_t (output cycle-detection trace -- information) is not in effect. if not Debug_Flag_Underscore_T then @@ -5387,7 +5387,7 @@ package body Bindo.Graphs is pragma Assert (Present (G)); pragma Assert (Present (Vertex)); - -- Nothing to do when switch -d_t (output cycle detection trace + -- Nothing to do when switch -d_t (output cycle-detection trace -- information) is not in effect. if not Debug_Flag_Underscore_T then diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index c467617..678f009 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -322,9 +322,9 @@ package body Bindo is -- In addition, GNATbind does not create an edge to the body of the -- pragma argument. -- - -- -d_t Output cycle detection trace information + -- -d_t Output cycle-detection trace information -- - -- GNATbind outputs trace information on cycle detection activities + -- GNATbind outputs trace information on cycle-detection activities -- to standard output. -- -- -d_A Output ALI invocation tables diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 89bb7f8..a81de09 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -368,7 +368,7 @@ package body Debug is -- d_q -- d_r -- d_s - -- d_t Output cycle detection trace information + -- d_t Output cycle-detection trace information -- d_u -- d_v -- d_w @@ -1150,7 +1150,7 @@ package body Debug is -- elaboration order and no longer creates an implicit dependency on -- the body of the argument. - -- d_t GNATBIND output trace information of cycle detection activities to + -- d_t GNATBIND output trace information of cycle-detection activities to -- standard output. -- d_A GNATBIND output the contents of all ALI invocation-related tables diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 448f981..feeac7b 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -2594,8 +2594,8 @@ package body Exp_Ch6 is ---------------------------------- function Is_Class_Wide_Interface_Type (E : Entity_Id) return Boolean is - Typ : Entity_Id := E; DDT : Entity_Id; + Typ : Entity_Id := E; begin if Has_Non_Limited_View (Typ) then diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb index c66296b..c5d10f7 100644 --- a/gcc/ada/sem_ch10.adb +++ b/gcc/ada/sem_ch10.adb @@ -4355,7 +4355,7 @@ package body Sem_Ch10 is end; end if; - -- The With_Clause may be on a grand-child or one of its further + -- The With_Clause may be on a grandchild or one of its further -- descendants, which makes a child immediately visible. Examine -- ancestry to determine whether such a child exists. For example, -- if current unit is A.C, and with_clause is on A.X.Y.Z, then X @@ -4394,7 +4394,7 @@ package body Sem_Ch10 is -- Scan context of current unit, to check whether there is -- a with_clause on the same unit as a private with-clause -- on a parent, in which case child unit is visible. If the - -- unit is a grand-child, the same applies to its parent. + -- unit is a grandchild, the same applies to its parent. ---------------- -- In_Context -- diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 1ccbb52..dc7f774 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -12551,6 +12551,10 @@ package body Sem_Ch13 is function Has_Generic_Parent (E : Entity_Id) return Boolean; -- Return True if any ancestor is a generic type + ------------------------ + -- Has_Generic_Parent -- + ------------------------ + function Has_Generic_Parent (E : Entity_Id) return Boolean is Ancestor_Type : Entity_Id := Etype (E); @@ -12562,10 +12566,12 @@ package body Sem_Ch13 is Ancestor_Type := Etype (Ancestor_Type); end loop; - return Present (Ancestor_Type) - and then Is_Generic_Type (Ancestor_Type); + return + Present (Ancestor_Type) and then Is_Generic_Type (Ancestor_Type); end Has_Generic_Parent; + -- Start of processing for Rep_Item_Too_Early + begin -- Cannot apply non-operational rep items to generic types diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 9e32cea..e936cbb 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -3651,7 +3651,7 @@ package body Sem_Ch3 is procedure Analyze_Object_Declaration (N : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Id : constant Entity_Id := Defining_Identifier (N); - Next_Decl : constant Node_Id := Next (N); + Next_Decl : constant Node_Id := Next (N); Act_T : Entity_Id; T : Entity_Id; @@ -4507,12 +4507,11 @@ package body Sem_Ch3 is declare Check : constant Node_Id := - Make_Predicate_Check (T, New_Occurrence_Of (Id, Loc)); + Make_Predicate_Check (T, New_Occurrence_Of (Id, Loc)); begin if No (Next_Decl) then Append_To (List_Containing (N), Check); - else Insert_Before (Next_Decl, Check); end if; diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 8806cbf..2b0a8ed 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -6178,20 +6178,17 @@ package body Sem_Ch4 is and then Ekind (Entity (Name (N))) = E_Function and then Present (Homonym (Entity (Name (N)))) then - - -- A name may appear overloaded if it has a homonym, even if - -- that homonym is non-overloadable, in which case the overload - -- list is in fact empty. This specialized case deserves a - -- special message if the homonym is a child package. + -- A name may appear overloaded if it has a homonym, even if that + -- homonym is non-overloadable, in which case the overload list is + -- in fact empty. This specialized case deserves a special message + -- if the homonym is a child package. declare Nam : constant Node_Id := Name (N); H : constant Entity_Id := Homonym (Entity (Nam)); begin - if Ekind (H) = E_Package - and then Is_Child_Unit (H) - then + if Ekind (H) = E_Package and then Is_Child_Unit (H) then Error_Msg_Qual_Level := 2; Error_Msg_NE ("if an entity in package& is meant, ", Nam, H); Error_Msg_NE ("\use a fully qualified name", Nam, H); @@ -6208,9 +6205,9 @@ package body Sem_Ch4 is end if; end loop; - -- If all interpretations are procedures, this deserves a - -- more precise message. Ditto if this appears as the prefix - -- of a selected component, which may be a lexical error. + -- If all interpretations are procedures, this deserves a more + -- precise message. Ditto if this appears as the prefix of a + -- selected component, which may be a lexical error. Error_Msg_N ("\context requires function call, found procedure name", Nam); @@ -6226,8 +6223,7 @@ package body Sem_Ch4 is elsif Nkind (N) = N_Procedure_Call_Statement and then not Void_Interp_Seen then - Error_Msg_N ( - "\function name found in procedure call", Nam); + Error_Msg_N ("\function name found in procedure call", Nam); end if; All_Errors_Mode := Err_Mode; diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 119a2ee..e00cd57 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -11342,7 +11342,7 @@ package body Sem_Ch6 is goto Continue; end if; - -- Protect against malformed parameter types. + -- Protect against malformed parameter types if Nkind (Ptype) not in N_Has_Entity then Formal_Type := Any_Type; diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb index e97f15e..e0d20ef 100644 --- a/gcc/ada/sem_ch7.adb +++ b/gcc/ada/sem_ch7.adb @@ -790,7 +790,7 @@ package body Sem_Ch7 is -- Deactivate expansion inside the body of ignored Ghost entities, -- as this code will ultimately be ignored. This avoids requiring the -- presence of run-time units which are not needed. Only do this for - -- user entities, as internally generated entitities might still need + -- user entities, as internally generated entities might still need -- to be expanded (e.g. those generated for types). if Present (Ignored_Ghost_Region) @@ -1063,7 +1063,7 @@ package body Sem_Ch7 is -- to the linker as their Is_Public flag is set to True. This proactive -- approach is necessary because an inlined or a generic body for which -- code is generated in other units may need to see these entities. Cut - -- down the number of global symbols that do not neet public visibility + -- down the number of global symbols that do not need public visibility -- as this has two beneficial effects: -- (1) It makes the compilation process more efficient. -- (2) It gives the code generator more leeway to optimize within each @@ -1883,7 +1883,7 @@ package body Sem_Ch7 is end if; -- Nested package specs that do not require bodies are not checked for - -- ineffective use clauses due to the possbility of subunits. This is + -- ineffective use clauses due to the possibility of subunits. This is -- because at this stage it is impossible to tell whether there will be -- a separate body. @@ -2261,7 +2261,7 @@ package body Sem_Ch7 is procedure Swap_Private_Dependents (Priv_Deps : Elist_Id); -- When the full view of a private type is made available, we do the -- same for its private dependents under proper visibility conditions. - -- When compiling a grand-chid unit this needs to be done recursively. + -- When compiling a grandchild unit this needs to be done recursively. ----------------------------- -- Swap_Private_Dependents -- @@ -3196,7 +3196,7 @@ package body Sem_Ch7 is E : Entity_Id; Requires_Body : Boolean := False; - -- Flag set when the unit has at least one construct that requries + -- Flag set when the unit has at least one construct that requires -- completion in a body. begin diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 4f56c53..db642f0 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -8471,14 +8471,12 @@ package body Sem_Res is Get_Next_Interp (I, It); end loop; - -- If expansion is active and this is wn inherited operation, + -- If expansion is active and this is an inherited operation, -- replace it with its ancestor. This must not be done during - -- preanalysis because the type nay not be frozen yet, as when - -- the context is a pre/post condition. + -- preanalysis because the type may not be frozen yet, as when + -- the context is a precondition or postcondition. - if Present (Alias (Entity (N))) - and then Expander_Active - then + if Present (Alias (Entity (N))) and then Expander_Active then Set_Entity (N, Alias (Entity (N))); end if; end; diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index af7dcd5..a9384b8 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -1302,9 +1302,7 @@ package body Sem_SPARK is begin -- Only SPARK bodies are analyzed - if No (Prag) - or else Get_SPARK_Mode_From_Annotation (Prag) /= Opt.On - then + if No (Prag) or else Get_SPARK_Mode_From_Annotation (Prag) /= Opt.On then return; end if; @@ -1314,8 +1312,9 @@ package body Sem_SPARK is and then Is_Anonymous_Access_Type (Etype (Spec_Id)) and then not Is_Traversal_Function (Spec_Id) then - Error_Msg_N ("anonymous access type for result only allowed for " - & "traveral functions", Spec_Id); + Error_Msg_N + ("anonymous access type for result only allowed for traveral " + & "functions", Spec_Id); return; end if; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 1c26634..e011c09 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -8716,9 +8716,7 @@ package body Sem_Util is if Is_Subprogram_Or_Generic_Subprogram (Subp) then Body_Id := Subprogram_Body_Entity (Subp); - elsif Is_Entry (Subp) - or else Is_Task_Type (Subp) - then + elsif Is_Entry (Subp) or else Is_Task_Type (Subp) then Body_Id := Corresponding_Body (Parent (Subp)); -- ??? It should be possible to retrieve the Refined_Global on the diff --git a/gcc/ada/warnsw.ads b/gcc/ada/warnsw.ads index 5875ecd..422f8df 100644 --- a/gcc/ada/warnsw.ads +++ b/gcc/ada/warnsw.ads @@ -41,8 +41,8 @@ package Warnsw is Warn_On_Anonymous_Allocators : Boolean := False; -- Warn when allocators for anonymous access types are present, which, -- although not illegal in Ada, may be confusing to users due to how - -- accessibility checks get generated. Off by default, modified by use of - -- -gnatw_a/_A and set as part of -gnatwa. + -- accessibility checks get generated. Off by default, modified by use + -- of -gnatw_a/_A and set as part of -gnatwa. Warn_On_Late_Primitives : Boolean := False; -- Warn when tagged type public primitives are defined after its private -- cgit v1.1 From 5b4ce2a0360a79751107c245c2e44c0932835164 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Wed, 10 Jul 2019 09:01:38 +0000 Subject: [Ada] Spurious error on case expression with limited result This patch modifies the expansion of case expressions to prevent a spurious error caused by the use of assignment statements to capture the result of the case expression when the associated type is limited. 2019-07-10 Hristian Kirtchev gcc/ada/ * exp_ch4.adb (Expand_N_Case_Expression): Mark the generated assignments to the temporary result as being OK because the expansion of case expressions is correct by construction. (Is_Copy_Type): Update the predicate to match the comment within. gcc/testsuite/ * gnat.dg/limited2.adb, gnat.dg/limited2_pack_1.adb, gnat.dg/limited2_pack_1.ads, gnat.dg/limited2_pack_2.adb, gnat.dg/limited2_pack_2.ads: New testcase. From-SVN: r273336 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/exp_ch4.adb | 9 ++++++--- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gnat.dg/limited2.adb | 8 ++++++++ gcc/testsuite/gnat.dg/limited2_pack_1.adb | 5 +++++ gcc/testsuite/gnat.dg/limited2_pack_1.ads | 8 ++++++++ gcc/testsuite/gnat.dg/limited2_pack_2.adb | 21 +++++++++++++++++++++ gcc/testsuite/gnat.dg/limited2_pack_2.ads | 5 +++++ 8 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/limited2.adb create mode 100644 gcc/testsuite/gnat.dg/limited2_pack_1.adb create mode 100644 gcc/testsuite/gnat.dg/limited2_pack_1.ads create mode 100644 gcc/testsuite/gnat.dg/limited2_pack_2.adb create mode 100644 gcc/testsuite/gnat.dg/limited2_pack_2.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f3f7217..adcb6a9 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,13 @@ 2019-07-10 Hristian Kirtchev + * exp_ch4.adb (Expand_N_Case_Expression): Mark the generated + assignments to the temporary result as being OK because the + expansion of case expressions is correct by construction. + (Is_Copy_Type): Update the predicate to match the comment + within. + +2019-07-10 Hristian Kirtchev + * bindo-graphs.adb, bindo.adb, debug.adb, exp_ch6.adb, sem_ch10.adb, sem_ch13.adb, sem_ch3.adb, sem_ch4.adb, sem_ch6.adb, sem_ch7.adb, sem_res.adb, sem_spark.adb, diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index b4159a7..f18632a 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -5087,7 +5087,6 @@ package body Exp_Ch4 is ------------------------------ procedure Expand_N_Case_Expression (N : Node_Id) is - function Is_Copy_Type (Typ : Entity_Id) return Boolean; -- Return True if we can copy objects of this type when expanding a case -- expression. @@ -5106,7 +5105,7 @@ package body Exp_Ch4 is or else (Minimize_Expression_With_Actions and then Is_Constrained (Underlying_Type (Typ)) - and then not Is_Limited_View (Underlying_Type (Typ))); + and then not Is_Limited_Type (Underlying_Type (Typ))); end Is_Copy_Type; -- Local variables @@ -5283,6 +5282,7 @@ package body Exp_Ch4 is declare Alt_Expr : Node_Id := Expression (Alt); Alt_Loc : constant Source_Ptr := Sloc (Alt_Expr); + LHS : Node_Id; Stmts : List_Id; begin @@ -5312,9 +5312,12 @@ package body Exp_Ch4 is -- Target := AX['Unrestricted_Access]; else + LHS := New_Occurrence_Of (Target, Loc); + Set_Assignment_OK (LHS); + Stmts := New_List ( Make_Assignment_Statement (Alt_Loc, - Name => New_Occurrence_Of (Target, Loc), + Name => LHS, Expression => Alt_Expr)); end if; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5c247f16..21c5e31 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-10 Hristian Kirtchev + + * gnat.dg/limited2.adb, gnat.dg/limited2_pack_1.adb, + gnat.dg/limited2_pack_1.ads, gnat.dg/limited2_pack_2.adb, + gnat.dg/limited2_pack_2.ads: New testcase. + 2019-07-10 Ed Schonberg * gnat.dg/equal8.adb, gnat.dg/equal8.ads, diff --git a/gcc/testsuite/gnat.dg/limited2.adb b/gcc/testsuite/gnat.dg/limited2.adb new file mode 100644 index 0000000..e3b28ec --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited2.adb @@ -0,0 +1,8 @@ +-- { dg-do compile } + +with Limited2_Pack_2; + +procedure Limited2 is +begin + Limited2_Pack_2.Create (P => Limited2_Pack_2.C1); +end Limited2; diff --git a/gcc/testsuite/gnat.dg/limited2_pack_1.adb b/gcc/testsuite/gnat.dg/limited2_pack_1.adb new file mode 100644 index 0000000..1f6e616 --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited2_pack_1.adb @@ -0,0 +1,5 @@ +package body Limited2_Pack_1 is + type B is record + F : Integer := 0; + end record; +end Limited2_Pack_1; diff --git a/gcc/testsuite/gnat.dg/limited2_pack_1.ads b/gcc/testsuite/gnat.dg/limited2_pack_1.ads new file mode 100644 index 0000000..c7d0950 --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited2_pack_1.ads @@ -0,0 +1,8 @@ +package Limited2_Pack_1 is + type A is limited private; + type A_Ptr is access all A; + +private + type B; + type A is access all B; +end Limited2_Pack_1; diff --git a/gcc/testsuite/gnat.dg/limited2_pack_2.adb b/gcc/testsuite/gnat.dg/limited2_pack_2.adb new file mode 100644 index 0000000..2a4ddd1 --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited2_pack_2.adb @@ -0,0 +1,21 @@ +with Limited2_Pack_1; + +package body Limited2_Pack_2 is + Obj_1 : Limited2_Pack_1.A; + Obj_2 : Limited2_Pack_1.A; + Obj_3 : Limited2_Pack_1.A; + + procedure M (R : Limited2_Pack_1.A) is + begin + null; + end M; + + procedure Create (P : in C) is + begin + M (R => Obj_1); + M (R => (case P is + when C1 => Obj_1, + when C2 => Obj_2, + when C3 => Obj_3)); + end Create; +end Limited2_Pack_2; diff --git a/gcc/testsuite/gnat.dg/limited2_pack_2.ads b/gcc/testsuite/gnat.dg/limited2_pack_2.ads new file mode 100644 index 0000000..efc1ab6 --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited2_pack_2.ads @@ -0,0 +1,5 @@ +package Limited2_Pack_2 is + type C is (C1, C2, C3); + + procedure Create (P : in C); +end Limited2_Pack_2; -- cgit v1.1 From 1c6f14b64b4e4bf1a01efe41c013f690b22bdce2 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 10 Jul 2019 09:01:43 +0000 Subject: [Ada] GNAT RM: add note about debuggers for Scalar_Storage_Order 2019-07-10 Eric Botcazou gcc/ada/ * doc/gnat_rm/implementation_defined_attributes.rst (Scalar_Storage_Order): Minor tweaks. Add note about debuggers. * gnat_rm.texi: Regenerate. From-SVN: r273337 --- gcc/ada/ChangeLog | 6 ++++++ .../doc/gnat_rm/implementation_defined_attributes.rst | 19 +++++++++++-------- gcc/ada/gnat_rm.texi | 19 +++++++++++-------- 3 files changed, 28 insertions(+), 16 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index adcb6a9..e870be4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-10 Eric Botcazou + + * doc/gnat_rm/implementation_defined_attributes.rst + (Scalar_Storage_Order): Minor tweaks. Add note about debuggers. + * gnat_rm.texi: Regenerate. + 2019-07-10 Hristian Kirtchev * exp_ch4.adb (Expand_N_Case_Expression): Mark the generated diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst index 0b4f780..c75d994 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst @@ -967,8 +967,8 @@ of the use of this feature: -- the former is used. -Other properties are as for standard representation attribute ``Bit_Order``, -as defined by Ada RM 13.5.3(4). The default is ``System.Default_Bit_Order``. +Other properties are as for the standard representation attribute ``Bit_Order`` +defined by Ada RM 13.5.3(4). The default is ``System.Default_Bit_Order``. For a record type ``T``, if ``T'Scalar_Storage_Order`` is specified explicitly, it shall be equal to ``T'Bit_Order``. Note: @@ -978,8 +978,8 @@ specified explicitly and set to the same value. Derived types inherit an explicitly set scalar storage order from their parent types. This may be overridden for the derived type by giving an explicit scalar -storage order for the derived type. For a record extension, the derived type -must have the same scalar storage order as the parent type. +storage order for it. However, for a record extension, the derived type must +have the same scalar storage order as the parent type. A component of a record type that is itself a record or an array and that does not start and end on a byte boundary must have have the same scalar storage @@ -1018,15 +1018,18 @@ inheritance in the case of a derived type), then the default is normally the native ordering of the target, but this default can be overridden using pragma ``Default_Scalar_Storage_Order``. -Note that if a component of ``T`` is itself of a record or array type, -the specfied ``Scalar_Storage_Order`` does *not* apply to that nested type: -an explicit attribute definition clause must be provided for the component -type as well if desired. +If a component of ``T`` is itself of a record or array type, the specfied +``Scalar_Storage_Order`` does *not* apply to that nested type: an explicit +attribute definition clause must be provided for the component type as well +if desired. Note that the scalar storage order only affects the in-memory data representation. It has no effect on the representation used by stream attributes. +Note that debuggers may be unable to display the correct value of scalar +components of a type for which the opposite storage order is specified. + .. _Attribute_Simple_Storage_Pool: Attribute Simple_Storage_Pool diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 2de8802..597752f 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -11270,8 +11270,8 @@ for Date'Scalar_Storage_Order use System.High_Order_First; -- the former is used. @end example -Other properties are as for standard representation attribute @code{Bit_Order}, -as defined by Ada RM 13.5.3(4). The default is @code{System.Default_Bit_Order}. +Other properties are as for the standard representation attribute @code{Bit_Order} +defined by Ada RM 13.5.3(4). The default is @code{System.Default_Bit_Order}. For a record type @code{T}, if @code{T'Scalar_Storage_Order} is specified explicitly, it shall be equal to @code{T'Bit_Order}. Note: @@ -11281,8 +11281,8 @@ specified explicitly and set to the same value. Derived types inherit an explicitly set scalar storage order from their parent types. This may be overridden for the derived type by giving an explicit scalar -storage order for the derived type. For a record extension, the derived type -must have the same scalar storage order as the parent type. +storage order for it. However, for a record extension, the derived type must +have the same scalar storage order as the parent type. A component of a record type that is itself a record or an array and that does not start and end on a byte boundary must have have the same scalar storage @@ -11332,15 +11332,18 @@ inheritance in the case of a derived type), then the default is normally the native ordering of the target, but this default can be overridden using pragma @code{Default_Scalar_Storage_Order}. -Note that if a component of @code{T} is itself of a record or array type, -the specfied @code{Scalar_Storage_Order} does @emph{not} apply to that nested type: -an explicit attribute definition clause must be provided for the component -type as well if desired. +If a component of @code{T} is itself of a record or array type, the specfied +@code{Scalar_Storage_Order} does @emph{not} apply to that nested type: an explicit +attribute definition clause must be provided for the component type as well +if desired. Note that the scalar storage order only affects the in-memory data representation. It has no effect on the representation used by stream attributes. +Note that debuggers may be unable to display the correct value of scalar +components of a type for which the opposite storage order is specified. + @node Attribute Simple_Storage_Pool,Attribute Small,Attribute Scalar_Storage_Order,Implementation Defined Attributes @anchor{gnat_rm/implementation_defined_attributes attribute-simple-storage-pool}@anchor{e7}@anchor{gnat_rm/implementation_defined_attributes id5}@anchor{19c} @section Attribute Simple_Storage_Pool -- cgit v1.1 From 9ab234e531354d939c2105e8005153d7554f7cdd Mon Sep 17 00:00:00 2001 From: Corentin Gay Date: Wed, 10 Jul 2019 09:01:48 +0000 Subject: [Ada] sysdep.c: correct include directives ordering Some VxWorks headers are relying on types that are defined in `vxWorks.h` but do not include it themselves, we move the include directive for `vxWorks.h` at the top of the include directives. 2019-07-10 Corentin Gay gcc/ada/ * sysdep.c: Put include directive for 'vxWorks.h' before any other VxWorks headers. From-SVN: r273338 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sysdep.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e870be4..61afaff 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Corentin Gay + + * sysdep.c: Put include directive for 'vxWorks.h' before any + other VxWorks headers. + 2019-07-10 Eric Botcazou * doc/gnat_rm/implementation_defined_attributes.rst diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c index a5f325d..66c29d3 100644 --- a/gcc/ada/sysdep.c +++ b/gcc/ada/sysdep.c @@ -33,6 +33,7 @@ GNAT Run Time Library */ #ifdef __vxworks +#include "vxWorks.h" #include "ioLib.h" #if ! defined (VTHREADS) #include "dosFsLib.h" @@ -41,7 +42,6 @@ # include "nfsLib.h" #endif #include "selectLib.h" -#include "vxWorks.h" #include "version.h" #if defined (__RTP__) # include "vwModNum.h" -- cgit v1.1 From 27572ba35feadc66d1a8c1f85a5c12e8bc4a010b Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 10 Jul 2019 09:01:53 +0000 Subject: [Ada] Allow multiple units per file in GNATprove For analysis tools that rely on information generated in ALI files, but do not generate object files, the frontend did not generate the special extension names like file~2.ali for unit 2 in the file. This is needed to be able to analyze files with multiple units. Now fixed. There is no impact on compilation. 2019-07-10 Yannick Moy gcc/ada/ * osint-c.adb (Set_File_Name): Always add extension for multiple units per file mode. From-SVN: r273339 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/osint-c.adb | 30 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 61afaff..2e57398 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Yannick Moy + + * osint-c.adb (Set_File_Name): Always add extension for multiple + units per file mode. + 2019-07-10 Corentin Gay * sysdep.c: Put include directive for 'vxWorks.h' before any diff --git a/gcc/ada/osint-c.adb b/gcc/ada/osint-c.adb index 8af5aa0..9fb9ee3 100644 --- a/gcc/ada/osint-c.adb +++ b/gcc/ada/osint-c.adb @@ -385,6 +385,21 @@ package body Osint.C is end if; end loop; + -- If we are in multiple-units-per-file mode, then add a ~nnn extension + -- to the name. + + if Multiple_Unit_Index /= 0 then + declare + Exten : constant String := Name_Buffer (Dot_Index .. Name_Len); + begin + Name_Len := Dot_Index - 1; + Add_Char_To_Name_Buffer (Multi_Unit_Index_Character); + Add_Nat_To_Name_Buffer (Multiple_Unit_Index); + Dot_Index := Name_Len + 1; + Add_Str_To_Name_Buffer (Exten); + end; + end if; + -- Make sure that the output file name matches the source file name. -- To compare them, remove file name directories and extensions. @@ -395,21 +410,6 @@ package body Osint.C is Name_Buffer (Dot_Index) := '.'; - -- If we are in multiple unit per file mode, then add ~nnn - -- extension to the name before doing the comparison. - - if Multiple_Unit_Index /= 0 then - declare - Exten : constant String := Name_Buffer (Dot_Index .. Name_Len); - begin - Name_Len := Dot_Index - 1; - Add_Char_To_Name_Buffer (Multi_Unit_Index_Character); - Add_Nat_To_Name_Buffer (Multiple_Unit_Index); - Dot_Index := Name_Len + 1; - Add_Str_To_Name_Buffer (Exten); - end; - end if; - -- Remove extension preparing to replace it declare -- cgit v1.1 From 9ead6ee5c84ed6a5d670e0c5a46d0b1e9a926ca3 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 10 Jul 2019 09:01:58 +0000 Subject: [Ada] Improve support for tuning branch probability heuristics This adds a new GNAT.Branch_Prediction package to make it possible to tune the branch probability heuristics more finely. This package contains the equivalent of __builtin_expect in C/C++ plus a couple of specializations. The following program gives a summary of the usage: package Q is I : Integer; pragma Volatile (I); end Q; with GNAT.Branch_Prediction; use GNAT.Branch_Prediction; with Text_IO; use Text_IO; with Q; use Q; procedure P is begin if Unlikely (I = 0) then Put_Line ("Zero was passed"); return; end if; if Likely (I > 0) then Put_Line ("A positive number was passed"); else Put_Line ("A negative number was passed"); end if; if Expect ((I rem 2) = 0, False) then Put_Line ("An even number was passed"); else Put_Line ("An odd number was passed"); end if; end; 2019-07-10 Eric Botcazou gcc/ada/ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add g-brapre. * libgnat/g-brapre.ads: New package specification. * doc/gnat_rm/the_gnat_library.rst: Document it. * gnat_rm.texi: Regenerate. From-SVN: r273340 --- gcc/ada/ChangeLog | 7 + gcc/ada/Makefile.rtl | 1 + gcc/ada/doc/gnat_rm/the_gnat_library.rst | 11 + gcc/ada/gnat_rm.texi | 333 ++++++++++++++++--------------- gcc/ada/libgnat/g-brapre.ads | 68 +++++++ 5 files changed, 260 insertions(+), 160 deletions(-) create mode 100644 gcc/ada/libgnat/g-brapre.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2e57398..0959008 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-10 Eric Botcazou + + * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add g-brapre. + * libgnat/g-brapre.ads: New package specification. + * doc/gnat_rm/the_gnat_library.rst: Document it. + * gnat_rm.texi: Regenerate. + 2019-07-10 Yannick Moy * osint-c.adb (Set_File_Name): Always add extension for multiple diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 9e3d67e..3df2ff5 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -387,6 +387,7 @@ GNATRTL_NONTASKING_OBJS= \ g-arrspl$(objext) \ g-awk$(objext) \ g-binenv$(objext) \ + g-brapre$(objext) \ g-bubsor$(objext) \ g-busora$(objext) \ g-busorg$(objext) \ diff --git a/gcc/ada/doc/gnat_rm/the_gnat_library.rst b/gcc/ada/doc/gnat_rm/the_gnat_library.rst index 08497f3..6b9a410 100644 --- a/gcc/ada/doc/gnat_rm/the_gnat_library.rst +++ b/gcc/ada/doc/gnat_rm/the_gnat_library.rst @@ -722,6 +722,17 @@ Provides access to key=value associations captured at bind time. These associations can be specified using the :switch:`-V` binder command line switch. +.. _`GNAT.Branch_Prediction_(g-brapre.ads)`: + +``GNAT.Branch_Prediction`` (:file:`g-brapre.ads`) +================================================= + +.. index:: GNAT.Branch_Prediction (g-brapre.ads) + +.. index:: Branch Prediction + +Provides routines giving hints to the branch predictor of the code generator. + .. _`GNAT.Bounded_Buffers_(g-boubuf.ads)`: ``GNAT.Bounded_Buffers`` (:file:`g-boubuf.ads`) diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 597752f..77f91b0 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -729,6 +729,7 @@ The GNAT Library * GNAT.Array_Split (g-arrspl.ads): GNAT Array_Split g-arrspl ads. * GNAT.AWK (g-awk.ads): GNAT AWK g-awk ads. * GNAT.Bind_Environment (g-binenv.ads): GNAT Bind_Environment g-binenv ads. +* GNAT.Branch_Prediction (g-brapre.ads): GNAT Branch_Prediction g-brapre ads. * GNAT.Bounded_Buffers (g-boubuf.ads): GNAT Bounded_Buffers g-boubuf ads. * GNAT.Bounded_Mailboxes (g-boumai.ads): GNAT Bounded_Mailboxes g-boumai ads. * GNAT.Bubble_Sort (g-bubsor.ads): GNAT Bubble_Sort g-bubsor ads. @@ -23013,6 +23014,7 @@ of GNAT, and will generate a warning message. * GNAT.Array_Split (g-arrspl.ads): GNAT Array_Split g-arrspl ads. * GNAT.AWK (g-awk.ads): GNAT AWK g-awk ads. * GNAT.Bind_Environment (g-binenv.ads): GNAT Bind_Environment g-binenv ads. +* GNAT.Branch_Prediction (g-brapre.ads): GNAT Branch_Prediction g-brapre ads. * GNAT.Bounded_Buffers (g-boubuf.ads): GNAT Bounded_Buffers g-boubuf ads. * GNAT.Bounded_Mailboxes (g-boumai.ads): GNAT Bounded_Mailboxes g-boumai ads. * GNAT.Bubble_Sort (g-bubsor.ads): GNAT Bubble_Sort g-bubsor ads. @@ -23819,7 +23821,7 @@ Provides AWK-like parsing functions, with an easy interface for parsing one or more files containing formatted data. The file is viewed as a database where each record is a line and a field is a data element in this line. -@node GNAT Bind_Environment g-binenv ads,GNAT Bounded_Buffers g-boubuf ads,GNAT AWK g-awk ads,The GNAT Library +@node GNAT Bind_Environment g-binenv ads,GNAT Branch_Prediction g-brapre ads,GNAT AWK g-awk ads,The GNAT Library @anchor{gnat_rm/the_gnat_library gnat-bind-environment-g-binenv-ads}@anchor{326}@anchor{gnat_rm/the_gnat_library id45}@anchor{327} @section @code{GNAT.Bind_Environment} (@code{g-binenv.ads}) @@ -23832,8 +23834,19 @@ Provides access to key=value associations captured at bind time. These associations can be specified using the @code{-V} binder command line switch. -@node GNAT Bounded_Buffers g-boubuf ads,GNAT Bounded_Mailboxes g-boumai ads,GNAT Bind_Environment g-binenv ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id46}@anchor{328}@anchor{gnat_rm/the_gnat_library gnat-bounded-buffers-g-boubuf-ads}@anchor{329} +@node GNAT Branch_Prediction g-brapre ads,GNAT Bounded_Buffers g-boubuf ads,GNAT Bind_Environment g-binenv ads,The GNAT Library +@anchor{gnat_rm/the_gnat_library id46}@anchor{328}@anchor{gnat_rm/the_gnat_library gnat-branch-prediction-g-brapre-ads}@anchor{329} +@section @code{GNAT.Branch_Prediction} (@code{g-brapre.ads}) + + +@geindex GNAT.Branch_Prediction (g-brapre.ads) + +@geindex Branch Prediction + +Provides routines giving hints to the branch predictor of the code generator. + +@node GNAT Bounded_Buffers g-boubuf ads,GNAT Bounded_Mailboxes g-boumai ads,GNAT Branch_Prediction g-brapre ads,The GNAT Library +@anchor{gnat_rm/the_gnat_library id47}@anchor{32a}@anchor{gnat_rm/the_gnat_library gnat-bounded-buffers-g-boubuf-ads}@anchor{32b} @section @code{GNAT.Bounded_Buffers} (@code{g-boubuf.ads}) @@ -23848,7 +23861,7 @@ useful directly or as parts of the implementations of other abstractions, such as mailboxes. @node GNAT Bounded_Mailboxes g-boumai ads,GNAT Bubble_Sort g-bubsor ads,GNAT Bounded_Buffers g-boubuf ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id47}@anchor{32a}@anchor{gnat_rm/the_gnat_library gnat-bounded-mailboxes-g-boumai-ads}@anchor{32b} +@anchor{gnat_rm/the_gnat_library gnat-bounded-mailboxes-g-boumai-ads}@anchor{32c}@anchor{gnat_rm/the_gnat_library id48}@anchor{32d} @section @code{GNAT.Bounded_Mailboxes} (@code{g-boumai.ads}) @@ -23861,7 +23874,7 @@ such as mailboxes. Provides a thread-safe asynchronous intertask mailbox communication facility. @node GNAT Bubble_Sort g-bubsor ads,GNAT Bubble_Sort_A g-busora ads,GNAT Bounded_Mailboxes g-boumai ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-bubsor-ads}@anchor{32c}@anchor{gnat_rm/the_gnat_library id48}@anchor{32d} +@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-bubsor-ads}@anchor{32e}@anchor{gnat_rm/the_gnat_library id49}@anchor{32f} @section @code{GNAT.Bubble_Sort} (@code{g-bubsor.ads}) @@ -23876,7 +23889,7 @@ data items. Exchange and comparison procedures are provided by passing access-to-procedure values. @node GNAT Bubble_Sort_A g-busora ads,GNAT Bubble_Sort_G g-busorg ads,GNAT Bubble_Sort g-bubsor ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id49}@anchor{32e}@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{32f} +@anchor{gnat_rm/the_gnat_library id50}@anchor{330}@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-a-g-busora-ads}@anchor{331} @section @code{GNAT.Bubble_Sort_A} (@code{g-busora.ads}) @@ -23892,7 +23905,7 @@ access-to-procedure values. This is an older version, retained for compatibility. Usually @code{GNAT.Bubble_Sort} will be preferable. @node GNAT Bubble_Sort_G g-busorg ads,GNAT Byte_Order_Mark g-byorma ads,GNAT Bubble_Sort_A g-busora ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-g-busorg-ads}@anchor{330}@anchor{gnat_rm/the_gnat_library id50}@anchor{331} +@anchor{gnat_rm/the_gnat_library gnat-bubble-sort-g-g-busorg-ads}@anchor{332}@anchor{gnat_rm/the_gnat_library id51}@anchor{333} @section @code{GNAT.Bubble_Sort_G} (@code{g-busorg.ads}) @@ -23908,7 +23921,7 @@ if the procedures can be inlined, at the expense of duplicating code for multiple instantiations. @node GNAT Byte_Order_Mark g-byorma ads,GNAT Byte_Swapping g-bytswa ads,GNAT Bubble_Sort_G g-busorg ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-byte-order-mark-g-byorma-ads}@anchor{332}@anchor{gnat_rm/the_gnat_library id51}@anchor{333} +@anchor{gnat_rm/the_gnat_library gnat-byte-order-mark-g-byorma-ads}@anchor{334}@anchor{gnat_rm/the_gnat_library id52}@anchor{335} @section @code{GNAT.Byte_Order_Mark} (@code{g-byorma.ads}) @@ -23924,7 +23937,7 @@ the encoding of the string. The routine includes detection of special XML sequences for various UCS input formats. @node GNAT Byte_Swapping g-bytswa ads,GNAT Calendar g-calend ads,GNAT Byte_Order_Mark g-byorma ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-byte-swapping-g-bytswa-ads}@anchor{334}@anchor{gnat_rm/the_gnat_library id52}@anchor{335} +@anchor{gnat_rm/the_gnat_library gnat-byte-swapping-g-bytswa-ads}@anchor{336}@anchor{gnat_rm/the_gnat_library id53}@anchor{337} @section @code{GNAT.Byte_Swapping} (@code{g-bytswa.ads}) @@ -23938,7 +23951,7 @@ General routines for swapping the bytes in 2-, 4-, and 8-byte quantities. Machine-specific implementations are available in some cases. @node GNAT Calendar g-calend ads,GNAT Calendar Time_IO g-catiio ads,GNAT Byte_Swapping g-bytswa ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{336}@anchor{gnat_rm/the_gnat_library id53}@anchor{337} +@anchor{gnat_rm/the_gnat_library id54}@anchor{338}@anchor{gnat_rm/the_gnat_library gnat-calendar-g-calend-ads}@anchor{339} @section @code{GNAT.Calendar} (@code{g-calend.ads}) @@ -23952,7 +23965,7 @@ Also provides conversion of @code{Ada.Calendar.Time} values to and from the C @code{timeval} format. @node GNAT Calendar Time_IO g-catiio ads,GNAT CRC32 g-crc32 ads,GNAT Calendar g-calend ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id54}@anchor{338}@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{339} +@anchor{gnat_rm/the_gnat_library id55}@anchor{33a}@anchor{gnat_rm/the_gnat_library gnat-calendar-time-io-g-catiio-ads}@anchor{33b} @section @code{GNAT.Calendar.Time_IO} (@code{g-catiio.ads}) @@ -23963,7 +23976,7 @@ C @code{timeval} format. @geindex GNAT.Calendar.Time_IO (g-catiio.ads) @node GNAT CRC32 g-crc32 ads,GNAT Case_Util g-casuti ads,GNAT Calendar Time_IO g-catiio ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id55}@anchor{33a}@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{33b} +@anchor{gnat_rm/the_gnat_library id56}@anchor{33c}@anchor{gnat_rm/the_gnat_library gnat-crc32-g-crc32-ads}@anchor{33d} @section @code{GNAT.CRC32} (@code{g-crc32.ads}) @@ -23980,7 +23993,7 @@ of this algorithm see Aug. 1988. Sarwate, D.V. @node GNAT Case_Util g-casuti ads,GNAT CGI g-cgi ads,GNAT CRC32 g-crc32 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id56}@anchor{33c}@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{33d} +@anchor{gnat_rm/the_gnat_library id57}@anchor{33e}@anchor{gnat_rm/the_gnat_library gnat-case-util-g-casuti-ads}@anchor{33f} @section @code{GNAT.Case_Util} (@code{g-casuti.ads}) @@ -23995,7 +24008,7 @@ without the overhead of the full casing tables in @code{Ada.Characters.Handling}. @node GNAT CGI g-cgi ads,GNAT CGI Cookie g-cgicoo ads,GNAT Case_Util g-casuti ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id57}@anchor{33e}@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{33f} +@anchor{gnat_rm/the_gnat_library id58}@anchor{340}@anchor{gnat_rm/the_gnat_library gnat-cgi-g-cgi-ads}@anchor{341} @section @code{GNAT.CGI} (@code{g-cgi.ads}) @@ -24010,7 +24023,7 @@ builds a table whose index is the key and provides some services to deal with this table. @node GNAT CGI Cookie g-cgicoo ads,GNAT CGI Debug g-cgideb ads,GNAT CGI g-cgi ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-cgi-cookie-g-cgicoo-ads}@anchor{340}@anchor{gnat_rm/the_gnat_library id58}@anchor{341} +@anchor{gnat_rm/the_gnat_library gnat-cgi-cookie-g-cgicoo-ads}@anchor{342}@anchor{gnat_rm/the_gnat_library id59}@anchor{343} @section @code{GNAT.CGI.Cookie} (@code{g-cgicoo.ads}) @@ -24025,7 +24038,7 @@ Common Gateway Interface (CGI). It exports services to deal with Web cookies (piece of information kept in the Web client software). @node GNAT CGI Debug g-cgideb ads,GNAT Command_Line g-comlin ads,GNAT CGI Cookie g-cgicoo ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-cgi-debug-g-cgideb-ads}@anchor{342}@anchor{gnat_rm/the_gnat_library id59}@anchor{343} +@anchor{gnat_rm/the_gnat_library gnat-cgi-debug-g-cgideb-ads}@anchor{344}@anchor{gnat_rm/the_gnat_library id60}@anchor{345} @section @code{GNAT.CGI.Debug} (@code{g-cgideb.ads}) @@ -24037,7 +24050,7 @@ This is a package to help debugging CGI (Common Gateway Interface) programs written in Ada. @node GNAT Command_Line g-comlin ads,GNAT Compiler_Version g-comver ads,GNAT CGI Debug g-cgideb ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id60}@anchor{344}@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{345} +@anchor{gnat_rm/the_gnat_library id61}@anchor{346}@anchor{gnat_rm/the_gnat_library gnat-command-line-g-comlin-ads}@anchor{347} @section @code{GNAT.Command_Line} (@code{g-comlin.ads}) @@ -24050,7 +24063,7 @@ including the ability to scan for named switches with optional parameters and expand file names using wildcard notations. @node GNAT Compiler_Version g-comver ads,GNAT Ctrl_C g-ctrl_c ads,GNAT Command_Line g-comlin ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{346}@anchor{gnat_rm/the_gnat_library id61}@anchor{347} +@anchor{gnat_rm/the_gnat_library gnat-compiler-version-g-comver-ads}@anchor{348}@anchor{gnat_rm/the_gnat_library id62}@anchor{349} @section @code{GNAT.Compiler_Version} (@code{g-comver.ads}) @@ -24068,7 +24081,7 @@ of the compiler if a consistent tool set is used to compile all units of a partition). @node GNAT Ctrl_C g-ctrl_c ads,GNAT Current_Exception g-curexc ads,GNAT Compiler_Version g-comver ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{348}@anchor{gnat_rm/the_gnat_library id62}@anchor{349} +@anchor{gnat_rm/the_gnat_library gnat-ctrl-c-g-ctrl-c-ads}@anchor{34a}@anchor{gnat_rm/the_gnat_library id63}@anchor{34b} @section @code{GNAT.Ctrl_C} (@code{g-ctrl_c.ads}) @@ -24079,7 +24092,7 @@ of a partition). Provides a simple interface to handle Ctrl-C keyboard events. @node GNAT Current_Exception g-curexc ads,GNAT Debug_Pools g-debpoo ads,GNAT Ctrl_C g-ctrl_c ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id63}@anchor{34a}@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{34b} +@anchor{gnat_rm/the_gnat_library id64}@anchor{34c}@anchor{gnat_rm/the_gnat_library gnat-current-exception-g-curexc-ads}@anchor{34d} @section @code{GNAT.Current_Exception} (@code{g-curexc.ads}) @@ -24096,7 +24109,7 @@ This is particularly useful in simulating typical facilities for obtaining information about exceptions provided by Ada 83 compilers. @node GNAT Debug_Pools g-debpoo ads,GNAT Debug_Utilities g-debuti ads,GNAT Current_Exception g-curexc ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-debug-pools-g-debpoo-ads}@anchor{34c}@anchor{gnat_rm/the_gnat_library id64}@anchor{34d} +@anchor{gnat_rm/the_gnat_library gnat-debug-pools-g-debpoo-ads}@anchor{34e}@anchor{gnat_rm/the_gnat_library id65}@anchor{34f} @section @code{GNAT.Debug_Pools} (@code{g-debpoo.ads}) @@ -24113,7 +24126,7 @@ problems. See @code{The GNAT Debug_Pool Facility} section in the @cite{GNAT User's Guide}. @node GNAT Debug_Utilities g-debuti ads,GNAT Decode_String g-decstr ads,GNAT Debug_Pools g-debpoo ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id65}@anchor{34e}@anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{34f} +@anchor{gnat_rm/the_gnat_library gnat-debug-utilities-g-debuti-ads}@anchor{350}@anchor{gnat_rm/the_gnat_library id66}@anchor{351} @section @code{GNAT.Debug_Utilities} (@code{g-debuti.ads}) @@ -24126,7 +24139,7 @@ to and from string images of address values. Supports both C and Ada formats for hexadecimal literals. @node GNAT Decode_String g-decstr ads,GNAT Decode_UTF8_String g-deutst ads,GNAT Debug_Utilities g-debuti ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-decode-string-g-decstr-ads}@anchor{350}@anchor{gnat_rm/the_gnat_library id66}@anchor{351} +@anchor{gnat_rm/the_gnat_library id67}@anchor{352}@anchor{gnat_rm/the_gnat_library gnat-decode-string-g-decstr-ads}@anchor{353} @section @code{GNAT.Decode_String} (@code{g-decstr.ads}) @@ -24150,7 +24163,7 @@ Useful in conjunction with Unicode character coding. Note there is a preinstantiation for UTF-8. See next entry. @node GNAT Decode_UTF8_String g-deutst ads,GNAT Directory_Operations g-dirope ads,GNAT Decode_String g-decstr ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-decode-utf8-string-g-deutst-ads}@anchor{352}@anchor{gnat_rm/the_gnat_library id67}@anchor{353} +@anchor{gnat_rm/the_gnat_library gnat-decode-utf8-string-g-deutst-ads}@anchor{354}@anchor{gnat_rm/the_gnat_library id68}@anchor{355} @section @code{GNAT.Decode_UTF8_String} (@code{g-deutst.ads}) @@ -24171,7 +24184,7 @@ preinstantiation for UTF-8. See next entry. A preinstantiation of GNAT.Decode_Strings for UTF-8 encoding. @node GNAT Directory_Operations g-dirope ads,GNAT Directory_Operations Iteration g-diopit ads,GNAT Decode_UTF8_String g-deutst ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{354}@anchor{gnat_rm/the_gnat_library id68}@anchor{355} +@anchor{gnat_rm/the_gnat_library id69}@anchor{356}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-g-dirope-ads}@anchor{357} @section @code{GNAT.Directory_Operations} (@code{g-dirope.ads}) @@ -24184,7 +24197,7 @@ the current directory, making new directories, and scanning the files in a directory. @node GNAT Directory_Operations Iteration g-diopit ads,GNAT Dynamic_HTables g-dynhta ads,GNAT Directory_Operations g-dirope ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id69}@anchor{356}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{357} +@anchor{gnat_rm/the_gnat_library id70}@anchor{358}@anchor{gnat_rm/the_gnat_library gnat-directory-operations-iteration-g-diopit-ads}@anchor{359} @section @code{GNAT.Directory_Operations.Iteration} (@code{g-diopit.ads}) @@ -24196,7 +24209,7 @@ A child unit of GNAT.Directory_Operations providing additional operations for iterating through directories. @node GNAT Dynamic_HTables g-dynhta ads,GNAT Dynamic_Tables g-dyntab ads,GNAT Directory_Operations Iteration g-diopit ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id70}@anchor{358}@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{359} +@anchor{gnat_rm/the_gnat_library id71}@anchor{35a}@anchor{gnat_rm/the_gnat_library gnat-dynamic-htables-g-dynhta-ads}@anchor{35b} @section @code{GNAT.Dynamic_HTables} (@code{g-dynhta.ads}) @@ -24214,7 +24227,7 @@ dynamic instances of the hash table, while an instantiation of @code{GNAT.HTable} creates a single instance of the hash table. @node GNAT Dynamic_Tables g-dyntab ads,GNAT Encode_String g-encstr ads,GNAT Dynamic_HTables g-dynhta ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-dynamic-tables-g-dyntab-ads}@anchor{35a}@anchor{gnat_rm/the_gnat_library id71}@anchor{35b} +@anchor{gnat_rm/the_gnat_library gnat-dynamic-tables-g-dyntab-ads}@anchor{35c}@anchor{gnat_rm/the_gnat_library id72}@anchor{35d} @section @code{GNAT.Dynamic_Tables} (@code{g-dyntab.ads}) @@ -24234,7 +24247,7 @@ dynamic instances of the table, while an instantiation of @code{GNAT.Table} creates a single instance of the table type. @node GNAT Encode_String g-encstr ads,GNAT Encode_UTF8_String g-enutst ads,GNAT Dynamic_Tables g-dyntab ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id72}@anchor{35c}@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{35d} +@anchor{gnat_rm/the_gnat_library id73}@anchor{35e}@anchor{gnat_rm/the_gnat_library gnat-encode-string-g-encstr-ads}@anchor{35f} @section @code{GNAT.Encode_String} (@code{g-encstr.ads}) @@ -24256,7 +24269,7 @@ encoding method. Useful in conjunction with Unicode character coding. Note there is a preinstantiation for UTF-8. See next entry. @node GNAT Encode_UTF8_String g-enutst ads,GNAT Exception_Actions g-excact ads,GNAT Encode_String g-encstr ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-encode-utf8-string-g-enutst-ads}@anchor{35e}@anchor{gnat_rm/the_gnat_library id73}@anchor{35f} +@anchor{gnat_rm/the_gnat_library gnat-encode-utf8-string-g-enutst-ads}@anchor{360}@anchor{gnat_rm/the_gnat_library id74}@anchor{361} @section @code{GNAT.Encode_UTF8_String} (@code{g-enutst.ads}) @@ -24277,7 +24290,7 @@ Note there is a preinstantiation for UTF-8. See next entry. A preinstantiation of GNAT.Encode_Strings for UTF-8 encoding. @node GNAT Exception_Actions g-excact ads,GNAT Exception_Traces g-exctra ads,GNAT Encode_UTF8_String g-enutst ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-exception-actions-g-excact-ads}@anchor{360}@anchor{gnat_rm/the_gnat_library id74}@anchor{361} +@anchor{gnat_rm/the_gnat_library gnat-exception-actions-g-excact-ads}@anchor{362}@anchor{gnat_rm/the_gnat_library id75}@anchor{363} @section @code{GNAT.Exception_Actions} (@code{g-excact.ads}) @@ -24290,7 +24303,7 @@ for specific exceptions, or when any exception is raised. This can be used for instance to force a core dump to ease debugging. @node GNAT Exception_Traces g-exctra ads,GNAT Exceptions g-except ads,GNAT Exception_Actions g-excact ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-exception-traces-g-exctra-ads}@anchor{362}@anchor{gnat_rm/the_gnat_library id75}@anchor{363} +@anchor{gnat_rm/the_gnat_library gnat-exception-traces-g-exctra-ads}@anchor{364}@anchor{gnat_rm/the_gnat_library id76}@anchor{365} @section @code{GNAT.Exception_Traces} (@code{g-exctra.ads}) @@ -24304,7 +24317,7 @@ Provides an interface allowing to control automatic output upon exception occurrences. @node GNAT Exceptions g-except ads,GNAT Expect g-expect ads,GNAT Exception_Traces g-exctra ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id76}@anchor{364}@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{365} +@anchor{gnat_rm/the_gnat_library id77}@anchor{366}@anchor{gnat_rm/the_gnat_library gnat-exceptions-g-except-ads}@anchor{367} @section @code{GNAT.Exceptions} (@code{g-except.ads}) @@ -24325,7 +24338,7 @@ predefined exceptions, and for example allow raising @code{Constraint_Error} with a message from a pure subprogram. @node GNAT Expect g-expect ads,GNAT Expect TTY g-exptty ads,GNAT Exceptions g-except ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{366}@anchor{gnat_rm/the_gnat_library id77}@anchor{367} +@anchor{gnat_rm/the_gnat_library id78}@anchor{368}@anchor{gnat_rm/the_gnat_library gnat-expect-g-expect-ads}@anchor{369} @section @code{GNAT.Expect} (@code{g-expect.ads}) @@ -24341,7 +24354,7 @@ It is not implemented for cross ports, and in particular is not implemented for VxWorks or LynxOS. @node GNAT Expect TTY g-exptty ads,GNAT Float_Control g-flocon ads,GNAT Expect g-expect ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id78}@anchor{368}@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{369} +@anchor{gnat_rm/the_gnat_library id79}@anchor{36a}@anchor{gnat_rm/the_gnat_library gnat-expect-tty-g-exptty-ads}@anchor{36b} @section @code{GNAT.Expect.TTY} (@code{g-exptty.ads}) @@ -24353,7 +24366,7 @@ ports. It is not implemented for cross ports, and in particular is not implemented for VxWorks or LynxOS. @node GNAT Float_Control g-flocon ads,GNAT Formatted_String g-forstr ads,GNAT Expect TTY g-exptty ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id79}@anchor{36a}@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{36b} +@anchor{gnat_rm/the_gnat_library id80}@anchor{36c}@anchor{gnat_rm/the_gnat_library gnat-float-control-g-flocon-ads}@anchor{36d} @section @code{GNAT.Float_Control} (@code{g-flocon.ads}) @@ -24367,7 +24380,7 @@ library calls may cause this mode to be modified, and the Reset procedure in this package can be used to reestablish the required mode. @node GNAT Formatted_String g-forstr ads,GNAT Heap_Sort g-heasor ads,GNAT Float_Control g-flocon ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id80}@anchor{36c}@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{36d} +@anchor{gnat_rm/the_gnat_library id81}@anchor{36e}@anchor{gnat_rm/the_gnat_library gnat-formatted-string-g-forstr-ads}@anchor{36f} @section @code{GNAT.Formatted_String} (@code{g-forstr.ads}) @@ -24382,7 +24395,7 @@ derived from Integer, Float or enumerations as values for the formatted string. @node GNAT Heap_Sort g-heasor ads,GNAT Heap_Sort_A g-hesora ads,GNAT Formatted_String g-forstr ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{36e}@anchor{gnat_rm/the_gnat_library id81}@anchor{36f} +@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-heasor-ads}@anchor{370}@anchor{gnat_rm/the_gnat_library id82}@anchor{371} @section @code{GNAT.Heap_Sort} (@code{g-heasor.ads}) @@ -24396,7 +24409,7 @@ access-to-procedure values. The algorithm used is a modified heap sort that performs approximately N*log(N) comparisons in the worst case. @node GNAT Heap_Sort_A g-hesora ads,GNAT Heap_Sort_G g-hesorg ads,GNAT Heap_Sort g-heasor ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id82}@anchor{370}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-a-g-hesora-ads}@anchor{371} +@anchor{gnat_rm/the_gnat_library id83}@anchor{372}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-a-g-hesora-ads}@anchor{373} @section @code{GNAT.Heap_Sort_A} (@code{g-hesora.ads}) @@ -24412,7 +24425,7 @@ This differs from @code{GNAT.Heap_Sort} in having a less convenient interface, but may be slightly more efficient. @node GNAT Heap_Sort_G g-hesorg ads,GNAT HTable g-htable ads,GNAT Heap_Sort_A g-hesora ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id83}@anchor{372}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{373} +@anchor{gnat_rm/the_gnat_library id84}@anchor{374}@anchor{gnat_rm/the_gnat_library gnat-heap-sort-g-g-hesorg-ads}@anchor{375} @section @code{GNAT.Heap_Sort_G} (@code{g-hesorg.ads}) @@ -24426,7 +24439,7 @@ if the procedures can be inlined, at the expense of duplicating code for multiple instantiations. @node GNAT HTable g-htable ads,GNAT IO g-io ads,GNAT Heap_Sort_G g-hesorg ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id84}@anchor{374}@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{375} +@anchor{gnat_rm/the_gnat_library id85}@anchor{376}@anchor{gnat_rm/the_gnat_library gnat-htable-g-htable-ads}@anchor{377} @section @code{GNAT.HTable} (@code{g-htable.ads}) @@ -24439,7 +24452,7 @@ data. Provides two approaches, one a simple static approach, and the other allowing arbitrary dynamic hash tables. @node GNAT IO g-io ads,GNAT IO_Aux g-io_aux ads,GNAT HTable g-htable ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id85}@anchor{376}@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{377} +@anchor{gnat_rm/the_gnat_library id86}@anchor{378}@anchor{gnat_rm/the_gnat_library gnat-io-g-io-ads}@anchor{379} @section @code{GNAT.IO} (@code{g-io.ads}) @@ -24455,7 +24468,7 @@ Standard_Input, and writing characters, strings and integers to either Standard_Output or Standard_Error. @node GNAT IO_Aux g-io_aux ads,GNAT Lock_Files g-locfil ads,GNAT IO g-io ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{378}@anchor{gnat_rm/the_gnat_library id86}@anchor{379} +@anchor{gnat_rm/the_gnat_library id87}@anchor{37a}@anchor{gnat_rm/the_gnat_library gnat-io-aux-g-io-aux-ads}@anchor{37b} @section @code{GNAT.IO_Aux} (@code{g-io_aux.ads}) @@ -24469,7 +24482,7 @@ Provides some auxiliary functions for use with Text_IO, including a test for whether a file exists, and functions for reading a line of text. @node GNAT Lock_Files g-locfil ads,GNAT MBBS_Discrete_Random g-mbdira ads,GNAT IO_Aux g-io_aux ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id87}@anchor{37a}@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{37b} +@anchor{gnat_rm/the_gnat_library id88}@anchor{37c}@anchor{gnat_rm/the_gnat_library gnat-lock-files-g-locfil-ads}@anchor{37d} @section @code{GNAT.Lock_Files} (@code{g-locfil.ads}) @@ -24483,7 +24496,7 @@ Provides a general interface for using files as locks. Can be used for providing program level synchronization. @node GNAT MBBS_Discrete_Random g-mbdira ads,GNAT MBBS_Float_Random g-mbflra ads,GNAT Lock_Files g-locfil ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id88}@anchor{37c}@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{37d} +@anchor{gnat_rm/the_gnat_library id89}@anchor{37e}@anchor{gnat_rm/the_gnat_library gnat-mbbs-discrete-random-g-mbdira-ads}@anchor{37f} @section @code{GNAT.MBBS_Discrete_Random} (@code{g-mbdira.ads}) @@ -24495,7 +24508,7 @@ The original implementation of @code{Ada.Numerics.Discrete_Random}. Uses a modified version of the Blum-Blum-Shub generator. @node GNAT MBBS_Float_Random g-mbflra ads,GNAT MD5 g-md5 ads,GNAT MBBS_Discrete_Random g-mbdira ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id89}@anchor{37e}@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{37f} +@anchor{gnat_rm/the_gnat_library id90}@anchor{380}@anchor{gnat_rm/the_gnat_library gnat-mbbs-float-random-g-mbflra-ads}@anchor{381} @section @code{GNAT.MBBS_Float_Random} (@code{g-mbflra.ads}) @@ -24507,7 +24520,7 @@ The original implementation of @code{Ada.Numerics.Float_Random}. Uses a modified version of the Blum-Blum-Shub generator. @node GNAT MD5 g-md5 ads,GNAT Memory_Dump g-memdum ads,GNAT MBBS_Float_Random g-mbflra ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id90}@anchor{380}@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{381} +@anchor{gnat_rm/the_gnat_library id91}@anchor{382}@anchor{gnat_rm/the_gnat_library gnat-md5-g-md5-ads}@anchor{383} @section @code{GNAT.MD5} (@code{g-md5.ads}) @@ -24520,7 +24533,7 @@ the HMAC-MD5 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT Memory_Dump g-memdum ads,GNAT Most_Recent_Exception g-moreex ads,GNAT MD5 g-md5 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id91}@anchor{382}@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{383} +@anchor{gnat_rm/the_gnat_library id92}@anchor{384}@anchor{gnat_rm/the_gnat_library gnat-memory-dump-g-memdum-ads}@anchor{385} @section @code{GNAT.Memory_Dump} (@code{g-memdum.ads}) @@ -24533,7 +24546,7 @@ standard output or standard error files. Uses GNAT.IO for actual output. @node GNAT Most_Recent_Exception g-moreex ads,GNAT OS_Lib g-os_lib ads,GNAT Memory_Dump g-memdum ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id92}@anchor{384}@anchor{gnat_rm/the_gnat_library gnat-most-recent-exception-g-moreex-ads}@anchor{385} +@anchor{gnat_rm/the_gnat_library gnat-most-recent-exception-g-moreex-ads}@anchor{386}@anchor{gnat_rm/the_gnat_library id93}@anchor{387} @section @code{GNAT.Most_Recent_Exception} (@code{g-moreex.ads}) @@ -24547,7 +24560,7 @@ various logging purposes, including duplicating functionality of some Ada 83 implementation dependent extensions. @node GNAT OS_Lib g-os_lib ads,GNAT Perfect_Hash_Generators g-pehage ads,GNAT Most_Recent_Exception g-moreex ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-os-lib-g-os-lib-ads}@anchor{386}@anchor{gnat_rm/the_gnat_library id93}@anchor{387} +@anchor{gnat_rm/the_gnat_library gnat-os-lib-g-os-lib-ads}@anchor{388}@anchor{gnat_rm/the_gnat_library id94}@anchor{389} @section @code{GNAT.OS_Lib} (@code{g-os_lib.ads}) @@ -24563,7 +24576,7 @@ including a portable spawn procedure, and access to environment variables and error return codes. @node GNAT Perfect_Hash_Generators g-pehage ads,GNAT Random_Numbers g-rannum ads,GNAT OS_Lib g-os_lib ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-perfect-hash-generators-g-pehage-ads}@anchor{388}@anchor{gnat_rm/the_gnat_library id94}@anchor{389} +@anchor{gnat_rm/the_gnat_library gnat-perfect-hash-generators-g-pehage-ads}@anchor{38a}@anchor{gnat_rm/the_gnat_library id95}@anchor{38b} @section @code{GNAT.Perfect_Hash_Generators} (@code{g-pehage.ads}) @@ -24581,7 +24594,7 @@ hashcode are in the same order. These hashing functions are very convenient for use with realtime applications. @node GNAT Random_Numbers g-rannum ads,GNAT Regexp g-regexp ads,GNAT Perfect_Hash_Generators g-pehage ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-random-numbers-g-rannum-ads}@anchor{38a}@anchor{gnat_rm/the_gnat_library id95}@anchor{38b} +@anchor{gnat_rm/the_gnat_library gnat-random-numbers-g-rannum-ads}@anchor{38c}@anchor{gnat_rm/the_gnat_library id96}@anchor{38d} @section @code{GNAT.Random_Numbers} (@code{g-rannum.ads}) @@ -24593,7 +24606,7 @@ Provides random number capabilities which extend those available in the standard Ada library and are more convenient to use. @node GNAT Regexp g-regexp ads,GNAT Registry g-regist ads,GNAT Random_Numbers g-rannum ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{255}@anchor{gnat_rm/the_gnat_library id96}@anchor{38c} +@anchor{gnat_rm/the_gnat_library gnat-regexp-g-regexp-ads}@anchor{255}@anchor{gnat_rm/the_gnat_library id97}@anchor{38e} @section @code{GNAT.Regexp} (@code{g-regexp.ads}) @@ -24609,7 +24622,7 @@ simplest of the three pattern matching packages provided, and is particularly suitable for 'file globbing' applications. @node GNAT Registry g-regist ads,GNAT Regpat g-regpat ads,GNAT Regexp g-regexp ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{38d}@anchor{gnat_rm/the_gnat_library id97}@anchor{38e} +@anchor{gnat_rm/the_gnat_library id98}@anchor{38f}@anchor{gnat_rm/the_gnat_library gnat-registry-g-regist-ads}@anchor{390} @section @code{GNAT.Registry} (@code{g-regist.ads}) @@ -24623,7 +24636,7 @@ registry API, but at a lower level of abstraction, refer to the Win32.Winreg package provided with the Win32Ada binding @node GNAT Regpat g-regpat ads,GNAT Rewrite_Data g-rewdat ads,GNAT Registry g-regist ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id98}@anchor{38f}@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{390} +@anchor{gnat_rm/the_gnat_library id99}@anchor{391}@anchor{gnat_rm/the_gnat_library gnat-regpat-g-regpat-ads}@anchor{392} @section @code{GNAT.Regpat} (@code{g-regpat.ads}) @@ -24638,7 +24651,7 @@ from the original V7 style regular expression library written in C by Henry Spencer (and binary compatible with this C library). @node GNAT Rewrite_Data g-rewdat ads,GNAT Secondary_Stack_Info g-sestin ads,GNAT Regpat g-regpat ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id99}@anchor{391}@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{392} +@anchor{gnat_rm/the_gnat_library id100}@anchor{393}@anchor{gnat_rm/the_gnat_library gnat-rewrite-data-g-rewdat-ads}@anchor{394} @section @code{GNAT.Rewrite_Data} (@code{g-rewdat.ads}) @@ -24652,7 +24665,7 @@ full content to be processed is not loaded into memory all at once. This makes this interface usable for large files or socket streams. @node GNAT Secondary_Stack_Info g-sestin ads,GNAT Semaphores g-semaph ads,GNAT Rewrite_Data g-rewdat ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id100}@anchor{393}@anchor{gnat_rm/the_gnat_library gnat-secondary-stack-info-g-sestin-ads}@anchor{394} +@anchor{gnat_rm/the_gnat_library id101}@anchor{395}@anchor{gnat_rm/the_gnat_library gnat-secondary-stack-info-g-sestin-ads}@anchor{396} @section @code{GNAT.Secondary_Stack_Info} (@code{g-sestin.ads}) @@ -24664,7 +24677,7 @@ Provide the capability to query the high water mark of the current task's secondary stack. @node GNAT Semaphores g-semaph ads,GNAT Serial_Communications g-sercom ads,GNAT Secondary_Stack_Info g-sestin ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id101}@anchor{395}@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{396} +@anchor{gnat_rm/the_gnat_library id102}@anchor{397}@anchor{gnat_rm/the_gnat_library gnat-semaphores-g-semaph-ads}@anchor{398} @section @code{GNAT.Semaphores} (@code{g-semaph.ads}) @@ -24675,7 +24688,7 @@ secondary stack. Provides classic counting and binary semaphores using protected types. @node GNAT Serial_Communications g-sercom ads,GNAT SHA1 g-sha1 ads,GNAT Semaphores g-semaph ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-serial-communications-g-sercom-ads}@anchor{397}@anchor{gnat_rm/the_gnat_library id102}@anchor{398} +@anchor{gnat_rm/the_gnat_library gnat-serial-communications-g-sercom-ads}@anchor{399}@anchor{gnat_rm/the_gnat_library id103}@anchor{39a} @section @code{GNAT.Serial_Communications} (@code{g-sercom.ads}) @@ -24687,7 +24700,7 @@ Provides a simple interface to send and receive data over a serial port. This is only supported on GNU/Linux and Windows. @node GNAT SHA1 g-sha1 ads,GNAT SHA224 g-sha224 ads,GNAT Serial_Communications g-sercom ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-sha1-g-sha1-ads}@anchor{399}@anchor{gnat_rm/the_gnat_library id103}@anchor{39a} +@anchor{gnat_rm/the_gnat_library gnat-sha1-g-sha1-ads}@anchor{39b}@anchor{gnat_rm/the_gnat_library id104}@anchor{39c} @section @code{GNAT.SHA1} (@code{g-sha1.ads}) @@ -24700,7 +24713,7 @@ and RFC 3174, and the HMAC-SHA1 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT SHA224 g-sha224 ads,GNAT SHA256 g-sha256 ads,GNAT SHA1 g-sha1 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-sha224-g-sha224-ads}@anchor{39b}@anchor{gnat_rm/the_gnat_library id104}@anchor{39c} +@anchor{gnat_rm/the_gnat_library gnat-sha224-g-sha224-ads}@anchor{39d}@anchor{gnat_rm/the_gnat_library id105}@anchor{39e} @section @code{GNAT.SHA224} (@code{g-sha224.ads}) @@ -24713,7 +24726,7 @@ and the HMAC-SHA224 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT SHA256 g-sha256 ads,GNAT SHA384 g-sha384 ads,GNAT SHA224 g-sha224 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id105}@anchor{39d}@anchor{gnat_rm/the_gnat_library gnat-sha256-g-sha256-ads}@anchor{39e} +@anchor{gnat_rm/the_gnat_library gnat-sha256-g-sha256-ads}@anchor{39f}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a0} @section @code{GNAT.SHA256} (@code{g-sha256.ads}) @@ -24726,7 +24739,7 @@ and the HMAC-SHA256 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT SHA384 g-sha384 ads,GNAT SHA512 g-sha512 ads,GNAT SHA256 g-sha256 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{39f}@anchor{gnat_rm/the_gnat_library id106}@anchor{3a0} +@anchor{gnat_rm/the_gnat_library gnat-sha384-g-sha384-ads}@anchor{3a1}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a2} @section @code{GNAT.SHA384} (@code{g-sha384.ads}) @@ -24739,7 +24752,7 @@ and the HMAC-SHA384 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT SHA512 g-sha512 ads,GNAT Signals g-signal ads,GNAT SHA384 g-sha384 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3a1}@anchor{gnat_rm/the_gnat_library id107}@anchor{3a2} +@anchor{gnat_rm/the_gnat_library id108}@anchor{3a3}@anchor{gnat_rm/the_gnat_library gnat-sha512-g-sha512-ads}@anchor{3a4} @section @code{GNAT.SHA512} (@code{g-sha512.ads}) @@ -24752,7 +24765,7 @@ and the HMAC-SHA512 message authentication function as described in RFC 2104 and FIPS PUB 198. @node GNAT Signals g-signal ads,GNAT Sockets g-socket ads,GNAT SHA512 g-sha512 ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-signals-g-signal-ads}@anchor{3a3}@anchor{gnat_rm/the_gnat_library id108}@anchor{3a4} +@anchor{gnat_rm/the_gnat_library id109}@anchor{3a5}@anchor{gnat_rm/the_gnat_library gnat-signals-g-signal-ads}@anchor{3a6} @section @code{GNAT.Signals} (@code{g-signal.ads}) @@ -24764,7 +24777,7 @@ Provides the ability to manipulate the blocked status of signals on supported targets. @node GNAT Sockets g-socket ads,GNAT Source_Info g-souinf ads,GNAT Signals g-signal ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id109}@anchor{3a5}@anchor{gnat_rm/the_gnat_library gnat-sockets-g-socket-ads}@anchor{3a6} +@anchor{gnat_rm/the_gnat_library gnat-sockets-g-socket-ads}@anchor{3a7}@anchor{gnat_rm/the_gnat_library id110}@anchor{3a8} @section @code{GNAT.Sockets} (@code{g-socket.ads}) @@ -24779,7 +24792,7 @@ on all native GNAT ports and on VxWorks cross prots. It is not implemented for the LynxOS cross port. @node GNAT Source_Info g-souinf ads,GNAT Spelling_Checker g-speche ads,GNAT Sockets g-socket ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-source-info-g-souinf-ads}@anchor{3a7}@anchor{gnat_rm/the_gnat_library id110}@anchor{3a8} +@anchor{gnat_rm/the_gnat_library gnat-source-info-g-souinf-ads}@anchor{3a9}@anchor{gnat_rm/the_gnat_library id111}@anchor{3aa} @section @code{GNAT.Source_Info} (@code{g-souinf.ads}) @@ -24793,7 +24806,7 @@ subprograms yielding the date and time of the current compilation (like the C macros @code{__DATE__} and @code{__TIME__}) @node GNAT Spelling_Checker g-speche ads,GNAT Spelling_Checker_Generic g-spchge ads,GNAT Source_Info g-souinf ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-g-speche-ads}@anchor{3a9}@anchor{gnat_rm/the_gnat_library id111}@anchor{3aa} +@anchor{gnat_rm/the_gnat_library id112}@anchor{3ab}@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-g-speche-ads}@anchor{3ac} @section @code{GNAT.Spelling_Checker} (@code{g-speche.ads}) @@ -24805,7 +24818,7 @@ Provides a function for determining whether one string is a plausible near misspelling of another string. @node GNAT Spelling_Checker_Generic g-spchge ads,GNAT Spitbol Patterns g-spipat ads,GNAT Spelling_Checker g-speche ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id112}@anchor{3ab}@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-generic-g-spchge-ads}@anchor{3ac} +@anchor{gnat_rm/the_gnat_library gnat-spelling-checker-generic-g-spchge-ads}@anchor{3ad}@anchor{gnat_rm/the_gnat_library id113}@anchor{3ae} @section @code{GNAT.Spelling_Checker_Generic} (@code{g-spchge.ads}) @@ -24818,7 +24831,7 @@ determining whether one string is a plausible near misspelling of another string. @node GNAT Spitbol Patterns g-spipat ads,GNAT Spitbol g-spitbo ads,GNAT Spelling_Checker_Generic g-spchge ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id113}@anchor{3ad}@anchor{gnat_rm/the_gnat_library gnat-spitbol-patterns-g-spipat-ads}@anchor{3ae} +@anchor{gnat_rm/the_gnat_library gnat-spitbol-patterns-g-spipat-ads}@anchor{3af}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b0} @section @code{GNAT.Spitbol.Patterns} (@code{g-spipat.ads}) @@ -24834,7 +24847,7 @@ the SNOBOL4 dynamic pattern construction and matching capabilities, using the efficient algorithm developed by Robert Dewar for the SPITBOL system. @node GNAT Spitbol g-spitbo ads,GNAT Spitbol Table_Boolean g-sptabo ads,GNAT Spitbol Patterns g-spipat ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3af}@anchor{gnat_rm/the_gnat_library id114}@anchor{3b0} +@anchor{gnat_rm/the_gnat_library gnat-spitbol-g-spitbo-ads}@anchor{3b1}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b2} @section @code{GNAT.Spitbol} (@code{g-spitbo.ads}) @@ -24849,7 +24862,7 @@ useful for constructing arbitrary mappings from strings in the style of the SNOBOL4 TABLE function. @node GNAT Spitbol Table_Boolean g-sptabo ads,GNAT Spitbol Table_Integer g-sptain ads,GNAT Spitbol g-spitbo ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-boolean-g-sptabo-ads}@anchor{3b1}@anchor{gnat_rm/the_gnat_library id115}@anchor{3b2} +@anchor{gnat_rm/the_gnat_library id116}@anchor{3b3}@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-boolean-g-sptabo-ads}@anchor{3b4} @section @code{GNAT.Spitbol.Table_Boolean} (@code{g-sptabo.ads}) @@ -24864,7 +24877,7 @@ for type @code{Standard.Boolean}, giving an implementation of sets of string values. @node GNAT Spitbol Table_Integer g-sptain ads,GNAT Spitbol Table_VString g-sptavs ads,GNAT Spitbol Table_Boolean g-sptabo ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-integer-g-sptain-ads}@anchor{3b3}@anchor{gnat_rm/the_gnat_library id116}@anchor{3b4} +@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-integer-g-sptain-ads}@anchor{3b5}@anchor{gnat_rm/the_gnat_library id117}@anchor{3b6} @section @code{GNAT.Spitbol.Table_Integer} (@code{g-sptain.ads}) @@ -24881,7 +24894,7 @@ for type @code{Standard.Integer}, giving an implementation of maps from string to integer values. @node GNAT Spitbol Table_VString g-sptavs ads,GNAT SSE g-sse ads,GNAT Spitbol Table_Integer g-sptain ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id117}@anchor{3b5}@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3b6} +@anchor{gnat_rm/the_gnat_library id118}@anchor{3b7}@anchor{gnat_rm/the_gnat_library gnat-spitbol-table-vstring-g-sptavs-ads}@anchor{3b8} @section @code{GNAT.Spitbol.Table_VString} (@code{g-sptavs.ads}) @@ -24898,7 +24911,7 @@ a variable length string type, giving an implementation of general maps from strings to strings. @node GNAT SSE g-sse ads,GNAT SSE Vector_Types g-ssvety ads,GNAT Spitbol Table_VString g-sptavs ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id118}@anchor{3b7}@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3b8} +@anchor{gnat_rm/the_gnat_library id119}@anchor{3b9}@anchor{gnat_rm/the_gnat_library gnat-sse-g-sse-ads}@anchor{3ba} @section @code{GNAT.SSE} (@code{g-sse.ads}) @@ -24910,7 +24923,7 @@ targets. It exposes vector component types together with a general introduction to the binding contents and use. @node GNAT SSE Vector_Types g-ssvety ads,GNAT String_Hash g-strhas ads,GNAT SSE g-sse ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-sse-vector-types-g-ssvety-ads}@anchor{3b9}@anchor{gnat_rm/the_gnat_library id119}@anchor{3ba} +@anchor{gnat_rm/the_gnat_library gnat-sse-vector-types-g-ssvety-ads}@anchor{3bb}@anchor{gnat_rm/the_gnat_library id120}@anchor{3bc} @section @code{GNAT.SSE.Vector_Types} (@code{g-ssvety.ads}) @@ -24919,7 +24932,7 @@ introduction to the binding contents and use. SSE vector types for use with SSE related intrinsics. @node GNAT String_Hash g-strhas ads,GNAT Strings g-string ads,GNAT SSE Vector_Types g-ssvety ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-string-hash-g-strhas-ads}@anchor{3bb}@anchor{gnat_rm/the_gnat_library id120}@anchor{3bc} +@anchor{gnat_rm/the_gnat_library gnat-string-hash-g-strhas-ads}@anchor{3bd}@anchor{gnat_rm/the_gnat_library id121}@anchor{3be} @section @code{GNAT.String_Hash} (@code{g-strhas.ads}) @@ -24931,7 +24944,7 @@ Provides a generic hash function working on arrays of scalars. Both the scalar type and the hash result type are parameters. @node GNAT Strings g-string ads,GNAT String_Split g-strspl ads,GNAT String_Hash g-strhas ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3bd}@anchor{gnat_rm/the_gnat_library id121}@anchor{3be} +@anchor{gnat_rm/the_gnat_library gnat-strings-g-string-ads}@anchor{3bf}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c0} @section @code{GNAT.Strings} (@code{g-string.ads}) @@ -24941,7 +24954,7 @@ Common String access types and related subprograms. Basically it defines a string access and an array of string access types. @node GNAT String_Split g-strspl ads,GNAT Table g-table ads,GNAT Strings g-string ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-string-split-g-strspl-ads}@anchor{3bf}@anchor{gnat_rm/the_gnat_library id122}@anchor{3c0} +@anchor{gnat_rm/the_gnat_library gnat-string-split-g-strspl-ads}@anchor{3c1}@anchor{gnat_rm/the_gnat_library id123}@anchor{3c2} @section @code{GNAT.String_Split} (@code{g-strspl.ads}) @@ -24955,7 +24968,7 @@ to the resulting slices. This package is instantiated from @code{GNAT.Array_Split}. @node GNAT Table g-table ads,GNAT Task_Lock g-tasloc ads,GNAT String_Split g-strspl ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3c1}@anchor{gnat_rm/the_gnat_library id123}@anchor{3c2} +@anchor{gnat_rm/the_gnat_library id124}@anchor{3c3}@anchor{gnat_rm/the_gnat_library gnat-table-g-table-ads}@anchor{3c4} @section @code{GNAT.Table} (@code{g-table.ads}) @@ -24975,7 +24988,7 @@ while an instantiation of @code{GNAT.Dynamic_Tables} creates a type that can be used to define dynamic instances of the table. @node GNAT Task_Lock g-tasloc ads,GNAT Time_Stamp g-timsta ads,GNAT Table g-table ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id124}@anchor{3c3}@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3c4} +@anchor{gnat_rm/the_gnat_library id125}@anchor{3c5}@anchor{gnat_rm/the_gnat_library gnat-task-lock-g-tasloc-ads}@anchor{3c6} @section @code{GNAT.Task_Lock} (@code{g-tasloc.ads}) @@ -24992,7 +25005,7 @@ single global task lock. Appropriate for use in situations where contention between tasks is very rarely expected. @node GNAT Time_Stamp g-timsta ads,GNAT Threads g-thread ads,GNAT Task_Lock g-tasloc ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id125}@anchor{3c5}@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3c6} +@anchor{gnat_rm/the_gnat_library id126}@anchor{3c7}@anchor{gnat_rm/the_gnat_library gnat-time-stamp-g-timsta-ads}@anchor{3c8} @section @code{GNAT.Time_Stamp} (@code{g-timsta.ads}) @@ -25007,7 +25020,7 @@ represents the current date and time in ISO 8601 format. This is a very simple routine with minimal code and there are no dependencies on any other unit. @node GNAT Threads g-thread ads,GNAT Traceback g-traceb ads,GNAT Time_Stamp g-timsta ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-threads-g-thread-ads}@anchor{3c7}@anchor{gnat_rm/the_gnat_library id126}@anchor{3c8} +@anchor{gnat_rm/the_gnat_library id127}@anchor{3c9}@anchor{gnat_rm/the_gnat_library gnat-threads-g-thread-ads}@anchor{3ca} @section @code{GNAT.Threads} (@code{g-thread.ads}) @@ -25024,7 +25037,7 @@ further details if your program has threads that are created by a non-Ada environment which then accesses Ada code. @node GNAT Traceback g-traceb ads,GNAT Traceback Symbolic g-trasym ads,GNAT Threads g-thread ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id127}@anchor{3c9}@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3ca} +@anchor{gnat_rm/the_gnat_library id128}@anchor{3cb}@anchor{gnat_rm/the_gnat_library gnat-traceback-g-traceb-ads}@anchor{3cc} @section @code{GNAT.Traceback} (@code{g-traceb.ads}) @@ -25036,7 +25049,7 @@ Provides a facility for obtaining non-symbolic traceback information, useful in various debugging situations. @node GNAT Traceback Symbolic g-trasym ads,GNAT UTF_32 g-table ads,GNAT Traceback g-traceb ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3cb}@anchor{gnat_rm/the_gnat_library id128}@anchor{3cc} +@anchor{gnat_rm/the_gnat_library gnat-traceback-symbolic-g-trasym-ads}@anchor{3cd}@anchor{gnat_rm/the_gnat_library id129}@anchor{3ce} @section @code{GNAT.Traceback.Symbolic} (@code{g-trasym.ads}) @@ -25045,7 +25058,7 @@ in various debugging situations. @geindex Trace back facilities @node GNAT UTF_32 g-table ads,GNAT Wide_Spelling_Checker g-u3spch ads,GNAT Traceback Symbolic g-trasym ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id129}@anchor{3cd}@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3ce} +@anchor{gnat_rm/the_gnat_library id130}@anchor{3cf}@anchor{gnat_rm/the_gnat_library gnat-utf-32-g-table-ads}@anchor{3d0} @section @code{GNAT.UTF_32} (@code{g-table.ads}) @@ -25064,7 +25077,7 @@ lower case to upper case fold routine corresponding to the Ada 2005 rules for identifier equivalence. @node GNAT Wide_Spelling_Checker g-u3spch ads,GNAT Wide_Spelling_Checker g-wispch ads,GNAT UTF_32 g-table ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-u3spch-ads}@anchor{3cf}@anchor{gnat_rm/the_gnat_library id130}@anchor{3d0} +@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-u3spch-ads}@anchor{3d1}@anchor{gnat_rm/the_gnat_library id131}@anchor{3d2} @section @code{GNAT.Wide_Spelling_Checker} (@code{g-u3spch.ads}) @@ -25077,7 +25090,7 @@ near misspelling of another wide wide string, where the strings are represented using the UTF_32_String type defined in System.Wch_Cnv. @node GNAT Wide_Spelling_Checker g-wispch ads,GNAT Wide_String_Split g-wistsp ads,GNAT Wide_Spelling_Checker g-u3spch ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-wispch-ads}@anchor{3d1}@anchor{gnat_rm/the_gnat_library id131}@anchor{3d2} +@anchor{gnat_rm/the_gnat_library gnat-wide-spelling-checker-g-wispch-ads}@anchor{3d3}@anchor{gnat_rm/the_gnat_library id132}@anchor{3d4} @section @code{GNAT.Wide_Spelling_Checker} (@code{g-wispch.ads}) @@ -25089,7 +25102,7 @@ Provides a function for determining whether one wide string is a plausible near misspelling of another wide string. @node GNAT Wide_String_Split g-wistsp ads,GNAT Wide_Wide_Spelling_Checker g-zspche ads,GNAT Wide_Spelling_Checker g-wispch ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id132}@anchor{3d3}@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3d4} +@anchor{gnat_rm/the_gnat_library id133}@anchor{3d5}@anchor{gnat_rm/the_gnat_library gnat-wide-string-split-g-wistsp-ads}@anchor{3d6} @section @code{GNAT.Wide_String_Split} (@code{g-wistsp.ads}) @@ -25103,7 +25116,7 @@ to the resulting slices. This package is instantiated from @code{GNAT.Array_Split}. @node GNAT Wide_Wide_Spelling_Checker g-zspche ads,GNAT Wide_Wide_String_Split g-zistsp ads,GNAT Wide_String_Split g-wistsp ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-wide-wide-spelling-checker-g-zspche-ads}@anchor{3d5}@anchor{gnat_rm/the_gnat_library id133}@anchor{3d6} +@anchor{gnat_rm/the_gnat_library gnat-wide-wide-spelling-checker-g-zspche-ads}@anchor{3d7}@anchor{gnat_rm/the_gnat_library id134}@anchor{3d8} @section @code{GNAT.Wide_Wide_Spelling_Checker} (@code{g-zspche.ads}) @@ -25115,7 +25128,7 @@ Provides a function for determining whether one wide wide string is a plausible near misspelling of another wide wide string. @node GNAT Wide_Wide_String_Split g-zistsp ads,Interfaces C Extensions i-cexten ads,GNAT Wide_Wide_Spelling_Checker g-zspche ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library gnat-wide-wide-string-split-g-zistsp-ads}@anchor{3d7}@anchor{gnat_rm/the_gnat_library id134}@anchor{3d8} +@anchor{gnat_rm/the_gnat_library gnat-wide-wide-string-split-g-zistsp-ads}@anchor{3d9}@anchor{gnat_rm/the_gnat_library id135}@anchor{3da} @section @code{GNAT.Wide_Wide_String_Split} (@code{g-zistsp.ads}) @@ -25129,7 +25142,7 @@ to the resulting slices. This package is instantiated from @code{GNAT.Array_Split}. @node Interfaces C Extensions i-cexten ads,Interfaces C Streams i-cstrea ads,GNAT Wide_Wide_String_Split g-zistsp ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3d9}@anchor{gnat_rm/the_gnat_library id135}@anchor{3da} +@anchor{gnat_rm/the_gnat_library interfaces-c-extensions-i-cexten-ads}@anchor{3db}@anchor{gnat_rm/the_gnat_library id136}@anchor{3dc} @section @code{Interfaces.C.Extensions} (@code{i-cexten.ads}) @@ -25140,7 +25153,7 @@ for use with either manually or automatically generated bindings to C libraries. @node Interfaces C Streams i-cstrea ads,Interfaces Packed_Decimal i-pacdec ads,Interfaces C Extensions i-cexten ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3db}@anchor{gnat_rm/the_gnat_library id136}@anchor{3dc} +@anchor{gnat_rm/the_gnat_library interfaces-c-streams-i-cstrea-ads}@anchor{3dd}@anchor{gnat_rm/the_gnat_library id137}@anchor{3de} @section @code{Interfaces.C.Streams} (@code{i-cstrea.ads}) @@ -25153,7 +25166,7 @@ This package is a binding for the most commonly used operations on C streams. @node Interfaces Packed_Decimal i-pacdec ads,Interfaces VxWorks i-vxwork ads,Interfaces C Streams i-cstrea ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3dd}@anchor{gnat_rm/the_gnat_library id137}@anchor{3de} +@anchor{gnat_rm/the_gnat_library id138}@anchor{3df}@anchor{gnat_rm/the_gnat_library interfaces-packed-decimal-i-pacdec-ads}@anchor{3e0} @section @code{Interfaces.Packed_Decimal} (@code{i-pacdec.ads}) @@ -25168,7 +25181,7 @@ from a packed decimal format compatible with that used on IBM mainframes. @node Interfaces VxWorks i-vxwork ads,Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces Packed_Decimal i-pacdec ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id138}@anchor{3df}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e0} +@anchor{gnat_rm/the_gnat_library id139}@anchor{3e1}@anchor{gnat_rm/the_gnat_library interfaces-vxworks-i-vxwork-ads}@anchor{3e2} @section @code{Interfaces.VxWorks} (@code{i-vxwork.ads}) @@ -25184,7 +25197,7 @@ In particular, it interfaces with the VxWorks hardware interrupt facilities. @node Interfaces VxWorks Int_Connection i-vxinco ads,Interfaces VxWorks IO i-vxwoio ads,Interfaces VxWorks i-vxwork ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3e1}@anchor{gnat_rm/the_gnat_library id139}@anchor{3e2} +@anchor{gnat_rm/the_gnat_library interfaces-vxworks-int-connection-i-vxinco-ads}@anchor{3e3}@anchor{gnat_rm/the_gnat_library id140}@anchor{3e4} @section @code{Interfaces.VxWorks.Int_Connection} (@code{i-vxinco.ads}) @@ -25200,7 +25213,7 @@ intConnect() with a custom routine for installing interrupt handlers. @node Interfaces VxWorks IO i-vxwoio ads,System Address_Image s-addima ads,Interfaces VxWorks Int_Connection i-vxinco ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3e3}@anchor{gnat_rm/the_gnat_library id140}@anchor{3e4} +@anchor{gnat_rm/the_gnat_library interfaces-vxworks-io-i-vxwoio-ads}@anchor{3e5}@anchor{gnat_rm/the_gnat_library id141}@anchor{3e6} @section @code{Interfaces.VxWorks.IO} (@code{i-vxwoio.ads}) @@ -25223,7 +25236,7 @@ function codes. A particular use of this package is to enable the use of Get_Immediate under VxWorks. @node System Address_Image s-addima ads,System Assertions s-assert ads,Interfaces VxWorks IO i-vxwoio ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id141}@anchor{3e5}@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3e6} +@anchor{gnat_rm/the_gnat_library system-address-image-s-addima-ads}@anchor{3e7}@anchor{gnat_rm/the_gnat_library id142}@anchor{3e8} @section @code{System.Address_Image} (@code{s-addima.ads}) @@ -25239,7 +25252,7 @@ function that gives an (implementation dependent) string which identifies an address. @node System Assertions s-assert ads,System Atomic_Counters s-atocou ads,System Address_Image s-addima ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3e7}@anchor{gnat_rm/the_gnat_library id142}@anchor{3e8} +@anchor{gnat_rm/the_gnat_library system-assertions-s-assert-ads}@anchor{3e9}@anchor{gnat_rm/the_gnat_library id143}@anchor{3ea} @section @code{System.Assertions} (@code{s-assert.ads}) @@ -25255,7 +25268,7 @@ by an run-time assertion failure, as well as the routine that is used internally to raise this assertion. @node System Atomic_Counters s-atocou ads,System Memory s-memory ads,System Assertions s-assert ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id143}@anchor{3e9}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3ea} +@anchor{gnat_rm/the_gnat_library id144}@anchor{3eb}@anchor{gnat_rm/the_gnat_library system-atomic-counters-s-atocou-ads}@anchor{3ec} @section @code{System.Atomic_Counters} (@code{s-atocou.ads}) @@ -25269,7 +25282,7 @@ on most targets, including all Alpha, ia64, PowerPC, SPARC V9, x86, and x86_64 platforms. @node System Memory s-memory ads,System Multiprocessors s-multip ads,System Atomic_Counters s-atocou ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3eb}@anchor{gnat_rm/the_gnat_library id144}@anchor{3ec} +@anchor{gnat_rm/the_gnat_library system-memory-s-memory-ads}@anchor{3ed}@anchor{gnat_rm/the_gnat_library id145}@anchor{3ee} @section @code{System.Memory} (@code{s-memory.ads}) @@ -25287,7 +25300,7 @@ calls to this unit may be made for low level allocation uses (for example see the body of @code{GNAT.Tables}). @node System Multiprocessors s-multip ads,System Multiprocessors Dispatching_Domains s-mudido ads,System Memory s-memory ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id145}@anchor{3ed}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3ee} +@anchor{gnat_rm/the_gnat_library id146}@anchor{3ef}@anchor{gnat_rm/the_gnat_library system-multiprocessors-s-multip-ads}@anchor{3f0} @section @code{System.Multiprocessors} (@code{s-multip.ads}) @@ -25300,7 +25313,7 @@ in GNAT we also make it available in Ada 95 and Ada 2005 (where it is technically an implementation-defined addition). @node System Multiprocessors Dispatching_Domains s-mudido ads,System Partition_Interface s-parint ads,System Multiprocessors s-multip ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3ef}@anchor{gnat_rm/the_gnat_library id146}@anchor{3f0} +@anchor{gnat_rm/the_gnat_library system-multiprocessors-dispatching-domains-s-mudido-ads}@anchor{3f1}@anchor{gnat_rm/the_gnat_library id147}@anchor{3f2} @section @code{System.Multiprocessors.Dispatching_Domains} (@code{s-mudido.ads}) @@ -25313,7 +25326,7 @@ in GNAT we also make it available in Ada 95 and Ada 2005 (where it is technically an implementation-defined addition). @node System Partition_Interface s-parint ads,System Pool_Global s-pooglo ads,System Multiprocessors Dispatching_Domains s-mudido ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id147}@anchor{3f1}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3f2} +@anchor{gnat_rm/the_gnat_library id148}@anchor{3f3}@anchor{gnat_rm/the_gnat_library system-partition-interface-s-parint-ads}@anchor{3f4} @section @code{System.Partition_Interface} (@code{s-parint.ads}) @@ -25326,7 +25339,7 @@ is used primarily in a distribution context when using Annex E with @code{GLADE}. @node System Pool_Global s-pooglo ads,System Pool_Local s-pooloc ads,System Partition_Interface s-parint ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id148}@anchor{3f3}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3f4} +@anchor{gnat_rm/the_gnat_library id149}@anchor{3f5}@anchor{gnat_rm/the_gnat_library system-pool-global-s-pooglo-ads}@anchor{3f6} @section @code{System.Pool_Global} (@code{s-pooglo.ads}) @@ -25343,7 +25356,7 @@ declared. It uses malloc/free to allocate/free and does not attempt to do any automatic reclamation. @node System Pool_Local s-pooloc ads,System Restrictions s-restri ads,System Pool_Global s-pooglo ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3f5}@anchor{gnat_rm/the_gnat_library id149}@anchor{3f6} +@anchor{gnat_rm/the_gnat_library system-pool-local-s-pooloc-ads}@anchor{3f7}@anchor{gnat_rm/the_gnat_library id150}@anchor{3f8} @section @code{System.Pool_Local} (@code{s-pooloc.ads}) @@ -25360,7 +25373,7 @@ a list of allocated blocks, so that all storage allocated for the pool can be freed automatically when the pool is finalized. @node System Restrictions s-restri ads,System Rident s-rident ads,System Pool_Local s-pooloc ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id150}@anchor{3f7}@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{3f8} +@anchor{gnat_rm/the_gnat_library system-restrictions-s-restri-ads}@anchor{3f9}@anchor{gnat_rm/the_gnat_library id151}@anchor{3fa} @section @code{System.Restrictions} (@code{s-restri.ads}) @@ -25376,7 +25389,7 @@ compiler determined information on which restrictions are violated by one or more packages in the partition. @node System Rident s-rident ads,System Strings Stream_Ops s-ststop ads,System Restrictions s-restri ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{3f9}@anchor{gnat_rm/the_gnat_library id151}@anchor{3fa} +@anchor{gnat_rm/the_gnat_library system-rident-s-rident-ads}@anchor{3fb}@anchor{gnat_rm/the_gnat_library id152}@anchor{3fc} @section @code{System.Rident} (@code{s-rident.ads}) @@ -25392,7 +25405,7 @@ since the necessary instantiation is included in package System.Restrictions. @node System Strings Stream_Ops s-ststop ads,System Unsigned_Types s-unstyp ads,System Rident s-rident ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library id152}@anchor{3fb}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{3fc} +@anchor{gnat_rm/the_gnat_library id153}@anchor{3fd}@anchor{gnat_rm/the_gnat_library system-strings-stream-ops-s-ststop-ads}@anchor{3fe} @section @code{System.Strings.Stream_Ops} (@code{s-ststop.ads}) @@ -25408,7 +25421,7 @@ stream attributes are applied to string types, but the subprograms in this package can be used directly by application programs. @node System Unsigned_Types s-unstyp ads,System Wch_Cnv s-wchcnv ads,System Strings Stream_Ops s-ststop ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{3fd}@anchor{gnat_rm/the_gnat_library id153}@anchor{3fe} +@anchor{gnat_rm/the_gnat_library system-unsigned-types-s-unstyp-ads}@anchor{3ff}@anchor{gnat_rm/the_gnat_library id154}@anchor{400} @section @code{System.Unsigned_Types} (@code{s-unstyp.ads}) @@ -25421,7 +25434,7 @@ also contains some related definitions for other specialized types used by the compiler in connection with packed array types. @node System Wch_Cnv s-wchcnv ads,System Wch_Con s-wchcon ads,System Unsigned_Types s-unstyp ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{3ff}@anchor{gnat_rm/the_gnat_library id154}@anchor{400} +@anchor{gnat_rm/the_gnat_library system-wch-cnv-s-wchcnv-ads}@anchor{401}@anchor{gnat_rm/the_gnat_library id155}@anchor{402} @section @code{System.Wch_Cnv} (@code{s-wchcnv.ads}) @@ -25442,7 +25455,7 @@ encoding method. It uses definitions in package @code{System.Wch_Con}. @node System Wch_Con s-wchcon ads,,System Wch_Cnv s-wchcnv ads,The GNAT Library -@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{401}@anchor{gnat_rm/the_gnat_library id155}@anchor{402} +@anchor{gnat_rm/the_gnat_library id156}@anchor{403}@anchor{gnat_rm/the_gnat_library system-wch-con-s-wchcon-ads}@anchor{404} @section @code{System.Wch_Con} (@code{s-wchcon.ads}) @@ -25454,7 +25467,7 @@ in ordinary strings. These definitions are used by the package @code{System.Wch_Cnv}. @node Interfacing to Other Languages,Specialized Needs Annexes,The GNAT Library,Top -@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{403}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{404} +@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-other-languages}@anchor{11}@anchor{gnat_rm/interfacing_to_other_languages doc}@anchor{405}@anchor{gnat_rm/interfacing_to_other_languages id1}@anchor{406} @chapter Interfacing to Other Languages @@ -25472,7 +25485,7 @@ provided. @end menu @node Interfacing to C,Interfacing to C++,,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{405}@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{406} +@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-c}@anchor{407}@anchor{gnat_rm/interfacing_to_other_languages id2}@anchor{408} @section Interfacing to C @@ -25612,7 +25625,7 @@ of the length corresponding to the @code{type'Size} value in Ada. @end itemize @node Interfacing to C++,Interfacing to COBOL,Interfacing to C,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{407}@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{49} +@anchor{gnat_rm/interfacing_to_other_languages id4}@anchor{409}@anchor{gnat_rm/interfacing_to_other_languages id3}@anchor{49} @section Interfacing to C++ @@ -25669,7 +25682,7 @@ The @code{External_Name} is the name of the C++ RTTI symbol. You can then cover a specific C++ exception in an exception handler. @node Interfacing to COBOL,Interfacing to Fortran,Interfacing to C++,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages id5}@anchor{408}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{409} +@anchor{gnat_rm/interfacing_to_other_languages id5}@anchor{40a}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-cobol}@anchor{40b} @section Interfacing to COBOL @@ -25677,7 +25690,7 @@ Interfacing to COBOL is achieved as described in section B.4 of the Ada Reference Manual. @node Interfacing to Fortran,Interfacing to non-GNAT Ada code,Interfacing to COBOL,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages id6}@anchor{40a}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{40b} +@anchor{gnat_rm/interfacing_to_other_languages id6}@anchor{40c}@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-fortran}@anchor{40d} @section Interfacing to Fortran @@ -25687,7 +25700,7 @@ multi-dimensional array causes the array to be stored in column-major order as required for convenient interface to Fortran. @node Interfacing to non-GNAT Ada code,,Interfacing to Fortran,Interfacing to Other Languages -@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{40c}@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{40d} +@anchor{gnat_rm/interfacing_to_other_languages interfacing-to-non-gnat-ada-code}@anchor{40e}@anchor{gnat_rm/interfacing_to_other_languages id7}@anchor{40f} @section Interfacing to non-GNAT Ada code @@ -25711,7 +25724,7 @@ values or simple record types without variants, or simple array types with fixed bounds. @node Specialized Needs Annexes,Implementation of Specific Ada Features,Interfacing to Other Languages,Top -@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{40e}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{40f} +@anchor{gnat_rm/specialized_needs_annexes specialized-needs-annexes}@anchor{12}@anchor{gnat_rm/specialized_needs_annexes doc}@anchor{410}@anchor{gnat_rm/specialized_needs_annexes id1}@anchor{411} @chapter Specialized Needs Annexes @@ -25752,7 +25765,7 @@ in Ada 2005) is fully implemented. @end table @node Implementation of Specific Ada Features,Implementation of Ada 2012 Features,Specialized Needs Annexes,Top -@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{410}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{411} +@anchor{gnat_rm/implementation_of_specific_ada_features implementation-of-specific-ada-features}@anchor{13}@anchor{gnat_rm/implementation_of_specific_ada_features doc}@anchor{412}@anchor{gnat_rm/implementation_of_specific_ada_features id1}@anchor{413} @chapter Implementation of Specific Ada Features @@ -25770,7 +25783,7 @@ facilities. @end menu @node Machine Code Insertions,GNAT Implementation of Tasking,,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{168}@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{412} +@anchor{gnat_rm/implementation_of_specific_ada_features machine-code-insertions}@anchor{168}@anchor{gnat_rm/implementation_of_specific_ada_features id2}@anchor{414} @section Machine Code Insertions @@ -25938,7 +25951,7 @@ according to normal visibility rules. In particular if there is no qualification is required. @node GNAT Implementation of Tasking,GNAT Implementation of Shared Passive Packages,Machine Code Insertions,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{413}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{414} +@anchor{gnat_rm/implementation_of_specific_ada_features id3}@anchor{415}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-tasking}@anchor{416} @section GNAT Implementation of Tasking @@ -25954,7 +25967,7 @@ to compliance with the Real-Time Systems Annex. @end menu @node Mapping Ada Tasks onto the Underlying Kernel Threads,Ensuring Compliance with the Real-Time Annex,,GNAT Implementation of Tasking -@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{415}@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{416} +@anchor{gnat_rm/implementation_of_specific_ada_features mapping-ada-tasks-onto-the-underlying-kernel-threads}@anchor{417}@anchor{gnat_rm/implementation_of_specific_ada_features id4}@anchor{418} @subsection Mapping Ada Tasks onto the Underlying Kernel Threads @@ -26023,7 +26036,7 @@ support this functionality when the parent contains more than one task. @geindex Forking a new process @node Ensuring Compliance with the Real-Time Annex,Support for Locking Policies,Mapping Ada Tasks onto the Underlying Kernel Threads,GNAT Implementation of Tasking -@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{417}@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{418} +@anchor{gnat_rm/implementation_of_specific_ada_features id5}@anchor{419}@anchor{gnat_rm/implementation_of_specific_ada_features ensuring-compliance-with-the-real-time-annex}@anchor{41a} @subsection Ensuring Compliance with the Real-Time Annex @@ -26074,7 +26087,7 @@ placed at the end. @c Support_for_Locking_Policies @node Support for Locking Policies,,Ensuring Compliance with the Real-Time Annex,GNAT Implementation of Tasking -@anchor{gnat_rm/implementation_of_specific_ada_features support-for-locking-policies}@anchor{419} +@anchor{gnat_rm/implementation_of_specific_ada_features support-for-locking-policies}@anchor{41b} @subsection Support for Locking Policies @@ -26108,7 +26121,7 @@ then ceiling locking is used. Otherwise, the @code{Ceiling_Locking} policy is ignored. @node GNAT Implementation of Shared Passive Packages,Code Generation for Array Aggregates,GNAT Implementation of Tasking,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{41a}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{41b} +@anchor{gnat_rm/implementation_of_specific_ada_features id6}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features gnat-implementation-of-shared-passive-packages}@anchor{41d} @section GNAT Implementation of Shared Passive Packages @@ -26209,7 +26222,7 @@ GNAT supports shared passive packages on all platforms except for OpenVMS. @node Code Generation for Array Aggregates,The Size of Discriminated Records with Default Discriminants,GNAT Implementation of Shared Passive Packages,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features code-generation-for-array-aggregates}@anchor{41c}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{41d} +@anchor{gnat_rm/implementation_of_specific_ada_features code-generation-for-array-aggregates}@anchor{41e}@anchor{gnat_rm/implementation_of_specific_ada_features id7}@anchor{41f} @section Code Generation for Array Aggregates @@ -26240,7 +26253,7 @@ component values and static subtypes also lead to simpler code. @end menu @node Static constant aggregates with static bounds,Constant aggregates with unconstrained nominal types,,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{41e}@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{41f} +@anchor{gnat_rm/implementation_of_specific_ada_features static-constant-aggregates-with-static-bounds}@anchor{420}@anchor{gnat_rm/implementation_of_specific_ada_features id8}@anchor{421} @subsection Static constant aggregates with static bounds @@ -26287,7 +26300,7 @@ Zero2: constant two_dim := (others => (others => 0)); @end example @node Constant aggregates with unconstrained nominal types,Aggregates with static bounds,Static constant aggregates with static bounds,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features constant-aggregates-with-unconstrained-nominal-types}@anchor{420}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{421} +@anchor{gnat_rm/implementation_of_specific_ada_features constant-aggregates-with-unconstrained-nominal-types}@anchor{422}@anchor{gnat_rm/implementation_of_specific_ada_features id9}@anchor{423} @subsection Constant aggregates with unconstrained nominal types @@ -26302,7 +26315,7 @@ Cr_Unc : constant One_Unc := (12,24,36); @end example @node Aggregates with static bounds,Aggregates with nonstatic bounds,Constant aggregates with unconstrained nominal types,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{422}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{423} +@anchor{gnat_rm/implementation_of_specific_ada_features id10}@anchor{424}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-static-bounds}@anchor{425} @subsection Aggregates with static bounds @@ -26330,7 +26343,7 @@ end loop; @end example @node Aggregates with nonstatic bounds,Aggregates in assignment statements,Aggregates with static bounds,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{424}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{425} +@anchor{gnat_rm/implementation_of_specific_ada_features id11}@anchor{426}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-with-nonstatic-bounds}@anchor{427} @subsection Aggregates with nonstatic bounds @@ -26341,7 +26354,7 @@ have to be applied to sub-arrays individually, if they do not have statically compatible subtypes. @node Aggregates in assignment statements,,Aggregates with nonstatic bounds,Code Generation for Array Aggregates -@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{426}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{427} +@anchor{gnat_rm/implementation_of_specific_ada_features id12}@anchor{428}@anchor{gnat_rm/implementation_of_specific_ada_features aggregates-in-assignment-statements}@anchor{429} @subsection Aggregates in assignment statements @@ -26383,7 +26396,7 @@ a temporary (created either by the front-end or the code generator) and then that temporary will be copied onto the target. @node The Size of Discriminated Records with Default Discriminants,Strict Conformance to the Ada Reference Manual,Code Generation for Array Aggregates,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{428}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{429} +@anchor{gnat_rm/implementation_of_specific_ada_features id13}@anchor{42a}@anchor{gnat_rm/implementation_of_specific_ada_features the-size-of-discriminated-records-with-default-discriminants}@anchor{42b} @section The Size of Discriminated Records with Default Discriminants @@ -26463,7 +26476,7 @@ say) must be consistent, so it is imperative that the object, once created, remain invariant. @node Strict Conformance to the Ada Reference Manual,,The Size of Discriminated Records with Default Discriminants,Implementation of Specific Ada Features -@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{42a}@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{42b} +@anchor{gnat_rm/implementation_of_specific_ada_features strict-conformance-to-the-ada-reference-manual}@anchor{42c}@anchor{gnat_rm/implementation_of_specific_ada_features id14}@anchor{42d} @section Strict Conformance to the Ada Reference Manual @@ -26490,7 +26503,7 @@ behavior (although at the cost of a significant performance penalty), so infinite and NaN values are properly generated. @node Implementation of Ada 2012 Features,Obsolescent Features,Implementation of Specific Ada Features,Top -@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{42c}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{42d} +@anchor{gnat_rm/implementation_of_ada_2012_features doc}@anchor{42e}@anchor{gnat_rm/implementation_of_ada_2012_features implementation-of-ada-2012-features}@anchor{14}@anchor{gnat_rm/implementation_of_ada_2012_features id1}@anchor{42f} @chapter Implementation of Ada 2012 Features @@ -28656,7 +28669,7 @@ RM References: H.04 (8/1) @end itemize @node Obsolescent Features,Compatibility and Porting Guide,Implementation of Ada 2012 Features,Top -@anchor{gnat_rm/obsolescent_features id1}@anchor{42e}@anchor{gnat_rm/obsolescent_features doc}@anchor{42f}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15} +@anchor{gnat_rm/obsolescent_features id1}@anchor{430}@anchor{gnat_rm/obsolescent_features doc}@anchor{431}@anchor{gnat_rm/obsolescent_features obsolescent-features}@anchor{15} @chapter Obsolescent Features @@ -28675,7 +28688,7 @@ compatibility purposes. @end menu @node pragma No_Run_Time,pragma Ravenscar,,Obsolescent Features -@anchor{gnat_rm/obsolescent_features id2}@anchor{430}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{431} +@anchor{gnat_rm/obsolescent_features id2}@anchor{432}@anchor{gnat_rm/obsolescent_features pragma-no-run-time}@anchor{433} @section pragma No_Run_Time @@ -28688,7 +28701,7 @@ preferred usage is to use an appropriately configured run-time that includes just those features that are to be made accessible. @node pragma Ravenscar,pragma Restricted_Run_Time,pragma No_Run_Time,Obsolescent Features -@anchor{gnat_rm/obsolescent_features id3}@anchor{432}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{433} +@anchor{gnat_rm/obsolescent_features id3}@anchor{434}@anchor{gnat_rm/obsolescent_features pragma-ravenscar}@anchor{435} @section pragma Ravenscar @@ -28697,7 +28710,7 @@ The pragma @code{Ravenscar} has exactly the same effect as pragma is part of the new Ada 2005 standard. @node pragma Restricted_Run_Time,pragma Task_Info,pragma Ravenscar,Obsolescent Features -@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{434}@anchor{gnat_rm/obsolescent_features id4}@anchor{435} +@anchor{gnat_rm/obsolescent_features pragma-restricted-run-time}@anchor{436}@anchor{gnat_rm/obsolescent_features id4}@anchor{437} @section pragma Restricted_Run_Time @@ -28707,7 +28720,7 @@ preferred since the Ada 2005 pragma @code{Profile} is intended for this kind of implementation dependent addition. @node pragma Task_Info,package System Task_Info s-tasinf ads,pragma Restricted_Run_Time,Obsolescent Features -@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{436}@anchor{gnat_rm/obsolescent_features id5}@anchor{437} +@anchor{gnat_rm/obsolescent_features pragma-task-info}@anchor{438}@anchor{gnat_rm/obsolescent_features id5}@anchor{439} @section pragma Task_Info @@ -28733,7 +28746,7 @@ in the spec of package System.Task_Info in the runtime library. @node package System Task_Info s-tasinf ads,,pragma Task_Info,Obsolescent Features -@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{438}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{439} +@anchor{gnat_rm/obsolescent_features package-system-task-info}@anchor{43a}@anchor{gnat_rm/obsolescent_features package-system-task-info-s-tasinf-ads}@anchor{43b} @section package System.Task_Info (@code{s-tasinf.ads}) @@ -28743,7 +28756,7 @@ to support the @code{Task_Info} pragma. The predefined Ada package standard replacement for GNAT's @code{Task_Info} functionality. @node Compatibility and Porting Guide,GNU Free Documentation License,Obsolescent Features,Top -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{43a}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{43b} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-and-porting-guide}@anchor{16}@anchor{gnat_rm/compatibility_and_porting_guide doc}@anchor{43c}@anchor{gnat_rm/compatibility_and_porting_guide id1}@anchor{43d} @chapter Compatibility and Porting Guide @@ -28765,7 +28778,7 @@ applications developed in other Ada environments. @end menu @node Writing Portable Fixed-Point Declarations,Compatibility with Ada 83,,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{43c}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{43d} +@anchor{gnat_rm/compatibility_and_porting_guide id2}@anchor{43e}@anchor{gnat_rm/compatibility_and_porting_guide writing-portable-fixed-point-declarations}@anchor{43f} @section Writing Portable Fixed-Point Declarations @@ -28887,7 +28900,7 @@ If you follow this scheme you will be guaranteed that your fixed-point types will be portable. @node Compatibility with Ada 83,Compatibility between Ada 95 and Ada 2005,Writing Portable Fixed-Point Declarations,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{43e}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{43f} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-ada-83}@anchor{440}@anchor{gnat_rm/compatibility_and_porting_guide id3}@anchor{441} @section Compatibility with Ada 83 @@ -28915,7 +28928,7 @@ following subsections treat the most likely issues to be encountered. @end menu @node Legal Ada 83 programs that are illegal in Ada 95,More deterministic semantics,,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{440}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{441} +@anchor{gnat_rm/compatibility_and_porting_guide id4}@anchor{442}@anchor{gnat_rm/compatibility_and_porting_guide legal-ada-83-programs-that-are-illegal-in-ada-95}@anchor{443} @subsection Legal Ada 83 programs that are illegal in Ada 95 @@ -29015,7 +29028,7 @@ the fix is usually simply to add the @code{(<>)} to the generic declaration. @end itemize @node More deterministic semantics,Changed semantics,Legal Ada 83 programs that are illegal in Ada 95,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{442}@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{443} +@anchor{gnat_rm/compatibility_and_porting_guide more-deterministic-semantics}@anchor{444}@anchor{gnat_rm/compatibility_and_porting_guide id5}@anchor{445} @subsection More deterministic semantics @@ -29043,7 +29056,7 @@ which open select branches are executed. @end itemize @node Changed semantics,Other language compatibility issues,More deterministic semantics,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{444}@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{445} +@anchor{gnat_rm/compatibility_and_porting_guide id6}@anchor{446}@anchor{gnat_rm/compatibility_and_porting_guide changed-semantics}@anchor{447} @subsection Changed semantics @@ -29085,7 +29098,7 @@ covers only the restricted range. @end itemize @node Other language compatibility issues,,Changed semantics,Compatibility with Ada 83 -@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{446}@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{447} +@anchor{gnat_rm/compatibility_and_porting_guide other-language-compatibility-issues}@anchor{448}@anchor{gnat_rm/compatibility_and_porting_guide id7}@anchor{449} @subsection Other language compatibility issues @@ -29118,7 +29131,7 @@ include @code{pragma Interface} and the floating point type attributes @end itemize @node Compatibility between Ada 95 and Ada 2005,Implementation-dependent characteristics,Compatibility with Ada 83,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{448}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{449} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-between-ada-95-and-ada-2005}@anchor{44a}@anchor{gnat_rm/compatibility_and_porting_guide id8}@anchor{44b} @section Compatibility between Ada 95 and Ada 2005 @@ -29190,7 +29203,7 @@ can declare a function returning a value from an anonymous access type. @end itemize @node Implementation-dependent characteristics,Compatibility with Other Ada Systems,Compatibility between Ada 95 and Ada 2005,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{44a}@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{44b} +@anchor{gnat_rm/compatibility_and_porting_guide implementation-dependent-characteristics}@anchor{44c}@anchor{gnat_rm/compatibility_and_porting_guide id9}@anchor{44d} @section Implementation-dependent characteristics @@ -29213,7 +29226,7 @@ transition from certain Ada 83 compilers. @end menu @node Implementation-defined pragmas,Implementation-defined attributes,,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{44c}@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{44d} +@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-pragmas}@anchor{44e}@anchor{gnat_rm/compatibility_and_porting_guide id10}@anchor{44f} @subsection Implementation-defined pragmas @@ -29235,7 +29248,7 @@ avoiding compiler rejection of units that contain such pragmas; they are not relevant in a GNAT context and hence are not otherwise implemented. @node Implementation-defined attributes,Libraries,Implementation-defined pragmas,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{44e}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{44f} +@anchor{gnat_rm/compatibility_and_porting_guide id11}@anchor{450}@anchor{gnat_rm/compatibility_and_porting_guide implementation-defined-attributes}@anchor{451} @subsection Implementation-defined attributes @@ -29249,7 +29262,7 @@ Ada 83, GNAT supplies the attributes @code{Bit}, @code{Machine_Size} and @code{Type_Class}. @node Libraries,Elaboration order,Implementation-defined attributes,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{450}@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{451} +@anchor{gnat_rm/compatibility_and_porting_guide libraries}@anchor{452}@anchor{gnat_rm/compatibility_and_porting_guide id12}@anchor{453} @subsection Libraries @@ -29278,7 +29291,7 @@ be preferable to retrofit the application using modular types. @end itemize @node Elaboration order,Target-specific aspects,Libraries,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{452}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{453} +@anchor{gnat_rm/compatibility_and_porting_guide elaboration-order}@anchor{454}@anchor{gnat_rm/compatibility_and_porting_guide id13}@anchor{455} @subsection Elaboration order @@ -29314,7 +29327,7 @@ pragmas either globally (as an effect of the @emph{-gnatE} switch) or locally @end itemize @node Target-specific aspects,,Elaboration order,Implementation-dependent characteristics -@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{454}@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{455} +@anchor{gnat_rm/compatibility_and_porting_guide target-specific-aspects}@anchor{456}@anchor{gnat_rm/compatibility_and_porting_guide id14}@anchor{457} @subsection Target-specific aspects @@ -29327,10 +29340,10 @@ on the robustness of the original design. Moreover, Ada 95 (and thus Ada 2005 and Ada 2012) are sometimes incompatible with typical Ada 83 compiler practices regarding implicit packing, the meaning of the Size attribute, and the size of access values. -GNAT's approach to these issues is described in @ref{456,,Representation Clauses}. +GNAT's approach to these issues is described in @ref{458,,Representation Clauses}. @node Compatibility with Other Ada Systems,Representation Clauses,Implementation-dependent characteristics,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{457}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{458} +@anchor{gnat_rm/compatibility_and_porting_guide id15}@anchor{459}@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-other-ada-systems}@anchor{45a} @section Compatibility with Other Ada Systems @@ -29373,7 +29386,7 @@ far beyond this minimal set, as described in the next section. @end itemize @node Representation Clauses,Compatibility with HP Ada 83,Compatibility with Other Ada Systems,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{456}@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{459} +@anchor{gnat_rm/compatibility_and_porting_guide representation-clauses}@anchor{458}@anchor{gnat_rm/compatibility_and_porting_guide id16}@anchor{45b} @section Representation Clauses @@ -29466,7 +29479,7 @@ with thin pointers. @end itemize @node Compatibility with HP Ada 83,,Representation Clauses,Compatibility and Porting Guide -@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{45a}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{45b} +@anchor{gnat_rm/compatibility_and_porting_guide compatibility-with-hp-ada-83}@anchor{45c}@anchor{gnat_rm/compatibility_and_porting_guide id17}@anchor{45d} @section Compatibility with HP Ada 83 @@ -29496,7 +29509,7 @@ extension of package System. @end itemize @node GNU Free Documentation License,Index,Compatibility and Porting Guide,Top -@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{45c}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{45d} +@anchor{share/gnu_free_documentation_license gnu-fdl}@anchor{1}@anchor{share/gnu_free_documentation_license doc}@anchor{45e}@anchor{share/gnu_free_documentation_license gnu-free-documentation-license}@anchor{45f} @chapter GNU Free Documentation License diff --git a/gcc/ada/libgnat/g-brapre.ads b/gcc/ada/libgnat/g-brapre.ads new file mode 100644 index 0000000..9b88e35 --- /dev/null +++ b/gcc/ada/libgnat/g-brapre.ads @@ -0,0 +1,68 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT RUN-TIME COMPONENTS -- +-- -- +-- G N A T . B R A N C H _ P R E D I C T I O N -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- This package provides routines giving hints to the branch predictor of the +-- code generator. These hints are useful when optimization is enabled and the +-- branch probability heuristics are used (which is the default), but they are +-- overridden when profile feedback-directed optimization is used instead. + +-- The canonical pattern is to use them as the condition of an If statement: +-- +-- if Likely (X > 0) then +-- Do_Something; +-- end if; +-- +-- when it is not obvious that one outcome of the condition is more likely +-- than the other, or else to reverse the prediction made by the heuristics +-- in very peculiar cases. In the other cases, it is better not to use them, +-- because predicting how programs actually perform is notoriously hard. + +package GNAT.Branch_Prediction is + pragma Pure; + + function Expect (Condition : Boolean; Outcome : Boolean) return Boolean; + pragma Import (Intrinsic, Expect, "__builtin_expect"); + -- This function returns the value of its first parameter Condition and + -- tells the branch predictor that this value is expected to be Outcome. + + function Likely (Condition : Boolean) return Boolean; + pragma Import (Intrinsic, Likely, "__builtin_likely"); + -- This function returns the value of its parameter Condition and tells + -- the branch predictor that this value is expected to be True. Calling + -- it is strictly equivalent to calling Expect with Outcome set to True. + + function Unlikely (Condition : Boolean) return Boolean; + pragma Import (Intrinsic, Unlikely, "__builtin_unlikely"); + -- This function returns the value of its parameter Condition and tells + -- the branch predictor that this value is expected to be False. Calling + -- it is strictly equivalent to calling Expect with Outcome set to False. + +end GNAT.Branch_Prediction; -- cgit v1.1 From 9a5245da49541aa21f672b491503230403382b43 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Wed, 10 Jul 2019 09:02:03 +0000 Subject: [Ada] Spelling mistakes in error messages This patch updates certain error messages to eliminate spelling mistakes. No need for a test as this is a minor cosmetic fix. 2019-07-10 Hristian Kirtchev gcc/ada/ * sem_ch3.adb (Check_Nonoverridable_Aspects): Correct the spelling in certain error messages. (Check_Pragma_Implemented): Correct the spelling in certain error messages. From-SVN: r273341 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch3.adb | 34 +++++++++++++++++----------------- 2 files changed, 24 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0959008..4db8abc 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-10 Hristian Kirtchev + + * sem_ch3.adb (Check_Nonoverridable_Aspects): Correct the + spelling in certain error messages. + (Check_Pragma_Implemented): Correct the spelling in certain + error messages. + 2019-07-10 Eric Botcazou * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add g-brapre. diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index e936cbb..ae0a7bf 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -3009,14 +3009,15 @@ package body Sem_Ch3 is -- is consistent with that of the parent. declare - Par_Discr : constant Entity_Id := - Get_Reference_Discriminant (Par_Type); - Cur_Discr : constant Entity_Id := + Cur_Discr : constant Entity_Id := Get_Reference_Discriminant (Prev); + Par_Discr : constant Entity_Id := + Get_Reference_Discriminant (Par_Type); begin if Corresponding_Discriminant (Cur_Discr) /= Par_Discr then - Error_Msg_N ("aspect incosistent with that of parent", N); + Error_Msg_N + ("aspect inconsistent with that of parent", N); end if; -- Check that specification in partial view matches the @@ -3029,7 +3030,7 @@ package body Sem_Ch3 is Chars (Cur_Discr) then Error_Msg_N - ("aspect incosistent with that of parent", N); + ("aspect inconsistent with that of parent", N); end if; end; end if; @@ -10641,9 +10642,9 @@ package body Sem_Ch3 is if Ekind (Contr_Typ) /= E_Protected_Type then Error_Msg_Node_2 := Contr_Typ; Error_Msg_NE - ("interface subprogram & cannot be implemented by a " & - "primitive procedure of task type &", Subp_Alias, - Iface_Alias); + ("interface subprogram & cannot be implemented by a " + & "primitive procedure of task type &", + Subp_Alias, Iface_Alias); -- An interface subprogram whose implementation kind is By_ -- Protected_Procedure must be implemented by a procedure. @@ -10651,28 +10652,27 @@ package body Sem_Ch3 is elsif Ekind (Impl_Subp) /= E_Procedure then Error_Msg_Node_2 := Iface_Alias; Error_Msg_NE - ("type & must implement abstract subprogram & with a " & - "procedure", Subp_Alias, Contr_Typ); + ("type & must implement abstract subprogram & with a " + & "procedure", Subp_Alias, Contr_Typ); elsif Present (Get_Rep_Pragma (Impl_Subp, Name_Implemented)) and then Implementation_Kind (Impl_Subp) /= Impl_Kind then Error_Msg_Name_1 := Impl_Kind; Error_Msg_N - ("overriding operation& must have synchronization%", - Subp_Alias); + ("overriding operation& must have synchronization%", + Subp_Alias); end if; -- If primitive has Optional synchronization, overriding operation - -- must match if it has an explicit synchronization.. + -- must match if it has an explicit synchronization. elsif Present (Get_Rep_Pragma (Impl_Subp, Name_Implemented)) and then Implementation_Kind (Impl_Subp) /= Impl_Kind then - Error_Msg_Name_1 := Impl_Kind; - Error_Msg_N - ("overriding operation& must have syncrhonization%", - Subp_Alias); + Error_Msg_Name_1 := Impl_Kind; + Error_Msg_N + ("overriding operation& must have synchronization%", Subp_Alias); end if; end Check_Pragma_Implemented; -- cgit v1.1 From f35688c95a8ab5d3d6eeee51623d69705a00b115 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Wed, 10 Jul 2019 09:02:08 +0000 Subject: [Ada] Add an annotation for static analysis 2019-07-10 Arnaud Charlet gcc/ada/ * sfn_scan.adb (Scan_SFN_Pragmas): Add pragma Assert. From-SVN: r273342 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/sfn_scan.adb | 1 + 2 files changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4db8abc..f99b6db 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-10 Arnaud Charlet + + * sfn_scan.adb (Scan_SFN_Pragmas): Add pragma Assert. + 2019-07-10 Hristian Kirtchev * sem_ch3.adb (Check_Nonoverridable_Aspects): Correct the diff --git a/gcc/ada/sfn_scan.adb b/gcc/ada/sfn_scan.adb index 66e9a82..377ea19 100644 --- a/gcc/ada/sfn_scan.adb +++ b/gcc/ada/sfn_scan.adb @@ -607,6 +607,7 @@ package body SFN_Scan is exception when others => + pragma Assert (P'Valid); Cursor := P - S'First + 1; raise; end Scan_SFN_Pragmas; -- cgit v1.1 From 1ae0159eb46044545610b78fc4ea82427c45c568 Mon Sep 17 00:00:00 2001 From: Simon Buist Date: Wed, 10 Jul 2019 09:02:12 +0000 Subject: [Ada] Entity names are not unique This patch updates the Unique_Name procedure in order to prefix the string "ada___" to child units that have a nested subprogram or package, so that they do not clash with a parent package of the same name. This is for GNATprove only and does not affect regular compilation. 2019-07-10 Simon Buist gcc/ada/ * sem_util.ads (Child_Prefix): New constant. * sem_util.adb (Unique_Name): Add a special prefix to child units that have a nested subprogram or package. From-SVN: r273343 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/sem_util.adb | 2 ++ gcc/ada/sem_util.ads | 4 ++++ 3 files changed, 12 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f99b6db..7e609bd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-10 Simon Buist + + * sem_util.ads (Child_Prefix): New constant. + * sem_util.adb (Unique_Name): Add a special prefix to child + units that have a nested subprogram or package. + 2019-07-10 Arnaud Charlet * sfn_scan.adb (Scan_SFN_Pragmas): Add pragma Assert. diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index e011c09..448eea1 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -25781,6 +25781,8 @@ package body Sem_Util is end if; end; + elsif Is_Child_Unit (U) then + return Child_Prefix & Unique_Name (S) & "__" & This_Name; else return Unique_Name (S) & "__" & This_Name; end if; diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 3eb9d57..808d693 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -2854,6 +2854,10 @@ package Sem_Util is -- Return a unique name for entity E, which could be used to identify E -- across compilation units. + Child_Prefix : constant String := "ada___"; + -- Prefix for child packages when building a unique name for an entity. It + -- is included here to share between Unique_Name and gnatprove. + function Unit_Is_Visible (U : Entity_Id) return Boolean; -- Determine whether a compilation unit is visible in the current context, -- because there is a with_clause that makes the unit available. Used to -- cgit v1.1 From 764ffff09accf270243f43d0a8ad1e34d9883eec Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Wed, 10 Jul 2019 09:02:17 +0000 Subject: [Ada] Documentation of Img attribute out of date 2019-07-10 Justin Squirek gcc/ada/ * doc/gnat_rm/implementation_defined_attributes.rst: Add mention of 'Image attribute with 'Img's entry to mention additional added 2012 usage of Obj'Image. * doc/gnat_rm/implementation_defined_pragmas.rst: Correct mispelling of Async_Writers. * gnat_rm.texi: Regenerate. * sem_prag.adb (Analyze_Pragma): Correct mispelling of Async_Writers. * sem_util.adb (State_Has_Enabled_Property): Correct mispelling of Async_Writers. From-SVN: r273344 --- gcc/ada/ChangeLog | 13 +++++++++++++ gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst | 10 +++++----- gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst | 4 ++-- gcc/ada/gnat_rm.texi | 14 +++++++------- gcc/ada/sem_prag.adb | 4 ++-- gcc/ada/sem_util.adb | 4 ++-- 6 files changed, 31 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7e609bd..9e9e19d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2019-07-10 Justin Squirek + + * doc/gnat_rm/implementation_defined_attributes.rst: Add mention + of 'Image attribute with 'Img's entry to mention additional + added 2012 usage of Obj'Image. + * doc/gnat_rm/implementation_defined_pragmas.rst: Correct + mispelling of Async_Writers. + * gnat_rm.texi: Regenerate. + * sem_prag.adb (Analyze_Pragma): Correct mispelling of + Async_Writers. + * sem_util.adb (State_Has_Enabled_Property): Correct mispelling + of Async_Writers. + 2019-07-10 Simon Buist * sem_util.ads (Child_Prefix): New constant. diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst index c75d994..db75ea7 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst @@ -479,17 +479,17 @@ Attribute Img ============= .. index:: Img -The ``Img`` attribute differs from ``Image`` in that it is applied -directly to an object, and yields the same result as -``Image`` for the subtype of the object. This is convenient for -debugging: +The ``Img`` attribute differs from ``Image`` in that, while both can be +applied directly to an object, ``Img`` cannot be applied to types. + +Example usage of the attribute: .. code-block:: ada Put_Line ("X = " & X'Img); -has the same meaning as the more verbose: +which has the same meaning as the more verbose: .. code-block:: ada diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst index dff7798..04b0def 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst @@ -719,7 +719,7 @@ Syntax: .. code-block:: ada - pragma Asynch_Readers [ (boolean_EXPRESSION) ]; + pragma Async_Readers [ (boolean_EXPRESSION) ]; For the semantics of this pragma, see the entry for aspect ``Async_Readers`` in the SPARK 2014 Reference Manual, section 7.1.2. @@ -733,7 +733,7 @@ Syntax: .. code-block:: ada - pragma Asynch_Writers [ (boolean_EXPRESSION) ]; + pragma Async_Writers [ (boolean_EXPRESSION) ]; For the semantics of this pragma, see the entry for aspect ``Async_Writers`` in the SPARK 2014 Reference Manual, section 7.1.2. diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 77f91b0..257c394 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -2104,7 +2104,7 @@ case, and it is recommended that these two options not be used together. Syntax: @example -pragma Asynch_Readers [ (boolean_EXPRESSION) ]; +pragma Async_Readers [ (boolean_EXPRESSION) ]; @end example For the semantics of this pragma, see the entry for aspect @code{Async_Readers} in @@ -2118,7 +2118,7 @@ the SPARK 2014 Reference Manual, section 7.1.2. Syntax: @example -pragma Asynch_Writers [ (boolean_EXPRESSION) ]; +pragma Async_Writers [ (boolean_EXPRESSION) ]; @end example For the semantics of this pragma, see the entry for aspect @code{Async_Writers} in @@ -10713,16 +10713,16 @@ indicates whether or not the corresponding actual type has discriminants. @geindex Img -The @code{Img} attribute differs from @code{Image} in that it is applied -directly to an object, and yields the same result as -@code{Image} for the subtype of the object. This is convenient for -debugging: +The @code{Img} attribute differs from @code{Image} in that, while both can be +applied directly to an object, @code{Img} cannot be applied to types. + +Example usage of the attribute: @example Put_Line ("X = " & X'Img); @end example -has the same meaning as the more verbose: +which has the same meaning as the more verbose: @example Put_Line ("X = " & T'Image (X)); diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 7a4857f..969820e 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -13620,8 +13620,8 @@ package body Sem_Prag is -- Async_Readers/Async_Writers/Effective_Reads/Effective_Writes -- ------------------------------------------------------------------ - -- pragma Asynch_Readers [ (boolean_EXPRESSION) ]; - -- pragma Asynch_Writers [ (boolean_EXPRESSION) ]; + -- pragma Async_Readers [ (boolean_EXPRESSION) ]; + -- pragma Async_Writers [ (boolean_EXPRESSION) ]; -- pragma Effective_Reads [ (boolean_EXPRESSION) ]; -- pragma Effective_Writes [ (boolean_EXPRESSION) ]; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 448eea1..b6a31e6 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -10813,8 +10813,8 @@ package body Sem_Util is -- Simple option Synchronous -- -- enables disables - -- Asynch_Readers Effective_Reads - -- Asynch_Writers Effective_Writes + -- Async_Readers Effective_Reads + -- Async_Writers Effective_Writes -- -- Note that both forms of External have higher precedence than -- Synchronous (SPARK RM 7.1.4(9)). -- cgit v1.1 From 710e024086a51a1567fa39c7c95bbe5554d4c1fd Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 10 Jul 2019 09:02:22 +0000 Subject: [Ada] GNATpp: document the --source-line-breaks switch 2019-07-10 Bob Duff gcc/ada/ * doc/gnat_ugn/gnat_utility_programs.rst: Document gnatpp's --source-line-breaks switch. From-SVN: r273345 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9e9e19d..d7b265c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Bob Duff + + * doc/gnat_ugn/gnat_utility_programs.rst: Document gnatpp's + --source-line-breaks switch. + 2019-07-10 Justin Squirek * doc/gnat_rm/implementation_defined_attributes.rst: Add mention diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst index e20ea63..516c57c 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst @@ -3248,6 +3248,14 @@ Alternatively, you may run the script using the following command line: :switch:`--preserve-line-breaks` Preserve line breaks in the input, to the extent possible. + By default, line breaks are also inserted at appropriate + places. + + .. index:: --source-line-breaks (gnatpp) + + :switch:`--source-line-breaks` + Keep the line breaks from the source; do not insert or delete any + line breaks. The ``--comments`` switches are compatible with one another, except that the ``--comments-unchanged`` switch disables all other comment -- cgit v1.1 From 6056bc735d81633bdefe3b696c917d3e4ea20049 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Wed, 10 Jul 2019 09:02:27 +0000 Subject: [Ada] Improve gnatmem's doc for the depth switch 2019-07-10 Arnaud Charlet gcc/ada * doc/gnat_ugn/gnat_and_program_execution.rst: Improve gnatmem's doc for the depth switch. From-SVN: r273346 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst | 17 +++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d7b265c..246134c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Arnaud Charlet + + * doc/gnat_ugn/gnat_and_program_execution.rst: Improve gnatmem's + doc for the depth switch. + 2019-07-10 Bob Duff * doc/gnat_ugn/gnat_utility_programs.rst: Document gnatpp's diff --git a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst index 9cbdb15..de348e9 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst @@ -3972,7 +3972,7 @@ execution of this erroneous program: :: - $ gnatmem [ switches ] user_program + $ gnatmem [ switches ] [ DEPTH ] user_program The program must have been linked with the instrumented version of the allocation and deallocation routines. This is done by linking with the @@ -4062,15 +4062,16 @@ execution of this erroneous program: memory leaks. Omits statistical information. - .. index:: N switch (gnatmem) + .. index:: DEPTH switch (gnatmem) - :samp:`{N}` - ``N`` is an integer literal (usually between 1 and 10) which controls the - depth of the backtraces defining allocation root. The default value for - N is 1. The deeper the backtrace, the more precise the localization of + :samp:`{DEPTH}` + ``DEPTH`` is an integer literal (usually between 1 and 10) which controls + the depth of the backtraces defining allocation root. The default value for + DEPTH is 1. The deeper the backtrace, the more precise the localization of the root. Note that the total number of roots can depend on this - parameter. This parameter must be specified *before* the name of the - executable to be analyzed, to avoid ambiguity. + parameter, in other words there may be more roots when the requested + backtrace depth is higher. This parameter must be specified *before* the + name of the executable to be analyzed, to avoid ambiguity. .. index:: -b (gnatmem) -- cgit v1.1 From d036b2b8c29f8d53787417a1c0b0ddf814ab8b6b Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Wed, 10 Jul 2019 09:02:31 +0000 Subject: [Ada] Spurious error on discriminant of incomplete type This patch corrects the conformance verification of discriminants to provide symmetry between the analysis of incomplete and full view discriminants. As a result, types of discriminants always resolve to the proper view. 2019-07-10 Hristian Kirtchev gcc/ada/ * sem_ch6.adb (Check_Discriminant_Conformance): Use Find_Type to discover the type of a full view discriminant. gcc/testsuite/ * gnat.dg/incomplete7.adb, gnat.dg/incomplete7.ads: New testcase. From-SVN: r273347 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_ch6.adb | 2 +- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/incomplete7.adb | 5 +++++ gcc/testsuite/gnat.dg/incomplete7.ads | 31 +++++++++++++++++++++++++++++++ 5 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/incomplete7.adb create mode 100644 gcc/testsuite/gnat.dg/incomplete7.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 246134c..86e3508 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Hristian Kirtchev + + * sem_ch6.adb (Check_Discriminant_Conformance): Use Find_Type to + discover the type of a full view discriminant. + 2019-07-10 Arnaud Charlet * doc/gnat_ugn/gnat_and_program_execution.rst: Improve gnatmem's diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index e00cd57..25ee705 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -5960,7 +5960,7 @@ package body Sem_Ch6 is Access_Definition (N, Discriminant_Type (New_Discr)); else - Analyze (Discriminant_Type (New_Discr)); + Find_Type (Discriminant_Type (New_Discr)); New_Discr_Type := Etype (Discriminant_Type (New_Discr)); -- Ada 2005: if the discriminant definition carries a null diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 21c5e31..b658817 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-10 Hristian Kirtchev + * gnat.dg/incomplete7.adb, gnat.dg/incomplete7.ads: New testcase. + +2019-07-10 Hristian Kirtchev + * gnat.dg/limited2.adb, gnat.dg/limited2_pack_1.adb, gnat.dg/limited2_pack_1.ads, gnat.dg/limited2_pack_2.adb, gnat.dg/limited2_pack_2.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/incomplete7.adb b/gcc/testsuite/gnat.dg/incomplete7.adb new file mode 100644 index 0000000..34accbe --- /dev/null +++ b/gcc/testsuite/gnat.dg/incomplete7.adb @@ -0,0 +1,5 @@ +-- { dg-do compile } + +package body Incomplete7 is + procedure Foo is null; +end Incomplete7; diff --git a/gcc/testsuite/gnat.dg/incomplete7.ads b/gcc/testsuite/gnat.dg/incomplete7.ads new file mode 100644 index 0000000..3c1ade7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/incomplete7.ads @@ -0,0 +1,31 @@ +package Incomplete7 is + type Color; + type Color is (red, green, blue); + + type Action (C : Color := Color'(red)); + type Action (C : Color := Color'(red)) is record + case C is + when red => + Stop_Time : Positive; + + when others => + Go_For_It : Integer; + end case; + end record; + + type Num; + type Num is new Integer; + + type Rec (N : Num := Num'(1)); + type Rec (N : Num := Num'(1)) is record + case N is + when 1 => + One : Integer; + + when others => + null; + end case; + end record; + + procedure Foo; +end Incomplete7; -- cgit v1.1 From 1bc68e0d30bc801a279da653196d66d36312831b Mon Sep 17 00:00:00 2001 From: Claire Dross Date: Wed, 10 Jul 2019 09:02:36 +0000 Subject: [Ada] Fix possible crashes in GNATprove analysis of pointers The new analysis of SPARK pointer rules could crash on some constructs. Now fixed. There is no impact on compilation. 2019-07-10 Claire Dross gcc/ada/ * sem_spark.adb (Check_Expression): Allow digits constraints as input. (Illegal_Global_Usage): Pass in the entity. (Is_Subpath_Expression): New function to allow different nodes as inner parts of a path expression. (Read_Indexes): Allow concatenation and aggregates with box expressions. Allow attributes Update and Loop_Entry. (Check_Expression): Allow richer membership test. (Check_Node): Ignore bodies of generics. (Get_Root_Object): Allow concatenation and attributes. From-SVN: r273348 --- gcc/ada/ChangeLog | 13 +++++ gcc/ada/sem_spark.adb | 131 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 124 insertions(+), 20 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 86e3508..2ef2faf 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2019-07-10 Claire Dross + + * sem_spark.adb (Check_Expression): Allow digits constraints as + input. + (Illegal_Global_Usage): Pass in the entity. + (Is_Subpath_Expression): New function to allow different nodes + as inner parts of a path expression. + (Read_Indexes): Allow concatenation and aggregates with box + expressions. Allow attributes Update and Loop_Entry. + (Check_Expression): Allow richer membership test. + (Check_Node): Ignore bodies of generics. + (Get_Root_Object): Allow concatenation and attributes. + 2019-07-10 Hristian Kirtchev * sem_ch6.adb (Check_Discriminant_Conformance): Use Find_Type to diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index a9384b8..1504333 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -640,7 +640,8 @@ package body Sem_SPARK is procedure Check_Expression (Expr : Node_Id; Mode : Extended_Checking_Mode); pragma Precondition (Nkind_In (Expr, N_Index_Or_Discriminant_Constraint, N_Range_Constraint, - N_Subtype_Indication) + N_Subtype_Indication, + N_Digits_Constraint) or else Nkind (Expr) in N_Subexpr); procedure Check_Globals (Subp : Entity_Id); @@ -738,7 +739,7 @@ package body Sem_SPARK is -- the debugger to look into a hash table. pragma Unreferenced (Hp); - procedure Illegal_Global_Usage (N : Node_Or_Entity_Id); + procedure Illegal_Global_Usage (N : Node_Or_Entity_Id; E : Entity_Id); pragma No_Return (Illegal_Global_Usage); -- A procedure that is called when deep globals or aliased globals are used -- without any global aspect. @@ -750,6 +751,9 @@ package body Sem_SPARK is function Is_Path_Expression (Expr : Node_Id) return Boolean; -- Return whether Expr corresponds to a path + function Is_Subpath_Expression (Expr : Node_Id) return Boolean; + -- Return True if Expr can be part of a path expression + function Is_Prefix_Or_Almost (Pref, Expr : Node_Id) return Boolean; -- Determine if the candidate Prefix is indeed a prefix of Expr, or almost -- a prefix, in the sense that they could still refer to overlapping memory @@ -1302,7 +1306,9 @@ package body Sem_SPARK is begin -- Only SPARK bodies are analyzed - if No (Prag) or else Get_SPARK_Mode_From_Annotation (Prag) /= Opt.On then + if No (Prag) + or else Get_SPARK_Mode_From_Annotation (Prag) /= Opt.On + then return; end if; @@ -1312,9 +1318,8 @@ package body Sem_SPARK is and then Is_Anonymous_Access_Type (Etype (Spec_Id)) and then not Is_Traversal_Function (Spec_Id) then - Error_Msg_N - ("anonymous access type for result only allowed for traveral " - & "functions", Spec_Id); + Error_Msg_N ("anonymous access type for result only allowed for " + & "traveral functions", Spec_Id); return; end if; @@ -1568,7 +1573,7 @@ package body Sem_SPARK is -- Start of processing for Read_Indexes begin - if not Is_Path_Expression (Expr) then + if not Is_Subpath_Expression (Expr) then Error_Msg_N ("name expected here for move/borrow/observe", Expr); return; end if; @@ -1603,6 +1608,10 @@ package body Sem_SPARK is Read_Params (Expr); Check_Globals (Get_Called_Entity (Expr)); + when N_Op_Concat => + Read_Expression (Left_Opnd (Expr)); + Read_Expression (Right_Opnd (Expr)); + when N_Qualified_Expression | N_Type_Conversion | N_Unchecked_Type_Conversion @@ -1644,7 +1653,8 @@ package body Sem_SPARK is -- There can be only one element for a value of deep type -- in order to avoid aliasing. - if Is_Deep (Etype (Expression (Assoc))) + if not (Box_Present (Assoc)) + and then Is_Deep (Etype (Expression (Assoc))) and then not Is_Singleton_Choice (CL) then Error_Msg_F @@ -1655,7 +1665,9 @@ package body Sem_SPARK is -- The subexpressions of an aggregate are moved as part -- of the implicit assignments. - Move_Expression (Expression (Assoc)); + if not Box_Present (Assoc) then + Move_Expression (Expression (Assoc)); + end if; Next (Assoc); end loop; @@ -1689,12 +1701,28 @@ package body Sem_SPARK is -- The subexpressions of an aggregate are moved as part -- of the implicit assignments. - Move_Expression (Expression (Assoc)); + if not Box_Present (Assoc) then + Move_Expression (Expression (Assoc)); + end if; Next (Assoc); end loop; end; + when N_Attribute_Reference => + pragma Assert + (Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Loop_Entry + or else + Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update); + + Read_Expression (Prefix (Expr)); + + if Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update + then + Read_Expression_List (Expressions (Expr)); + end if; + when others => raise Program_Error; end case; @@ -1758,6 +1786,13 @@ package body Sem_SPARK is end if; return; + when N_Digits_Constraint => + Read_Expression (Digits_Expression (Expr)); + if Present (Range_Constraint (Expr)) then + Read_Expression (Range_Constraint (Expr)); + end if; + return; + when others => null; end case; @@ -1767,12 +1802,28 @@ package body Sem_SPARK is case N_Subexpr'(Nkind (Expr)) is when N_Binary_Op - | N_Membership_Test | N_Short_Circuit => Read_Expression (Left_Opnd (Expr)); Read_Expression (Right_Opnd (Expr)); + when N_Membership_Test => + Read_Expression (Left_Opnd (Expr)); + if Present (Right_Opnd (Expr)) then + Read_Expression (Right_Opnd (Expr)); + else + declare + Cases : constant List_Id := Alternatives (Expr); + Cur_Case : Node_Id := First (Cases); + + begin + while Present (Cur_Case) loop + Read_Expression (Cur_Case); + Next (Cur_Case); + end loop; + end; + end if; + when N_Unary_Op => Read_Expression (Right_Opnd (Expr)); @@ -1856,6 +1907,14 @@ package body Sem_SPARK is when Attribute_Modulus => null; + -- The following attributes apply to types; there are no + -- expressions to read. + + when Attribute_Class + | Attribute_Storage_Size + => + null; + -- Postconditions should not be analyzed when Attribute_Old @@ -2418,13 +2477,17 @@ package body Sem_SPARK is Check_Call_Statement (N); when N_Package_Body => - Check_Package_Body (N); + if not Is_Generic_Unit (Unique_Defining_Entity (N)) then + Check_Package_Body (N); + end if; when N_Subprogram_Body | N_Entry_Body | N_Task_Body => - Check_Callable_Body (N); + if not Is_Generic_Unit (Unique_Defining_Entity (N)) then + Check_Callable_Body (N); + end if; when N_Protected_Body => Check_List (Declarations (N)); @@ -3399,7 +3462,7 @@ package body Sem_SPARK is if not Inside_Elaboration and then C = null then - Illegal_Global_Usage (N); + Illegal_Global_Usage (N, N); end if; return (R => Unfolded, Tree_Access => C); @@ -3498,7 +3561,7 @@ package body Sem_SPARK is Through_Traversal : Boolean := True) return Entity_Id is begin - if not Is_Path_Expression (Expr) then + if not Is_Subpath_Expression (Expr) then Error_Msg_N ("name expected here for path", Expr); return Empty; end if; @@ -3517,12 +3580,13 @@ package body Sem_SPARK is return Get_Root_Object (Prefix (Expr), Through_Traversal); -- There is no root object for an (extension) aggregate, allocator, - -- or NULL. + -- concat, or NULL. when N_Aggregate | N_Allocator | N_Extension_Aggregate | N_Null + | N_Op_Concat => return Empty; @@ -3545,6 +3609,15 @@ package body Sem_SPARK is => return Get_Root_Object (Expression (Expr), Through_Traversal); + when N_Attribute_Reference => + pragma Assert + (Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Loop_Entry + or else + Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Update); + return Empty; + when others => raise Program_Error; end case; @@ -3646,9 +3719,10 @@ package body Sem_SPARK is -- Illegal_Global_Usage -- -------------------------- - procedure Illegal_Global_Usage (N : Node_Or_Entity_Id) is + procedure Illegal_Global_Usage (N : Node_Or_Entity_Id; E : Entity_Id) + is begin - Error_Msg_NE ("cannot use global variable & of deep type", N, N); + Error_Msg_NE ("cannot use global variable & of deep type", N, E); Error_Msg_N ("\without prior declaration in a Global aspect", N); Errout.Finalize (Last_Call => True); Errout.Output_Messages; @@ -3668,7 +3742,7 @@ package body Sem_SPARK is when E_Array_Type | E_Array_Subtype => - return Is_Deep (Component_Type (Typ)); + return Is_Deep (Component_Type (Underlying_Type (Typ))); when Record_Kind => declare @@ -3861,6 +3935,23 @@ package body Sem_SPARK is end Is_Prefix_Or_Almost; --------------------------- + -- Is_Subpath_Expression -- + --------------------------- + + function Is_Subpath_Expression (Expr : Node_Id) return Boolean is + begin + return Is_Path_Expression (Expr) + or else (Nkind (Expr) = N_Attribute_Reference + and then + (Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Update + or else + Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Loop_Entry)) + or else Nkind (Expr) = N_Op_Concat; + end Is_Subpath_Expression; + + --------------------------- -- Is_Traversal_Function -- --------------------------- @@ -4397,7 +4488,7 @@ package body Sem_SPARK is if not Inside_Elaboration and then Get (Current_Perm_Env, Root) = null then - Illegal_Global_Usage (Expr); + Illegal_Global_Usage (Expr, Root); end if; -- During elaboration, only the validity of operations is checked, no -- cgit v1.1 From 179682a55cbe229442cf3886e338148be0b12a96 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Wed, 10 Jul 2019 09:02:42 +0000 Subject: [Ada] Fix spurious messages on global variables for SPARK pointer support Pointer support in GNATprove leads to spurious messages about global variables, with local variables declared in local packages and protected components. Now fixed. There is no impact on compilation. 2019-07-10 Yannick Moy gcc/ada/ * sem_aux.adb, sem_aux.ads (Is_Protected_Operation): New function to determine if a subprogram is protected. * sem_spark.adb (Setup_Protected_Components): New procedure to add protected components to the environment. (Check_Callable_Body): Call the new Setup_Protected_Components. (Check_Package_Spec): Merge local environment with enclosing one when done. From-SVN: r273349 --- gcc/ada/ChangeLog | 10 ++++++++++ gcc/ada/sem_aux.adb | 12 ++++++++++++ gcc/ada/sem_aux.ads | 4 ++++ gcc/ada/sem_spark.adb | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 76 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2ef2faf..e781181 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-07-10 Yannick Moy + + * sem_aux.adb, sem_aux.ads (Is_Protected_Operation): New + function to determine if a subprogram is protected. + * sem_spark.adb (Setup_Protected_Components): New procedure to + add protected components to the environment. + (Check_Callable_Body): Call the new Setup_Protected_Components. + (Check_Package_Spec): Merge local environment with enclosing one + when done. + 2019-07-10 Claire Dross * sem_spark.adb (Check_Expression): Allow digits constraints as diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb index 0954032..6a93a39 100644 --- a/gcc/ada/sem_aux.adb +++ b/gcc/ada/sem_aux.adb @@ -1324,6 +1324,18 @@ package body Sem_Aux is end if; end Is_Limited_View; + ---------------------------- + -- Is_Protected_Operation -- + ---------------------------- + + function Is_Protected_Operation (E : Entity_Id) return Boolean is + begin + return Is_Entry (E) + or else (Is_Subprogram (E) + and then Nkind (Parent (Unit_Declaration_Node (E))) = + N_Protected_Definition); + end Is_Protected_Operation; + ---------------------- -- Nearest_Ancestor -- ---------------------- diff --git a/gcc/ada/sem_aux.ads b/gcc/ada/sem_aux.ads index f3b7f24..55cfefa 100644 --- a/gcc/ada/sem_aux.ads +++ b/gcc/ada/sem_aux.ads @@ -357,6 +357,10 @@ package Sem_Aux is -- these types). This older routine overlaps with the previous one, this -- should be cleaned up??? + function Is_Protected_Operation (E : Entity_Id) return Boolean; + -- Given a subprogram or entry, determines whether E is a protected entry + -- or subprogram. + function Nearest_Ancestor (Typ : Entity_Id) return Entity_Id; -- Given a subtype Typ, this function finds out the nearest ancestor from -- which constraints and predicates are inherited. There is no simple link diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 1504333..10c82ff 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -876,6 +876,10 @@ package body Sem_SPARK is -- Takes a subprogram as input, and sets up the environment by adding -- formal parameters with appropriate permissions. + procedure Setup_Protected_Components (Subp : Entity_Id); + -- Takes a protected operation as input, and sets up the environment by + -- adding protected components with appropriate permissions. + ---------------------- -- Global Variables -- ---------------------- @@ -1336,6 +1340,13 @@ package body Sem_SPARK is Setup_Globals (Spec_Id); end if; + -- For protected operations, add protected components to the environment + -- with adequate permissions. + + if Is_Protected_Operation (Spec_Id) then + Setup_Protected_Components (Spec_Id); + end if; + -- Analyze the body of the subprogram Check_List (Declarations (Body_N)); @@ -2634,9 +2645,13 @@ package body Sem_SPARK is Check_List (Private_Declarations (Spec)); end if; - -- Restore the saved environment and free the current one + -- Restore the saved environment and free the current one. As part of + -- the restoration, the environment of the package spec is merged in + -- the enclosing environment, which may be an enclosing + -- package/subprogram spec or body which has access to the variables + -- of the package spec. - Move_Env (Saved_Env, Current_Perm_Env); + Merge_Env (Saved_Env, Current_Perm_Env); Inside_Elaboration := Save_In_Elab; end if; @@ -5418,4 +5433,37 @@ package body Sem_SPARK is end loop; end Setup_Parameters; + -------------------------------- + -- Setup_Protected_Components -- + -------------------------------- + + procedure Setup_Protected_Components (Subp : Entity_Id) is + Typ : constant Entity_Id := Scope (Subp); + Comp : Entity_Id; + Kind : Formal_Kind; + + begin + Comp := First_Component_Or_Discriminant (Typ); + + -- The protected object is an implicit input of protected functions, and + -- an implicit input-output of protected procedures and entries. + + if Ekind (Subp) = E_Function then + Kind := E_In_Parameter; + else + Kind := E_In_Out_Parameter; + end if; + + while Present (Comp) loop + Setup_Parameter_Or_Global + (Id => Comp, + Typ => Underlying_Type (Etype (Comp)), + Kind => Kind, + Subp => Subp, + Global_Var => False, + Expl => Comp); + Next_Component_Or_Discriminant (Comp); + end loop; + end Setup_Protected_Components; + end Sem_SPARK; -- cgit v1.1 From c14dc27e91ccd6bdc86ac0b875892396dc84a985 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Wed, 10 Jul 2019 09:02:47 +0000 Subject: [Ada] Crash on aggregate for limited type in extended return This patch fixes a compiler abort on an extended return statement whose expression is an aggregate (to be built in place) for a discriminated record with a limited component. The build-in-place mechanism creates an access type and a renaming declaration through which individual components are assigned. The renamed object is constrained because it is limited, and the renaming declaration does not need to create a local subtype indication for it, which may lead to type mismatches in the back-end, and is in any case redundant. This patch extends this optimization to the case of records that are limited only because of a limitied component, and not because they are explicit declared limited. 2019-07-10 Ed Schonberg gcc/ada/ * sem_ch8.adb (Check_Constrained_Object): A record that is limited because of the presence of a limited component is constrained, and no subtype indiciation needs to be created for it, just as is the case for declared limited records. gcc/testsuite/ * gnat.dg/limited3.adb, gnat.dg/limited3_pkg.adb, gnat.dg/limited3_pkg.ads: New testcase. From-SVN: r273350 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch8.adb | 13 +++++++++---- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/limited3.adb | 11 +++++++++++ gcc/testsuite/gnat.dg/limited3_pkg.adb | 20 ++++++++++++++++++++ gcc/testsuite/gnat.dg/limited3_pkg.ads | 30 ++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/limited3.adb create mode 100644 gcc/testsuite/gnat.dg/limited3_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/limited3_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e781181..6e9ba85 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-10 Ed Schonberg + + * sem_ch8.adb (Check_Constrained_Object): A record that is + limited because of the presence of a limited component is + constrained, and no subtype indiciation needs to be created for + it, just as is the case for declared limited records. + 2019-07-10 Yannick Moy * sem_aux.adb, sem_aux.ads (Is_Protected_Operation): New diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 03b6235..58abc9c 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -802,12 +802,17 @@ package body Sem_Ch8 is null; -- If a record is limited its size is invariant. This is the case - -- in particular with record types with an access discirminant + -- in particular with record types with an access discriminant -- that are used in iterators. This is an optimization, but it -- also prevents typing anomalies when the prefix is further - -- expanded. Limited types with discriminants are included. - - elsif Is_Limited_Record (Typ) + -- expanded. This also applies to limited types with access + -- discriminants. + -- Note that we cannot just use the Is_Limited_Record flag because + -- it does not apply to records with limited components, for which + -- this syntactic flag is not set, but whose size is also fixed. + + elsif (Is_Record_Type (Typ) + and then Is_Limited_Type (Typ)) or else (Ekind (Typ) = E_Limited_Private_Type and then Has_Discriminants (Typ) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b658817..e2dc5fe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Ed Schonberg + + * gnat.dg/limited3.adb, gnat.dg/limited3_pkg.adb, + gnat.dg/limited3_pkg.ads: New testcase. + 2019-07-10 Hristian Kirtchev * gnat.dg/incomplete7.adb, gnat.dg/incomplete7.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/limited3.adb b/gcc/testsuite/gnat.dg/limited3.adb new file mode 100644 index 0000000..a0da49d --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited3.adb @@ -0,0 +1,11 @@ +-- { dg-do run } + +with Limited3_Pkg; use Limited3_Pkg; + +procedure Limited3 is + R1 : Rec := F (15); + R2 : Rec := F (-1); + R3 : Var_Rec := FS (20); +begin + null; +end Limited3; diff --git a/gcc/testsuite/gnat.dg/limited3_pkg.adb b/gcc/testsuite/gnat.dg/limited3_pkg.adb new file mode 100644 index 0000000..71e271d --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited3_pkg.adb @@ -0,0 +1,20 @@ +package body Limited3_Pkg is + function F (I : Integer) return Rec is + begin + return (D => False, I => I); + end; + + function FS (X : Integer) return Var_Rec is + begin + return (X, (1..X => '?'), Tag => <>); + end FS; + + function F2 (I : Integer) return Rec2 is + begin + if I > 0 then + return (D => False, I => I); + else + return (D => True, L => new Limited_Rec); + end if; + end; +end Limited3_Pkg; diff --git a/gcc/testsuite/gnat.dg/limited3_pkg.ads b/gcc/testsuite/gnat.dg/limited3_pkg.ads new file mode 100644 index 0000000..52f211d --- /dev/null +++ b/gcc/testsuite/gnat.dg/limited3_pkg.ads @@ -0,0 +1,30 @@ +package Limited3_Pkg is + + type Limited_Rec is limited + null record; + + type Var_Rec (X : Integer) is record + Name : String (1 .. X); + Tag : Limited_Rec; + end record; + + type Rec (D : Boolean := True) is record + case D is + when True => L : Limited_Rec; + when False => I : Integer; + end case; + end record; + + function F (I : Integer) return Rec; + + function FS (X : Integer) return Var_Rec; + + type Rec2 (D : Boolean := True) is record + case D is + when True => L : access Limited_Rec; + when False => I : Integer; + end case; + end record; + + function F2 (I : Integer) return Rec2; +end Limited3_Pkg; -- cgit v1.1 From ccba4bf136ef7012e7387119a86da56575802c4f Mon Sep 17 00:00:00 2001 From: Doug Rupp Date: Wed, 10 Jul 2019 09:02:51 +0000 Subject: [Ada] Do not attempt to re-arm guard page on x86_64-vx7(r2) A change in the API prohibits accessing Tcb fields directly. The bug in VxWorks7 (failure to re-arm the guard page) now appears to be fixed, so this is no long necessary. 2019-07-10 Doug Rupp gcc/ada/ * init.c: Do not attempt to re-arm guard page on x86_64-vx7(r2). From-SVN: r273351 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/init.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6e9ba85..996dd18 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-10 Doug Rupp + + * init.c: Do not attempt to re-arm guard page on x86_64-vx7(r2). + 2019-07-10 Ed Schonberg * sem_ch8.adb (Check_Constrained_Object): A record that is diff --git a/gcc/ada/init.c b/gcc/ada/init.c index 00f32e5..300a7e1 100644 --- a/gcc/ada/init.c +++ b/gcc/ada/init.c @@ -1725,7 +1725,7 @@ __gnat_install_handler (void) #include #endif -#if ((defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6)) || defined (__x86_64__)) && !defined(__RTP__) +#if ((defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6))) && !defined(__RTP__) #define VXWORKS_FORCE_GUARD_PAGE 1 #include extern size_t vxIntStackOverflowSize; -- cgit v1.1 From 4669743bd255d2ab4ff33672e8843a914e5c1d35 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Wed, 10 Jul 2019 09:02:55 +0000 Subject: [Ada] Spurious run-time error with 64-bit modular types As a lexical element an integer literal has type Universal_Integer, i.e is compatible with any integer type. This is semantically consistent and simplifies type checking and subsequent constant folding when applicable. An exception is caused by 64-bit modular types, whose upper bound is not representable in a non-static context that will use 64-bit integers at run-time. For such cases we need to preserve the information that the analyzed literal has that modular type. For simplicity we preseve the information for all integer literals that result from a modular operation. This happens after prior analysis (or construction) of the literal, and after type checking and resolution. 2019-07-10 Ed Schonberg gcc/ada/ * sem_ch2.adb (Analyze_Integer_Literal): Preserve the type of the literal if prior analysis determined that its type is a modular integer type. gcc/testsuite/ * gnat.dg/modular5.adb: New testcase. From-SVN: r273352 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/sem_ch2.adb | 21 ++++++++++++++++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/modular5.adb | 26 ++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/modular5.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 996dd18..94fab7f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-10 Ed Schonberg + + * sem_ch2.adb (Analyze_Integer_Literal): Preserve the type of + the literal if prior analysis determined that its type is a + modular integer type. + 2019-07-10 Doug Rupp * init.c: Do not attempt to re-arm guard page on x86_64-vx7(r2). diff --git a/gcc/ada/sem_ch2.adb b/gcc/ada/sem_ch2.adb index 3b46ad5..0a282d4 100644 --- a/gcc/ada/sem_ch2.adb +++ b/gcc/ada/sem_ch2.adb @@ -24,12 +24,14 @@ ------------------------------------------------------------------------------ with Atree; use Atree; +with Einfo; use Einfo; with Namet; use Namet; with Opt; use Opt; with Restrict; use Restrict; with Rident; use Rident; with Sem_Ch8; use Sem_Ch8; with Sem_Dim; use Sem_Dim; +-- with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; with Stand; use Stand; with Uintp; use Uintp; @@ -83,7 +85,24 @@ package body Sem_Ch2 is procedure Analyze_Integer_Literal (N : Node_Id) is begin - Set_Etype (N, Universal_Integer); + -- As a lexical element, an integer literal has type Universal_Integer, + -- i.e., is compatible with any integer type. This is semantically + -- consistent and simplifies type checking and subsequent constant + -- folding when needed. An exception is caused by 64-bit modular types, + -- whose upper bound is not representable in a nonstatic context that + -- will use 64-bit integers at run time. For such cases, we need to + -- preserve the information that the analyzed literal has that modular + -- type. For simplicity, we preserve the information for all integer + -- literals that result from a modular operation. This happens after + -- prior analysis (or construction) of the literal, and after type + -- checking and resolution. + + if No (Etype (N)) + or else not Is_Modular_Integer_Type (Etype (N)) + then + Set_Etype (N, Universal_Integer); + end if; + Set_Is_Static_Expression (N); end Analyze_Integer_Literal; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e2dc5fe..a953397 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-10 Ed Schonberg + * gnat.dg/modular5.adb: New testcase. + +2019-07-10 Ed Schonberg + * gnat.dg/limited3.adb, gnat.dg/limited3_pkg.adb, gnat.dg/limited3_pkg.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/modular5.adb b/gcc/testsuite/gnat.dg/modular5.adb new file mode 100644 index 0000000..7fcf59c --- /dev/null +++ b/gcc/testsuite/gnat.dg/modular5.adb @@ -0,0 +1,26 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +procedure Modular5 is + type U64 is mod 2 ** 64; + Maybe : Boolean := 2 ** 10 < U64'Succ (U64'last - 1); + For_Sure : Boolean := U64'(18446744073709551615) > 2; + Ditto : Boolean := 18446744073709551615 > 2; + + generic + type TG is mod <>; + package PG is + X : TG; + pragma Assert (for all K in 1 .. 2 => 2 ** K <= TG'Last); + pragma Assert (for all K in 1 .. 2 => 2 ** K <= TG'Last - 1); + + Maybe : Boolean := 2 ** 10 < TG'Succ (TG'last - 1); + For_Sure : Boolean := TG'(18446744073709551615) > 2; + end PG; + + package IG is new PG (U64); + +begin + pragma Assert (for all K in 1 .. 2 => 2 ** K <= U64'Last); + pragma Assert (for all K in 1 .. 2 => 2 ** K <= U64'Last - 1); +end Modular5; -- cgit v1.1 From f861d731ca497443702f78b78d5090063c17539d Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Wed, 10 Jul 2019 09:03:00 +0000 Subject: [Ada] System.Strings.Stream_Ops: do not depend on Stream_IO Dependence was only from Ada.Streams.Stream_IO.End_Error exception which is renaming of the Ada.IO_Exceptions.End_Error. Use Ada.IO_Exceptions.End_Error directly. 2019-07-10 Dmitriy Anisimkov gcc/ada/ * libgnat/s-ststop.adb: Remove System.Strings.Stream_Ops dependence on System.Streams.Stream_IO. From-SVN: r273353 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/libgnat/s-ststop.adb | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 94fab7f..1ebe119 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Dmitriy Anisimkov + + * libgnat/s-ststop.adb: Remove System.Strings.Stream_Ops + dependence on System.Streams.Stream_IO. + 2019-07-10 Ed Schonberg * sem_ch2.adb (Analyze_Integer_Literal): Preserve the type of diff --git a/gcc/ada/libgnat/s-ststop.adb b/gcc/ada/libgnat/s-ststop.adb index 9f5c6ec..cf594b0 100644 --- a/gcc/ada/libgnat/s-ststop.adb +++ b/gcc/ada/libgnat/s-ststop.adb @@ -31,8 +31,8 @@ pragma Compiler_Unit_Warning; +with Ada.IO_Exceptions; use Ada.IO_Exceptions; with Ada.Streams; use Ada.Streams; -with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO; with Ada.Unchecked_Conversion; with System; use System; -- cgit v1.1 From 8389386c6d55d57afc3ae01f71546ac4468f7926 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 10 Jul 2019 13:24:32 +0000 Subject: gimple-parser.c (c_parser_gimple_postfix_expression): Support _Literal (int *) &x for address literals. 2019-07-10 Richard Biener c/ * gimple-parser.c (c_parser_gimple_postfix_expression): Support _Literal (int *) &x for address literals. * tree-ssa-sccvn.c (vn_reference_lookup_3): Look at valueized LHS whenever possible. * gcc.dg/torture/ssa-fre-5.c: New testcase. * gcc.dg/torture/ssa-fre-6.c: Likewise. * gcc.dg/torture/ssa-fre-7.c: Likewise. From-SVN: r273354 --- gcc/ChangeLog | 5 ++++ gcc/c/ChangeLog | 5 ++++ gcc/c/gimple-parser.c | 6 +++-- gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/gcc.dg/torture/ssa-fre-5.c | 27 ++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/ssa-fre-6.c | 27 ++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/ssa-fre-7.c | 29 +++++++++++++++++++++ gcc/tree-ssa-sccvn.c | 43 ++++++++++++++++++++++++++------ 8 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/ssa-fre-5.c create mode 100644 gcc/testsuite/gcc.dg/torture/ssa-fre-6.c create mode 100644 gcc/testsuite/gcc.dg/torture/ssa-fre-7.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f98633..ac390d65 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Richard Biener + + * tree-ssa-sccvn.c (vn_reference_lookup_3): Look at valueized + LHS whenever possible. + 2019-07-09 Jan Hubicka * tree-ssa-alias.c (nonoverlapping_component_refs_p_1): Break out diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 29836ff..bb0573e 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Richard Biener + + * gimple-parser.c (c_parser_gimple_postfix_expression): Support + _Literal (int *) &x for address literals. + 2019-07-09 Martin Sebor PR c++/61339 diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index 9a65394..a0ea721 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -1606,8 +1606,10 @@ c_parser_gimple_postfix_expression (gimple_parser &parser) tree val = c_parser_gimple_postfix_expression (parser).value; if (! val || val == error_mark_node - || ! CONSTANT_CLASS_P (val) - || (addr_p && TREE_CODE (val) != STRING_CST)) + || (!CONSTANT_CLASS_P (val) + && !(addr_p + && (TREE_CODE (val) == STRING_CST + || DECL_P (val))))) { c_parser_error (parser, "invalid _Literal"); return expr; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a953397..840d9c1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-10 Richard Biener + + * gcc.dg/torture/ssa-fre-5.c: New testcase. + * gcc.dg/torture/ssa-fre-6.c: Likewise. + * gcc.dg/torture/ssa-fre-7.c: Likewise. + 2019-07-10 Ed Schonberg * gnat.dg/modular5.adb: New testcase. diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c new file mode 100644 index 0000000..5ee9d64 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-5.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ +/* { dg-additional-options "-fgimple -fdump-tree-fre1" } */ + +typedef int v4si __attribute__((vector_size(16))); + +int __GIMPLE (ssa,startwith("fre")) +foo () +{ + int * p; + int i; + int x[4]; + long unsigned int _1; + long unsigned int _2; + int _7; + + __BB(2): + i_3 = 0; + _1 = (long unsigned int) i_3; + _2 = _1 * 4ul; + p_4 = _Literal (int *) &x + _2; + __MEM ((v4si *)p_4) = _Literal (v4si) { 1, 2, 3, 4 }; + _7 = x[0]; + return _7; +} + +/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c new file mode 100644 index 0000000..ecdd8f6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-6.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ +/* { dg-additional-options "-fgimple -fdump-tree-fre1" } */ + +typedef int v4si __attribute__((vector_size(16))); + +int __GIMPLE (ssa,startwith("fre")) +foo () +{ + int * p; + int i; + int x[4]; + long unsigned int _1; + long unsigned int _2; + int _7; + + __BB(2): + i_3 = 0; + _1 = (long unsigned int) i_3; + _2 = _1 * 4ul; + p_4 = _Literal (int *) &x + _2; + __MEM ((v4si *)p_4) = _Literal (v4si) {}; + _7 = x[0]; + return _7; +} + +/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/ssa-fre-7.c b/gcc/testsuite/gcc.dg/torture/ssa-fre-7.c new file mode 100644 index 0000000..07f3c9d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/ssa-fre-7.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ +/* { dg-additional-options "-fgimple -fdump-tree-fre1" } */ + +typedef int v4si __attribute__((vector_size(16))); + +int __GIMPLE (ssa,startwith("fre")) +foo (int c) +{ + int * p; + int i; + int x[4]; + long unsigned int _1; + long unsigned int _2; + int _7; + v4si _6; + + __BB(2): + i_3 = 0; + _1 = (long unsigned int) i_3; + _2 = _1 * 4ul; + p_4 = _Literal (int *) &x + _2; + _6 = _Literal (v4si) { c_5(D), c_5(D), c_5(D), c_5(D) }; + __MEM ((v4si *)p_4) = _6; + _7 = x[0]; + return _7; +} + +/* { dg-final { scan-tree-dump "return c_5\\(D\\);" "fre1" } } */ diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 9186f15..777cf58 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2488,12 +2488,22 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0) { + tree lhs = gimple_assign_lhs (def_stmt); tree base2; poly_int64 offset2, size2, maxsize2; HOST_WIDE_INT offset2i, size2i; bool reverse; - base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt), - &offset2, &size2, &maxsize2, &reverse); + if (lhs_ref_ok) + { + base2 = ao_ref_base (&lhs_ref); + offset2 = lhs_ref.offset; + size2 = lhs_ref.size; + maxsize2 = lhs_ref.max_size; + reverse = reverse_storage_order_for_component_p (lhs); + } + else + base2 = get_ref_base_and_extent (lhs, + &offset2, &size2, &maxsize2, &reverse); if (known_size_p (maxsize2) && known_eq (maxsize2, size2) && adjust_offsets_for_equal_base_address (base, &offset, @@ -2541,12 +2551,22 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, || (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME && is_gimple_min_invariant (SSA_VAL (gimple_assign_rhs1 (def_stmt)))))) { + tree lhs = gimple_assign_lhs (def_stmt); tree base2; poly_int64 offset2, size2, maxsize2; HOST_WIDE_INT offset2i, size2i; bool reverse; - base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt), - &offset2, &size2, &maxsize2, &reverse); + if (lhs_ref_ok) + { + base2 = ao_ref_base (&lhs_ref); + offset2 = lhs_ref.offset; + size2 = lhs_ref.size; + maxsize2 = lhs_ref.max_size; + reverse = reverse_storage_order_for_component_p (lhs); + } + else + base2 = get_ref_base_and_extent (lhs, + &offset2, &size2, &maxsize2, &reverse); if (base2 && !reverse && known_eq (maxsize2, size2) @@ -2627,12 +2647,21 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, downstream, not so much for actually doing the insertion. */ && data->partial_defs.is_empty ()) { + tree lhs = gimple_assign_lhs (def_stmt); tree base2; poly_int64 offset2, size2, maxsize2; bool reverse; - base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt), - &offset2, &size2, &maxsize2, - &reverse); + if (lhs_ref_ok) + { + base2 = ao_ref_base (&lhs_ref); + offset2 = lhs_ref.offset; + size2 = lhs_ref.size; + maxsize2 = lhs_ref.max_size; + reverse = reverse_storage_order_for_component_p (lhs); + } + else + base2 = get_ref_base_and_extent (lhs, + &offset2, &size2, &maxsize2, &reverse); tree def_rhs = gimple_assign_rhs1 (def_stmt); if (!reverse && known_size_p (maxsize2) -- cgit v1.1 From 95efa2279195e2b86afc986fd6e917c2704575d0 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 10 Jul 2019 13:40:12 +0000 Subject: re PR tree-optimization/91126 (Incorrect constant propagation of BIT_FIELD_REF) 2019-07-10 Richard Biener PR tree-optimization/91126 * tree-ssa-sccvn.c (n_walk_cb_data::push_partial_def): Adjust native encoding offset for BYTES_BIG_ENDIAN. (vn_reference_lookup_3): Likewise. * gcc.dg/torture/pr91126.c: New testcase. From-SVN: r273355 --- gcc/ChangeLog | 7 +++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr91126.c | 28 ++++++++++++++++++++++++++++ gcc/tree-ssa-sccvn.c | 25 +++++++++++++++++++++++-- 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr91126.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac390d65..9b32482 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2019-07-10 Richard Biener + PR tree-optimization/91126 + * tree-ssa-sccvn.c (n_walk_cb_data::push_partial_def): Adjust + native encoding offset for BYTES_BIG_ENDIAN. + (vn_reference_lookup_3): Likewise. + +2019-07-10 Richard Biener + * tree-ssa-sccvn.c (vn_reference_lookup_3): Look at valueized LHS whenever possible. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 840d9c1..e531f0a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2019-07-10 Richard Biener + PR tree-optimization/91126 + * gcc.dg/torture/pr91126.c: New testcase. + +2019-07-10 Richard Biener + * gcc.dg/torture/ssa-fre-5.c: New testcase. * gcc.dg/torture/ssa-fre-6.c: Likewise. * gcc.dg/torture/ssa-fre-7.c: Likewise. diff --git a/gcc/testsuite/gcc.dg/torture/pr91126.c b/gcc/testsuite/gcc.dg/torture/pr91126.c new file mode 100644 index 0000000..8e34815 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr91126.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ + +struct S +{ + __INT32_TYPE__ a : 24; + __INT32_TYPE__ b : 8; +} s; + +int +main() +{ + s.a = 0xfefefe; + s.b = 0xfe; + unsigned char c; + c = ((unsigned char *)&s)[0]; + if (c != 0xfe) + __builtin_abort (); + c = ((unsigned char *)&s)[1]; + if (c != 0xfe) + __builtin_abort (); + c = ((unsigned char *)&s)[2]; + if (c != 0xfe) + __builtin_abort (); + c = ((unsigned char *)&s)[3]; + if (c != 0xfe) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 777cf58..73c77d1 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1832,10 +1832,20 @@ vn_walk_cb_data::push_partial_def (const pd_data &pd, tree vuse, 0, MIN ((HOST_WIDE_INT)sizeof (buffer), pd.size)); else { + unsigned pad = 0; + if (BYTES_BIG_ENDIAN + && is_a (TYPE_MODE (TREE_TYPE (pd.rhs)))) + { + /* On big-endian the padding is at the 'front' so + just skip the initial bytes. */ + fixed_size_mode mode = as_a + (TYPE_MODE (TREE_TYPE (pd.rhs))); + pad = GET_MODE_SIZE (mode) - pd.size; + } len = native_encode_expr (pd.rhs, buffer + MAX (0, pd.offset), sizeof (buffer - MAX (0, pd.offset)), - MAX (0, -pd.offset)); + MAX (0, -pd.offset) + pad); if (len <= 0 || len < (pd.size - MAX (0, -pd.offset))) { @@ -2588,9 +2598,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, tree rhs = gimple_assign_rhs1 (def_stmt); if (TREE_CODE (rhs) == SSA_NAME) rhs = SSA_VAL (rhs); + unsigned pad = 0; + if (BYTES_BIG_ENDIAN + && is_a (TYPE_MODE (TREE_TYPE (rhs)))) + { + /* On big-endian the padding is at the 'front' so + just skip the initial bytes. */ + fixed_size_mode mode + = as_a (TYPE_MODE (TREE_TYPE (rhs))); + pad = GET_MODE_SIZE (mode) - size2i / BITS_PER_UNIT; + } len = native_encode_expr (rhs, buffer, sizeof (buffer), - (offseti - offset2i) / BITS_PER_UNIT); + ((offseti - offset2i) / BITS_PER_UNIT + + pad)); if (len > 0 && len * BITS_PER_UNIT >= maxsizei) { tree type = vr->type; -- cgit v1.1 From 12bb04368e7fcbdd8d3744a440eee23c9293958f Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 10 Jul 2019 17:16:12 +0200 Subject: Fix wi::lshift 2019-07-10 Marc Glisse * wide-int.h (wi::lshift): Reject negative values for the fast path. From-SVN: r273356 --- gcc/ChangeLog | 4 ++++ gcc/wide-int.h | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b32482..f109a8c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2019-07-10 Marc Glisse + + * wide-int.h (wi::lshift): Reject negative values for the fast path. + 2019-07-10 Richard Biener PR tree-optimization/91126 diff --git a/gcc/wide-int.h b/gcc/wide-int.h index bb8ced1..6c816cc 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -3034,8 +3034,7 @@ wi::lshift (const T1 &x, const T2 &y) if (STATIC_CONSTANT_P (xi.precision > HOST_BITS_PER_WIDE_INT) ? (STATIC_CONSTANT_P (shift < HOST_BITS_PER_WIDE_INT - 1) && xi.len == 1 - && xi.val[0] <= (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) - HOST_WIDE_INT_MAX >> shift)) + && IN_RANGE (xi.val[0], 0, HOST_WIDE_INT_MAX >> shift)) : precision <= HOST_BITS_PER_WIDE_INT) { val[0] = xi.ulow () << shift; -- cgit v1.1 From 613caed2feb9cfc8158308670b59df3d031ec629 Mon Sep 17 00:00:00 2001 From: Vladimir Makarov Date: Wed, 10 Jul 2019 16:07:10 +0000 Subject: re PR target/91102 (aarch64 ICE on Linux kernel with -Os starting with r270266) 2019-07-10 Vladimir Makarov PR target/91102 * lra-constraints.c (process_alt_operands): Don't match user defined regs only if they are early clobbers. 2019-07-10 Vladimir Makarov PR target/91102 * gcc.target/aarch64/pr91102.c: New test. From-SVN: r273357 --- gcc/ChangeLog | 6 ++++++ gcc/lra-constraints.c | 17 +++++++++++++---- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/aarch64/pr91102.c | 26 ++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/pr91102.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f109a8c..e7004e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-10 Vladimir Makarov + + PR target/91102 + * lra-constraints.c (process_alt_operands): Don't match user + defined regs only if they are early clobbers. + 2019-07-10 Marc Glisse * wide-int.h (wi::lshift): Reject negative values for the fast path. diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index d1d99e0..55d8d13 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -2172,8 +2172,9 @@ process_alt_operands (int only_alternative) else { /* Operands don't match. If the operands are - different user defined explicit hard registers, - then we cannot make them match. */ + different user defined explicit hard + registers, then we cannot make them match + when one is early clobber operand. */ if ((REG_P (*curr_id->operand_loc[nop]) || SUBREG_P (*curr_id->operand_loc[nop])) && (REG_P (*curr_id->operand_loc[m]) @@ -2192,9 +2193,17 @@ process_alt_operands (int only_alternative) && REG_P (m_reg) && HARD_REGISTER_P (m_reg) && REG_USERVAR_P (m_reg)) - break; + { + int i; + + for (i = 0; i < early_clobbered_regs_num; i++) + if (m == early_clobbered_nops[i]) + break; + if (i < early_clobbered_regs_num + || early_clobber_p) + break; + } } - /* Both operands must allow a reload register, otherwise we cannot make them match. */ if (curr_alt[m] == NO_REGS) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e531f0a..6b2bf88 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Vladimir Makarov + + PR target/91102 + * gcc.target/aarch64/pr91102.c: New test. + 2019-07-10 Richard Biener PR tree-optimization/91126 diff --git a/gcc/testsuite/gcc.target/aarch64/pr91102.c b/gcc/testsuite/gcc.target/aarch64/pr91102.c new file mode 100644 index 0000000..70b9904 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr91102.c @@ -0,0 +1,26 @@ +/* PR target/91102 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int +foo (long d, long l) +{ + register long e asm ("x1") = d; + register long f asm("x2") = l; + asm ("" : : "r" (e), "r" (f)); + return 3; +} + +struct T { int i; int j; }; +union S { long h; struct T t; }; + +void +bar (union S b) +{ + while (1) + { + union S c = b; + c.t.j++; + b.h = foo (b.h, c.h); + } +} -- cgit v1.1 From b59ff58620d1d4ffff5c74bd9f9f10f3cb222d8e Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 10 Jul 2019 16:15:52 +0000 Subject: PR testsuite/91132 - test gcc.dg/strlenopt-67.c in r273317 fails gcc/testsuite/ChangeLog: * gcc.dg/strlenopt-67.c: Removed second copy of test. From-SVN: r273358 --- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/strlenopt-67.c | 52 ------------------------------------- 2 files changed, 5 insertions(+), 52 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6b2bf88..7172061 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-10 Martin Sebor + + PR testsuite/91132 + * gcc.dg/strlenopt-67.c: Removed second copy of test. + 2019-07-10 Vladimir Makarov PR target/91102 diff --git a/gcc/testsuite/gcc.dg/strlenopt-67.c b/gcc/testsuite/gcc.dg/strlenopt-67.c index a2bcfba..e1b1de2 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-67.c +++ b/gcc/testsuite/gcc.dg/strlenopt-67.c @@ -50,55 +50,3 @@ int f8 (void) } /* { dg-final { scan-tree-dump-times "abort|strlen" 0 "optimized" } } */ -/* PR tree-optimization/ - incorrrect strlen result after second strcpy - into the same destination. - { dg-do compile } - { dg-options "-O2 -Wall -fdump-tree-optimized" } */ - -// #include "strlenopt.h" - -char a[4]; - -int f4 (void) -{ - char b[4]; - __builtin_strcpy (b, "12"); - - int i = __builtin_strcmp (a, b); - - __builtin_strcpy (b, "123"); - if (__builtin_strlen (b) != 3) - __builtin_abort (); - - return i; -} - -int f6 (void) -{ - char b[6]; - __builtin_strcpy (b, "1234"); - - int i = __builtin_strcmp (a, b); - - __builtin_strcpy (b, "12345"); - if (__builtin_strlen (b) != 5) - __builtin_abort (); - - return i; -} - -int f8 (void) -{ - char b[8]; - __builtin_strcpy (b, "1234"); - - int i = __builtin_strcmp (a, b); - - __builtin_strcpy (b, "1234567"); - if (__builtin_strlen (b) != 7) - __builtin_abort (); - - return i; -} - -/* { dg-final { scan-tree-dump-times "abort|strlen" 0 "optimized" } } */ -- cgit v1.1 From 41112d9519d48a503864a157d90fd3c6ef974bfe Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 10 Jul 2019 17:56:40 +0000 Subject: compiler: add break label in 1,2-case select statement lowering CL 184998 added optimizations for one- and two-case select statements. But it didn't handle break statement in the select case correctly. Specifically, it didn't add the label definition, so it could result in a dangling goto. This CL fixes this, by adding the label definition. A test case is CL 185520. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/185519 From-SVN: r273359 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/statements.cc | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 410afb0..582ded3 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -7a8e10be0ddb8909ce25a264d03b24cee4df60cc +170ecdf6b2eab8aac2b8c852fa95d3c36d6bf604 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 1e88fab..b0b576f 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -5855,6 +5855,10 @@ Select_statement::lower_one_case(Block* b) Statement::make_block_statement(scase.statements(), scase.location()); b->add_statement(bs); + Statement* label = + Statement::make_unnamed_label_statement(this->break_label()); + b->add_statement(label); + this->is_lowered_ = true; return Statement::make_block_statement(b, loc); } @@ -5958,6 +5962,10 @@ Select_statement::lower_two_case(Block* b) Statement::make_if_statement(call, bchan, defcase.statements(), loc); b->add_statement(ifs); + Statement* label = + Statement::make_unnamed_label_statement(this->break_label()); + b->add_statement(label); + this->is_lowered_ = true; return Statement::make_block_statement(b, loc); } -- cgit v1.1 From 4b8d9b23371d3ee0f7a9c1d99e80745400542930 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 10 Jul 2019 18:12:54 +0000 Subject: compiler: finalize methods when importing types This patch changes the compiler to be more aggressive about finalizing methods on imported types, to avoid problems with interface types that are imported but remain unreachable until a later stage in the compilation. The normal pattern prior to this change was that the import process would leave imported interface types alone, and rely on Gogo::finalize_methods to locate and finalize all interface types at a later point. This way of doing things was not working in all cases due to the fact that we can import an interface type that is only reachable from the body of an inlinable function, meaning that we can't "find" the type during the methods finalize phase. The importer's Import::read_types() now makes a pass over all imported types to finalize methods on any newly imported type, which takes care of the issue. New test case for this problem in CL 185517. Fixes golang/go#33013 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/185518 From-SVN: r273364 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/gogo.cc | 18 ------------------ gcc/go/gofrontend/gogo.h | 18 ++++++++++++++++++ gcc/go/gofrontend/import.cc | 39 ++++++++++++++++++++++++++++++++++++++- gcc/go/gofrontend/import.h | 10 ++++++++-- 5 files changed, 65 insertions(+), 22 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 582ded3..7b3f874 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -170ecdf6b2eab8aac2b8c852fa95d3c36d6bf604 +ec754ff4617d564d3dc377121ea9ac5e55f6535a The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 3abf7ea..234a4f4 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -3422,24 +3422,6 @@ Gogo::create_function_descriptors() this->traverse(&cfd); } -// Look for interface types to finalize methods of inherited -// interfaces. - -class Finalize_methods : public Traverse -{ - public: - Finalize_methods(Gogo* gogo) - : Traverse(traverse_types), - gogo_(gogo) - { } - - int - type(Type*); - - private: - Gogo* gogo_; -}; - // Finalize the methods of an interface type. int diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index c4d5bab..cb8e25f 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -3556,6 +3556,24 @@ class Traverse Expressions_seen* expressions_seen_; }; +// This class looks for interface types to finalize methods of inherited +// interfaces. + +class Finalize_methods : public Traverse +{ + public: + Finalize_methods(Gogo* gogo) + : Traverse(traverse_types), + gogo_(gogo) + { } + + int + type(Type*); + + private: + Gogo* gogo_; +}; + // A class which makes it easier to insert new statements before the // current statement during a traversal. diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index abf0b54..ad7ba7f 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -290,10 +290,16 @@ Import::Import(Stream* stream, Location location) : gogo_(NULL), stream_(stream), location_(location), package_(NULL), add_to_globals_(false), packages_(), type_data_(), type_pos_(0), type_offsets_(), builtin_types_((- SMALLEST_BUILTIN_CODE) + 1), - types_(), version_(EXPORT_FORMAT_UNKNOWN) + types_(), finalizer_(NULL), version_(EXPORT_FORMAT_UNKNOWN) { } +Import::~Import() +{ + if (this->finalizer_ != NULL) + delete this->finalizer_; +} + // Import the data in the associated stream. Package* @@ -672,9 +678,40 @@ Import::read_types() this->gogo_->add_named_type(nt); } + // Finalize methods for any imported types. This is done after most of + // read_types() is complete so as to avoid method finalization of a type + // whose methods refer to types that are only partially read in. + // See issue #33013 for more on why this is needed. + this->finalize_methods(); + return true; } +void +Import::finalize_methods() +{ + if (this->finalizer_ == NULL) + this->finalizer_ = new Finalize_methods(gogo_); + Unordered_set(Type*) real_for_named; + for (size_t i = 1; i < this->types_.size(); i++) + { + Type* type = this->types_[i]; + if (type != NULL && type->named_type() != NULL) + { + this->finalizer_->type(type); + real_for_named.insert(type->named_type()->real_type()); + } + } + for (size_t i = 1; i < this->types_.size(); i++) + { + Type* type = this->types_[i]; + if (type != NULL + && type->named_type() == NULL + && real_for_named.find(type) == real_for_named.end()) + this->finalizer_->type(type); + } +} + // Import a constant. void diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h index db51f72..ea01bbc 100644 --- a/gcc/go/gofrontend/import.h +++ b/gcc/go/gofrontend/import.h @@ -20,6 +20,7 @@ class Expression; class Import_function_body; class Temporary_statement; class Unnamed_label; +class Finalize_methods; // Expressions can be imported either directly from import data (for // simple constant expressions that can appear in a const declaration @@ -207,8 +208,7 @@ class Import : public Import_expression // Constructor. Import(Stream*, Location); - virtual ~Import() - {} + virtual ~Import(); // Register the builtin types. void @@ -423,6 +423,10 @@ class Import : public Import_expression return true; } + // Finalize methods for newly imported types. + void + finalize_methods(); + // The general IR. Gogo* gogo_; // The stream from which to read import data. @@ -446,6 +450,8 @@ class Import : public Import_expression std::vector builtin_types_; // Mapping from exported type codes to Type structures. std::vector types_; + // Helper for finalizing methods. + Finalize_methods* finalizer_; // Version of export data we're reading. Export_data_version version_; }; -- cgit v1.1 From 8ba8ebffc4621552febf47eea470c260488418b5 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 10 Jul 2019 18:41:44 +0000 Subject: [arm] Fix BE index for single-var vector initialisers (PR91060) If a vector constructor has a single nonconstant element, neon_expand_vector_init loads the constant lanes and then inserts the nonconstant value. The problem was that it was doing the insertion using the arm_neon.h neon_vset_lane patterns, which use architectural lane numbering rather than GCC lane numbering. 2019-07-10 Richard Sandiford gcc/ PR target/91060 * config/arm/iterators.md (V2DI_ONLY): New mode iterator. * config/arm/neon.md (vec_set_internal): Add a '@' prefix. (vec_setv2di_internal): Reexpress as... (@vec_set_internal): ...this. * config/arm/arm.c (neon_expand_vector_init): Use gen_vec_set_internal rather than gen_neon_vset_lane. From-SVN: r273365 --- gcc/ChangeLog | 10 ++++++++++ gcc/config/arm/arm.c | 35 ++--------------------------------- gcc/config/arm/iterators.md | 3 +++ gcc/config/arm/neon.md | 14 +++++++------- 4 files changed, 22 insertions(+), 40 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e7004e3..4c75120 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-07-10 Richard Sandiford + + PR target/91060 + * config/arm/iterators.md (V2DI_ONLY): New mode iterator. + * config/arm/neon.md (vec_set_internal): Add a '@' prefix. + (vec_setv2di_internal): Reexpress as... + (@vec_set_internal): ...this. + * config/arm/arm.c (neon_expand_vector_init): Use gen_vec_set_internal + rather than gen_neon_vset_lane. + 2019-07-10 Vladimir Makarov PR target/91102 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f42a7b1..81286ca 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -12471,7 +12471,7 @@ neon_expand_vector_init (rtx target, rtx vals) if (n_var == 1) { rtx copy = copy_rtx (vals); - rtx index = GEN_INT (one_var); + rtx merge_mask = GEN_INT (1 << one_var); /* Load constant part of vector, substitute neighboring value for varying element. */ @@ -12480,38 +12480,7 @@ neon_expand_vector_init (rtx target, rtx vals) /* Insert variable. */ x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, one_var)); - switch (mode) - { - case E_V8QImode: - emit_insn (gen_neon_vset_lanev8qi (target, x, target, index)); - break; - case E_V16QImode: - emit_insn (gen_neon_vset_lanev16qi (target, x, target, index)); - break; - case E_V4HImode: - emit_insn (gen_neon_vset_lanev4hi (target, x, target, index)); - break; - case E_V8HImode: - emit_insn (gen_neon_vset_lanev8hi (target, x, target, index)); - break; - case E_V2SImode: - emit_insn (gen_neon_vset_lanev2si (target, x, target, index)); - break; - case E_V4SImode: - emit_insn (gen_neon_vset_lanev4si (target, x, target, index)); - break; - case E_V2SFmode: - emit_insn (gen_neon_vset_lanev2sf (target, x, target, index)); - break; - case E_V4SFmode: - emit_insn (gen_neon_vset_lanev4sf (target, x, target, index)); - break; - case E_V2DImode: - emit_insn (gen_neon_vset_lanev2di (target, x, target, index)); - break; - default: - gcc_unreachable (); - } + emit_insn (gen_vec_set_internal (mode, target, x, merge_mask, target)); return; } diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index e03a720..eca1663 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -186,6 +186,9 @@ ;; Modes with 8-bit elements. (define_mode_iterator VE [V8QI V16QI]) +;; V2DI only (for use with @ patterns). +(define_mode_iterator V2DI_ONLY [V2DI]) + ;; Modes with 64-bit elements only. (define_mode_iterator V64 [DI V2DI]) diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 4bfe770..6333e0e 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -319,7 +319,7 @@ "vld1.\t{%q0}, %A1" [(set_attr "type" "neon_load1_1reg")]) -(define_insn "vec_set_internal" +(define_insn "@vec_set_internal" [(set (match_operand:VD_LANE 0 "s_register_operand" "=w,w") (vec_merge:VD_LANE (vec_duplicate:VD_LANE @@ -340,7 +340,7 @@ } [(set_attr "type" "neon_load1_all_lanes,neon_from_gp")]) -(define_insn "vec_set_internal" +(define_insn "@vec_set_internal" [(set (match_operand:VQ2 0 "s_register_operand" "=w,w") (vec_merge:VQ2 (vec_duplicate:VQ2 @@ -369,12 +369,12 @@ [(set_attr "type" "neon_load1_all_lanes,neon_from_gp")] ) -(define_insn "vec_setv2di_internal" - [(set (match_operand:V2DI 0 "s_register_operand" "=w,w") - (vec_merge:V2DI - (vec_duplicate:V2DI +(define_insn "@vec_set_internal" + [(set (match_operand:V2DI_ONLY 0 "s_register_operand" "=w,w") + (vec_merge:V2DI_ONLY + (vec_duplicate:V2DI_ONLY (match_operand:DI 1 "nonimmediate_operand" "Um,r")) - (match_operand:V2DI 3 "s_register_operand" "0,0") + (match_operand:V2DI_ONLY 3 "s_register_operand" "0,0") (match_operand:SI 2 "immediate_operand" "i,i")))] "TARGET_NEON" { -- cgit v1.1 From 2cb7362310288cce61244e39f90fccd75b1c28e1 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 10 Jul 2019 18:41:51 +0000 Subject: Fix folding of vector EQ/NE For vector1 != vector2, we returned false if any elements were equal, rather than if all elements were equal. 2019-07-10 Richard Sandiford gcc/ * fold-const.c (fold_relational_const): Fix folding of vector-to-scalar NE_EXPRs. (test_vector_folding): Add more tests. From-SVN: r273366 --- gcc/ChangeLog | 6 ++++++ gcc/fold-const.c | 14 +++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4c75120..6166215 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-07-10 Richard Sandiford + * fold-const.c (fold_relational_const): Fix folding of + vector-to-scalar NE_EXPRs. + (test_vector_folding): Add more tests. + +2019-07-10 Richard Sandiford + PR target/91060 * config/arm/iterators.md (V2DI_ONLY): New mode iterator. * config/arm/neon.md (vec_set_internal): Add a '@' prefix. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0ca472d..edb23fd 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -14026,13 +14026,13 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1) { tree elem0 = VECTOR_CST_ELT (op0, i); tree elem1 = VECTOR_CST_ELT (op1, i); - tree tmp = fold_relational_const (code, type, elem0, elem1); + tree tmp = fold_relational_const (EQ_EXPR, type, elem0, elem1); if (tmp == NULL_TREE) return NULL_TREE; if (integer_zerop (tmp)) - return constant_boolean_node (false, type); + return constant_boolean_node (code == NE_EXPR, type); } - return constant_boolean_node (true, type); + return constant_boolean_node (code == EQ_EXPR, type); } tree_vector_builder elts; if (!elts.new_binary_operation (type, op0, op1, false)) @@ -14803,6 +14803,7 @@ test_vector_folding () tree type = build_vector_type (inner_type, 4); tree zero = build_zero_cst (type); tree one = build_one_cst (type); + tree index = build_index_vector (type, 0, 1); /* Verify equality tests that return a scalar boolean result. */ tree res_type = boolean_type_node; @@ -14810,6 +14811,13 @@ test_vector_folding () ASSERT_TRUE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type, zero, zero))); ASSERT_TRUE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, zero, one))); ASSERT_FALSE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, one, one))); + ASSERT_TRUE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, index, one))); + ASSERT_FALSE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type, + index, one))); + ASSERT_FALSE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, + index, index))); + ASSERT_TRUE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type, + index, index))); } /* Verify folding of VEC_DUPLICATE_EXPRs. */ -- cgit v1.1 From 4b5c5391849dd58f8cf3764b642da95e7e1aaaca Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 10 Jul 2019 19:29:56 +0000 Subject: [Darwin, PPC] Collate the system library spec into one expression. There's no need to redefine this dependent on the target header (that only works in the case that we have self-hosting which is less and less likely for the older system versions). Actually, what we need is for the correct library set to be used based on the SDK(s) that can target the chosen system. gcc/ChangeLog: 2019-07-10 Iain Sandoe * config/rs6000/darwin.h (LIB_SPEC): Collate this spec here. * config/rs6000/darwin7.h (LIB_SPEC): Remove. * config/rs6000/darwin8.h (LIB_SPEC): Remove. (DEF_MIN_OSX_VERSION): New. From-SVN: r273369 --- gcc/ChangeLog | 7 +++++++ gcc/config/rs6000/darwin.h | 18 ++++++++++++++++++ gcc/config/rs6000/darwin7.h | 12 +----------- gcc/config/rs6000/darwin8.h | 14 ++------------ 4 files changed, 28 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6166215..5d3c8d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-10 Iain Sandoe + + * config/rs6000/darwin.h (LIB_SPEC): Collate this spec here. + * config/rs6000/darwin7.h (LIB_SPEC): Remove. + * config/rs6000/darwin8.h (LIB_SPEC): Remove. + (DEF_MIN_OSX_VERSION): New. + 2019-07-10 Richard Sandiford * fold-const.c (fold_relational_const): Fix folding of diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index b0b5047..272cd45 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -86,6 +86,24 @@ extern int darwin_emit_picsym_stub; #define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128 +/* Machine dependent libraries. + Include libmx when targeting Darwin 7.0 and above, but before libSystem, + since the functions are actually in libSystem but for 7.x compatibility + we want them to be looked for in libmx first. + Include libSystemStubs when compiling against 10.3 - 10.5 SDKs (we assume + this is the case when targetting these) - but not for 64-bit long double. + Don't do either for m64, the library is either a dummy or non-existent. +*/ + +#undef LIB_SPEC +#define LIB_SPEC \ +"%{!static: \ + %{!m64:%{!mlong-double-64: \ + %{pg:%:version-compare(>< 10.3 10.5 mmacosx-version-min= -lSystemStubs_profile)} \ + %{!pg:%:version-compare(>< 10.3 10.5 mmacosx-version-min= -lSystemStubs)} \ + %:version-compare(>< 10.3 10.4 mmacosx-version-min= -lmx)}} \ + -lSystem \ +}" /* We want -fPIC by default, unless we're using -static to compile for the kernel or some such. The "-faltivec" option should have been diff --git a/gcc/config/rs6000/darwin7.h b/gcc/config/rs6000/darwin7.h index d299074..6a3adc0 100644 --- a/gcc/config/rs6000/darwin7.h +++ b/gcc/config/rs6000/darwin7.h @@ -17,21 +17,11 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ -/* Machine dependent libraries. Include libmx when compiling for - Darwin 7.0 and above, but before libSystem, since the functions are - actually in libSystem but for 7.x compatibility we want them to be - looked for in libmx first. Include libmx by default because otherwise - libstdc++ isn't usable. */ - -#undef LIB_SPEC -#define LIB_SPEC "%{!static:\ - %:version-compare(!< 10.3 mmacosx-version-min= -lmx)\ - -lSystem}" - /* This generation of tools (specifically the archive tool) did not export weak symbols from the TOC. */ #undef TARGET_WEAK_NOT_IN_ARCHIVE_TOC #define TARGET_WEAK_NOT_IN_ARCHIVE_TOC 1 +/* Default to the last version, with most support for C++. */ #undef DEF_MIN_OSX_VERSION #define DEF_MIN_OSX_VERSION "10.3.9" diff --git a/gcc/config/rs6000/darwin8.h b/gcc/config/rs6000/darwin8.h index ca4ede2..ec5a8af 100644 --- a/gcc/config/rs6000/darwin8.h +++ b/gcc/config/rs6000/darwin8.h @@ -17,15 +17,5 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ -/* Machine dependent libraries. Include libmx when compiling on - Darwin 7.0 and above, but before libSystem, since the functions are - actually in libSystem but for 7.x compatibility we want them to be - looked for in libmx first---but only do this if 7.x compatibility - is a concern, which it's not in 64-bit mode. Include - libSystemStubs when compiling on (not necessarily for) 8.0 and - above and not 64-bit long double. */ - -#undef LIB_SPEC -#define LIB_SPEC "%{!static:\ - %{!mlong-double-64:%{pg:-lSystemStubs_profile;:-lSystemStubs}} \ - %{!m64:%:version-compare(>< 10.3 10.4 mmacosx-version-min= -lmx)} -lSystem}" +#undef DEF_MIN_OSX_VERSION +#define DEF_MIN_OSX_VERSION "10.4" -- cgit v1.1 From 4ded6adc51bbcf3d4b6f43a91c76b0628815a8cd Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Wed, 10 Jul 2019 19:34:03 +0000 Subject: predicates.md (cint34_operand): Update SIGNED_34BIT_OFFSET_P call. 2019-07-10 Michael Meissner * config/rs6000/predicates.md (cint34_operand): Update SIGNED_34BIT_OFFSET_P call. (pcrel_address): Update SIGNED_34BIT_OFFSET_P call. (pcrel_external_address): Update SIGNED_34BIT_OFFSET_P call. * config/rs6000/rs6000.c (rs6000_prefixed_address): Update SIGNED_16BIT_OFFSET_P and SIGNED_34BIT_OFFSET_P calls. * config/rs6000/rs6000.h (SIGNED_16BIT_OFFSET_P): Remove EXTRA argument. (SIGNED_34BIT_OFFSET_P): Remove EXTRA argument. (SIGNED_16BIT_OFFSET_EXTRA_P): New macro, like SIGNED_16BIT_OFFSET_P with an EXTRA argument. (SIGNED_34BIT_OFFSET_EXTRA_P): New macro, like SIGNED_34BIT_OFFSET_P with an EXTRA argument. From-SVN: r273370 --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/config/rs6000/predicates.md | 6 +++--- gcc/config/rs6000/rs6000.c | 4 ++-- gcc/config/rs6000/rs6000.h | 27 +++++++++++++++++++-------- 4 files changed, 40 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d3c8d4..e5c05e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2019-07-10 Michael Meissner + + * config/rs6000/predicates.md (cint34_operand): Update + SIGNED_34BIT_OFFSET_P call. + (pcrel_address): Update SIGNED_34BIT_OFFSET_P call. + (pcrel_external_address): Update SIGNED_34BIT_OFFSET_P call. + * config/rs6000/rs6000.c (rs6000_prefixed_address): Update + SIGNED_16BIT_OFFSET_P and SIGNED_34BIT_OFFSET_P calls. + * config/rs6000/rs6000.h (SIGNED_16BIT_OFFSET_P): Remove EXTRA + argument. + (SIGNED_34BIT_OFFSET_P): Remove EXTRA argument. + (SIGNED_16BIT_OFFSET_EXTRA_P): New macro, like + SIGNED_16BIT_OFFSET_P with an EXTRA argument. + (SIGNED_34BIT_OFFSET_EXTRA_P): New macro, like + SIGNED_34BIT_OFFSET_P with an EXTRA argument. + 2019-07-10 Iain Sandoe * config/rs6000/darwin.h (LIB_SPEC): Collate this spec here. diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 45fa40a..e64f772 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -309,7 +309,7 @@ if (!TARGET_PREFIXED_ADDR) return 0; - return SIGNED_34BIT_OFFSET_P (INTVAL (op), 0); + return SIGNED_34BIT_OFFSET_P (INTVAL (op)); }) ;; Return 1 if op is a register that is not special. @@ -1638,7 +1638,7 @@ rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); - if (!CONST_INT_P (op1) || !SIGNED_34BIT_OFFSET_P (INTVAL (op1), 0)) + if (!CONST_INT_P (op1) || !SIGNED_34BIT_OFFSET_P (INTVAL (op1))) return false; op = op0; @@ -1673,7 +1673,7 @@ rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); - if (!CONST_INT_P (op1) || !SIGNED_34BIT_OFFSET_P (INTVAL (op1), 0)) + if (!CONST_INT_P (op1) || !SIGNED_34BIT_OFFSET_P (INTVAL (op1))) return false; op = op0; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ccc9d76..39fa6ec 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -21523,11 +21523,11 @@ rs6000_prefixed_address (rtx addr, machine_mode mode) return false; HOST_WIDE_INT value = INTVAL (op1); - if (!SIGNED_34BIT_OFFSET_P (value, 0)) + if (!SIGNED_34BIT_OFFSET_P (value)) return false; /* Offset larger than 16-bits? */ - if (!SIGNED_16BIT_OFFSET_P (value, 0)) + if (!SIGNED_16BIT_OFFSET_P (value)) return true; /* DQ instruction (bottom 4 bits must be 0) for vectors. */ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 9193d9e..5f3b9ed 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2526,16 +2526,27 @@ typedef struct GTY(()) machine_function #pragma GCC poison TARGET_FLOAT128 OPTION_MASK_FLOAT128 MASK_FLOAT128 #endif -/* Whether a given VALUE is a valid 16- or 34-bit signed offset. EXTRA is the - amount that we can't touch at the high end of the range (typically if the - address is split into smaller addresses, the extra covers the addresses - which might be generated when the insn is split). */ -#define SIGNED_16BIT_OFFSET_P(VALUE, EXTRA) \ - IN_RANGE (VALUE, \ +/* Whether a given VALUE is a valid 16 or 34-bit signed offset. */ +#define SIGNED_16BIT_OFFSET_P(VALUE) \ + IN_RANGE ((VALUE), \ + -(HOST_WIDE_INT_1 << 15), \ + (HOST_WIDE_INT_1 << 15) - 1) + +#define SIGNED_34BIT_OFFSET_P(VALUE) \ + IN_RANGE ((VALUE), \ + -(HOST_WIDE_INT_1 << 33), \ + (HOST_WIDE_INT_1 << 33) - 1) + +/* Like SIGNED_16BIT_OFFSET_P and SIGNED_34BIT_OFFSET_P, but with an extra + argument that gives a length to validate a range of addresses, to allow for + splitting insns into several insns, each of which has an offsettable + address. */ +#define SIGNED_16BIT_OFFSET_EXTRA_P(VALUE, EXTRA) \ + IN_RANGE ((VALUE), \ -(HOST_WIDE_INT_1 << 15), \ (HOST_WIDE_INT_1 << 15) - 1 - (EXTRA)) -#define SIGNED_34BIT_OFFSET_P(VALUE, EXTRA) \ - IN_RANGE (VALUE, \ +#define SIGNED_34BIT_OFFSET_EXTRA_P(VALUE, EXTRA) \ + IN_RANGE ((VALUE), \ -(HOST_WIDE_INT_1 << 33), \ (HOST_WIDE_INT_1 << 33) - 1 - (EXTRA)) -- cgit v1.1 From 639000e2121c2b15f6cdd555ca3f666305b3684d Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 11 Jul 2019 00:16:15 +0000 Subject: Daily bump. From-SVN: r273375 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c3e1766..bc314b8 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190710 +20190711 -- cgit v1.1 From 3e66e7b0d1efa3f78a5598884e2d5d526894833e Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 11 Jul 2019 07:32:04 +0000 Subject: re PR middle-end/91131 (Bad bitfield coalescing) 2019-07-11 Richard Biener PR middle-end/91131 * gimplify.c (gimplify_compound_literal_expr): Force a temporary when the object is volatile and we have not cleared it even though there are no nonzero elements. * gcc.target/i386/pr91131.c: New testcase. From-SVN: r273376 --- gcc/ChangeLog | 7 +++++++ gcc/gimplify.c | 2 +- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/i386/pr91131.c | 19 +++++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr91131.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e5c05e5..ee70694 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-11 Richard Biener + + PR middle-end/91131 + * gimplify.c (gimplify_compound_literal_expr): Force a temporary + when the object is volatile and we have not cleared it even though + there are no nonzero elements. + 2019-07-10 Michael Meissner * config/rs6000/predicates.md (cint34_operand): Update diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 239988b..146a86c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -5005,7 +5005,7 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, one field to assign, initialize the target from a temporary. */ if (TREE_THIS_VOLATILE (object) && !TREE_ADDRESSABLE (type) - && num_nonzero_elements > 0 + && (num_nonzero_elements > 0 || !cleared) && vec_safe_length (elts) > 1) { tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7172061..efebc72 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Richard Biener + + PR middle-end/91131 + * gcc.target/i386/pr91131.c: New testcase. + 2019-07-10 Martin Sebor PR testsuite/91132 diff --git a/gcc/testsuite/gcc.target/i386/pr91131.c b/gcc/testsuite/gcc.target/i386/pr91131.c new file mode 100644 index 0000000..85008ff --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91131.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct Reg_T { + unsigned int a : 3; + unsigned int b : 1; + unsigned int c : 4; +}; + +volatile struct Reg_T Reg_A; + +int +main () +{ + Reg_A = (struct Reg_T){ .a = 0, .b = 0, .c = 0 }; + return 0; +} + +/* { dg-final { scan-assembler-times "mov\[^\r\n\]*Reg_A" 1 } } */ -- cgit v1.1 From 435a6d9580fa1675537a4d2a3151802a15064d3d Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Thu, 11 Jul 2019 07:50:58 +0000 Subject: Do not try to further refine a VR_UNDEFINED result when intersecting value_ranges. From-SVN: r273377 --- gcc/ChangeLog | 6 ++++++ gcc/tree-vrp.c | 5 +++++ 2 files changed, 11 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee70694..f171853 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-11 Aldy Hernandez + + * tree-vrp.c (intersect_ranges): If we know the intersection is + empty, there is no need to conservatively add anything else to + the set. + 2019-07-11 Richard Biener PR middle-end/91131 diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index dc7f825..594ee9a 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -5977,6 +5977,11 @@ intersect_ranges (enum value_range_kind *vr0type, gcc_unreachable (); } + /* If we know the intersection is empty, there's no need to + conservatively add anything else to the set. */ + if (*vr0type == VR_UNDEFINED) + return; + /* As a fallback simply use { *VRTYPE, *VR0MIN, *VR0MAX } as result for the intersection. That's always a conservative correct estimate unless VR1 is a constant singleton range -- cgit v1.1 From a34badbdf000e931dfa1a1291cf2739e2c75e68d Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 11 Jul 2019 08:01:07 +0000 Subject: [Ada] Avoid spurious warning on wrong order of operator call arguments GNAT issues a warning under -gnatwa when actuals for a call are named like the formals, but in a different order. This is inappropriate for calls to operators in infix form, when e.g. Right <= Left is in general the intended order. Special case calls to operators to avoid that spurious warning. 2019-07-11 Yannick Moy gcc/ada/ * sem_res.adb (Check_Argument_Order): Special case calls to operators. gcc/testsuite/ * gnat.dg/warn21.adb, gnat.dg/warn21.ads: New testcase. From-SVN: r273378 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_res.adb | 7 ++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/warn21.adb | 6 ++++++ gcc/testsuite/gnat.dg/warn21.ads | 18 ++++++++++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/warn21.adb create mode 100644 gcc/testsuite/gnat.dg/warn21.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1ebe119..a2316ea 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Yannick Moy + + * sem_res.adb (Check_Argument_Order): Special case calls to + operators. + 2019-07-10 Dmitriy Anisimkov * libgnat/s-ststop.adb: Remove System.Strings.Stream_Ops diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index db642f0..78cbac0 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -3458,12 +3458,17 @@ package body Sem_Res is begin -- Nothing to do if no parameters, or original node is neither a -- function call nor a procedure call statement (happens in the - -- operator-transformed-to-function call case), or the call does + -- operator-transformed-to-function call case), or the call is to an + -- operator symbol (which is usually in infix form), or the call does -- not come from source, or this warning is off. if not Warn_On_Parameter_Order or else No (Parameter_Associations (N)) or else Nkind (Original_Node (N)) not in N_Subprogram_Call + or else (Nkind (Name (N)) = N_Identifier + and then Present (Entity (Name (N))) + and then Nkind (Entity (Name (N))) + = N_Defining_Operator_Symbol) or else not Comes_From_Source (N) then return; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index efebc72..24ecc21 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Yannick Moy + + * gnat.dg/warn21.adb, gnat.dg/warn21.ads: New testcase. + 2019-07-11 Richard Biener PR middle-end/91131 diff --git a/gcc/testsuite/gnat.dg/warn21.adb b/gcc/testsuite/gnat.dg/warn21.adb new file mode 100644 index 0000000..123dfdc --- /dev/null +++ b/gcc/testsuite/gnat.dg/warn21.adb @@ -0,0 +1,6 @@ +-- { dg-do compile } +-- { dg-options "-gnata -gnatwa" } + +package body Warn21 is + procedure Foo is null; +end Warn21; diff --git a/gcc/testsuite/gnat.dg/warn21.ads b/gcc/testsuite/gnat.dg/warn21.ads new file mode 100644 index 0000000..a091467 --- /dev/null +++ b/gcc/testsuite/gnat.dg/warn21.ads @@ -0,0 +1,18 @@ +package Warn21 is + + type Set is new Integer; + + function "<=" (Left : Set; Right : Set) return Boolean; + + function "=" (Left : Set; Right : Set) return Boolean with + Post => "="'Result = (Left <= Right and Right <= Left); + + procedure Foo; + +private + + function "<=" (Left : Set; Right : Set) return Boolean is (True); + function "=" (Left : Set; Right : Set) return Boolean is + (Left <= Right and Right <= Left); + +end Warn21; -- cgit v1.1 From 490ed9ba846d15baba24646b7ecf3ed6b7c19fcb Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 11 Jul 2019 08:01:21 +0000 Subject: [Ada] Elaboration order v4.0 and infinite loops This patch introduces binder switch -d_S which prompts the various phases of the elaboration order mechanism to output a short message concerning their commencement and completion. The output is useful when trying to determine whether a phase is stuck in an infinite loop. ------------ -- Source -- ------------ -- main.adb procedure Main is begin null; end Main; ---------------------------- -- Compilation and output -- ---------------------------- $ gnatmake -q main.adb -bargs -d_S -d_V elaborating units... collecting units... units collected. constructing library graph... validating library graph... library graph validated. library graph constructed. constructing invocation graph... validating invocation graph... invocation graph validated. invocation graph constructed. augmenting library graph... library graph augmented. discovering components... components discovered. validating elaboration order... elaboration order validated. units elaborated. 2019-07-11 Hristian Kirtchev gcc/ada/ * bindo.adb: Update the section of switches and debugging elaboration issues. * bindo.ads: Add type Elaboration_Phase. * bindo-augmentors.adb: Add use clause for Bindo.Writers.Phase_Writers. (Augment_Library_Graph): Signal the start and end of the aubmentation phase. * bindo-builders.adb: Add with and use clause for Bindo.Writers. Add use clause for Bindo.Writers.Phase_Writers. (Build_Invocation_Graph): Signal the start and end of the invocation graph construction phase. (Build_Library_Graph): Signal the start and end of the library graph construction phase. * bindo-diagnostics.adb: Add use clause for Bindo.Writers.Phase_Writers. (Diagnose_Cycle): Signal the start and end of the cycle diagnostic phase. * bindo-elaborators.adb: Add use clause for Bindo.Writers.Phase_Writers. (Elaborate_Units): Signal the start and end of the unit elaboration phase. * bindo-graphs.adb: Add use clause for Bindo.Writers.Phase_Writers. (Find_Components): Signal the start and end of the component discovery phase. (Find_Cycles): Signal the start and end of the cycle discovery phase. * bindo-units.adb: Add with and use clause for Bindo.Writers. Add use clause for Bindo.Writers.Phase_Writers. (Collect_Elaborable_Units): Signal the start and end of the unit collection phase. * bindo-validators.adb: Add with and use clause for Bindo.Writers. Add use clause for Bindo.Writers.Phase_Writers. (Validate_Cycles, Validate_Elaboration_Order, Validate_Invocation_Graph, Validate_Library_Graph): Signal the start and end of the libray graph validation phase. * bindo-writers.ads, bindo-writers.adb: Add new nested package Phase_Writers. * debug.adb: Update the documentation of switch d_S. From-SVN: r273379 --- gcc/ada/ChangeLog | 42 +++++++++++++++++++++ gcc/ada/bindo-augmentors.adb | 8 +++- gcc/ada/bindo-builders.adb | 10 +++++ gcc/ada/bindo-diagnostics.adb | 5 +++ gcc/ada/bindo-elaborators.adb | 4 ++ gcc/ada/bindo-graphs.adb | 8 ++++ gcc/ada/bindo-units.adb | 8 ++++ gcc/ada/bindo-validators.adb | 27 +++++++++++-- gcc/ada/bindo-writers.adb | 88 +++++++++++++++++++++++++++++++++++++++++++ gcc/ada/bindo-writers.ads | 17 +++++++++ gcc/ada/bindo.adb | 10 +++++ gcc/ada/bindo.ads | 18 +++++++++ gcc/ada/debug.adb | 7 +++- 13 files changed, 246 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a2316ea..fa580d2 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,45 @@ +2019-07-11 Hristian Kirtchev + + * bindo.adb: Update the section of switches and debugging + elaboration issues. + * bindo.ads: Add type Elaboration_Phase. + * bindo-augmentors.adb: Add use clause for + Bindo.Writers.Phase_Writers. + (Augment_Library_Graph): Signal the start and end of the + aubmentation phase. + * bindo-builders.adb: Add with and use clause for Bindo.Writers. + Add use clause for Bindo.Writers.Phase_Writers. + (Build_Invocation_Graph): Signal the start and end of the + invocation graph construction phase. + (Build_Library_Graph): Signal the start and end of the library + graph construction phase. + * bindo-diagnostics.adb: Add use clause for + Bindo.Writers.Phase_Writers. + (Diagnose_Cycle): Signal the start and end of the cycle + diagnostic phase. + * bindo-elaborators.adb: Add use clause for + Bindo.Writers.Phase_Writers. + (Elaborate_Units): Signal the start and end of the unit + elaboration phase. + * bindo-graphs.adb: Add use clause for + Bindo.Writers.Phase_Writers. + (Find_Components): Signal the start and end of the component + discovery phase. + (Find_Cycles): Signal the start and end of the cycle discovery + phase. + * bindo-units.adb: Add with and use clause for Bindo.Writers. + Add use clause for Bindo.Writers.Phase_Writers. + (Collect_Elaborable_Units): Signal the start and end of the unit + collection phase. + * bindo-validators.adb: Add with and use clause for + Bindo.Writers. Add use clause for Bindo.Writers.Phase_Writers. + (Validate_Cycles, Validate_Elaboration_Order, + Validate_Invocation_Graph, Validate_Library_Graph): Signal the + start and end of the libray graph validation phase. + * bindo-writers.ads, bindo-writers.adb: Add new nested package + Phase_Writers. + * debug.adb: Update the documentation of switch d_S. + 2019-07-11 Yannick Moy * sem_res.adb (Check_Argument_Order): Special case calls to diff --git a/gcc/ada/bindo-augmentors.adb b/gcc/ada/bindo-augmentors.adb index e0e2338..57fb541 100644 --- a/gcc/ada/bindo-augmentors.adb +++ b/gcc/ada/bindo-augmentors.adb @@ -27,7 +27,9 @@ with Debug; use Debug; with Output; use Output; with Types; use Types; -with Bindo.Writers; use Bindo.Writers; +with Bindo.Writers; +use Bindo.Writers; +use Bindo.Writers.Phase_Writers; package body Bindo.Augmentors is @@ -124,6 +126,8 @@ package body Bindo.Augmentors is return; end if; + Start_Phase (Library_Graph_Augmentation); + -- Prepare the statistics data Longest_Path := 0; @@ -131,6 +135,8 @@ package body Bindo.Augmentors is Visit_Elaboration_Roots (Inv_Graph, Lib_Graph); Write_Statistics; + + End_Phase (Library_Graph_Augmentation); end Augment_Library_Graph; ---------------------------- diff --git a/gcc/ada/bindo-builders.adb b/gcc/ada/bindo-builders.adb index 351b10d..9919007 100644 --- a/gcc/ada/bindo-builders.adb +++ b/gcc/ada/bindo-builders.adb @@ -37,6 +37,10 @@ use Bindo.Validators; use Bindo.Validators.Invocation_Graph_Validators; use Bindo.Validators.Library_Graph_Validators; +with Bindo.Writers; +use Bindo.Writers; +use Bindo.Writers.Phase_Writers; + with GNAT; use GNAT; with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables; @@ -99,6 +103,8 @@ package body Bindo.Builders is begin pragma Assert (Present (Lib_G)); + Start_Phase (Invocation_Graph_Construction); + -- Prepare the global data Inv_Graph := @@ -111,6 +117,7 @@ package body Bindo.Builders is For_Each_Elaborable_Unit (Create_Edges'Access); Validate_Invocation_Graph (Inv_Graph); + End_Phase (Invocation_Graph_Construction); return Inv_Graph; end Build_Invocation_Graph; @@ -375,6 +382,8 @@ package body Bindo.Builders is function Build_Library_Graph return Library_Graph is begin + Start_Phase (Library_Graph_Construction); + -- Prepare the global data Lib_Graph := @@ -388,6 +397,7 @@ package body Bindo.Builders is Create_Forced_Edges; Validate_Library_Graph (Lib_Graph); + End_Phase (Library_Graph_Construction); return Lib_Graph; end Build_Library_Graph; diff --git a/gcc/ada/bindo-diagnostics.adb b/gcc/ada/bindo-diagnostics.adb index 9dbdfc0..6f19ac0 100644 --- a/gcc/ada/bindo-diagnostics.adb +++ b/gcc/ada/bindo-diagnostics.adb @@ -36,6 +36,7 @@ use Bindo.Validators.Cycle_Validators; with Bindo.Writers; use Bindo.Writers; use Bindo.Writers.Cycle_Writers; +use Bindo.Writers.Phase_Writers; package body Bindo.Diagnostics is @@ -348,6 +349,8 @@ package body Bindo.Diagnostics is Next_Edge : Library_Graph_Edge_Id; begin + Start_Phase (Cycle_Diagnostics); + First_Edge := No_Library_Graph_Edge; -- Inspect the edges of the cycle in pairs, emitting diagnostics based @@ -402,6 +405,8 @@ package body Bindo.Diagnostics is (G => Lib_Graph, Cycle => Cycle, First_Edge => First_Edge); + + End_Phase (Cycle_Diagnostics); end Diagnose_Cycle; -------------------------------------- diff --git a/gcc/ada/bindo-elaborators.adb b/gcc/ada/bindo-elaborators.adb index 0d9f207..9e207e1 100644 --- a/gcc/ada/bindo-elaborators.adb +++ b/gcc/ada/bindo-elaborators.adb @@ -54,6 +54,7 @@ use Bindo.Writers.Dependency_Writers; use Bindo.Writers.Elaboration_Order_Writers; use Bindo.Writers.Invocation_Graph_Writers; use Bindo.Writers.Library_Graph_Writers; +use Bindo.Writers.Phase_Writers; use Bindo.Writers.Unit_Closure_Writers; with GNAT; use GNAT; @@ -711,6 +712,8 @@ package body Bindo.Elaborators is Status : Elaboration_Order_Status; begin + Start_Phase (Unit_Elaboration); + -- Initialize all unit-related data structures and gather all units -- that need elaboration. @@ -786,6 +789,7 @@ package body Bindo.Elaborators is -- Destroy all unit-related data structures Finalize_Units; + End_Phase (Unit_Elaboration); -- Halt the bind when there is no satisfactory elaboration order diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index d254b1c..9621bb4 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -31,6 +31,7 @@ with Output; use Output; with Bindo.Writers; use Bindo.Writers; +use Bindo.Writers.Phase_Writers; package body Bindo.Graphs is @@ -2636,6 +2637,8 @@ package body Bindo.Graphs is begin pragma Assert (Present (G)); + Start_Phase (Component_Discovery); + -- Initialize or reinitialize the components of the graph Initialize_Components (G); @@ -2660,6 +2663,7 @@ package body Bindo.Graphs is -- before they can be elaborated. Update_Pending_Predecessors_Of_Components (G); + End_Phase (Component_Discovery); end Find_Components; ----------------- @@ -2683,6 +2687,8 @@ package body Bindo.Graphs is begin pragma Assert (Present (G)); + Start_Phase (Cycle_Discovery); + -- The cycles of graph G are discovered using Tarjan's enumeration -- of the elementary circuits of a directed-graph algorithm. Do not -- modify this code unless you intimately understand the algorithm. @@ -2721,6 +2727,8 @@ package body Bindo.Graphs is Cycle_Count => Cycle_Count, Cycle_Limit => All_Cycle_Limit); end loop; + + End_Phase (Cycle_Discovery); end Find_Cycles; -------------------------------- diff --git a/gcc/ada/bindo-units.adb b/gcc/ada/bindo-units.adb index 8b8fc28..284aa62 100644 --- a/gcc/ada/bindo-units.adb +++ b/gcc/ada/bindo-units.adb @@ -23,6 +23,10 @@ -- -- ------------------------------------------------------------------------------ +with Bindo.Writers; +use Bindo.Writers; +use Bindo.Writers.Phase_Writers; + package body Bindo.Units is ------------------- @@ -79,9 +83,13 @@ package body Bindo.Units is procedure Collect_Elaborable_Units is begin + Start_Phase (Unit_Collection); + for U_Id in ALI.Units.First .. ALI.Units.Last loop Process_Unit (U_Id); end loop; + + End_Phase (Unit_Collection); end Collect_Elaborable_Units; ------------------------ diff --git a/gcc/ada/bindo-validators.adb b/gcc/ada/bindo-validators.adb index b711a91..584d33f 100644 --- a/gcc/ada/bindo-validators.adb +++ b/gcc/ada/bindo-validators.adb @@ -27,7 +27,12 @@ with Debug; use Debug; with Output; use Output; with Types; use Types; -with Bindo.Units; use Bindo.Units; +with Bindo.Units; +use Bindo.Units; + +with Bindo.Writers; +use Bindo.Writers; +use Bindo.Writers.Phase_Writers; package body Bindo.Validators is @@ -188,6 +193,8 @@ package body Bindo.Validators is return; end if; + Start_Phase (Cycle_Validation); + Iter := Iterate_All_Cycles (G); while Has_Next (Iter) loop Next (Iter, Cycle); @@ -195,6 +202,8 @@ package body Bindo.Validators is Validate_Cycle (G, Cycle); end loop; + End_Phase (Cycle_Validation); + if Has_Invalid_Cycle then raise Invalid_Cycle; end if; @@ -330,8 +339,12 @@ package body Bindo.Validators is return; end if; + Start_Phase (Elaboration_Order_Validation); + Validate_Units (Order); + End_Phase (Elaboration_Order_Validation); + if Has_Invalid_Data then raise Invalid_Elaboration_Order; end if; @@ -444,8 +457,12 @@ package body Bindo.Validators is return; end if; + Start_Phase (Invocation_Graph_Validation); + Validate_Invocation_Graph_Vertices (G); - Validate_Invocation_Graph_Edges (G); + Validate_Invocation_Graph_Edges (G); + + End_Phase (Invocation_Graph_Validation); if Has_Invalid_Data then raise Invalid_Invocation_Graph; @@ -638,8 +655,12 @@ package body Bindo.Validators is return; end if; + Start_Phase (Library_Graph_Validation); + Validate_Library_Graph_Vertices (G); - Validate_Library_Graph_Edges (G); + Validate_Library_Graph_Edges (G); + + End_Phase (Library_Graph_Validation); if Has_Invalid_Data then raise Invalid_Library_Graph; diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb index c4784d4..021d50f 100644 --- a/gcc/ada/bindo-writers.adb +++ b/gcc/ada/bindo-writers.adb @@ -1404,6 +1404,94 @@ package body Bindo.Writers is end Write_Statistics; end Library_Graph_Writers; + ------------------- + -- Phase_Writers -- + ------------------- + + package body Phase_Writers is + + subtype Phase_Message is String (1 .. 32); + + -- The following table contains the phase-specific messages for phase + -- completion. + + End_Messages : constant array (Elaboration_Phase) of Phase_Message := + (Component_Discovery => "components discovered. ", + Cycle_Diagnostics => "cycle diagnosed. ", + Cycle_Discovery => "cycles discovered. ", + Cycle_Validation => "cycles validated. ", + Elaboration_Order_Validation => "elaboration order validated. ", + Invocation_Graph_Construction => "invocation graph constructed. ", + Invocation_Graph_Validation => "invocation graph validated. ", + Library_Graph_Augmentation => "library graph augmented. ", + Library_Graph_Construction => "library graph constructed. ", + Library_Graph_Elaboration => "library graph elaborated. ", + Library_Graph_Validation => "library graph validated. ", + Unit_Collection => "units collected. ", + Unit_Elaboration => "units elaborated. "); + + -- The following table contains the phase-specific messages for phase + -- commencement. + + Start_Messages : constant array (Elaboration_Phase) of Phase_Message := + (Component_Discovery => "discovering components... ", + Cycle_Diagnostics => "diagnosing cycle... ", + Cycle_Discovery => "discovering cycles... ", + Cycle_Validation => "validating cycles... ", + Elaboration_Order_Validation => "validating elaboration order... ", + Invocation_Graph_Construction => "constructing invocation graph...", + Invocation_Graph_Validation => "validating invocation graph... ", + Library_Graph_Augmentation => "augmenting library graph... ", + Library_Graph_Construction => "constructing library graph... ", + Library_Graph_Elaboration => "elaborating library graph... ", + Library_Graph_Validation => "validating library graph... ", + Unit_Collection => "collecting units... ", + Unit_Elaboration => "elaborating units... "); + + ----------------------- + -- Local subprograms -- + ----------------------- + + procedure Write_Phase_Message (Msg : Phase_Message); + pragma Inline (Write_Phase_Message); + -- Write elaboration phase-related message Msg to standard output + + --------------- + -- End_Phase -- + --------------- + + procedure End_Phase (Phase : Elaboration_Phase) is + begin + Write_Phase_Message (End_Messages (Phase)); + end End_Phase; + + ----------------- + -- Start_Phase -- + ----------------- + + procedure Start_Phase (Phase : Elaboration_Phase) is + begin + Write_Phase_Message (Start_Messages (Phase)); + end Start_Phase; + + ------------------------- + -- Write_Phase_Message -- + ------------------------- + + procedure Write_Phase_Message (Msg : Phase_Message) is + begin + -- Nothing to do when switch -d_S (output elaboration order status) + -- is not in effect. + + if not Debug_Flag_Underscore_SS then + return; + end if; + + Write_Str (Msg); + Write_Eol; + end Write_Phase_Message; + end Phase_Writers; + -------------------------- -- Unit_Closure_Writers -- -------------------------- diff --git a/gcc/ada/bindo-writers.ads b/gcc/ada/bindo-writers.ads index 01e48e4..66483d0 100644 --- a/gcc/ada/bindo-writers.ads +++ b/gcc/ada/bindo-writers.ads @@ -132,6 +132,23 @@ package Bindo.Writers is end Library_Graph_Writers; + ------------------- + -- Phase_Writers -- + ------------------- + + package Phase_Writers is + procedure End_Phase (Phase : Elaboration_Phase); + pragma Inline (End_Phase); + -- Write the end message associated with elaboration phase Phase to + -- standard output. + + procedure Start_Phase (Phase : Elaboration_Phase); + pragma Inline (Start_Phase); + -- Write the start message associated with elaboration phase Phase to + -- standard output. + + end Phase_Writers; + -------------------------- -- Unit_Closure_Writers -- -------------------------- diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index 678f009..d5830ca 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -355,6 +355,11 @@ package body Bindo is -- -- GNATbind output the cycle paths in text format to standard output -- + -- -d_S Output elaboration-order status information + -- + -- GNATbind outputs trace information concerning the status of its + -- various phases to standard output. + -- -- -d_T Output elaboration-order trace information -- -- GNATbind outputs trace information on elaboration-order detection @@ -416,6 +421,11 @@ package body Bindo is -- plgv -- print library-graph vertex -- pu -- print units -- + -- * Apparent infinite loop + -- + -- The elaboration order mechanism appears to be stuck in an infinite + -- loop. Use switch -d_S to output the status of each elaboration phase. + -- -- * Invalid elaboration order -- -- The elaboration order is invalid when: diff --git a/gcc/ada/bindo.ads b/gcc/ada/bindo.ads index b0ebe62..ae35c95 100644 --- a/gcc/ada/bindo.ads +++ b/gcc/ada/bindo.ads @@ -31,6 +31,24 @@ with Namet; use Namet; package Bindo is + -- The following type represents the various phases of the elaboration + -- order mechanism. + + type Elaboration_Phase is + (Component_Discovery, + Cycle_Diagnostics, + Cycle_Discovery, + Cycle_Validation, + Elaboration_Order_Validation, + Invocation_Graph_Construction, + Invocation_Graph_Validation, + Library_Graph_Augmentation, + Library_Graph_Construction, + Library_Graph_Elaboration, + Library_Graph_Validation, + Unit_Collection, + Unit_Elaboration); + -- The following type represents the various kinds of precedence between -- two items. diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index a81de09..44f0b9e 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -394,8 +394,8 @@ package body Debug is -- d_P Output cycle paths -- d_Q -- d_R - -- d_S - -- d_T Output elaboration order trace information + -- d_S Output elaboration-order status + -- d_T Output elaboration-order trace information -- d_U -- d_V Validate bindo cycles, graphs, and order -- d_W @@ -1167,6 +1167,9 @@ package body Debug is -- d_P GNATBIND outputs the cycle paths to standard output + -- d_S GNATBIND outputs trace information concerning the status of its + -- various phases to standard output. + -- d_T GNATBIND outputs trace information of elaboration order detection -- activities to standard output. -- cgit v1.1 From a1a8b1726cf8de2ed244353a9c8cd2fab12e4c71 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 11 Jul 2019 08:01:25 +0000 Subject: [Ada] GNAT.Threads: Add a Get_Thread overload taking a Task_Id 2019-07-11 Arnaud Charlet gcc/ada/ * libgnarl/g-thread.ads, libgnarl/g-thread.adb (Get_Thread): Update comments. Add new version taking a Task_Id. From-SVN: r273380 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/libgnarl/g-thread.adb | 9 +++++++-- gcc/ada/libgnarl/g-thread.ads | 4 +++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index fa580d2..703280c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Arnaud Charlet + + * libgnarl/g-thread.ads, libgnarl/g-thread.adb (Get_Thread): + Update comments. Add new version taking a Task_Id. + 2019-07-11 Hristian Kirtchev * bindo.adb: Update the section of switches and debugging diff --git a/gcc/ada/libgnarl/g-thread.adb b/gcc/ada/libgnarl/g-thread.adb index f4ce92e..ae61937 100644 --- a/gcc/ada/libgnarl/g-thread.adb +++ b/gcc/ada/libgnarl/g-thread.adb @@ -168,9 +168,14 @@ package body GNAT.Threads is ---------------- procedure Get_Thread (Id : Address; Thread : Address) is - Thr : constant Thread_Id_Ptr := To_Thread (Thread); begin - Thr.all := Task_Primitives.Operations.Get_Thread_Id (To_Id (Id)); + To_Thread (Thread).all := + Task_Primitives.Operations.Get_Thread_Id (To_Id (Id)); + end Get_Thread; + + procedure Get_Thread (Id : Task_Id; Thread : Address) is + begin + Get_Thread (To_Addr (Id), Thread); end Get_Thread; ---------------------- diff --git a/gcc/ada/libgnarl/g-thread.ads b/gcc/ada/libgnarl/g-thread.ads index ad4a075..8792e9a 100644 --- a/gcc/ada/libgnarl/g-thread.ads +++ b/gcc/ada/libgnarl/g-thread.ads @@ -129,9 +129,11 @@ package GNAT.Threads is procedure Get_Thread (Id : System.Address; Thread : System.Address); pragma Export (C, Get_Thread, "__gnat_get_thread"); + procedure Get_Thread + (Id : Ada.Task_Identification.Task_Id; Thread : System.Address); -- This procedure is used to retrieve the thread id of a given task. -- The value Id is the value that was passed to the thread code procedure - -- at activation time. + -- at activation time or a Task_Id. -- Thread is a pointer to a thread id that will be updated by this -- procedure. -- -- cgit v1.1 From ccf173059688499749a30b3252cc3c4ea4ab0d0c Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Thu, 11 Jul 2019 08:01:30 +0000 Subject: [Ada] No warning for guaranteed accessibility check failures This patch corrects the generation of dynamic accessibility checks which are guaranteed to trigger errors during run time so as to give the user proper warning during unit compiliation. 2019-07-11 Justin Squirek gcc/ada/ * checks.adb (Apply_Accessibility_Check): Add check for constant folded conditions on accessibility checks. gcc/testsuite/ * gnat.dg/access7.adb: New testcase. From-SVN: r273381 --- gcc/ada/ChangeLog | 5 +++ gcc/ada/checks.adb | 25 ++++++++++--- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/access7.adb | 79 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/access7.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 703280c..9104658 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Justin Squirek + + * checks.adb (Apply_Accessibility_Check): Add check for constant + folded conditions on accessibility checks. + 2019-07-11 Arnaud Charlet * libgnarl/g-thread.ads, libgnarl/g-thread.adb (Get_Thread): diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 601b932..7ca66bd 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -577,6 +577,7 @@ package body Checks is Typ : Entity_Id; Insert_Node : Node_Id) is + Check_Cond : Node_Id; Loc : constant Source_Ptr := Sloc (N); Param_Ent : Entity_Id := Param_Entity (N); Param_Level : Node_Id; @@ -638,15 +639,29 @@ package body Checks is -- Raise Program_Error if the accessibility level of the access -- parameter is deeper than the level of the target access type. + Check_Cond := Make_Op_Gt (Loc, + Left_Opnd => Param_Level, + Right_Opnd => Type_Level); + Insert_Action (Insert_Node, Make_Raise_Program_Error (Loc, - Condition => - Make_Op_Gt (Loc, - Left_Opnd => Param_Level, - Right_Opnd => Type_Level), - Reason => PE_Accessibility_Check_Failed)); + Condition => Check_Cond, + Reason => PE_Accessibility_Check_Failed)); Analyze_And_Resolve (N); + + -- If constant folding has happened on the condition for the + -- generated error, then warn about it being unconditional. + + if Nkind (Check_Cond) = N_Identifier + and then Entity (Check_Cond) = Standard_True + then + Error_Msg_Warn := SPARK_Mode /= On; + Error_Msg_N + ("accessibility check fails<<", N); + Error_Msg_N + ("\Program_Error [<<", N); + end if; end if; end Apply_Accessibility_Check; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 24ecc21..3b393fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Justin Squirek + + * gnat.dg/access7.adb: New testcase. + 2019-07-11 Yannick Moy * gnat.dg/warn21.adb, gnat.dg/warn21.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/access7.adb b/gcc/testsuite/gnat.dg/access7.adb new file mode 100644 index 0000000..e481312 --- /dev/null +++ b/gcc/testsuite/gnat.dg/access7.adb @@ -0,0 +1,79 @@ +-- { dg-do run } + +with Interfaces; use Interfaces; + +procedure Access7 is + type t_p_string is access constant String; + subtype t_hash is Unsigned_32; + + -- Return a hash value for a given string + function hash(s: String) return t_hash is + h: t_hash := 0; + g: t_hash; + begin + for i in s'Range loop + h := Shift_Left(h, 4) + t_hash'(Character'Pos(s(i))); + g := h and 16#F000_0000#; + if (h and g) /= 0 then + h := h xor ((Shift_Right(g, 24) and 16#FF#) or g); + end if; + end loop; + return h; + end hash; + + type hash_entry is record + v: t_p_string; + hash: t_hash; + next: access hash_entry; + end record; + + type hashtable is array(t_hash range <>) of access hash_entry; + + protected pool is + procedure allocate (sp: out t_p_string; s: String; h: t_hash); + private + tab: hashtable(0..199999-1) := (others => null); + end pool; + + protected body pool is + procedure allocate(sp: out t_p_string; s: String; h: t_hash) is + p: access hash_entry; + slot: t_hash; + begin + slot := h mod tab'Length; + p := tab(slot); + while p /= null loop + -- quickly check hash, then length, only then slow comparison + if p.hash = h and then p.v.all'Length = s'Length + and then p.v.all = s + then + sp := p.v; -- shared string + return; + end if; + p := p.next; + end loop; + -- add to table + p := new hash_entry'(v => new String'(s), + hash => h, + next => tab(slot)); + tab(slot) := p; -- { dg-warning "accessibility check fails|Program_Error will be raised at run time" } + sp := p.v; -- shared string + end allocate; + end pool; + + -- Return the pooled string equal to a given String + function new_p_string(s: String) return t_p_string is + sp: t_p_string; + begin + pool.allocate(sp, s, hash(s)); + return sp; + end new_p_string; + + foo_string : t_p_string; +begin + foo_string := new_p_string("foo"); + raise Constraint_Error; +exception + when Program_Error => + null; +end Access7; -- cgit v1.1 From 6c1657116a2c9cf7c0c14b6dfa7f8bbb7672d3c8 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 11 Jul 2019 08:01:35 +0000 Subject: [Ada] New Repinfo.Input unit to read back JSON representation info. For some time the Repinfo unit has been able to output the representation information in the JSON data interchange format in addition to the usual text and binary formats. The new Repinfo.Input unit makes it possible to read back this information under this format and make it available to clients, the main one being ASIS. The big advantage of using this approach over manipulating a binary blob is that the writer and the reader of the JSON representation need not be binary compatible, i.e. in practice need not be the same version of the compiler or ASIS for the same target. The patch also adds a -gnatd_j switch to read back the information in the compiler itself, which makes it easy to keep the writer and the reader in sync using only one tool, namely the compiler. The typical usage is: gcc -c p.ads -gnatR4js gcc -c p.ads -gnatd_j to exercise respectively the writer and the reader from the compiler. 2019-07-11 Eric Botcazou gcc/ada/ * alloc.ads (Rep_JSON_Table_Initial): New constant. (Rep_JSON_Table_Increment): Likewise. * debug.adb: Document -gnatd_j switch. * gcc-interface/Make-lang.in (GNAT_ADA_OBJS): Add repinfo-input.o. * gnat1drv.adb: Add with clause for Repinfo.Input. Add with and use clauses for Sinput. (Read_JSON_Files_For_Repinfo): New procedure. (Gnat1drv1): Deal with -gnatd_j switch. * repinfo-input.ad[sb]: New unit. * snames.ads-tmpl (Name_Discriminant): New constant. (Name_Operands): Likewise. From-SVN: r273382 --- gcc/ada/ChangeLog | 15 + gcc/ada/alloc.ads | 3 + gcc/ada/debug.adb | 6 +- gcc/ada/gcc-interface/Make-lang.in | 1 + gcc/ada/gnat1drv.adb | 47 +- gcc/ada/repinfo-input.adb | 1350 ++++++++++++++++++++++++++++++++++++ gcc/ada/repinfo-input.ads | 78 +++ gcc/ada/snames.ads-tmpl | 5 + 8 files changed, 1503 insertions(+), 2 deletions(-) create mode 100644 gcc/ada/repinfo-input.adb create mode 100644 gcc/ada/repinfo-input.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9104658..48c72d6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,18 @@ +2019-07-11 Eric Botcazou + + * alloc.ads (Rep_JSON_Table_Initial): New constant. + (Rep_JSON_Table_Increment): Likewise. + * debug.adb: Document -gnatd_j switch. + * gcc-interface/Make-lang.in (GNAT_ADA_OBJS): Add + repinfo-input.o. + * gnat1drv.adb: Add with clause for Repinfo.Input. + Add with and use clauses for Sinput. + (Read_JSON_Files_For_Repinfo): New procedure. + (Gnat1drv1): Deal with -gnatd_j switch. + * repinfo-input.ad[sb]: New unit. + * snames.ads-tmpl (Name_Discriminant): New constant. + (Name_Operands): Likewise. + 2019-07-11 Justin Squirek * checks.adb (Apply_Accessibility_Check): Add check for constant diff --git a/gcc/ada/alloc.ads b/gcc/ada/alloc.ads index 18bf1e4a..f5faecb 100644 --- a/gcc/ada/alloc.ads +++ b/gcc/ada/alloc.ads @@ -116,6 +116,9 @@ package Alloc is Rep_Table_Initial : constant := 1000; -- Repinfo Rep_Table_Increment : constant := 200; + Rep_JSON_Table_Initial : constant := 10; -- Repinfo + Rep_JSON_Table_Increment : constant := 200; + Scope_Stack_Initial : constant := 10; -- Sem Scope_Stack_Increment : constant := 200; diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 44f0b9e..6df3d6f 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -154,7 +154,7 @@ package body Debug is -- d_g -- d_h -- d_i Ignore activations and calls to instances for elaboration - -- d_j + -- d_j Read JSON files and populate Repinfo tables (opposite of -gnatRjs) -- d_k -- d_l -- d_m @@ -988,6 +988,10 @@ package body Debug is -- subprogram or task type defined in an external instance for both -- the static and dynamic elaboration models. + -- d_j The compiler reads JSON files that would be generated by the same + -- compilation session if -gnatRjs was passed, in order to populate + -- the internal tables of the Repinfo unit from them. + -- d_p The compiler ignores calls to subprograms which verify the run-time -- semantics of invariants and postconditions in both the static and -- dynamic elaboration models. diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in index dd90c7b..b6a337a 100644 --- a/gcc/ada/gcc-interface/Make-lang.in +++ b/gcc/ada/gcc-interface/Make-lang.in @@ -355,6 +355,7 @@ GNAT_ADA_OBJS = \ ada/prep.o \ ada/prepcomp.o \ ada/put_scos.o \ + ada/repinfo-input.o \ ada/repinfo.o \ ada/restrict.o \ ada/rident.o \ diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index f0f8de7..2e4204b 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -51,6 +51,7 @@ with Output; use Output; with Par_SCO; with Prepcomp; with Repinfo; +with Repinfo.Input; with Restrict; with Rident; use Rident; with Rtsfind; @@ -66,6 +67,7 @@ with Sem_SPARK; use Sem_SPARK; with Sem_Type; with Set_Targ; with Sinfo; use Sinfo; +with Sinput; use Sinput; with Sinput.L; use Sinput.L; with Snames; use Snames; with Sprint; use Sprint; @@ -114,6 +116,12 @@ procedure Gnat1drv is -- the information provided by the back end in back annotation of declared -- entities (e.g. actual size and alignment values chosen by the back end). + procedure Read_JSON_Files_For_Repinfo; + -- This procedure exercises the JSON parser of Repinfo by reading back the + -- JSON files generated by -gnatRjs in a previous compilation session. It + -- is intended to make sure that the JSON generator and the JSON parser are + -- kept synchronized when the JSON format evolves. + ---------------------------- -- Adjust_Global_Switches -- ---------------------------- @@ -1037,6 +1045,38 @@ procedure Gnat1drv is -- end if; end Post_Compilation_Validation_Checks; + ----------------------------------- + -- Read_JSON_Files_For_Repinfo -- + ----------------------------------- + + procedure Read_JSON_Files_For_Repinfo is + begin + -- This is the same loop construct as in Repinfo.List_Rep_Info + + for U in Main_Unit .. Last_Unit loop + if In_Extended_Main_Source_Unit (Cunit_Entity (U)) then + declare + Nam : constant String := + Get_Name_String (File_Name (Source_Index (U))) & ".json"; + Namid : constant File_Name_Type := Name_Enter (Nam); + Index : constant Source_File_Index := Load_Config_File (Namid); + + begin + if Index = No_Source_File then + Write_Str ("cannot locate "); + Write_Line (Nam); + raise Unrecoverable_Error; + end if; + + Repinfo.Input.Read_JSON_Stream (Source_Text (Index).all, Nam); + exception + when Repinfo.Input.Invalid_JSON_Stream => + raise Unrecoverable_Error; + end; + end if; + end loop; + end Read_JSON_Files_For_Repinfo; + -- Local variables Back_End_Mode : Back_End.Back_End_Mode_Type; @@ -1103,7 +1143,6 @@ begin -- Acquire target parameters from system.ads (package System source) Targparm_Acquire : declare - use Sinput; S : Source_File_Index; N : File_Name_Type; @@ -1571,6 +1610,12 @@ begin Par_SCO.SCO_Record_Filtered; end if; + -- If -gnatd_j is specified, exercise the JSON parser of Repinfo + + if Debug_Flag_Underscore_J then + Read_JSON_Files_For_Repinfo; + end if; + -- Back end needs to explicitly unlock tables it needs to touch Atree.Lock; diff --git a/gcc/ada/repinfo-input.adb b/gcc/ada/repinfo-input.adb new file mode 100644 index 0000000..92ca510 --- /dev/null +++ b/gcc/ada/repinfo-input.adb @@ -0,0 +1,1350 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- R E P I N F O - I N P U T -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2018-2019, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +with Alloc; +with Csets; use Csets; +with Hostparm; use Hostparm; +with Namet; use Namet; +with Output; use Output; +with Snames; use Snames; +with Table; + +package body Repinfo.Input is + + SSU : constant := 8; + -- Value for Storage_Unit, we do not want to get this from TTypes, since + -- this introduces problematic dependencies in ASIS, and in any case this + -- value is assumed to be 8 for the implementation of the DDA. + + type JSON_Entity_Kind is (JE_Record_Type, JE_Array_Type, JE_Other); + -- Kind of an entiy + + type JSON_Entity_Node (Kind : JSON_Entity_Kind := JE_Other) is record + Esize : Node_Ref_Or_Val; + RM_Size : Node_Ref_Or_Val; + case Kind is + when JE_Record_Type => Variant : Nat; + when JE_Array_Type => Component_Size : Node_Ref_Or_Val; + when JE_Other => Dummy : Boolean; + end case; + end record; + pragma Unchecked_Union (JSON_Entity_Node); + -- Record to represent an entity + + package JSON_Entity_Table is new Table.Table ( + Table_Component_Type => JSON_Entity_Node, + Table_Index_Type => Nat, + Table_Low_Bound => 1, + Table_Initial => Alloc.Rep_JSON_Table_Initial, + Table_Increment => Alloc.Rep_JSON_Table_Increment, + Table_Name => "JSON_Entity_Table"); + -- Table of entities + + type JSON_Component_Node is record + Bit_Offset : Node_Ref_Or_Val; + Esize : Node_Ref_Or_Val; + end record; + -- Record to represent a component + + package JSON_Component_Table is new Table.Table ( + Table_Component_Type => JSON_Component_Node, + Table_Index_Type => Nat, + Table_Low_Bound => 1, + Table_Initial => Alloc.Rep_JSON_Table_Initial, + Table_Increment => Alloc.Rep_JSON_Table_Increment, + Table_Name => "JSON_Component_Table"); + -- Table of components + + type JSON_Variant_Node is record + Present : Node_Ref_Or_Val; + Variant : Nat; + Next : Nat; + end record; + -- Record to represent a variant + + package JSON_Variant_Table is new Table.Table ( + Table_Component_Type => JSON_Variant_Node, + Table_Index_Type => Nat, + Table_Low_Bound => 1, + Table_Initial => Alloc.Rep_JSON_Table_Initial, + Table_Increment => Alloc.Rep_JSON_Table_Increment, + Table_Name => "JSON_Variant_Table"); + -- Table of variants + + ------------------------------------- + -- Get_JSON_Component_Bit_Offset -- + ------------------------------------- + + function Get_JSON_Component_Bit_Offset + (Name : String; + Record_Name : String) return Node_Ref_Or_Val + is + Namid : constant Valid_Name_Id := Name_Find (Record_Name & '.' & Name); + Index : constant Int := Get_Name_Table_Int (Namid); + + begin + -- Return No_Uint if no information is available for the component + + if Index = 0 then + return No_Uint; + end if; + + return JSON_Component_Table.Table (Index).Bit_Offset; + end Get_JSON_Component_Bit_Offset; + + ------------------------------- + -- Get_JSON_Component_Size -- + ------------------------------- + + function Get_JSON_Component_Size (Name : String) return Node_Ref_Or_Val is + Namid : constant Valid_Name_Id := Name_Find (Name); + Index : constant Int := Get_Name_Table_Int (Namid); + + begin + -- Return No_Uint if no information is available for the component + + if Index = 0 then + return No_Uint; + end if; + + return JSON_Entity_Table.Table (Index).Component_Size; + end Get_JSON_Component_Size; + + ---------------------- + -- Get_JSON_Esize -- + ---------------------- + + function Get_JSON_Esize (Name : String) return Node_Ref_Or_Val is + Namid : constant Valid_Name_Id := Name_Find (Name); + Index : constant Int := Get_Name_Table_Int (Namid); + + begin + -- Return No_Uint if no information is available for the entity + + if Index = 0 then + return No_Uint; + end if; + + return JSON_Entity_Table.Table (Index).Esize; + end Get_JSON_Esize; + + ---------------------- + -- Get_JSON_Esize -- + ---------------------- + + function Get_JSON_Esize + (Name : String; + Record_Name : String) return Node_Ref_Or_Val + is + Namid : constant Valid_Name_Id := Name_Find (Record_Name & '.' & Name); + Index : constant Int := Get_Name_Table_Int (Namid); + + begin + -- Return No_Uint if no information is available for the entity + + if Index = 0 then + return No_Uint; + end if; + + return JSON_Component_Table.Table (Index).Esize; + end Get_JSON_Esize; + + ------------------------ + -- Get_JSON_RM_Size -- + ------------------------ + + function Get_JSON_RM_Size (Name : String) return Node_Ref_Or_Val is + Namid : constant Valid_Name_Id := Name_Find (Name); + Index : constant Int := Get_Name_Table_Int (Namid); + + begin + -- Return No_Uint if no information is available for the entity + + if Index = 0 then + return No_Uint; + end if; + + return JSON_Entity_Table.Table (Index).RM_Size; + end Get_JSON_RM_Size; + + ----------------------- + -- Read_JSON_Stream -- + ----------------------- + + procedure Read_JSON_Stream (Text : Text_Buffer; File_Name : String) is + + type Text_Position is record + Index : Text_Ptr := 0; + Line : Natural := 0; + Column : Natural := 0; + end record; + -- Record to represent position in the text + + type Token_Kind is + (J_NULL, + J_TRUE, + J_FALSE, + J_NUMBER, + J_INTEGER, + J_STRING, + J_ARRAY, + J_OBJECT, + J_ARRAY_END, + J_OBJECT_END, + J_COMMA, + J_COLON, + J_EOF); + -- JSON Token kind. Note that in ECMA 404 there is no notion of integer. + -- Only numbers are supported. In our implementation we return J_INTEGER + -- if there is no decimal part in the number. The semantic is that this + -- is a J_NUMBER token that might be represented as an integer. Special + -- token J_EOF means that end of stream has been reached. + + function Decode_Integer (Lo, Hi : Text_Ptr) return Uint; + -- Decode and return the integer in Text (Lo .. Hi) + + function Decode_Name (Lo, Hi : Text_Ptr) return Valid_Name_Id; + -- Decode and return the name in Text (Lo .. Hi) + + function Decode_Symbol (Lo, Hi : Text_Ptr) return TCode; + -- Decode and return the expression symbol in Text (Lo .. Hi) + + procedure Error (Msg : String); + pragma No_Return (Error); + -- Print an error message and raise an exception + + procedure Read_Entity; + -- Read an entity + + function Read_Name return Valid_Name_Id; + -- Read a name + + function Read_Name_With_Prefix return Valid_Name_Id; + -- Read a name and prepend a prefix + + function Read_Number return Uint; + -- Read a number + + function Read_Numerical_Expr return Node_Ref_Or_Val; + -- Read a numerical expression + + procedure Read_Record; + -- Read a record + + function Read_String return Valid_Name_Id; + -- Read a string + + procedure Read_Token + (Kind : out Token_Kind; + Token_Start : out Text_Position; + Token_End : out Text_Position); + -- Read a token and return it (this is a standard JSON lexer) + + procedure Read_Token_And_Error + (TK : Token_Kind; + Token_Start : out Text_Position; + Token_End : out Text_Position); + pragma Inline (Read_Token_And_Error); + -- Read a specified token and error out on failure + + function Read_Variant_Part return Nat; + -- Read a variant part + + procedure Skip_Value; + -- Skip a value + + Pos : Text_Position := (Text'First, 1, 1); + -- The current position in the text buffer + + Name_Buffer : Bounded_String (4 * Max_Name_Length); + -- The buffer used to build full qualifed names + + Prefix_Len : Natural := 0; + -- The length of the prefix present in Name_Buffer + + ---------------------- + -- Decode_Integer -- + ---------------------- + + function Decode_Integer (Lo, Hi : Text_Ptr) return Uint is + Len : constant Nat := Int (Hi) - Int (Lo) + 1; + + begin + -- Decode up to 9 characters manually, otherwise call into Uint + + if Len < 10 then + declare + Val : Int := 0; + + begin + for J in Lo .. Hi loop + Val := Val * 10 + + Character'Pos (Text (J)) - Character'Pos ('0'); + end loop; + return UI_From_Int (Val); + end; + + else + declare + Val : Uint := Uint_0; + + begin + for J in Lo .. Hi loop + Val := Val * 10 + + Character'Pos (Text (J)) - Character'Pos ('0'); + end loop; + return Val; + end; + end if; + end Decode_Integer; + + ------------------- + -- Decode_Name -- + ------------------- + + function Decode_Name (Lo, Hi : Text_Ptr) return Valid_Name_Id is + begin + -- Names are stored in lower case so fold them if need be + + if Is_Upper_Case_Letter (Text (Lo)) then + declare + S : String (Integer (Lo) .. Integer (Hi)); + + begin + for J in Lo .. Hi loop + S (Integer (J)) := Fold_Lower (Text (J)); + end loop; + + return Name_Find (S); + end; + + else + declare + S : String (Integer (Lo) .. Integer (Hi)); + for S'Address use Text (Lo)'Address; + + begin + return Name_Find (S); + end; + end if; + end Decode_Name; + + --------------------- + -- Decode_Symbol -- + --------------------- + + function Decode_Symbol (Lo, Hi : Text_Ptr) return TCode is + + function Cmp12 (A, B : Character) return Boolean; + pragma Inline (Cmp12); + -- Compare Text (Lo + 1 .. Lo + 2) with A & B. + + ------------- + -- Cmp12 -- + ------------- + + function Cmp12 (A, B : Character) return Boolean is + begin + return Text (Lo + 1) = A and then Text (Lo + 2) = B; + end Cmp12; + + Len : constant Nat := Int (Hi) - Int (Lo) + 1; + + -- Start of processing for Decode_Symbol + + begin + case Len is + when 1 => + case Text (Lo) is + when '+' => + return Plus_Expr; + when '-' => + return Minus_Expr; -- or Negate_Expr + when '*' => + return Mult_Expr; + when '<' => + return Lt_Expr; + when '>' => + return Gt_Expr; + when '&' => + return Bit_And_Expr; + when '#' => + return Discrim_Val; + when others => + null; + end case; + when 2 => + if Text (Lo) = '/' then + case Text (Lo + 1) is + when 't' => + return Trunc_Div_Expr; + when 'c' => + return Ceil_Div_Expr; + when 'f' => + return Floor_Div_Expr; + when 'e' => + return Exact_Div_Expr; + when others => + null; + end case; + elsif Text (Lo + 1) = '=' then + case Text (Lo) is + when '<' => + return Le_Expr; + when '>' => + return Ge_Expr; + when '=' => + return Eq_Expr; + when '!' => + return Ne_Expr; + when others => + null; + end case; + elsif Text (Lo) = 'o' and then Text (Lo + 1) = 'r' then + return Truth_Or_Expr; + end if; + when 3 => + case Text (Lo) is + when '?' => + if Cmp12 ('<', '>') then + return Cond_Expr; + end if; + when 'a' => + if Cmp12 ('b', 's') then + return Abs_Expr; + elsif Cmp12 ('n', 'd') then + return Truth_And_Expr; + end if; + when 'm' => + if Cmp12 ('a', 'x') then + return Max_Expr; + elsif Cmp12 ('i', 'n') then + return Min_Expr; + end if; + when 'n' => + if Cmp12 ('o', 't') then + return Truth_Not_Expr; + end if; + when 'x' => + if Cmp12 ('o', 'r') then + return Truth_Xor_Expr; + end if; + when 'v' => + if Cmp12 ('a', 'r') then + return Dynamic_Val; + end if; + when others => + null; + end case; + when 4 => + if Text (Lo) = 'm' + and then Text (Lo + 1) = 'o' + and then Text (Lo + 2) = 'd' + then + case Text (Lo + 3) is + when 't' => + return Trunc_Mod_Expr; + when 'c' => + return Ceil_Mod_Expr; + when 'f' => + return Floor_Mod_Expr; + when others => + null; + end case; + end if; + + pragma Annotate + (CodePeer, Intentional, + "condition predetermined", "Error called as defensive code"); + + when others => + null; + end case; + + Error ("unknown symbol"); + end Decode_Symbol; + + ----------- + -- Error -- + ----------- + + procedure Error (Msg : String) is + L : constant String := Pos.Line'Img; + C : constant String := Pos.Column'Img; + + begin + Set_Standard_Error; + Write_Eol; + Write_Str (File_Name); + Write_Char (':'); + Write_Str (L (L'First + 1 .. L'Last)); + Write_Char (':'); + Write_Str (C (C'First + 1 .. C'Last)); + Write_Char (':'); + Write_Line (Msg); + raise Invalid_JSON_Stream; + end Error; + + ------------------ + -- Read_Entity -- + ------------------ + + procedure Read_Entity is + Ent : JSON_Entity_Node; + Nam : Name_Id := No_Name; + Siz : Node_Ref_Or_Val; + Token_Start : Text_Position; + Token_End : Text_Position; + TK : Token_Kind; + + begin + Ent.Esize := No_Uint; + Ent.RM_Size := No_Uint; + Ent.Component_Size := No_Uint; + + -- Read the members as string : value pairs + + loop + case Read_String is + when Name_Name => + Nam := Read_Name; + when Name_Record => + if Nam = No_Name then + Error ("name expected"); + end if; + Ent.Variant := 0; + Prefix_Len := Natural (Length_Of_Name (Nam)); + Name_Buffer.Chars (1 .. Prefix_Len) := Get_Name_String (Nam); + Read_Record; + when Name_Variant => + Ent.Variant := Read_Variant_Part; + when Name_Size => + Siz := Read_Numerical_Expr; + Ent.Esize := Siz; + Ent.RM_Size := Siz; + when Name_Object_Size => + Ent.Esize := Read_Numerical_Expr; + when Name_Value_Size => + Ent.RM_Size := Read_Numerical_Expr; + when Name_Component_Size => + Ent.Component_Size := Read_Numerical_Expr; + when others => + Skip_Value; + end case; + + Read_Token (TK, Token_Start, Token_End); + if TK = J_OBJECT_END then + exit; + elsif TK /= J_COMMA then + Error ("comma expected"); + end if; + end loop; + + -- Store the entity into the table + + JSON_Entity_Table.Append (Ent); + + -- Associate the name with the entity + + if Nam = No_Name then + Error ("name expected"); + end if; + + Set_Name_Table_Int (Nam, JSON_Entity_Table.Last); + end Read_Entity; + + ----------------- + -- Read_Name -- + ----------------- + + function Read_Name return Valid_Name_Id is + Token_Start : Text_Position; + Token_End : Text_Position; + + begin + -- Read a single string + + Read_Token_And_Error (J_STRING, Token_Start, Token_End); + + return Decode_Name (Token_Start.Index + 1, Token_End.Index - 1); + end Read_Name; + + ----------------------------- + -- Read_Name_With_Prefix -- + ----------------------------- + + function Read_Name_With_Prefix return Valid_Name_Id is + Len : Natural; + Lo, Hi : Text_Ptr; + Token_Start : Text_Position; + Token_End : Text_Position; + + begin + -- Read a single string + + Read_Token_And_Error (J_STRING, Token_Start, Token_End); + Lo := Token_Start.Index + 1; + Hi := Token_End.Index - 1; + + -- Prepare for the concatenation with the prefix + + Len := Integer (Hi) - Integer (Lo) + 1; + if Prefix_Len + 1 + Len > Name_Buffer.Max_Length then + Error ("Name buffer too small"); + end if; + + Name_Buffer.Length := Prefix_Len + 1 + Len; + Name_Buffer.Chars (Prefix_Len + 1) := '.'; + + -- Names are stored in lower case so fold them if need be + + if Is_Upper_Case_Letter (Text (Lo)) then + for J in Lo .. Hi loop + Name_Buffer.Chars (Prefix_Len + 2 + Integer (J - Lo)) := + Fold_Lower (Text (J)); + end loop; + + else + declare + S : String (Integer (Lo) .. Integer (Hi)); + for S'Address use Text (Lo)'Address; + + begin + Name_Buffer.Chars (Prefix_Len + 2 .. Prefix_Len + 1 + Len) := S; + end; + end if; + + return Name_Find (Name_Buffer); + end Read_Name_With_Prefix; + + ------------------ + -- Read_Number -- + ------------------ + + function Read_Number return Uint is + Token_Start : Text_Position; + Token_End : Text_Position; + + begin + -- Only integers are to be expected here + + Read_Token_And_Error (J_INTEGER, Token_Start, Token_End); + + return Decode_Integer (Token_Start.Index, Token_End.Index); + end Read_Number; + + -------------------------- + -- Read_Numerical_Expr -- + -------------------------- + + function Read_Numerical_Expr return Node_Ref_Or_Val is + Code : TCode; + Nop : Integer; + Ops : array (1 .. 3) of Node_Ref_Or_Val; + TK : Token_Kind; + Token_Start : Text_Position; + Token_End : Text_Position; + + begin + -- Read either an integer or an expression + + Read_Token (TK, Token_Start, Token_End); + if TK = J_INTEGER then + return Decode_Integer (Token_Start.Index, Token_End.Index); + + elsif TK = J_OBJECT then + -- Read the code of the expression and decode it + + if Read_String /= Name_Code then + Error ("name expected"); + end if; + + Read_Token_And_Error (J_STRING, Token_Start, Token_End); + Code := Decode_Symbol (Token_Start.Index + 1, Token_End.Index - 1); + Read_Token_And_Error (J_COMMA, Token_Start, Token_End); + + -- Read the array of operands + + if Read_String /= Name_Operands then + Error ("operands expected"); + end if; + + Read_Token_And_Error (J_ARRAY, Token_Start, Token_End); + + Nop := 0; + Ops := (others => No_Uint); + loop + Nop := Nop + 1; + Ops (Nop) := Read_Numerical_Expr; + Read_Token (TK, Token_Start, Token_End); + if TK = J_ARRAY_END then + exit; + elsif TK /= J_COMMA then + Error ("comma expected"); + end if; + end loop; + + Read_Token_And_Error (J_OBJECT_END, Token_Start, Token_End); + + -- Resolve the ambiguity for '-' now + + if Code = Minus_Expr and then Nop = 1 then + Code := Negate_Expr; + end if; + + return Create_Node (Code, Ops (1), Ops (2), Ops (3)); + + else + Error ("numerical expression expected"); + end if; + end Read_Numerical_Expr; + + ------------------- + -- Read_Record -- + ------------------- + + procedure Read_Record is + Comp : JSON_Component_Node; + First_Bit : Node_Ref_Or_Val := No_Uint; + Is_First : Boolean := True; + Nam : Name_Id := No_Name; + Position : Node_Ref_Or_Val := No_Uint; + TK : Token_Kind; + Token_Start : Text_Position; + Token_End : Text_Position; + + begin + -- Read a possibly empty array of components + + Read_Token_And_Error (J_ARRAY, Token_Start, Token_End); + + loop + Read_Token (TK, Token_Start, Token_End); + if Is_First and then TK = J_ARRAY_END then + exit; + elsif TK /= J_OBJECT then + Error ("object expected"); + end if; + + -- Read the members as string : value pairs + + loop + case Read_String is + when Name_Name => + Nam := Read_Name_With_Prefix; + when Name_Discriminant => + Skip_Value; + when Name_Position => + Position := Read_Numerical_Expr; + when Name_First_Bit => + First_Bit := Read_Number; + when Name_Size => + Comp.Esize := Read_Numerical_Expr; + when others => + Error ("invalid component"); + end case; + + Read_Token (TK, Token_Start, Token_End); + if TK = J_OBJECT_END then + exit; + elsif TK /= J_COMMA then + Error ("comma expected"); + end if; + end loop; + + -- Compute Component_Bit_Offset from Position and First_Bit, + -- either symbolically or literally depending on Position. + + if Position = No_Uint or else First_Bit = No_Uint then + Error ("bit offset expected"); + end if; + + if Position < Uint_0 then + declare + Bit_Position : constant Node_Ref_Or_Val := + Create_Node (Mult_Expr, Position, UI_From_Int (SSU)); + begin + if First_Bit = Uint_0 then + Comp.Bit_Offset := Bit_Position; + else + Comp.Bit_Offset := + Create_Node (Plus_Expr, Bit_Position, First_Bit); + end if; + end; + else + Comp.Bit_Offset := Position * SSU + First_Bit; + end if; + + -- Store the component into the table + + JSON_Component_Table.Append (Comp); + + -- Associate the name with the component + + if Nam = No_Name then + Error ("name expected"); + end if; + + Set_Name_Table_Int (Nam, JSON_Component_Table.Last); + + Read_Token (TK, Token_Start, Token_End); + if TK = J_ARRAY_END then + exit; + elsif TK /= J_COMMA then + Error ("comma expected"); + end if; + + Is_First := False; + end loop; + end Read_Record; + + ------------------ + -- Read_String -- + ------------------ + + function Read_String return Valid_Name_Id is + Token_Start : Text_Position; + Token_End : Text_Position; + Nam : Valid_Name_Id; + + begin + -- Read the string and the following colon + + Read_Token_And_Error (J_STRING, Token_Start, Token_End); + Nam := Decode_Name (Token_Start.Index + 1, Token_End.Index - 1); + Read_Token_And_Error (J_COLON, Token_Start, Token_End); + + return Nam; + end Read_String; + + ------------------ + -- Read_Token -- + ------------------ + + procedure Read_Token + (Kind : out Token_Kind; + Token_Start : out Text_Position; + Token_End : out Text_Position) + is + procedure Next_Char; + -- Update Pos to point to next char + + function Is_Whitespace return Boolean; + pragma Inline (Is_Whitespace); + -- Return True of current character is a whitespace + + function Is_Structural_Token return Boolean; + pragma Inline (Is_Structural_Token); + -- Return True if current character is one of the structural tokens + + function Is_Token_Sep return Boolean; + pragma Inline (Is_Token_Sep); + -- Return True if current character is a token separator + + procedure Delimit_Keyword (Kw : String); + -- Helper function to parse tokens such as null, false and true + + --------------- + -- Next_Char -- + --------------- + + procedure Next_Char is + begin + if Pos.Index > Text'Last then + Pos.Column := Pos.Column + 1; + elsif Text (Pos.Index) = ASCII.LF then + Pos.Column := 1; + Pos.Line := Pos.Line + 1; + else + Pos.Column := Pos.Column + 1; + end if; + Pos.Index := Pos.Index + 1; + end Next_Char; + + ------------------- + -- Is_Whitespace -- + ------------------- + + function Is_Whitespace return Boolean is + begin + return + Pos.Index <= Text'Last + and then + (Text (Pos.Index) = ASCII.LF + or else + Text (Pos.Index) = ASCII.CR + or else + Text (Pos.Index) = ASCII.HT + or else + Text (Pos.Index) = ' '); + end Is_Whitespace; + + ------------------------- + -- Is_Structural_Token -- + ------------------------- + + function Is_Structural_Token return Boolean is + begin + return + Pos.Index <= Text'Last + and then + (Text (Pos.Index) = '[' + or else + Text (Pos.Index) = ']' + or else + Text (Pos.Index) = '{' + or else + Text (Pos.Index) = '}' + or else + Text (Pos.Index) = ',' + or else + Text (Pos.Index) = ':'); + end Is_Structural_Token; + + ------------------ + -- Is_Token_Sep -- + ------------------ + + function Is_Token_Sep return Boolean is + begin + return + Pos.Index > Text'Last + or else + Is_Whitespace + or else + Is_Structural_Token; + end Is_Token_Sep; + + --------------------- + -- Delimit_Keyword -- + --------------------- + + procedure Delimit_Keyword (Kw : String) is + pragma Unreferenced (Kw); + begin + while not Is_Token_Sep loop + Token_End := Pos; + Next_Char; + end loop; + end Delimit_Keyword; + + CC : Character; + Can_Be_Integer : Boolean := True; + + -- Start of processing for Read_Token + + begin + -- Skip leading whitespaces + + while Is_Whitespace loop + Next_Char; + end loop; + + -- Initialize token delimiters + + Token_Start := Pos; + Token_End := Pos; + + -- End of stream reached + + if Pos.Index > Text'Last then + Kind := J_EOF; + return; + end if; + + CC := Text (Pos.Index); + + if CC = '[' then + Next_Char; + Kind := J_ARRAY; + return; + elsif CC = ']' then + Next_Char; + Kind := J_ARRAY_END; + return; + elsif CC = '{' then + Next_Char; + Kind := J_OBJECT; + return; + elsif CC = '}' then + Next_Char; + Kind := J_OBJECT_END; + return; + elsif CC = ',' then + Next_Char; + Kind := J_COMMA; + return; + elsif CC = ':' then + Next_Char; + Kind := J_COLON; + return; + elsif CC = 'n' then + Delimit_Keyword ("null"); + Kind := J_NULL; + return; + elsif CC = 'f' then + Delimit_Keyword ("false"); + Kind := J_FALSE; + return; + elsif CC = 't' then + Delimit_Keyword ("true"); + Kind := J_TRUE; + return; + elsif CC = '"' then + -- We expect a string + -- Just scan till the end the of the string but do not attempt + -- to decode it. This means that even if we get a string token + -- it might not be a valid string from the ECMA 404 point of + -- view. + + Next_Char; + while Pos.Index <= Text'Last and then Text (Pos.Index) /= '"' loop + if Text (Pos.Index) in ASCII.NUL .. ASCII.US then + Error ("control character not allowed in string"); + end if; + + if Text (Pos.Index) = '\' then + Next_Char; + if Pos.Index > Text'Last then + Error ("non terminated string token"); + end if; + + case Text (Pos.Index) is + when 'u' => + for Idx in 1 .. 4 loop + Next_Char; + if Pos.Index > Text'Last + or else (Text (Pos.Index) not in 'a' .. 'f' + and then + Text (Pos.Index) not in 'A' .. 'F' + and then + Text (Pos.Index) not in '0' .. '9') + then + Error ("invalid unicode escape sequence"); + end if; + end loop; + when '\' | '/' | '"' | 'b' | 'f' | 'n' | 'r' | 't' => + null; + when others => + Error ("invalid escape sequence"); + end case; + end if; + Next_Char; + end loop; + + -- No quote found report and error + + if Pos.Index > Text'Last then + Error ("non terminated string token"); + end if; + + Token_End := Pos; + + -- Go to next char and ensure that this is separator. Indeed + -- construction such as "string1""string2" are not allowed + + Next_Char; + if not Is_Token_Sep then + Error ("invalid syntax"); + end if; + Kind := J_STRING; + return; + elsif CC = '-' or else CC in '0' .. '9' then + -- We expect a number + if CC = '-' then + Next_Char; + end if; + + if Pos.Index > Text'Last then + Error ("invalid number"); + end if; + + -- Parse integer part of a number. Superfluous leading zeros are + -- not allowed. + + if Text (Pos.Index) = '0' then + Token_End := Pos; + Next_Char; + elsif Text (Pos.Index) in '1' .. '9' then + Token_End := Pos; + Next_Char; + while Pos.Index <= Text'Last + and then Text (Pos.Index) in '0' .. '9' + loop + Token_End := Pos; + Next_Char; + end loop; + else + Error ("invalid number"); + end if; + + if Is_Token_Sep then + -- Valid integer number + + Kind := J_INTEGER; + return; + elsif Text (Pos.Index) /= '.' + and then Text (Pos.Index) /= 'e' + and then Text (Pos.Index) /= 'E' + then + Error ("invalid number"); + end if; + + -- Check for a fractional part + + if Text (Pos.Index) = '.' then + Can_Be_Integer := False; + Token_End := Pos; + Next_Char; + if Pos.Index > Text'Last + or else Text (Pos.Index) not in '0' .. '9' + then + Error ("invalid number"); + end if; + + while Pos.Index <= Text'Last + and then Text (Pos.Index) in '0' .. '9' + loop + Token_End := Pos; + Next_Char; + end loop; + + end if; + + -- Check for exponent part + + if Pos.Index <= Text'Last + and then (Text (Pos.Index) = 'e' or else Text (Pos.Index) = 'E') + then + Token_End := Pos; + Next_Char; + if Pos.Index > Text'Last then + Error ("invalid number"); + end if; + + if Text (Pos.Index) = '-' then + -- Also a few corner cases can lead to an integer, assume + -- that the number is not an integer. + + Can_Be_Integer := False; + end if; + + if Text (Pos.Index) = '-' or else Text (Pos.Index) = '+' then + Next_Char; + end if; + + if Pos.Index > Text'Last + or else Text (Pos.Index) not in '0' .. '9' + then + Error ("invalid number"); + end if; + + while Pos.Index <= Text'Last + and then Text (Pos.Index) in '0' .. '9' + loop + Token_End := Pos; + Next_Char; + end loop; + end if; + + if Is_Token_Sep then + -- Valid decimal number + + if Can_Be_Integer then + Kind := J_INTEGER; + else + Kind := J_NUMBER; + end if; + return; + else + Error ("invalid number"); + end if; + elsif CC = EOF then + Kind := J_EOF; + else + Error ("Unexpected character"); + end if; + end Read_Token; + + ---------------------------- + -- Read_Token_And_Error -- + ---------------------------- + + procedure Read_Token_And_Error + (TK : Token_Kind; + Token_Start : out Text_Position; + Token_End : out Text_Position) + is + Kind : Token_Kind; + + begin + -- Read a token and errout out if not of the expected kind + + Read_Token (Kind, Token_Start, Token_End); + if Kind /= TK then + Error ("specific token expected"); + end if; + end Read_Token_And_Error; + + ------------------------- + -- Read_Variant_Part -- + ------------------------- + + function Read_Variant_Part return Nat is + Next : Nat := 0; + TK : Token_Kind; + Token_Start : Text_Position; + Token_End : Text_Position; + Var : JSON_Variant_Node; + + begin + -- Read a non-empty array of components + + Read_Token_And_Error (J_ARRAY, Token_Start, Token_End); + + loop + Read_Token_And_Error (J_OBJECT, Token_Start, Token_End); + + Var.Variant := 0; + + -- Read the members as string : value pairs + + loop + case Read_String is + when Name_Present => + Var.Present := Read_Numerical_Expr; + when Name_Record => + Read_Record; + when Name_Variant => + Var.Variant := Read_Variant_Part; + when others => + Error ("invalid variant"); + end case; + + Read_Token (TK, Token_Start, Token_End); + if TK = J_OBJECT_END then + exit; + elsif TK /= J_COMMA then + Error ("comma expected"); + end if; + end loop; + + -- Chain the variant and store it into the table + + Var.Next := Next; + JSON_Variant_Table.Append (Var); + Next := JSON_Variant_Table.Last; + + Read_Token (TK, Token_Start, Token_End); + if TK = J_ARRAY_END then + exit; + elsif TK /= J_COMMA then + Error ("comma expected"); + end if; + end loop; + + return Next; + end Read_Variant_Part; + + ------------------ + -- Skip_Value -- + ------------------ + + procedure Skip_Value is + Array_Depth : Natural := 0; + Object_Depth : Natural := 0; + TK : Token_Kind; + Token_Start : Text_Position; + Token_End : Text_Position; + + begin + -- Read a value without recursing + + loop + Read_Token (TK, Token_Start, Token_End); + + case TK is + when J_STRING | J_INTEGER | J_NUMBER => + null; + when J_ARRAY => + Array_Depth := Array_Depth + 1; + when J_ARRAY_END => + Array_Depth := Array_Depth - 1; + when J_OBJECT => + Object_Depth := Object_Depth + 1; + when J_OBJECT_END => + Object_Depth := Object_Depth - 1; + when J_COLON | J_COMMA => + if Array_Depth = 0 and then Object_Depth = 0 then + Error ("value expected"); + end if; + when others => + Error ("value expected"); + end case; + + exit when Array_Depth = 0 and then Object_Depth = 0; + end loop; + end Skip_Value; + + Token_Start : Text_Position; + Token_End : Text_Position; + TK : Token_Kind; + Is_First : Boolean := True; + + -- Start of processing for Read_JSON_Stream + + begin + -- Read a possibly empty array of entities + + Read_Token_And_Error (J_ARRAY, Token_Start, Token_End); + + loop + Read_Token (TK, Token_Start, Token_End); + if Is_First and then TK = J_ARRAY_END then + exit; + elsif TK /= J_OBJECT then + Error ("object expected"); + end if; + + Read_Entity; + + Read_Token (TK, Token_Start, Token_End); + if TK = J_ARRAY_END then + exit; + elsif TK /= J_COMMA then + Error ("comma expected"); + end if; + + Is_First := False; + end loop; + end Read_JSON_Stream; + +end Repinfo.Input; diff --git a/gcc/ada/repinfo-input.ads b/gcc/ada/repinfo-input.ads new file mode 100644 index 0000000..e418feb --- /dev/null +++ b/gcc/ada/repinfo-input.ads @@ -0,0 +1,78 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- R E P I N F O - I N P U T -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2018-2019, Free Software Foundation, Inc. -- +-- -- +-- GNAT is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- This package provides an alternate way of populating the internal tables +-- of Repinfo from a JSON input rather than the binary blob of the tree file. +-- Note that this is an additive mechanism, i.e. nothing is destroyed in the +-- internal state of the unit when it is used. + +-- The first step is to feed the unit with a JSON stream of a specified format +-- (see the spec of Repinfo for its description) by means of Read_JSON_Stream. +-- Then, for each entity whose representation information is present in the +-- JSON stream, the appropriate Get_JSON_* routines can be invoked to override +-- the eponymous fields of the entity in the tree. + +package Repinfo.Input is + + function Get_JSON_Esize (Name : String) return Node_Ref_Or_Val; + -- Returns the Esize value of the entity specified by Name, which is not + -- the component of a record type, or else No_Uint if no representation + -- information was supplied for the entity. Name is the full qualified name + -- of the entity in lower case letters. + + function Get_JSON_RM_Size (Name : String) return Node_Ref_Or_Val; + -- Likewise for the RM_Size + + function Get_JSON_Component_Size (Name : String) return Node_Ref_Or_Val; + -- Likewise for the Component_Size of an array type + + function Get_JSON_Component_Bit_Offset + (Name : String; + Record_Name : String) return Node_Ref_Or_Val; + -- Returns the Component_Bit_Offset of the component specified by Name, + -- which is declared in the record type specified by Record_Name, or else + -- No_Uint if no representation information was supplied for the component. + -- Name is the unqualified name of the component whereas Record_Name is the + -- full qualified name of the record type, both in lower case letters. + + function Get_JSON_Esize + (Name : String; + Record_Name : String) return Node_Ref_Or_Val; + -- Likewise for the Esize + + Invalid_JSON_Stream : exception; + -- Raised if a format error is detected in the JSON stream + + procedure Read_JSON_Stream (Text : Text_Buffer; File_Name : String); + -- Reads a JSON stream and populates internal tables from it. File_Name is + -- only used in error messages issued by the JSON parser. + +end Repinfo.Input; diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl index 21cc0f4..2715310 100644 --- a/gcc/ada/snames.ads-tmpl +++ b/gcc/ada/snames.ads-tmpl @@ -1511,6 +1511,11 @@ package Snames is Name_Runtime_Library_Dir : constant Name_Id := N + $; Name_Runtime_Source_Dir : constant Name_Id := N + $; + -- Additional names used by the Repinfo unit + + Name_Discriminant : constant Name_Id := N + $; + Name_Operands : constant Name_Id := N + $; + -- Other miscellaneous names used in front end Name_Unaligned_Valid : constant Name_Id := N + $; -- cgit v1.1 From a3d1ca0127cf4ca6bb8d0da5a525d17dfc58cbc9 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 11 Jul 2019 08:01:39 +0000 Subject: [Ada] Missing finalization of private protected type This patch updates the analysis of protected types to properly mark the type as having controlled components when it contains at least one such component. This in turn marks a potential partial view as requiring finalization actions. ------------ -- Source -- ------------ -- types.ads with Ada.Finalization; use Ada.Finalization; package Types is type Ctrl_Typ is new Controlled with null record; procedure Finalize (Obj : in out Ctrl_Typ); type Prot_Typ is limited private; private protected type Prot_Typ is private Comp : Ctrl_Typ; end Prot_Typ; end Types; -- types.adb with Ada.Text_IO; use Ada.Text_IO; package body Types is procedure Finalize (Obj : in out Ctrl_Typ) is begin Put_Line ("finalize"); end Finalize; protected body Prot_Typ is end Prot_Typ; end Types; -- main.adb with Types; use Types; procedure Main is Obj : Prot_Typ; begin null; end Main; 2019-07-11 Hristian Kirtchev gcc/ada/ * exp_util.ads, exp_util.adb (Needs_Finalization): Move to Sem_Util. * sem_ch9.adb (Analyze_Protected_Definition): Code cleanup. Mark the protected type as having controlled components when it contains at least one such component. * sem_util.ads, sem_util.adb (Needs_Finalization): New function. From-SVN: r273383 --- gcc/ada/ChangeLog | 10 ++++++ gcc/ada/exp_util.adb | 92 +--------------------------------------------------- gcc/ada/exp_util.ads | 4 --- gcc/ada/sem_ch9.adb | 48 ++++++++++++++------------- gcc/ada/sem_util.adb | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/ada/sem_util.ads | 4 +++ 6 files changed, 129 insertions(+), 117 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 48c72d6..93a6fdc 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-07-11 Hristian Kirtchev + + * exp_util.ads, exp_util.adb (Needs_Finalization): Move to + Sem_Util. + * sem_ch9.adb (Analyze_Protected_Definition): Code cleanup. Mark + the protected type as having controlled components when it + contains at least one such component. + * sem_util.ads, sem_util.adb (Needs_Finalization): New + function. + 2019-07-11 Eric Botcazou * alloc.ads (Rep_JSON_Table_Initial): New constant. diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index e4fbd8b..b677a72 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -10554,94 +10554,6 @@ package body Exp_Util is end if; end Needs_Constant_Address; - ------------------------ - -- Needs_Finalization -- - ------------------------ - - function Needs_Finalization (Typ : Entity_Id) return Boolean is - function Has_Some_Controlled_Component - (Input_Typ : Entity_Id) return Boolean; - -- Determine whether type Input_Typ has at least one controlled - -- component. - - ----------------------------------- - -- Has_Some_Controlled_Component -- - ----------------------------------- - - function Has_Some_Controlled_Component - (Input_Typ : Entity_Id) return Boolean - is - Comp : Entity_Id; - - begin - -- When a type is already frozen and has at least one controlled - -- component, or is manually decorated, it is sufficient to inspect - -- flag Has_Controlled_Component. - - if Has_Controlled_Component (Input_Typ) then - return True; - - -- Otherwise inspect the internals of the type - - elsif not Is_Frozen (Input_Typ) then - if Is_Array_Type (Input_Typ) then - return Needs_Finalization (Component_Type (Input_Typ)); - - elsif Is_Record_Type (Input_Typ) then - Comp := First_Component (Input_Typ); - while Present (Comp) loop - if Needs_Finalization (Etype (Comp)) then - return True; - end if; - - Next_Component (Comp); - end loop; - end if; - end if; - - return False; - end Has_Some_Controlled_Component; - - -- Start of processing for Needs_Finalization - - begin - -- Certain run-time configurations and targets do not provide support - -- for controlled types. - - if Restriction_Active (No_Finalization) then - return False; - - -- C++ types are not considered controlled. It is assumed that the non- - -- Ada side will handle their clean up. - - elsif Convention (Typ) = Convention_CPP then - return False; - - -- Class-wide types are treated as controlled because derivations from - -- the root type may introduce controlled components. - - elsif Is_Class_Wide_Type (Typ) then - return True; - - -- Concurrent types are controlled as long as their corresponding record - -- is controlled. - - elsif Is_Concurrent_Type (Typ) - and then Present (Corresponding_Record_Type (Typ)) - and then Needs_Finalization (Corresponding_Record_Type (Typ)) - then - return True; - - -- Otherwise the type is controlled when it is either derived from type - -- [Limited_]Controlled and not subject to aspect Disable_Controlled, or - -- contains at least one controlled component. - - else - return - Is_Controlled (Typ) or else Has_Some_Controlled_Component (Typ); - end if; - end Needs_Finalization; - ---------------------------- -- New_Class_Wide_Subtype -- ---------------------------- @@ -12170,9 +12082,7 @@ package body Exp_Util is Typ : Entity_Id; begin - if No (L) - or else Is_Empty_List (L) - then + if No (L) or else Is_Empty_List (L) then return False; end if; diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index 7cb9d2d..c0848c7 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -944,10 +944,6 @@ package Exp_Util is -- consist of constants, when the object has a nontrivial initialization -- or is controlled. - function Needs_Finalization (Typ : Entity_Id) return Boolean; - -- Determine whether type Typ is controlled and this requires finalization - -- actions. - function Non_Limited_Designated_Type (T : Entity_Id) return Entity_Id; -- An anonymous access type may designate a limited view. Check whether -- non-limited view is available during expansion, to examine components diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb index 19fff57..0696f92 100644 --- a/gcc/ada/sem_ch9.adb +++ b/gcc/ada/sem_ch9.adb @@ -1897,9 +1897,6 @@ package body Sem_Ch9 is ---------------------------------- procedure Analyze_Protected_Definition (N : Node_Id) is - E : Entity_Id; - L : Entity_Id; - procedure Undelay_Itypes (T : Entity_Id); -- Itypes created for the private components of a protected type -- do not receive freeze nodes, because there is no scope in which @@ -1932,9 +1929,7 @@ package body Sem_Ch9 is end if; while Present (Comp) loop - if Is_Type (Comp) - and then Is_Itype (Comp) - then + if Is_Type (Comp) and then Is_Itype (Comp) then Set_Has_Delayed_Freeze (Comp, False); Set_Is_Frozen (Comp); @@ -1942,9 +1937,7 @@ package body Sem_Ch9 is Layout_Type (Comp); end if; - if Is_Record_Type (Comp) - or else Is_Protected_Type (Comp) - then + if Is_Record_Type (Comp) or else Is_Protected_Type (Comp) then Undelay_Itypes (Comp); end if; end if; @@ -1953,6 +1946,12 @@ package body Sem_Ch9 is end loop; end Undelay_Itypes; + -- Local variables + + Prot_Typ : constant Entity_Id := Current_Scope; + Item_Id : Entity_Id; + Last_Id : Entity_Id; + -- Start of processing for Analyze_Protected_Definition begin @@ -1963,32 +1962,37 @@ package body Sem_Ch9 is if Present (Private_Declarations (N)) and then not Is_Empty_List (Private_Declarations (N)) then - L := Last_Entity (Current_Scope); + Last_Id := Last_Entity (Prot_Typ); Analyze_Declarations (Private_Declarations (N)); - if Present (L) then - Set_First_Private_Entity (Current_Scope, Next_Entity (L)); + if Present (Last_Id) then + Set_First_Private_Entity (Prot_Typ, Next_Entity (Last_Id)); else - Set_First_Private_Entity (Current_Scope, - First_Entity (Current_Scope)); + Set_First_Private_Entity (Prot_Typ, First_Entity (Prot_Typ)); end if; end if; - E := First_Entity (Current_Scope); - while Present (E) loop - if Ekind_In (E, E_Function, E_Procedure) then - Set_Convention (E, Convention_Protected); + Item_Id := First_Entity (Prot_Typ); + while Present (Item_Id) loop + if Ekind_In (Item_Id, E_Function, E_Procedure) then + Set_Convention (Item_Id, Convention_Protected); else - Propagate_Concurrent_Flags (Current_Scope, Etype (E)); + Propagate_Concurrent_Flags (Prot_Typ, Etype (Item_Id)); + + if Chars (Item_Id) /= Name_uParent + and then Needs_Finalization (Etype (Item_Id)) + then + Set_Has_Controlled_Component (Prot_Typ); + end if; end if; - Next_Entity (E); + Next_Entity (Item_Id); end loop; - Undelay_Itypes (Current_Scope); + Undelay_Itypes (Prot_Typ); Check_Max_Entries (N, Max_Protected_Entries); - Process_End_Label (N, 'e', Current_Scope); + Process_End_Label (N, 'e', Prot_Typ); end Analyze_Protected_Definition; ---------------------------------------- diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index b6a31e6..147c281 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -19418,6 +19418,94 @@ package body Sem_Util is return Empty; end Nearest_Enclosing_Instance; + ------------------------ + -- Needs_Finalization -- + ------------------------ + + function Needs_Finalization (Typ : Entity_Id) return Boolean is + function Has_Some_Controlled_Component + (Input_Typ : Entity_Id) return Boolean; + -- Determine whether type Input_Typ has at least one controlled + -- component. + + ----------------------------------- + -- Has_Some_Controlled_Component -- + ----------------------------------- + + function Has_Some_Controlled_Component + (Input_Typ : Entity_Id) return Boolean + is + Comp : Entity_Id; + + begin + -- When a type is already frozen and has at least one controlled + -- component, or is manually decorated, it is sufficient to inspect + -- flag Has_Controlled_Component. + + if Has_Controlled_Component (Input_Typ) then + return True; + + -- Otherwise inspect the internals of the type + + elsif not Is_Frozen (Input_Typ) then + if Is_Array_Type (Input_Typ) then + return Needs_Finalization (Component_Type (Input_Typ)); + + elsif Is_Record_Type (Input_Typ) then + Comp := First_Component (Input_Typ); + while Present (Comp) loop + if Needs_Finalization (Etype (Comp)) then + return True; + end if; + + Next_Component (Comp); + end loop; + end if; + end if; + + return False; + end Has_Some_Controlled_Component; + + -- Start of processing for Needs_Finalization + + begin + -- Certain run-time configurations and targets do not provide support + -- for controlled types. + + if Restriction_Active (No_Finalization) then + return False; + + -- C++ types are not considered controlled. It is assumed that the non- + -- Ada side will handle their clean up. + + elsif Convention (Typ) = Convention_CPP then + return False; + + -- Class-wide types are treated as controlled because derivations from + -- the root type may introduce controlled components. + + elsif Is_Class_Wide_Type (Typ) then + return True; + + -- Concurrent types are controlled as long as their corresponding record + -- is controlled. + + elsif Is_Concurrent_Type (Typ) + and then Present (Corresponding_Record_Type (Typ)) + and then Needs_Finalization (Corresponding_Record_Type (Typ)) + then + return True; + + -- Otherwise the type is controlled when it is either derived from type + -- [Limited_]Controlled and not subject to aspect Disable_Controlled, or + -- contains at least one controlled component. + + else + return + Is_Controlled (Typ) or else Has_Some_Controlled_Component (Typ); + end if; + end Needs_Finalization; + ---------------------- -- Needs_One_Actual -- ---------------------- diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 808d693..35ef111 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -2220,6 +2220,10 @@ package Sem_Util is -- Return the entity of the nearest enclosing instance which encapsulates -- entity E. If no such instance exits, return Empty. + function Needs_Finalization (Typ : Entity_Id) return Boolean; + -- Determine whether type Typ is controlled and this requires finalization + -- actions. + function Needs_One_Actual (E : Entity_Id) return Boolean; -- Returns True if a function has defaults for all but its first formal, -- which is a controlling formal. Used in Ada 2005 mode to solve the -- cgit v1.1 From e2a2d49440c8f8253d15054b6147810a88a10242 Mon Sep 17 00:00:00 2001 From: Thomas Quinot Date: Thu, 11 Jul 2019 08:01:44 +0000 Subject: [Ada] Fix crash on dynamic predicate when generating SCOs A pragma Check for Dynamic_Predicate does not correspond to any source construct that has a provisionally-disabled SCO. 2019-07-11 Thomas Quinot gcc/ada/ * sem_prag.adb (Analyze_Pragma, case pragma Check): Do not call Set_SCO_Pragma_Enabled for the dynamic predicate case. gcc/testsuite/ * gnat.dg/scos1.adb: New testcase. From-SVN: r273384 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_prag.adb | 9 +++++++-- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/scos1.adb | 26 ++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/scos1.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 93a6fdc..79ee0b1 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Thomas Quinot + + * sem_prag.adb (Analyze_Pragma, case pragma Check): Do not call + Set_SCO_Pragma_Enabled for the dynamic predicate case. + 2019-07-11 Hristian Kirtchev * exp_util.ads, exp_util.adb (Needs_Finalization): Move to diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 969820e..1a2a759 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -14113,9 +14113,14 @@ package body Sem_Prag is Expr := Get_Pragma_Arg (Arg2); - -- Deal with SCO generation + -- Mark the pragma (or, if rewritten from an aspect, the original + -- aspect) as enabled. Nothing to do for an internally generated + -- check for a dynamic predicate. - if Is_Checked (N) and then not Split_PPC (N) then + if Is_Checked (N) + and then not Split_PPC (N) + and then Cname /= Name_Dynamic_Predicate + then Set_SCO_Pragma_Enabled (Loc); end if; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3b393fb..66d1e3e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Thomas Quinot + + * gnat.dg/scos1.adb: New testcase. + 2019-07-11 Justin Squirek * gnat.dg/access7.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/scos1.adb b/gcc/testsuite/gnat.dg/scos1.adb new file mode 100644 index 0000000..778c071 --- /dev/null +++ b/gcc/testsuite/gnat.dg/scos1.adb @@ -0,0 +1,26 @@ +-- { dg-do compile } +-- { dg-options "-gnata -gnateS" } + +procedure SCOs1 with SPARK_Mode => On is + + LEN_IN_BITS : constant := 20; + + M_SIZE_BYTES : constant := 2 ** LEN_IN_BITS; + ET_BYTES : constant := (M_SIZE_BYTES - 4); + + type T_BYTES is new Integer range 0 .. ET_BYTES with Size => 32; + subtype TYPE5_SCALAR is T_BYTES + with Dynamic_Predicate => TYPE5_SCALAR mod 4 = 0; + + type E_16_BYTES is new Integer; + subtype RD_BYTES is E_16_BYTES + with Dynamic_Predicate => RD_BYTES mod 4 = 0; + + function "-" (left : TYPE5_SCALAR; right : RD_BYTES) return TYPE5_SCALAR + is ( left - TYPE5_SCALAR(right) ) + with Pre => TYPE5_SCALAR(right) <= left and then + left - TYPE5_SCALAR(right) <= T_BYTES'Last, Inline_Always; + +begin + null; +end SCOs1; -- cgit v1.1 From dd8b4c118e15b03a9f8ca748be0c3415e8df788a Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 11 Jul 2019 08:01:49 +0000 Subject: [Ada] Link error due to negated intrinsic comparison This patch corrects the resolution of operator "not" when the expression being negated is an equality operator to prevent the transformation of an intrinsic equality operator into a function call. 2019-07-11 Hristian Kirtchev gcc/ada/ * sem_res.adb (Resolve_Op_Not): Do not rewrite an equality operator into a function call when the operator is intrinsic. gcc/testsuite/ * gnat.dg/equal9.adb: New testcase. From-SVN: r273385 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_res.adb | 9 +++++++-- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/equal9.adb | 26 ++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/equal9.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 79ee0b1..9d5a50f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Hristian Kirtchev + + * sem_res.adb (Resolve_Op_Not): Do not rewrite an equality + operator into a function call when the operator is intrinsic. + 2019-07-11 Thomas Quinot * sem_prag.adb (Analyze_Pragma, case pragma Check): Do not call diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 78cbac0..c17b28d 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -10091,15 +10091,20 @@ package body Sem_Res is declare Opnd : constant Node_Id := Right_Opnd (N); + Op_Id : Entity_Id; + begin if B_Typ = Standard_Boolean and then Nkind_In (Opnd, N_Op_Eq, N_Op_Ne) and then Is_Overloaded (Opnd) then Resolve_Equality_Op (Opnd, B_Typ); + Op_Id := Entity (Opnd); - if Ekind (Entity (Opnd)) = E_Function then - Rewrite_Operator_As_Call (Opnd, Entity (Opnd)); + if Ekind (Op_Id) = E_Function + and then not Is_Intrinsic_Subprogram (Op_Id) + then + Rewrite_Operator_As_Call (Opnd, Op_Id); end if; if not Inside_A_Generic or else Is_Entity_Name (Opnd) then diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 66d1e3e..a761f79 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Hristian Kirtchev + + * gnat.dg/equal9.adb: New testcase. + 2019-07-11 Thomas Quinot * gnat.dg/scos1.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/equal9.adb b/gcc/testsuite/gnat.dg/equal9.adb new file mode 100644 index 0000000..aa60d5b --- /dev/null +++ b/gcc/testsuite/gnat.dg/equal9.adb @@ -0,0 +1,26 @@ +-- { dg-do run } + +with Ada.Text_IO; use Ada.Text_IO; +with System; use System; + +procedure Equal9 is + Val : Address := Null_Address; +begin + if Val = Null_Address then + Put_Line ("= OK"); + else + raise Program_Error; + end if; + + if Val /= Null_Address then + raise Program_Error; + else + Put_Line ("/= OK"); + end if; + + if not (Val = Null_Address) then + raise Program_Error; + else + Put_Line ("not = OK"); + end if; +end Equal9; -- cgit v1.1 From a081ded4df03e30cd4aefa1e946eb31aa423bfb2 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 11 Jul 2019 08:01:54 +0000 Subject: [Ada] Compile-time evaluation of predicate checks This patch recognizes case of dynamic predicates on integer subtypes that are simple enough to be evaluated statically when the argument is itself a literal. Even though in many cases such predicate checks will be removed by the back-end with any level of optimization, it is preferable to perform this constant folding in the front-end, wich also cleans up the output of CCG, as well as producing explicit warnings when the test will fail. 2019-07-11 Ed Schonberg gcc/ada/ * exp_ch6.adb (Can_Fold_Predicate_Call): New function, subsidiary of Expand_Call_Helper, to compute statically a predicate check when the argument is a static integer. gcc/testsuite/ * gnat.dg/predicate11.adb: New testcase. From-SVN: r273386 --- gcc/ada/ChangeLog | 6 ++ gcc/ada/exp_ch6.adb | 101 ++++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/predicate11.adb | 19 +++++++ 4 files changed, 130 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/predicate11.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9d5a50f..b79a817 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-11 Ed Schonberg + + * exp_ch6.adb (Can_Fold_Predicate_Call): New function, + subsidiary of Expand_Call_Helper, to compute statically a + predicate check when the argument is a static integer. + 2019-07-11 Hristian Kirtchev * sem_res.adb (Resolve_Op_Not): Do not rewrite an equality diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index feeac7b..0251d00 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -2319,6 +2319,13 @@ package body Exp_Ch6 is -- Adds invariant checks for every intermediate type between the range -- of a view converted argument to its ancestor (from parent to child). + function Can_Fold_Predicate_Call (P : Entity_Id) return Boolean; + -- Try to constant-fold a predicate check, which often enough is a + -- simple arithmetic expression that can be computed statically if + -- its argument is static. This cleans up the output of CCG, even + -- though useless predicate checks will be generally removed by + -- back-end optimizations. + function Inherited_From_Formal (S : Entity_Id) return Entity_Id; -- Within an instance, a type derived from an untagged formal derived -- type inherits from the original parent, not from the actual. The @@ -2467,6 +2474,89 @@ package body Exp_Ch6 is end if; end Add_View_Conversion_Invariants; + ----------------------------- + -- Can_Fold_Predicate_Call -- + ----------------------------- + + function Can_Fold_Predicate_Call (P : Entity_Id) return Boolean is + Actual : constant Node_Id := + First (Parameter_Associations (Call_Node)); + Subt : constant Entity_Id := Etype (First_Entity (P)); + Pred : Node_Id; + + function May_Fold (N : Node_Id) return Traverse_Result; + -- The predicate expression is foldable if it only contains operators + -- and literals. During this check, we also replace occurrences of + -- the formal of the constructed predicate function with the static + -- value of the actual. This is done on a copy of the analyzed + -- expression for the predicate. + + function May_Fold (N : Node_Id) return Traverse_Result is + begin + case Nkind (N) is + when N_Binary_Op | N_Unary_Op => + return OK; + + when N_Identifier | N_Expanded_Name => + if Ekind (Entity (N)) = E_In_Parameter + and then Entity (N) = First_Entity (P) + then + Rewrite (N, New_Copy (Actual)); + Set_Is_Static_Expression (N); + return OK; + + elsif Ekind (Entity (N)) = E_Enumeration_Literal then + return OK; + + else + return Abandon; + end if; + + when N_If_Expression | N_Case_Expression => + return OK; + + when N_Integer_Literal => + return OK; + + when others => + return Abandon; + end case; + end May_Fold; + + function Try_Fold is new Traverse_Func (May_Fold); + + -- Start of processing for Can_Fold_Predicate_Call + + begin + -- Folding is only interesting if the actual is static and its type + -- has a Dynamic_Predicate aspect. For CodePeer we preserve the + -- function call. + + if Nkind (Actual) /= N_Integer_Literal + or else not Has_Dynamic_Predicate_Aspect (Subt) + or else CodePeer_Mode + then + return False; + end if; + + -- Retrieve the analyzed expression for the predicate + + Pred := + New_Copy_Tree + (Expression (Find_Aspect (Subt, Aspect_Dynamic_Predicate))); + + if Try_Fold (Pred) = OK then + Rewrite (Call_Node, Pred); + Analyze_And_Resolve (Call_Node, Standard_Boolean); + return True; + + else + -- Continue expansion of function call + + return False; + end if; + end Can_Fold_Predicate_Call; + --------------------------- -- Inherited_From_Formal -- --------------------------- @@ -2815,6 +2905,17 @@ package body Exp_Ch6 is end; end if; + -- if this is a call to a predicate function, try to constant + -- fold it. + + if Nkind (Call_Node) = N_Function_Call + and then Is_Entity_Name (Name (Call_Node)) + and then Is_Predicate_Function (Subp) + and then Can_Fold_Predicate_Call (Subp) + then + return; + end if; + if Modify_Tree_For_C and then Nkind (Call_Node) = N_Function_Call and then Is_Entity_Name (Name (Call_Node)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a761f79..bbfada2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Ed Schonberg + + * gnat.dg/predicate11.adb: New testcase. + 2019-07-11 Hristian Kirtchev * gnat.dg/equal9.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/predicate11.adb b/gcc/testsuite/gnat.dg/predicate11.adb new file mode 100644 index 0000000..dc92a91 --- /dev/null +++ b/gcc/testsuite/gnat.dg/predicate11.adb @@ -0,0 +1,19 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +procedure Predicate11 is + type T_BYTES is new Integer range 0 .. 2**15 - 1 with Size => 32; + subtype TYPE5_SCALAR is T_BYTES + with Dynamic_Predicate => TYPE5_SCALAR mod 4 = 0; + subtype Cond is Integer + with dynamic_predicate => (if cond < 5 then false else True); + + Thing1 : Type5_Scalar := 7; -- { dg-warning "check will fail at run time" } + function OK (C :Type5_scalar) return Boolean is (True); + Thing2 : Type5_Scalar; + Thing3 : Cond; +begin + if not OK (7) then raise Program_Error; end if; -- { dg-warning "check will fail at run time" } + Thing2 := 8; + Thing3 := 1; -- { dg-warning "check will fail at run time" } +end; -- cgit v1.1 From bce6accb664712f2d046bad9566fee810b43fed6 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 11 Jul 2019 08:01:58 +0000 Subject: [Ada] Internal crash on illegal renaming This patch updates the retrieval of the renamed object name of an object renaming declaration to handle various name forms. No need for a test because one already exists, and reproducing requires a compiler built with assertions. 2019-07-11 Hristian Kirtchev gcc/ada/ * sem_ch8.adb (Analyze_Object_Renaming): Obtain the object being renamed using routine Get_Object_Name which takes care of various name forms. (Get_Object_Name): New routine. From-SVN: r273387 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch8.adb | 43 +++++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 10 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b79a817..cc7178b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-11 Hristian Kirtchev + + * sem_ch8.adb (Analyze_Object_Renaming): Obtain the object being + renamed using routine Get_Object_Name which takes care of + various name forms. + (Get_Object_Name): New routine. + 2019-07-11 Ed Schonberg * exp_ch6.adb (Can_Fold_Predicate_Call): New function, diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 58abc9c..90b0c65 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -774,6 +774,10 @@ package body Sem_Ch8 is -- has already established its actual subtype. This is only relevant -- if the renamed object is an explicit dereference. + function Get_Object_Name (Nod : Node_Id) return Node_Id; + -- Obtain the name of the object from node Nod which is being renamed by + -- the object renaming declaration N. + ------------------------------ -- Check_Constrained_Object -- ------------------------------ @@ -840,6 +844,33 @@ package body Sem_Ch8 is end if; end Check_Constrained_Object; + --------------------- + -- Get_Object_Name -- + --------------------- + + function Get_Object_Name (Nod : Node_Id) return Node_Id is + Obj_Nam : Node_Id; + + begin + Obj_Nam := Nod; + while Present (Obj_Nam) loop + if Nkind_In (Obj_Nam, N_Attribute_Reference, + N_Explicit_Dereference, + N_Indexed_Component, + N_Slice) + then + Obj_Nam := Prefix (Obj_Nam); + + elsif Nkind (Obj_Nam) = N_Selected_Component then + Obj_Nam := Selector_Name (Obj_Nam); + else + exit; + end if; + end loop; + + return Obj_Nam; + end Get_Object_Name; + -- Start of processing for Analyze_Object_Renaming begin @@ -1156,18 +1187,10 @@ package body Sem_Ch8 is elsif Ada_Version >= Ada_2005 and then Nkind (Nam) in N_Has_Entity then declare - Nam_Decl : Node_Id; - Nam_Ent : Entity_Id; + Nam_Ent : constant Entity_Id := Entity (Get_Object_Name (Nam)); + Nam_Decl : constant Node_Id := Declaration_Node (Nam_Ent); begin - if Nkind (Nam) = N_Attribute_Reference then - Nam_Ent := Entity (Prefix (Nam)); - else - Nam_Ent := Entity (Nam); - end if; - - Nam_Decl := Parent (Nam_Ent); - if Has_Null_Exclusion (N) and then not Has_Null_Exclusion (Nam_Decl) then -- cgit v1.1 From 29c64a0f6d13bf413cf338da23580e8a94ead23c Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 11 Jul 2019 08:02:03 +0000 Subject: [Ada] Minor reformatting 2019-07-11 Hristian Kirtchev gcc/ada/ * checks.adb, exp_ch6.adb, gnat1drv.adb, sem_aux.adb, sem_ch2.adb, sem_ch8.adb, sem_res.adb: Minor reformatting. From-SVN: r273388 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/checks.adb | 18 +++++++++--------- gcc/ada/exp_ch6.adb | 31 ++++++++++++++++++++++--------- gcc/ada/gnat1drv.adb | 7 ++++--- gcc/ada/sem_aux.adb | 9 +++++---- gcc/ada/sem_ch2.adb | 5 +---- gcc/ada/sem_ch8.adb | 3 +-- gcc/ada/sem_res.adb | 4 ++-- 8 files changed, 49 insertions(+), 33 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cc7178b..a17ab7e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-11 Hristian Kirtchev + * checks.adb, exp_ch6.adb, gnat1drv.adb, sem_aux.adb, + sem_ch2.adb, sem_ch8.adb, sem_res.adb: Minor reformatting. + +2019-07-11 Hristian Kirtchev + * sem_ch8.adb (Analyze_Object_Renaming): Obtain the object being renamed using routine Get_Object_Name which takes care of various name forms. diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 7ca66bd..984bb15 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -577,9 +577,10 @@ package body Checks is Typ : Entity_Id; Insert_Node : Node_Id) is + Loc : constant Source_Ptr := Sloc (N); + Check_Cond : Node_Id; - Loc : constant Source_Ptr := Sloc (N); - Param_Ent : Entity_Id := Param_Entity (N); + Param_Ent : Entity_Id := Param_Entity (N); Param_Level : Node_Id; Type_Level : Node_Id; @@ -639,9 +640,10 @@ package body Checks is -- Raise Program_Error if the accessibility level of the access -- parameter is deeper than the level of the target access type. - Check_Cond := Make_Op_Gt (Loc, - Left_Opnd => Param_Level, - Right_Opnd => Type_Level); + Check_Cond := + Make_Op_Gt (Loc, + Left_Opnd => Param_Level, + Right_Opnd => Type_Level); Insert_Action (Insert_Node, Make_Raise_Program_Error (Loc, @@ -657,10 +659,8 @@ package body Checks is and then Entity (Check_Cond) = Standard_True then Error_Msg_Warn := SPARK_Mode /= On; - Error_Msg_N - ("accessibility check fails<<", N); - Error_Msg_N - ("\Program_Error [<<", N); + Error_Msg_N ("accessibility check fails<<", N); + Error_Msg_N ("\Program_Error [<<", N); end if; end if; end Apply_Accessibility_Check; diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 0251d00..c23e9ee 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -2481,8 +2481,6 @@ package body Exp_Ch6 is function Can_Fold_Predicate_Call (P : Entity_Id) return Boolean is Actual : constant Node_Id := First (Parameter_Associations (Call_Node)); - Subt : constant Entity_Id := Etype (First_Entity (P)); - Pred : Node_Id; function May_Fold (N : Node_Id) return Traverse_Result; -- The predicate expression is foldable if it only contains operators @@ -2491,13 +2489,21 @@ package body Exp_Ch6 is -- value of the actual. This is done on a copy of the analyzed -- expression for the predicate. + -------------- + -- May_Fold -- + -------------- + function May_Fold (N : Node_Id) return Traverse_Result is begin case Nkind (N) is - when N_Binary_Op | N_Unary_Op => + when N_Binary_Op + | N_Unary_Op + => return OK; - when N_Identifier | N_Expanded_Name => + when N_Expanded_Name + | N_Identifier + => if Ekind (Entity (N)) = E_In_Parameter and then Entity (N) = First_Entity (P) then @@ -2512,7 +2518,9 @@ package body Exp_Ch6 is return Abandon; end if; - when N_If_Expression | N_Case_Expression => + when N_Case_Expression + | N_If_Expression + => return OK; when N_Integer_Literal => @@ -2525,6 +2533,11 @@ package body Exp_Ch6 is function Try_Fold is new Traverse_Func (May_Fold); + -- Local variables + + Subt : constant Entity_Id := Etype (First_Entity (P)); + Pred : Node_Id; + -- Start of processing for Can_Fold_Predicate_Call begin @@ -2542,17 +2555,17 @@ package body Exp_Ch6 is -- Retrieve the analyzed expression for the predicate Pred := - New_Copy_Tree - (Expression (Find_Aspect (Subt, Aspect_Dynamic_Predicate))); + New_Copy_Tree + (Expression (Find_Aspect (Subt, Aspect_Dynamic_Predicate))); if Try_Fold (Pred) = OK then Rewrite (Call_Node, Pred); Analyze_And_Resolve (Call_Node, Standard_Boolean); return True; - else - -- Continue expansion of function call + -- Otherwise continue the expansion of the function call + else return False; end if; end Can_Fold_Predicate_Call; diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 2e4204b..55a57dd 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -1056,9 +1056,10 @@ procedure Gnat1drv is for U in Main_Unit .. Last_Unit loop if In_Extended_Main_Source_Unit (Cunit_Entity (U)) then declare - Nam : constant String := - Get_Name_String (File_Name (Source_Index (U))) & ".json"; - Namid : constant File_Name_Type := Name_Enter (Nam); + Nam : constant String := + Get_Name_String + (File_Name (Source_Index (U))) & ".json"; + Namid : constant File_Name_Type := Name_Enter (Nam); Index : constant Source_File_Index := Load_Config_File (Namid); begin diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb index 6a93a39..71a3873 100644 --- a/gcc/ada/sem_aux.adb +++ b/gcc/ada/sem_aux.adb @@ -1330,10 +1330,11 @@ package body Sem_Aux is function Is_Protected_Operation (E : Entity_Id) return Boolean is begin - return Is_Entry (E) - or else (Is_Subprogram (E) - and then Nkind (Parent (Unit_Declaration_Node (E))) = - N_Protected_Definition); + return + Is_Entry (E) + or else (Is_Subprogram (E) + and then Nkind (Parent (Unit_Declaration_Node (E))) = + N_Protected_Definition); end Is_Protected_Operation; ---------------------- diff --git a/gcc/ada/sem_ch2.adb b/gcc/ada/sem_ch2.adb index 0a282d4..378269f 100644 --- a/gcc/ada/sem_ch2.adb +++ b/gcc/ada/sem_ch2.adb @@ -31,7 +31,6 @@ with Restrict; use Restrict; with Rident; use Rident; with Sem_Ch8; use Sem_Ch8; with Sem_Dim; use Sem_Dim; --- with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; with Stand; use Stand; with Uintp; use Uintp; @@ -97,9 +96,7 @@ package body Sem_Ch2 is -- prior analysis (or construction) of the literal, and after type -- checking and resolution. - if No (Etype (N)) - or else not Is_Modular_Integer_Type (Etype (N)) - then + if No (Etype (N)) or else not Is_Modular_Integer_Type (Etype (N)) then Set_Etype (N, Universal_Integer); end if; diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 90b0c65..c9d6151 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -815,8 +815,7 @@ package body Sem_Ch8 is -- it does not apply to records with limited components, for which -- this syntactic flag is not set, but whose size is also fixed. - elsif (Is_Record_Type (Typ) - and then Is_Limited_Type (Typ)) + elsif (Is_Record_Type (Typ) and then Is_Limited_Type (Typ)) or else (Ekind (Typ) = E_Limited_Private_Type and then Has_Discriminants (Typ) diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index c17b28d..730f173 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -3467,8 +3467,8 @@ package body Sem_Res is or else Nkind (Original_Node (N)) not in N_Subprogram_Call or else (Nkind (Name (N)) = N_Identifier and then Present (Entity (Name (N))) - and then Nkind (Entity (Name (N))) - = N_Defining_Operator_Symbol) + and then Nkind (Entity (Name (N))) = + N_Defining_Operator_Symbol) or else not Comes_From_Source (N) then return; -- cgit v1.1 From f9e5da46f7708d7eaf5a080e51dd6d5553bdf37a Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 11 Jul 2019 08:02:07 +0000 Subject: [Ada] Infinite loop on illegal declaration This patch updates predicate Null_Status to prevent an infinite recursion when the argument is an illegal object declaration of an access type. 2019-07-11 Hristian Kirtchev gcc/ada/ * sem_util.adb (Null_Status): Assume that an erroneous construct has an undefined null status. gcc/testsuite/ * gnat.dg/self_ref1.adb: New testcase. From-SVN: r273389 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_util.adb | 8 +++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/self_ref1.adb | 11 +++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/self_ref1.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a17ab7e..0a1bd24 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-11 Hristian Kirtchev + * sem_util.adb (Null_Status): Assume that an erroneous construct + has an undefined null status. + +2019-07-11 Hristian Kirtchev + * checks.adb, exp_ch6.adb, gnat1drv.adb, sem_aux.adb, sem_ch2.adb, sem_ch8.adb, sem_res.adb: Minor reformatting. diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 147c281..04d981a6 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -22367,9 +22367,15 @@ package body Sem_Util is -- Start of processing for Null_Status begin + -- Prevent cascaded errors or infinite loops when trying to determine + -- the null status of an erroneous construct. + + if Error_Posted (N) then + return Unknown; + -- An allocator always creates a non-null value - if Nkind (N) = N_Allocator then + elsif Nkind (N) = N_Allocator then return Is_Non_Null; -- Taking the 'Access of something yields a non-null value diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bbfada2..f0d066d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Hristian Kirtchev + + * gnat.dg/self_ref1.adb: New testcase. + 2019-07-11 Ed Schonberg * gnat.dg/predicate11.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/self_ref1.adb b/gcc/testsuite/gnat.dg/self_ref1.adb new file mode 100644 index 0000000..a65dbd9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/self_ref1.adb @@ -0,0 +1,11 @@ +-- { dg-do compile } + +procedure Self_Ref1 is + type Integer_Ptr is access all Integer; + Ptr : constant Integer_Ptr := Integer_Ptr (Ptr); -- { dg-error "object \"Ptr\" cannot be used before end of its declaration" } + +begin + if Ptr /= null then + null; + end if; +end Self_Ref1; -- cgit v1.1 From 852c41d488ce21428ea04999bf16143406460166 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Thu, 11 Jul 2019 08:02:12 +0000 Subject: [Ada] Document gnatpp's --spaces-only switch 2019-07-11 Bob Duff gcc/ada/ * doc/gnat_ugn/gnat_utility_programs.rst: Document gnatpp's --spaces-only switch. From-SVN: r273390 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0a1bd24..1b338d3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Bob Duff + + * doc/gnat_ugn/gnat_utility_programs.rst: Document gnatpp's + --spaces-only switch. + 2019-07-11 Hristian Kirtchev * sem_util.adb (Null_Status): Assume that an erroneous construct diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst index 516c57c..5ad86dc 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst @@ -3257,6 +3257,12 @@ Alternatively, you may run the script using the following command line: Keep the line breaks from the source; do not insert or delete any line breaks. + .. index:: --spaces-only (gnatpp) + + :switch:`--spaces-only` + Disable all formatting except for inserting and removing spaces. + This implies --source-line-breaks. + The ``--comments`` switches are compatible with one another, except that the ``--comments-unchanged`` switch disables all other comment formatting switches. -- cgit v1.1 From 4ae83b58d2316f22d6874b6901fa61fe0f823e3f Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Thu, 11 Jul 2019 08:02:17 +0000 Subject: [Ada] Fix inconsistent documentation for gnatmetric One part said all metrics are enabled by default (which is now true), and another part said the coupling metrics are disabled by default (which is no longer true). 2019-07-11 Bob Duff gcc/ada/ * doc/gnat_ugn/gnat_utility_programs.rst: Fix inconsistent documentation for gnatmetric. * gnat_ugn.texi: Regenerate. From-SVN: r273391 --- gcc/ada/ChangeLog | 6 ++ gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst | 90 ++++++++++++-------------- gcc/ada/gnat_ugn.texi | 2 +- 3 files changed, 50 insertions(+), 48 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1b338d3..a39069c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,11 @@ 2019-07-11 Bob Duff + * doc/gnat_ugn/gnat_utility_programs.rst: Fix inconsistent + documentation for gnatmetric. + * gnat_ugn.texi: Regenerate. + +2019-07-11 Bob Duff + * doc/gnat_ugn/gnat_utility_programs.rst: Document gnatpp's --spaces-only switch. diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst index 5ad86dc..fc39214 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst @@ -1214,7 +1214,7 @@ The following switches are available: :samp:`f` By default, gnathtml will generate html links only for global entities - ('with'ed units, global variables and types,...). If you specify + ('with'ed units, global variables and types,...). If you specify :switch:`-f` on the command line, then links will be generated for local entities too. @@ -1310,7 +1310,7 @@ Alternatively, you may run the script using the following command line: ``gnat2xml`` is a project-aware tool (see :ref:`Using_Project_Files_with_GNAT_Tools` for a description of - the project-related switches). The project file package that can specify + the project-related switches). The project file package that can specify ``gnat2xml`` switches is named ``gnat2xml``. .. _Switches_for_``gnat2xml``: @@ -1780,7 +1780,7 @@ Alternatively, you may run the script using the following command line: ``gnatcheck`` is a project-aware tool (see :ref:`Using_Project_Files_with_GNAT_Tools` for a description of - the project-related switches). The project file package that can specify + the project-related switches). The project file package that can specify ``gnatcheck`` switches is named ``Check``. For full details, plese refer to :title:`GNATcheck Reference Manual`. @@ -1804,11 +1804,11 @@ Alternatively, you may run the script using the following command line: for computing various program metrics. It takes an Ada source file as input and generates a file containing the metrics data as output. Various switches control which - metrics are computed and output. + metrics are reported. ``gnatmetric`` is a project-aware tool (see :ref:`Using_Project_Files_with_GNAT_Tools` for a description of - the project-related switches). The project file package that can specify + the project-related switches). The project file package that can specify ``gnatmetric`` switches is named ``Metrics``. The ``gnatmetric`` command has the form @@ -1921,9 +1921,9 @@ Alternatively, you may run the script using the following command line: .. index:: --short-file-names (gnatmetric) :switch:`--short-file-names` - Use 'short' source file names in the output. (The ``gnatmetric`` + Use 'short' source file names in the output. (The ``gnatmetric`` output includes the name(s) of the Ada source file(s) from which the - metrics are computed. By default each name includes the absolute + metrics are computed. By default each name includes the absolute path. The :switch:`--short-file-names` switch causes ``gnatmetric`` to exclude all directory information from the file names that are output.) @@ -1980,12 +1980,11 @@ Alternatively, you may run the script using the following command line: Specifying a set of metrics to compute -------------------------------------- - By default all the metrics are computed and reported. The switches - described in this subsection allow you to control, on an individual - basis, whether metrics are computed and reported. If at least one - positive metric switch is specified (that is, a switch that defines - that a given metric or set of metrics is to be computed), then only - explicitly specified metrics are reported. + By default all the metrics are reported. The switches described in this + subsection allow you to control, on an individual basis, whether metrics are + reported. If at least one positive metric switch is specified (that is, a + switch that defines that a given metric or set of metrics is to be computed), + then only explicitly specified metrics are reported. .. _Line_Metrics_Control: @@ -2023,7 +2022,7 @@ Alternatively, you may run the script using the following command line: code lines in bodies. You can use the following switches to select the specific line metrics - to be computed and reported. + to be reported. .. index:: --lines (gnatmetric) @@ -2089,10 +2088,9 @@ Alternatively, you may run the script using the following command line: :switch:`--lines-average` - Report the average number of code lines in subprogram bodies, task - bodies, entry bodies and statement sequences in package bodies. The - metric is computed and reported for the whole set of processed Ada - sources only. + Report the average number of code lines in subprogram bodies, task bodies, + entry bodies and statement sequences in package bodies. The metric is + reported for the whole set of processed Ada sources only. :switch:`--no-lines-average` @@ -2173,7 +2171,7 @@ Alternatively, you may run the script using the following command line: declarations. It is the total number of types that can be referenced from outside this compilation unit, plus the number of types from all the visible parts of all the visible generic - packages. Generic formal types are not counted. Only types, not + packages. Generic formal types are not counted. Only types, not subtypes, are included. Along with the total number of public types, the following @@ -2193,14 +2191,14 @@ Alternatively, you may run the script using the following command line: * *All types* This metric is computed for any compilation unit. It is equal to the total number of the declarations of different types given in - the compilation unit. The private and the corresponding full type + the compilation unit. The private and the corresponding full type declaration are counted as one type declaration. Incomplete type declarations and generic formal types are not counted. No distinction is made among different kinds of types (abstract, - private etc.); the total number of types is computed and reported. + private etc.); the total number of types is reported. - By default, all the syntax metrics are computed and reported. You can - use the following switches to select specific syntax metrics. + By default, all the syntax metrics are reported. You can use the following + switches to select specific syntax metrics. .. index:: --syntax (gnatmetric) @@ -2311,7 +2309,7 @@ Alternatively, you may run the script using the following command line: According to McCabe, both control statements and short-circuit control forms should be taken into account when computing cyclomatic - complexity. For Ada 2012 we have also take into account conditional + complexity. For Ada 2012 we have also take into account conditional expressions and quantified expressions. For each body, we compute three metric values: @@ -2364,9 +2362,8 @@ Alternatively, you may run the script using the following command line: code of assertions and predicates (that is, subprogram preconditions and postconditions, subtype predicates and type invariants) is also skipped. - By default, all the complexity metrics are computed and reported. - For more fine-grained control you can use - the following switches: + By default, all the complexity metrics are reported. For more fine-grained + control you can use the following switches: .. index:: --complexity (gnatmetric) @@ -2408,8 +2405,7 @@ Alternatively, you may run the script using the following command line: :switch:`--complexity-average` Report the average McCabe Cyclomatic Complexity for all the subprogram bodies, task bodies, entry bodies and statement sequences in package bodies. - The metric is computed and reported for whole set of processed Ada sources - only. + The metric is reported for whole set of processed Ada sources only. :switch:`--no-complexity-average` @@ -2623,8 +2619,8 @@ Alternatively, you may run the script using the following command line: by invoking ``gnatmetric`` with the corresponding project file and with the :switch:`-U` option. - By default, all the coupling metrics are disabled. You can use the following - switches to specify the coupling metrics to be computed and reported: + By default, all the coupling metrics are reported. You can use the following + switches to select specific syntax metrics. .. index:: --tagged-coupling (gnatmetric) .. index:: --hierarchy-coupling (gnatmetric) @@ -2854,14 +2850,14 @@ Alternatively, you may run the script using the following command line: of ``gnatpp``, which replaces the ASIS-based version. The ``gnatpp`` tool is a utility for source reformatting / pretty - printing. It takes an Ada source file as input and generates a - reformatted version as output. You can specify various style + printing. It takes an Ada source file as input and generates a + reformatted version as output. You can specify various style directives via switches; e.g., identifier case conventions, rules of indentation, and comment layout. ``gnatpp`` is a project-aware tool (see :ref:`Using_Project_Files_with_GNAT_Tools` for a description of - the project-related switches). The project file package that can specify + the project-related switches). The project file package that can specify ``gnatpp`` switches is named ``Pretty_Printer``. ``gnatpp`` cannot process sources that contain preprocessing @@ -3019,7 +3015,7 @@ Alternatively, you may run the script using the following command line: .. index:: --enum-upper-case (gnatpp) :switch:`--enum-upper-case` - Enumeration literals are in upper case. Overrides -n casing + Enumeration literals are in upper case. Overrides -n casing setting. .. index:: --enum-lower-case (gnatpp) @@ -3133,7 +3129,7 @@ Alternatively, you may run the script using the following command line: compatible. This group of ``gnatpp`` switches controls the layout of comments and - complex syntactic constructs. See :ref:`Formatting_Comments` for details + complex syntactic constructs. See :ref:`Formatting_Comments` for details on their effect. @@ -3750,10 +3746,10 @@ Alternatively, you may run the script using the following command line: the same line. A whole-line comment is indented according to the surrounding code, - with some exceptions. Comments that start in column 1 are kept - there. If possible, comments are not moved so far to the right that - the maximum line length is exceeded. The ``--comments-unchanged`` - option turns off comment formatting. Special-form comments such as + with some exceptions. Comments that start in column 1 are kept + there. If possible, comments are not moved so far to the right that + the maximum line length is exceeded. The ``--comments-unchanged`` + option turns off comment formatting. Special-form comments such as SPARK-style ``--#...`` are left alone. For an end-of-line comment, ``gnatpp`` tries to leave the same @@ -3778,7 +3774,7 @@ Alternatively, you may run the script using the following command line: are formatted according to the ``--comments-gnat-beginning`` and ``--comments-fill`` switches; other formatting switches are ignored. For example, ``--comments-only --comments-fill`` means to fill comment - paragraphs, and do nothing else. Likewise, ``--comments-only + paragraphs, and do nothing else. Likewise, ``--comments-only --comments-gnat-beginning`` ensures comments start with at least two spaces after ``--``, and ``--comments-only --comments-gnat-beginning --comments-fill`` does both. If ``--comments-only`` is given without @@ -3795,11 +3791,11 @@ Alternatively, you may run the script using the following command line: the same casing as the corresponding defining identifier. You control the casing for defining occurrences via the ``--name...`` - switches. With ``--name-case-as-declared``, which is the default, + switches. With ``--name-case-as-declared``, which is the default, defining occurrences appear exactly as in the source file where they - are declared. The other values for this switch -- + are declared. The other values for this switch -- ``--name-upper-case``, ``--name-lower-case``, ``--name-mixed-case`` - -- result in upper, lower, or mixed case, respectively. If + -- result in upper, lower, or mixed case, respectively. If ``gnatpp`` changes the casing of a defining occurrence, it analogously changes the casing of all the usage occurrences of this name. @@ -3807,7 +3803,7 @@ Alternatively, you may run the script using the following command line: If the defining occurrence of a name is not in the source compilation unit currently being processed by ``gnatpp``, the casing of each reference to this name is changed according to the switch (subject to - the dictionary file mechanism described below). Thus ``gnatpp`` acts + the dictionary file mechanism described below). Thus ``gnatpp`` acts as though the switch had affected the casing for the defining occurrence of the name. @@ -3844,7 +3840,7 @@ Alternatively, you may run the script using the following command line: ``-n`` switch or explicit dictionary files. For example, by default the names ``Ada.Text_IO`` and ``GNAT.OS_Lib`` will appear as just shown, even in the presence of - a ``--name-upper-case`` switch. To ensure that even + a ``--name-upper-case`` switch. To ensure that even such names are rendered in uppercase, additionally supply the --dictionary=- switch (or else place these names in upper case in a dictionary file). @@ -4754,7 +4750,7 @@ Alternatively, you may run the script using the following command line: :switch:`--subdir={dirname}` Test packages are placed in a subdirectory of the corresponding source directory, with the name ``dirname``. Thus, each set of unit tests is located - in a subdirectory of the code under test. If the sources are in separate + in a subdirectory of the code under test. If the sources are in separate directories, each source directory has a test subdirectory named ``dirname``. diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index db2adaf..29424e7 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -19024,7 +19024,7 @@ If you do not specify an extension, it will default to @code{htm}. @item @code{f} By default, gnathtml will generate html links only for global entities -('with'ed units, global variables and types,...). If you specify +('with'ed units, global variables and types,...). If you specify @code{-f} on the command line, then links will be generated for local entities too. @end table -- cgit v1.1 From ae59bda92bbab1a02562683dd54fb9c287307a9e Mon Sep 17 00:00:00 2001 From: Justin Squirek Date: Thu, 11 Jul 2019 08:02:21 +0000 Subject: [Ada] Pragma Unreferenced triggers undefined reference This patch corrects the generation of protected body declarations so that instances of pragma Unreferenced applied to formals don't falsly trigger undefined references. 2019-07-11 Justin Squirek gcc/ada/ * exp_ch9.adb (Build_Private_Protected_Declaration): Add exception for the moving of pragmas to internally generated specs for pragma Unreferenced. gcc/testsuite/ * gnat.dg/unreferenced2.adb: New testcase. From-SVN: r273392 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/exp_ch9.adb | 11 ++++++++++- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/unreferenced2.adb | 34 +++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/unreferenced2.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a39069c..b51a3cc 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-11 Justin Squirek + + * exp_ch9.adb (Build_Private_Protected_Declaration): Add + exception for the moving of pragmas to internally generated + specs for pragma Unreferenced. + 2019-07-11 Bob Duff * doc/gnat_ugn/gnat_utility_programs.rst: Fix inconsistent diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 7eb6eb5..077063f 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -3493,6 +3493,8 @@ package body Exp_Ch9 is procedure Move_Pragmas (From : Node_Id; To : Node_Id); -- Find all suitable source pragmas at the top of subprogram body From's -- declarations and insert them after arbitrary node To. + -- + -- Very similar to Move_Pragmas in sem_ch6 ??? --------------------- -- Analyze_Pragmas -- @@ -3544,7 +3546,14 @@ package body Exp_Ch9 is Next_Decl := Next (Decl); - if Nkind (Decl) = N_Pragma then + -- We add an exception here for Unreferenced pragmas since the + -- internally generated spec gets analyzed within + -- Build_Private_Protected_Declaration and will lead to spurious + -- warnings due to the way references are checked. + + if Nkind (Decl) = N_Pragma + and then Pragma_Name_Unmapped (Decl) /= Name_Unreferenced + then Remove (Decl); Insert_After (Insert_Nod, Decl); Insert_Nod := Decl; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f0d066d..eefe988 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Justin Squirek + + * gnat.dg/unreferenced2.adb: New testcase. + 2019-07-11 Hristian Kirtchev * gnat.dg/self_ref1.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/unreferenced2.adb b/gcc/testsuite/gnat.dg/unreferenced2.adb new file mode 100644 index 0000000..9576ef8 --- /dev/null +++ b/gcc/testsuite/gnat.dg/unreferenced2.adb @@ -0,0 +1,34 @@ +-- { dg-do compile } +-- { dg-options "-gnatf" } + +procedure Unreferenced2 is + + protected Example is + procedure Callme; + end Example; + + procedure Other (X : Boolean) is + begin + null; + end; + + protected body Example is + + procedure Internal (X : Boolean) is + pragma Unreferenced (X); + Y : Integer; + begin + Y := 3; + end Internal; + + procedure Callme is + begin + Internal (X => True); + end Callme; + + end Example; + +begin + Example.Callme; + Other (True); +end Unreferenced2; -- cgit v1.1 From d4ba738c67e5579d5a0dff07f20b36f3df9529d5 Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Thu, 11 Jul 2019 08:02:26 +0000 Subject: [Ada] GNAT.Sockets: add support for RAW sockets 2019-07-11 Dmitriy Anisimkov gcc/ada/ * libgnat/g-socket.ads (Mode_Type): Add a Socket_Raw enumerator. * libgnat/g-socket.adb (Modes): Handle Socket_Raw. From-SVN: r273393 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/libgnat/g-socket.adb | 3 ++- gcc/ada/libgnat/g-socket.ads | 9 +++++---- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index b51a3cc..e20d10c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Dmitriy Anisimkov + + * libgnat/g-socket.ads (Mode_Type): Add a Socket_Raw enumerator. + * libgnat/g-socket.adb (Modes): Handle Socket_Raw. + 2019-07-11 Justin Squirek * exp_ch9.adb (Build_Private_Protected_Declaration): Add diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb index 2c9b8c7..689389f 100644 --- a/gcc/ada/libgnat/g-socket.adb +++ b/gcc/ada/libgnat/g-socket.adb @@ -77,7 +77,8 @@ package body GNAT.Sockets is Modes : constant array (Mode_Type) of C.int := (Socket_Stream => SOSC.SOCK_STREAM, - Socket_Datagram => SOSC.SOCK_DGRAM); + Socket_Datagram => SOSC.SOCK_DGRAM, + Socket_Raw => SOSC.SOCK_RAW); Shutmodes : constant array (Shutmode_Type) of C.int := (Shut_Read => SOSC.SHUT_RD, diff --git a/gcc/ada/libgnat/g-socket.ads b/gcc/ada/libgnat/g-socket.ads index 6db3c54..342577a 100644 --- a/gcc/ada/libgnat/g-socket.ads +++ b/gcc/ada/libgnat/g-socket.ads @@ -475,16 +475,17 @@ package GNAT.Sockets is -- The order of the enumeration elements should not be changed unilaterally -- because the IPv6_TCP_Preferred routine rely on it. - type Mode_Type is (Socket_Stream, Socket_Datagram); + type Mode_Type is (Socket_Stream, Socket_Datagram, Socket_Raw); -- Stream sockets provide connection-oriented byte streams. Datagram - -- sockets support unreliable connectionless message based communication. + -- sockets support unreliable connectionless message-based communication. + -- Raw sockets provide raw network-protocol access. -- The order of the enumeration elements should not be changed unilaterally - -- because the IPv6_TCP_Preferred routine rely on it. + -- because the IPv6_TCP_Preferred routine relies on it. type Shutmode_Type is (Shut_Read, Shut_Write, Shut_Read_Write); -- When a process closes a socket, the policy is to retain any data queued -- until either a delivery or a timeout expiration (in this case, the data - -- are discarded). A finer control is available through shutdown. With + -- are discarded). Finer control is available through shutdown. With -- Shut_Read, no more data can be received from the socket. With_Write, no -- more data can be transmitted. Neither transmission nor reception can be -- performed with Shut_Read_Write. -- cgit v1.1 From 220dc4b2825745db538915298d0c79f2f12ce5e0 Mon Sep 17 00:00:00 2001 From: Hristian Kirtchev Date: Thu, 11 Jul 2019 08:02:30 +0000 Subject: [Ada] Elaboration order v4.0 and output of dependencies This patch adds a missing case to the mechanism that outputs the elaboration order dependencies of units. ------------ -- Source -- ------------ -- pack.ads package Pack is procedure Force_Body; end Pack; -- pack.adb package body Pack is procedure Force_Body is null; end Pack; -- main.adb with Pack; procedure Main is begin null; end Main; ---------------------------- -- Compilation and output -- ---------------------------- $ gnatmake -q main.adb -bargs -e ELABORATION ORDER DEPENDENCIES unit "pack (spec)" must be elaborated before unit "main (body)" reason: unit "main (body)" has with clause for unit "pack (spec)" unit "pack (spec)" must be elaborated before unit "pack (body)" reason: spec must be elaborated before body 2019-07-11 Hristian Kirtchev gcc/ada/ * bindo.adb: Remove the documentation of switch -d_N because it is no longer in use. * bindo-graphs.ads, bindo-graphs.adb (Is_Spec_Before_Body_Edge): New routine. * bindo-writers.adb (Write_Dependency_Edge): Add the missing case of a spec-before-body edge. From-SVN: r273394 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/bindo-graphs.adb | 15 +++++++++++++++ gcc/ada/bindo-graphs.ads | 7 +++++++ gcc/ada/bindo-writers.adb | 5 +++++ gcc/ada/bindo.adb | 6 +----- 5 files changed, 37 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e20d10c..accc3ee 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-11 Hristian Kirtchev + + * bindo.adb: Remove the documentation of switch -d_N because it + is no longer in use. + * bindo-graphs.ads, bindo-graphs.adb (Is_Spec_Before_Body_Edge): + New routine. + * bindo-writers.adb (Write_Dependency_Edge): Add the missing + case of a spec-before-body edge. + 2019-07-11 Dmitriy Anisimkov * libgnat/g-socket.ads (Mode_Type): Add a Socket_Raw enumerator. diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb index 9621bb4..c2f9d6c 100644 --- a/gcc/ada/bindo-graphs.adb +++ b/gcc/ada/bindo-graphs.adb @@ -4183,6 +4183,21 @@ package body Bindo.Graphs is return U_Rec.Utype = Is_Spec or else U_Rec.Utype = Is_Spec_Only; end Is_Spec; + ------------------------------ + -- Is_Spec_Before_Body_Edge -- + ------------------------------ + + function Is_Spec_Before_Body_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean + is + begin + pragma Assert (Present (G)); + pragma Assert (Present (Edge)); + + return Kind (G, Edge) = Spec_Before_Body_Edge; + end Is_Spec_Before_Body_Edge; + ----------------------- -- Is_Spec_With_Body -- ----------------------- diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads index 8323784..f376801 100644 --- a/gcc/ada/bindo-graphs.ads +++ b/gcc/ada/bindo-graphs.ads @@ -1166,6 +1166,13 @@ package Bindo.Graphs is pragma Inline (Is_Spec); -- Determine whether vertex Vertex of library graph G denotes a spec + function Is_Spec_Before_Body_Edge + (G : Library_Graph; + Edge : Library_Graph_Edge_Id) return Boolean; + pragma Inline (Is_Spec_Before_Body_Edge); + -- Determine whether edge Edge of library graph G links a predecessor + -- spec and a successor body belonging to the same unit. + function Is_Spec_With_Body (G : Library_Graph; Vertex : Library_Graph_Vertex_Id) return Boolean; diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb index 021d50f..1fcfb11 100644 --- a/gcc/ada/bindo-writers.adb +++ b/gcc/ada/bindo-writers.adb @@ -610,6 +610,11 @@ package body Bindo.Writers is & "elaboration time", Info => True); + elsif Is_Spec_Before_Body_Edge (G, Edge) then + Error_Msg_Output + (Msg => " reason: spec must be elaborated before body", + Info => True); + else pragma Assert (Is_With_Edge (G, Edge)); diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb index d5830ca..249ce972 100644 --- a/gcc/ada/bindo.adb +++ b/gcc/ada/bindo.adb @@ -347,13 +347,9 @@ package body Bindo is -- GNATbind outputs the library graph in textual format to standard -- output. -- - -- -d_N New bindo order - -- - -- GNATbind utilizes the new bindo elaboration order - -- -- -d_P Output cycle paths -- - -- GNATbind output the cycle paths in text format to standard output + -- GNATbind outputs the cycle paths in text format to standard output -- -- -d_S Output elaboration-order status information -- -- cgit v1.1 From 6ef13c4ff90e51d13162fd8328d873ae03e6b2b4 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 11 Jul 2019 08:02:35 +0000 Subject: [Ada] Remove redundant predicate checks This patch removes redundant dynamic predicate checks generated by type conversions in various contexts. The patch also recognizes additional such checks that can be evaluated statically when applied to constant values. No simple test available. 2019-07-11 Ed Schonberg gcc/ada/ * exp_ch4.adb (Expand_N_Type_Conversion): If a predicate check is generated, analyze it with range check suppressed, because that check has been previously applied. * exp_ch5.adb (Expand_N_Assignment_Statement): If the RHS is a type conversion to the type of the LHS, do not apply a predicate check to the RHS because it will have been generated already during its expansion. * exp_ch6.adb (Can_Fold_Predicate_Call): Extend processing to handle a predicate check on a constant entity whose value is static. From-SVN: r273395 --- gcc/ada/ChangeLog | 13 +++++++++++++ gcc/ada/exp_ch4.adb | 7 +++++-- gcc/ada/exp_ch5.adb | 20 +++++++++++++------- gcc/ada/exp_ch6.adb | 29 ++++++++++++++++++++--------- 4 files changed, 51 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index accc3ee..0b4871c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2019-07-11 Ed Schonberg + + * exp_ch4.adb (Expand_N_Type_Conversion): If a predicate check + is generated, analyze it with range check suppressed, because + that check has been previously applied. + * exp_ch5.adb (Expand_N_Assignment_Statement): If the RHS is a + type conversion to the type of the LHS, do not apply a predicate + check to the RHS because it will have been generated already + during its expansion. + * exp_ch6.adb (Can_Fold_Predicate_Call): Extend processing to + handle a predicate check on a constant entity whose value is + static. + 2019-07-11 Hristian Kirtchev * bindo.adb: Remove the documentation of switch -d_N because it diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index f18632a..7a1e0b8 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -12050,10 +12050,13 @@ package body Exp_Ch4 is begin -- Avoid infinite recursion on the subsequent expansion of - -- of the copy of the original type conversion. + -- of the copy of the original type conversion. When needed, + -- a range check has already been applied to the expression. Set_Comes_From_Source (New_Expr, False); - Insert_Action (N, Make_Predicate_Check (Target_Type, New_Expr)); + Insert_Action (N, + Make_Predicate_Check (Target_Type, New_Expr), + Suppress => Range_Check); end; end if; end Expand_N_Type_Conversion; diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index f1d12cb..18e9708 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -2021,15 +2021,21 @@ package body Exp_Ch5 is if not Suppress_Assignment_Checks (N) then - -- First deal with generation of range check if required + -- First deal with generation of range check if required, + -- and then predicate checks if the type carries a predicate. + -- If the Rhs is an expression these tests may have been applied + -- already. This is the case if the RHS is a type conversion. + -- Other such redundant checks could be removed ??? + + if Nkind (Rhs) /= N_Type_Conversion + or else Entity (Subtype_Mark (Rhs)) /= Typ + then + if Do_Range_Check (Rhs) then + Generate_Range_Check (Rhs, Typ, CE_Range_Check_Failed); + end if; - if Do_Range_Check (Rhs) then - Generate_Range_Check (Rhs, Typ, CE_Range_Check_Failed); + Apply_Predicate_Check (Rhs, Typ); end if; - - -- Then generate predicate check if required - - Apply_Predicate_Check (Rhs, Typ); end if; -- Check for a special case where a high level transformation is diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index c23e9ee..f38dd67 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -2479,8 +2479,7 @@ package body Exp_Ch6 is ----------------------------- function Can_Fold_Predicate_Call (P : Entity_Id) return Boolean is - Actual : constant Node_Id := - First (Parameter_Associations (Call_Node)); + Actual : Node_Id; function May_Fold (N : Node_Id) return Traverse_Result; -- The predicate expression is foldable if it only contains operators @@ -2533,10 +2532,11 @@ package body Exp_Ch6 is function Try_Fold is new Traverse_Func (May_Fold); - -- Local variables + -- Other lLocal variables - Subt : constant Entity_Id := Etype (First_Entity (P)); - Pred : Node_Id; + Subt : constant Entity_Id := Etype (First_Entity (P)); + Aspect : Node_Id; + Pred : Node_Id; -- Start of processing for Can_Fold_Predicate_Call @@ -2545,8 +2545,21 @@ package body Exp_Ch6 is -- has a Dynamic_Predicate aspect. For CodePeer we preserve the -- function call. - if Nkind (Actual) /= N_Integer_Literal + Actual := First (Parameter_Associations (Call_Node)); + Aspect := Find_Aspect (Subt, Aspect_Dynamic_Predicate); + + -- If actual is a declared constant, retrieve its value + + if Is_Entity_Name (Actual) + and then Ekind (Entity (Actual)) = E_Constant + then + Actual := Constant_Value (Entity (Actual)); + end if; + + if No (Actual) + or else Nkind (Actual) /= N_Integer_Literal or else not Has_Dynamic_Predicate_Aspect (Subt) + or else No (Aspect) or else CodePeer_Mode then return False; @@ -2554,9 +2567,7 @@ package body Exp_Ch6 is -- Retrieve the analyzed expression for the predicate - Pred := - New_Copy_Tree - (Expression (Find_Aspect (Subt, Aspect_Dynamic_Predicate))); + Pred := New_Copy_Tree (Expression (Aspect)); if Try_Fold (Pred) = OK then Rewrite (Call_Node, Pred); -- cgit v1.1 From 9d80f439131664ba852db64a6d5ac80a4d4e6f2e Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 11 Jul 2019 08:02:40 +0000 Subject: [Ada] errno.c: remove obsolete support for MaRTE OS 2019-07-11 Arnaud Charlet gcc/ada/ * errno.c: Remove obsolete support for MaRTE OS. From-SVN: r273396 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/errno.c | 15 ++------------- 2 files changed, 6 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0b4871c..a38990f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Arnaud Charlet + + * errno.c: Remove obsolete support for MaRTE OS. + 2019-07-11 Ed Schonberg * exp_ch4.adb (Expand_N_Type_Conversion): If a predicate check diff --git a/gcc/ada/errno.c b/gcc/ada/errno.c index a64ae87..18f14ea 100644 --- a/gcc/ada/errno.c +++ b/gcc/ada/errno.c @@ -35,21 +35,10 @@ as it may be defined using a macro. */ - +#ifndef _REENTRANT #define _REENTRANT -#define _THREAD_SAFE - -#ifdef MaRTE - -/* MaRTE OS provides its own implementation of errno related functionality. We - want to ensure the use of the MaRTE version for tasking programs (the MaRTE - library will not be linked if no tasking constructs are used), so we use the - weak symbols mechanism to use the MaRTE version whenever is available. */ - -#pragma weak __get_errno -#pragma weak __set_errno - #endif +#define _THREAD_SAFE #include int -- cgit v1.1 From 1048a1839fde97a1bd790b002dad8b79e172724f Mon Sep 17 00:00:00 2001 From: Claire Dross Date: Thu, 11 Jul 2019 08:02:44 +0000 Subject: [Ada] Memory corruption when using formal hashed sets or maps Add a check to avoid causing a buffer overflow when the map is empty 2019-07-11 Claire Dross gcc/ada/ * libgnat/a-cfhama.adb, libgnat/a-cfhase.adb (Free): Do not reset the Has_Element flag if no element is freed. From-SVN: r273397 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/libgnat/a-cfhama.adb | 7 +++++-- gcc/ada/libgnat/a-cfhase.adb | 7 +++++-- 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a38990f..2f8ad77 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Claire Dross + + * libgnat/a-cfhama.adb, libgnat/a-cfhase.adb (Free): Do not + reset the Has_Element flag if no element is freed. + 2019-07-11 Arnaud Charlet * errno.c: Remove obsolete support for MaRTE OS. diff --git a/gcc/ada/libgnat/a-cfhama.adb b/gcc/ada/libgnat/a-cfhama.adb index 2cdde01..580ca12 100644 --- a/gcc/ada/libgnat/a-cfhama.adb +++ b/gcc/ada/libgnat/a-cfhama.adb @@ -509,8 +509,11 @@ is procedure Free (HT : in out Map; X : Count_Type) is begin - HT.Nodes (X).Has_Element := False; - HT_Ops.Free (HT, X); + if X /= 0 then + pragma Assert (X <= HT.Capacity); + HT.Nodes (X).Has_Element := False; + HT_Ops.Free (HT, X); + end if; end Free; ---------------------- diff --git a/gcc/ada/libgnat/a-cfhase.adb b/gcc/ada/libgnat/a-cfhase.adb index ae8ae12..8cc220c 100644 --- a/gcc/ada/libgnat/a-cfhase.adb +++ b/gcc/ada/libgnat/a-cfhase.adb @@ -760,8 +760,11 @@ is procedure Free (HT : in out Set; X : Count_Type) is begin - HT.Nodes (X).Has_Element := False; - HT_Ops.Free (HT, X); + if X /= 0 then + pragma Assert (X <= HT.Capacity); + HT.Nodes (X).Has_Element := False; + HT_Ops.Free (HT, X); + end if; end Free; ---------------------- -- cgit v1.1 From 810097a72d1767627d2439bb94627b443f41bf7f Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimkov Date: Thu, 11 Jul 2019 08:02:49 +0000 Subject: [Ada] GNAT.Sockets: support ICMP, IGMP and RAW IP protocol levels 2019-07-11 Dmitriy Anisimkov gcc/ada/ * libgnat/g-socket.ads (Level_Type): Add enumerators for IP_Protocol_For_ICMP, IP_Protocol_For_IGMP, IP_Protocol_For_RAW_Level. * libgnat/g-socket.adb (Levels): Handle them. * s-oscons-tmplt.c: Import socket protocols defined in netinet/in.h. From-SVN: r273398 --- gcc/ada/ChangeLog | 9 ++++ gcc/ada/libgnat/g-socket.adb | 5 ++- gcc/ada/libgnat/g-socket.ads | 5 ++- gcc/ada/s-oscons-tmplt.c | 105 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2f8ad77..3b04ce8 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-11 Dmitriy Anisimkov + + * libgnat/g-socket.ads (Level_Type): Add enumerators for + IP_Protocol_For_ICMP, IP_Protocol_For_IGMP, + IP_Protocol_For_RAW_Level. + * libgnat/g-socket.adb (Levels): Handle them. + * s-oscons-tmplt.c: Import socket protocols defined in + netinet/in.h. + 2019-07-11 Claire Dross * libgnat/a-cfhama.adb, libgnat/a-cfhase.adb (Free): Do not diff --git a/gcc/ada/libgnat/g-socket.adb b/gcc/ada/libgnat/g-socket.adb index 689389f..ceb2cb0 100644 --- a/gcc/ada/libgnat/g-socket.adb +++ b/gcc/ada/libgnat/g-socket.adb @@ -73,7 +73,10 @@ package body GNAT.Sockets is IP_Protocol_For_IP_Level => SOSC.IPPROTO_IP, IP_Protocol_For_IPv6_Level => SOSC.IPPROTO_IPV6, IP_Protocol_For_UDP_Level => SOSC.IPPROTO_UDP, - IP_Protocol_For_TCP_Level => SOSC.IPPROTO_TCP); + IP_Protocol_For_TCP_Level => SOSC.IPPROTO_TCP, + IP_Protocol_For_ICMP_Level => SOSC.IPPROTO_ICMP, + IP_Protocol_For_IGMP_Level => SOSC.IPPROTO_IGMP, + IP_Protocol_For_RAW_Level => SOSC.IPPROTO_RAW); Modes : constant array (Mode_Type) of C.int := (Socket_Stream => SOSC.SOCK_STREAM, diff --git a/gcc/ada/libgnat/g-socket.ads b/gcc/ada/libgnat/g-socket.ads index 342577a..acd72f1 100644 --- a/gcc/ada/libgnat/g-socket.ads +++ b/gcc/ada/libgnat/g-socket.ads @@ -773,7 +773,10 @@ package GNAT.Sockets is IP_Protocol_For_IP_Level, IP_Protocol_For_IPv6_Level, IP_Protocol_For_UDP_Level, - IP_Protocol_For_TCP_Level); + IP_Protocol_For_TCP_Level, + IP_Protocol_For_ICMP_Level, + IP_Protocol_For_IGMP_Level, + IP_Protocol_For_RAW_Level); -- There are several options available to manipulate sockets. Each option -- has a name and several values available. Most of the time, the value diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index 1e883b9..655d68a 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -1292,6 +1292,111 @@ CND(IPPROTO_UDP, "UDP") #endif CND(IPPROTO_TCP, "TCP") +#ifndef IPPROTO_ICMP +# define IPPROTO_ICMP -1 +#endif +CND(IPPROTO_ICMP, "Internet Control Message Protocol") + +#ifndef IPPROTO_IGMP +# define IPPROTO_IGMP -1 +#endif +CND(IPPROTO_IGMP, "Internet Group Management Protocol") + +#ifndef IPPROTO_IPIP +# define IPPROTO_IPIP -1 +#endif +CND(IPPROTO_IPIP, "IPIP tunnels (older KA9Q tunnels use 94)") + +#ifndef IPPROTO_EGP +# define IPPROTO_EGP -1 +#endif +CND(IPPROTO_EGP, "Exterior Gateway Protocol") + +#ifndef IPPROTO_PUP +# define IPPROTO_PUP -1 +#endif +CND(IPPROTO_PUP, "PUP protocol") + +#ifndef IPPROTO_IDP +# define IPPROTO_IDP -1 +#endif +CND(IPPROTO_IDP, "XNS IDP protocol") + +#ifndef IPPROTO_TP +# define IPPROTO_TP -1 +#endif +CND(IPPROTO_TP, "SO Transport Protocol Class 4") + +#ifndef IPPROTO_DCCP +# define IPPROTO_DCCP -1 +#endif +CND(IPPROTO_DCCP, "Datagram Congestion Control Protocol") + +#ifndef IPPROTO_RSVP +# define IPPROTO_RSVP -1 +#endif +CND(IPPROTO_RSVP, "Reservation Protocol") + +#ifndef IPPROTO_GRE +# define IPPROTO_GRE -1 +#endif +CND(IPPROTO_GRE, "General Routing Encapsulation") + +#ifndef IPPROTO_ESP +# define IPPROTO_ESP -1 +#endif +CND(IPPROTO_ESP, "encapsulating security payload") + +#ifndef IPPROTO_AH +# define IPPROTO_AH -1 +#endif +CND(IPPROTO_AH, "authentication header") + +#ifndef IPPROTO_MTP +# define IPPROTO_MTP -1 +#endif +CND(IPPROTO_MTP, "Multicast Transport Protocol") + +#ifndef IPPROTO_BEETPH +# define IPPROTO_BEETPH -1 +#endif +CND(IPPROTO_BEETPH, "IP option pseudo header for BEET") + +#ifndef IPPROTO_ENCAP +# define IPPROTO_ENCAP -1 +#endif +CND(IPPROTO_ENCAP, "Encapsulation Header") + +#ifndef IPPROTO_PIM +# define IPPROTO_PIM -1 +#endif +CND(IPPROTO_PIM, "Protocol Independent Multicast") + +#ifndef IPPROTO_COMP +# define IPPROTO_COMP -1 +#endif +CND(IPPROTO_COMP, "Compression Header Protocol") + +#ifndef IPPROTO_SCTP +# define IPPROTO_SCTP -1 +#endif +CND(IPPROTO_SCTP, "Stream Control Transmission Protocol") + +#ifndef IPPROTO_UDPLITE +# define IPPROTO_UDPLITE -1 +#endif +CND(IPPROTO_UDPLITE, "UDP-Lite protocol") + +#ifndef IPPROTO_MPLS +# define IPPROTO_MPLS -1 +#endif +CND(IPPROTO_MPLS, "MPLS in IP") + +#ifndef IPPROTO_RAW +# define IPPROTO_RAW -1 +#endif +CND(IPPROTO_RAW, "Raw IP packets") + /* ------------------- -- cgit v1.1 From a13a714e710f13b6fa6f88481a3c94b7d2dbc8cf Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Thu, 11 Jul 2019 08:02:53 +0000 Subject: [Ada] Crash on protected type with self-referential component This patch fixes a compiler abort on a declarastion for a protected type PT when one of its private component is of type access PT. 2019-07-11 Ed Schonberg gcc/ada/ * exp_ch9.adb (Expand_N_Protected_Type_Declaaration): New subsidiary routine Replace_Access_Definition, to handle properly a protected type PT one of whose private components is of type access PT. gcc/testsuite/ * gnat.dg/prot8.adb, gnat.dg/prot8.ads: New testcase. From-SVN: r273399 --- gcc/ada/ChangeLog | 7 +++++ gcc/ada/exp_ch9.adb | 63 ++++++++++++++++++++++++++++++++++++++++- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gnat.dg/prot8.adb | 8 ++++++ gcc/testsuite/gnat.dg/prot8.ads | 10 +++++++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/prot8.adb create mode 100644 gcc/testsuite/gnat.dg/prot8.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 3b04ce8..dbe11d8 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-11 Ed Schonberg + + * exp_ch9.adb (Expand_N_Protected_Type_Declaaration): New + subsidiary routine Replace_Access_Definition, to handle properly + a protected type PT one of whose private components is of type + access PT. + 2019-07-11 Dmitriy Anisimkov * libgnat/g-socket.ads (Level_Type): Add enumerators for diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 077063f..99bd8d2 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -8928,6 +8928,8 @@ package body Exp_Ch9 is Current_Node : Node_Id := N; E_Count : Int; Entries_Aggr : Node_Id; + Rec_Decl : Node_Id; + Rec_Id : Entity_Id; procedure Check_Inlining (Subp : Entity_Id); -- If the original operation has a pragma Inline, propagate the flag @@ -8949,6 +8951,21 @@ package body Exp_Ch9 is -- For a protected operation that is an interrupt handler, add the -- freeze action that will register it as such. + procedure Replace_Access_Definition (Comp : Node_Id); + -- If a private component of the type is an access to itself, this + -- is not a reference to the current instance, but an access type out + -- of which one might construct a list. If such a component exists, we + -- create an incomplete type for the equivalent record type, and + -- a named access type for it, that replaces the access definition + -- of the original component. This is similar to what is done for + -- records in Check_Anonymous_Access_Components, but simpler, because + -- the corresponding record type has no previous declaration. + -- This needs to be done only once, even if there are several such + -- access components. The following entity stores the constructed + -- access type. + + Acc_T : Entity_Id := Empty; + -------------------- -- Check_Inlining -- -------------------- @@ -9096,6 +9113,41 @@ package body Exp_Ch9 is Append_Freeze_Action (Prot_Proc, RTS_Call); end Register_Handler; + ------------------------------- + -- Replace_Access_Definition -- + ------------------------------- + + procedure Replace_Access_Definition (Comp : Node_Id) is + Loc : constant Source_Ptr := Sloc (Comp); + Inc_T : Node_Id; + Inc_D : Node_Id; + Acc_Def : Node_Id; + Acc_D : Node_Id; + + begin + if No (Acc_T) then + Inc_T := Make_Defining_Identifier (Loc, Chars (Rec_Id)); + Inc_D := Make_Incomplete_Type_Declaration (Loc, Inc_T); + Acc_T := Make_Temporary (Loc, 'S'); + Acc_Def := + Make_Access_To_Object_Definition (Loc, + Subtype_Indication => New_Occurrence_Of (Inc_T, Loc)); + Acc_D := + Make_Full_Type_Declaration (Loc, + Defining_Identifier => Acc_T, + Type_Definition => Acc_Def); + + Insert_Before (Rec_Decl, Inc_D); + Analyze (Inc_D); + + Insert_Before (Rec_Decl, Acc_D); + Analyze (Acc_D); + end if; + + Set_Access_Definition (Comp, Empty); + Set_Subtype_Indication (Comp, New_Occurrence_Of (Acc_T, Loc)); + end Replace_Access_Definition; + -- Local variables Body_Arr : Node_Id; @@ -9107,7 +9159,6 @@ package body Exp_Ch9 is Obj_Def : Node_Id; Object_Comp : Node_Id; Priv : Node_Id; - Rec_Decl : Node_Id; Sub : Node_Id; -- Start of processing for Expand_N_Protected_Type_Declaration @@ -9117,6 +9168,7 @@ package body Exp_Ch9 is return; else Rec_Decl := Build_Corresponding_Record (N, Prot_Typ, Loc); + Rec_Id := Defining_Identifier (Rec_Decl); end if; Cdecls := Component_Items (Component_List (Type_Definition (Rec_Decl))); @@ -9262,6 +9314,15 @@ package body Exp_Ch9 is Access_Definition => New_Copy_Tree (Access_Definition (Old_Comp), Discr_Map)); + + -- A self-reference in the private part becomes a + -- self-reference to the corresponding record. + + if Entity (Subtype_Mark (Access_Definition (New_Comp))) + = Prot_Typ + then + Replace_Access_Definition (New_Comp); + end if; end if; New_Priv := diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eefe988..baef966 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Ed Schonberg + + * gnat.dg/prot8.adb, gnat.dg/prot8.ads: New testcase. + 2019-07-11 Justin Squirek * gnat.dg/unreferenced2.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/prot8.adb b/gcc/testsuite/gnat.dg/prot8.adb new file mode 100644 index 0000000..c390448 --- /dev/null +++ b/gcc/testsuite/gnat.dg/prot8.adb @@ -0,0 +1,8 @@ +-- { dg-do compile } + +package body Prot8 is + + protected body Prot is + end Prot; + +end Prot8; diff --git a/gcc/testsuite/gnat.dg/prot8.ads b/gcc/testsuite/gnat.dg/prot8.ads new file mode 100644 index 0000000..01424ce --- /dev/null +++ b/gcc/testsuite/gnat.dg/prot8.ads @@ -0,0 +1,10 @@ +package Prot8 is + + protected type Prot is + private + B : Boolean; + N : access Prot; + Ptr : access Prot; + end Prot; + +end Prot8; -- cgit v1.1 From 49d7a324591251967dd2ad759e903e393795310e Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 11 Jul 2019 08:02:58 +0000 Subject: [Ada] Makefile.rtl: add a warning about compilation flags 2019-07-11 Eric Botcazou gcc/ada/ * Makefile.rtl: Add warning note about compilation flags and capitalize. From-SVN: r273400 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/Makefile.rtl | 24 +++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index dbe11d8..cc3eb1d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Eric Botcazou + + * Makefile.rtl: Add warning note about compilation flags and + capitalize. + 2019-07-11 Ed Schonberg * exp_ch9.adb (Expand_N_Protected_Type_Declaaration): New diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 3df2ff5..80ba46d 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2688,9 +2688,15 @@ setup-rts: force $(LN_S) $(GNAT_SRC)/$(word 2,$(subst <, ,$(PAIR))) \ $(RTSDIR)/$(word 1,$(subst <, ,$(PAIR)));) -# Special flags - -# force no sibling call optimization on s-traceb.o so the number of stack +# Special flags. It is recommended not to change the compilation flags +# without a careful analysis of the consequences because (part of) the +# runtime implements low-level support that is outside of the semantics +# of the language and therefore needs to be treated differently from the +# other units. For example, the part of the runtime implementing the +# propagation of exceptions cannot itself be compiled with checks that +# may give rise to exceptions, e.g. stack overflow checks. + +# Force no sibling call optimization on s-traceb.o so the number of stack # frames to be skipped when computing a call chain is not modified by # optimization. We don't want inlining, either. @@ -2699,14 +2705,14 @@ s-traceb.o : s-traceb.adb s-traceb.ads $(NO_INLINE_ADAFLAGS) $(NO_SIBLING_ADAFLAGS) $(ADA_INCLUDES) $< \ $(OUTPUT_OPTION) -# compile s-tasdeb.o without optimization and with debug info so that it is +# Compile s-tasdeb.o without optimization and with debug info so that it is # always possible to set conditional breakpoints on tasks. s-tasdeb.o : s-tasdeb.adb s-tasdeb.ads $(ADAC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) -O0 $(ADA_INCLUDES) \ $< $(OUTPUT_OPTION) -# force no function reordering on a-except.o because of the exclusion bounds +# Force no function reordering on a-except.o because of the exclusion bounds # mechanism (see the source file for more detailed information). # force debugging information on a-except.o so that it is always # possible to set conditional breakpoints on exceptions. @@ -2717,7 +2723,7 @@ a-except.o : a-except.adb a-except.ads $(NO_INLINE_ADAFLAGS) $(NO_REORDER_ADAFLAGS) -O1 $(ADA_INCLUDES) \ $< $(OUTPUT_OPTION) -# compile s-excdeb.o without optimization and with debug info to let the +# Compile s-excdeb.o without optimization and with debug info to let the # debugger set breakpoints and inspect subprogram parameters on exception # related events. @@ -2725,21 +2731,21 @@ s-excdeb.o : s-excdeb.adb s-excdeb.ads s-except.ads $(ADAC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) -O0 \ $(ADA_INCLUDES) $< $(OUTPUT_OPTION) -# force debugging information on s-assert.o so that it is always +# Force debugging information on s-assert.o so that it is always # possible to set breakpoint on assert failures. s-assert.o : s-assert.adb s-assert.ads $(ADAC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) $(ADA_INCLUDES) \ $< $(OUTPUT_OPTION) -# force debugging information on a-tags.o so that the debugger can find +# Force debugging information on a-tags.o so that the debugger can find # the description of Ada.Tags.Type_Specific_Data. a-tags.o : a-tags.adb a-tags.ads $(ADAC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) $(ADA_INCLUDES) \ $< $(OUTPUT_OPTION) -# force no sibling call optimization on s-memory.o to avoid turning the +# Force no sibling call optimization on s-memory.o to avoid turning the # tail recursion in Alloc into a loop that confuses branch prediction. s-memory.o : s-memory.adb s-memory.ads -- cgit v1.1 From be04e8eda375765f5336316085f0c4bd4ef468d5 Mon Sep 17 00:00:00 2001 From: Patrick Bernardi Date: Thu, 11 Jul 2019 08:03:04 +0000 Subject: [Ada] Minimal binder The new minimal binder option ("-minimal") suppresses the generation of binder objects that are not strictly required for program operation. This option is suitable for space constrained applications and comes with the restriction that programs can no longer be debugged using GDB. 2019-07-11 Patrick Bernardi gcc/ada/ * bindgen.adb (Gen_Main): Do not generate a reference to Ada_Main_Program_Name when the Minimal_Binder flag is set. (Gen_Output_File_Ada): Do not output GNAT_Version and Ada_Main_Program_Name info if Minimal_Binder flag is set. * bindusg.adb: Add documentation for new -minimal switch. * gnatbind.adb (Scan_Bind_Arg): Scan -minimal switch. * opt.ads: Add new global flag Minimal_Binder to indicate if the binder should not produce global variables. * doc/gnat_ugn/building_executable_programs_with_gnat.rst: Update documentation with new binder -minimal switch. * gnat_ugn.texi: Regenerate. From-SVN: r273401 --- gcc/ada/ChangeLog | 14 +++++++++ gcc/ada/bindgen.adb | 36 ++++++++++++---------- gcc/ada/bindusg.adb | 6 ++++ .../building_executable_programs_with_gnat.rst | 11 ++++++- gcc/ada/gnat_ugn.texi | 19 ++++++++++++ gcc/ada/gnatbind.adb | 11 +++++++ gcc/ada/opt.ads | 6 ++++ 7 files changed, 86 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cc3eb1d..472a6fd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,17 @@ +2019-07-11 Patrick Bernardi + + * bindgen.adb (Gen_Main): Do not generate a reference to + Ada_Main_Program_Name when the Minimal_Binder flag is set. + (Gen_Output_File_Ada): Do not output GNAT_Version and + Ada_Main_Program_Name info if Minimal_Binder flag is set. + * bindusg.adb: Add documentation for new -minimal switch. + * gnatbind.adb (Scan_Bind_Arg): Scan -minimal switch. + * opt.ads: Add new global flag Minimal_Binder to indicate if the + binder should not produce global variables. + * doc/gnat_ugn/building_executable_programs_with_gnat.rst: + Update documentation with new binder -minimal switch. + * gnat_ugn.texi: Regenerate. + 2019-07-11 Eric Botcazou * Makefile.rtl: Add warning note about compilation flags and diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb index e135540..8ea8a6b 100644 --- a/gcc/ada/bindgen.adb +++ b/gcc/ada/bindgen.adb @@ -1810,9 +1810,11 @@ package body Bindgen is -- with a pragma Volatile in order to tell the compiler to preserve -- this variable at any level of optimization. - -- CodePeer and CCG do not need this extra code on the other hand + -- CodePeer and CCG do not need this extra code. The code is also not + -- needed if the binder is in "Minimal Binder" mode. if Bind_Main_Program + and then not Minimal_Binder and then not CodePeer_Mode and then not Generate_C_Code then @@ -2354,25 +2356,27 @@ package body Bindgen is -- program uses two Ada libraries). Also zero terminate the string -- so that its end can be found reliably at run time. - WBI (""); - WBI (" GNAT_Version : constant String :="); - WBI (" """ & Ver_Prefix & - Gnat_Version_String & - """ & ASCII.NUL;"); - WBI (" pragma Export (C, GNAT_Version, ""__gnat_version"");"); + if not Minimal_Binder then + WBI (""); + WBI (" GNAT_Version : constant String :="); + WBI (" """ & Ver_Prefix & + Gnat_Version_String & + """ & ASCII.NUL;"); + WBI (" pragma Export (C, GNAT_Version, ""__gnat_version"");"); - WBI (""); - Set_String (" Ada_Main_Program_Name : constant String := """); - Get_Name_String (Units.Table (First_Unit_Entry).Uname); + WBI (""); + Set_String (" Ada_Main_Program_Name : constant String := """); + Get_Name_String (Units.Table (First_Unit_Entry).Uname); - Set_Main_Program_Name; - Set_String (""" & ASCII.NUL;"); + Set_Main_Program_Name; + Set_String (""" & ASCII.NUL;"); - Write_Statement_Buffer; + Write_Statement_Buffer; - WBI - (" pragma Export (C, Ada_Main_Program_Name, " & - """__gnat_ada_main_program_name"");"); + WBI + (" pragma Export (C, Ada_Main_Program_Name, " & + """__gnat_ada_main_program_name"");"); + end if; end if; WBI (""); diff --git a/gcc/ada/bindusg.adb b/gcc/ada/bindusg.adb index 0207479..8331745 100644 --- a/gcc/ada/bindusg.adb +++ b/gcc/ada/bindusg.adb @@ -178,6 +178,12 @@ package body Bindusg is (" -mnnn Limit number of detected errors/warnings to nnn " & "(1-999999)"); + -- Line for -minimal switch + + Write_Line + (" -minimal Generate binder file suitable for space-constrained " + & "applications"); + -- Line for -M switch Write_Line diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index af8f8a4..2e867e2 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -6475,7 +6475,6 @@ be presented in subsequent sections. Rename generated main program from main to xyz. This option is supported on cross environments only. - .. index:: -m (gnatbind) :switch:`-m{n}` @@ -6488,6 +6487,16 @@ be presented in subsequent sections. A value of zero means that no limit is enforced. The equal sign is optional. + .. index:: -minimal (gnatbind) + +:switch:`-minimal` + Generate a binder file suitable for space-constrained applications. When + active, binder-generated objects not required for program operation are no + longer generated. **Warning:** this option comes with the following + limitations: + + * Debugging will not work; + * Programs using GNAT.Compiler_Version will not link. .. index:: -n (gnatbind) diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 29424e7..e3d6a3a 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -15892,6 +15892,25 @@ limit, then a message is output and the bind is abandoned. A value of zero means that no limit is enforced. The equal sign is optional. +@geindex -minimal (gnatbind) + +@item @code{-minimal} + +Generate a binder file suitable for space-constrained applications. When +active, binder-generated objects not required for program operation are no +longer generated. @strong{Warning:} this option comes with the following +limitations: + + +@itemize * + +@item +Debugging will not work; + +@item +Programs using GNAT.Compiler_Version will not link. +@end itemize + @geindex -n (gnatbind) @item @code{-n} diff --git a/gcc/ada/gnatbind.adb b/gcc/ada/gnatbind.adb index 40c85b9..a3b6a7e 100644 --- a/gcc/ada/gnatbind.adb +++ b/gcc/ada/gnatbind.adb @@ -474,6 +474,17 @@ procedure Gnatbind is Mapping_File := new String'(Argv (4 .. Argv'Last)); + -- -minimal + + elsif Argv (2 .. Argv'Last) = "minimal" then + if not Is_Cross_Compiler then + Write_Line + ("gnatbind: -minimal not expected to be used on native " & + "platforms"); + end if; + + Opt.Minimal_Binder := True; + -- -Mname elsif Argv'Length >= 3 and then Argv (2) = 'M' then diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads index 4c1cf6f..4d3e87e 100644 --- a/gcc/ada/opt.ads +++ b/gcc/ada/opt.ads @@ -1120,6 +1120,12 @@ package Opt is -- Maximum number of processes that should be spawned to carry out -- compilations. + Minimal_Binder : Boolean := False; + -- GNATBIND + -- Set to True to suppress the generation of objects by the binder that + -- are not strictly required for a program to run. Intended for ZFP + -- applications that have tight memory constraints. + Minimal_Recompilation : Boolean := False; -- GNATMAKE -- Set to True if minimal recompilation mode requested -- cgit v1.1 From a8fa1b3d08ea4cc31f858d2add1b22e62b8db5e1 Mon Sep 17 00:00:00 2001 From: Claire Dross Date: Thu, 11 Jul 2019 08:03:09 +0000 Subject: [Ada] Refactor ownership pointer checking in SPARK as a generic Ownership checking as done in SPARK should be applied only to SPARK code, which requires GNATprove knowledge of the SPARK_Mode boundary. Transform the checking unit into a generic to allow passing in the knowledge from GNATprove to that unit in GNAT sources. Keeping the code in GNAT sources makes it possible in the future to adapt it further (or simply instantiate it differently) to be used on Ada code, independently of GNATprove. There is no impact on compilation. 2019-07-11 Claire Dross gcc/ada/ * gnat1drv.adb: SPARK checking rules for pointer aliasing are moved to GNATprove backend. * sem_spark.ads, sem_spark.adb (Sem_SPARK): Is now a generic unit. Takes as parameters: - Retysp which is used to query the most underlying type visible in SPARK. We do not introduce aliasing checks for types which are not visibly deep. - Component_Is_Visible_In_SPARK is used to avoid doing pointer aliasing checks on components which are not visible in SPARK. - Emit_Messages returns True in the second phase of SPARK analysis. Error messages for failed aliasing checks are only output in this case. Additionally, errors on constructs not supported in SPARK are removed as duplicates of marking errors. Components are stored in the permission map using their original component to avoid inconsistencies between components of different views of the same type. (Check_Expression): Handle delta constraints. (Is_Deep): Exported so that we can check for SPARK restrictions on deep types inside SPARK semantic checkings. (Is_Traversal_Function): Exported so that we can check for SPARK restrictions on traversal functions inside SPARK semantic checkings. (Check_Call_Statement, Read_Indexes): Check wether we are dealing with a subprogram pointer type before querying called entity. (Is_Subpath_Expression): Image attribute can appear inside a path. (Check_Loop_Statement): Correct order of statements in the loop. (Check_Node): Ignore raise nodes. (Check_Statement): Use Last_Non_Pragma to get the object declaration in an extended return statement. From-SVN: r273402 --- gcc/ada/ChangeLog | 35 +++++ gcc/ada/gnat1drv.adb | 8 - gcc/ada/sem_spark.adb | 413 +++++++++++++++++++++++++++++++++----------------- gcc/ada/sem_spark.ads | 22 +++ 4 files changed, 329 insertions(+), 149 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 472a6fd..95c898b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,38 @@ +2019-07-11 Claire Dross + + * gnat1drv.adb: SPARK checking rules for pointer aliasing are + moved to GNATprove backend. + * sem_spark.ads, sem_spark.adb (Sem_SPARK): Is now a generic + unit. Takes as parameters: + - Retysp which is used to query the most underlying type + visible in SPARK. We do not introduce aliasing checks for + types which are not visibly deep. + - Component_Is_Visible_In_SPARK is used to avoid doing pointer + aliasing checks on components which are not visible in SPARK. + - Emit_Messages returns True in the second phase of SPARK + analysis. Error messages for failed aliasing checks are only + output in this case. + Additionally, errors on constructs not supported in SPARK are + removed as duplicates of marking errors. Components are stored + in the permission map using their original component to avoid + inconsistencies between components of different views of the + same type. + (Check_Expression): Handle delta constraints. + (Is_Deep): Exported so that we can check for SPARK restrictions + on deep types inside SPARK semantic checkings. + (Is_Traversal_Function): Exported so that we can check for SPARK + restrictions on traversal functions inside SPARK semantic + checkings. + (Check_Call_Statement, Read_Indexes): Check wether we are + dealing with a subprogram pointer type before querying called + entity. + (Is_Subpath_Expression): Image attribute can appear inside a + path. + (Check_Loop_Statement): Correct order of statements in the loop. + (Check_Node): Ignore raise nodes. + (Check_Statement): Use Last_Non_Pragma to get the object + declaration in an extended return statement. + 2019-07-11 Patrick Bernardi * bindgen.adb (Gen_Main): Do not generate a reference to diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 55a57dd..ecb3ccd 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -63,7 +63,6 @@ with Sem_Ch13; with Sem_Elim; with Sem_Eval; with Sem_Prag; -with Sem_SPARK; use Sem_SPARK; with Sem_Type; with Set_Targ; with Sinfo; use Sinfo; @@ -1586,13 +1585,6 @@ begin if GNATprove_Mode then - -- Perform the new SPARK checking rules for pointer aliasing. This is - -- only activated in GNATprove mode and on SPARK code. - - if Debug_Flag_FF then - Check_Safe_Pointers (Main_Unit_Node); - end if; - -- In GNATprove mode we're writing the ALI much earlier than usual -- as flow analysis needs the file present in order to append its -- own globals to it. diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 10c82ff..67aa453 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -641,7 +641,8 @@ package body Sem_SPARK is pragma Precondition (Nkind_In (Expr, N_Index_Or_Discriminant_Constraint, N_Range_Constraint, N_Subtype_Indication, - N_Digits_Constraint) + N_Digits_Constraint, + N_Delta_Constraint) or else Nkind (Expr) in N_Subexpr); procedure Check_Globals (Subp : Entity_Id); @@ -744,10 +745,6 @@ package body Sem_SPARK is -- A procedure that is called when deep globals or aliased globals are used -- without any global aspect. - function Is_Deep (Typ : Entity_Id) return Boolean; - -- A function that can tell if a type is deep or not. Returns true if the - -- type passed as argument is deep. - function Is_Path_Expression (Expr : Node_Id) return Boolean; -- Return whether Expr corresponds to a path @@ -759,8 +756,6 @@ package body Sem_SPARK is -- a prefix, in the sense that they could still refer to overlapping memory -- locations. - function Is_Traversal_Function (E : Entity_Id) return Boolean; - function Is_Traversal_Function_Call (Expr : Node_Id) return Boolean; function Loop_Of_Exit (N : Node_Id) return Entity_Id; @@ -959,7 +954,7 @@ package body Sem_SPARK is null; else Handle_Parameter_Or_Global (Expr => Item, - Formal_Typ => Etype (Item), + Formal_Typ => Retysp (Etype (Item)), Param_Mode => Kind, Subp => Subp, Global_Var => True); @@ -1076,9 +1071,12 @@ package body Sem_SPARK is and then (Is_Traversal_Function_Call (Expr) or else Get_Root_Object (Borrowed) /= Var) then - Error_Msg_NE - ("source of assignment must have & as root (SPARK RM 3.10(8)))", - Expr, Var); + if Emit_Messages then + Error_Msg_NE + ("source of assignment must have & as root" & + " (SPARK RM 3.10(8)))", + Expr, Var); + end if; return; end if; @@ -1105,9 +1103,12 @@ package body Sem_SPARK is and then (Is_Traversal_Function_Call (Expr) or else Get_Root_Object (Observed) /= Var) then - Error_Msg_NE - ("source of assignment must have & as root (SPARK RM 3.10(8)))", - Expr, Var); + if Emit_Messages then + Error_Msg_NE + ("source of assignment must have & as root" & + " (SPARK RM 3.10(8)))", + Expr, Var); + end if; return; end if; @@ -1197,15 +1198,19 @@ package body Sem_SPARK is if not Is_Decl then if not Is_Entity_Name (Target) then - Error_Msg_N - ("target of borrow must be stand-alone variable", - Target); + if Emit_Messages then + Error_Msg_N + ("target of borrow must be stand-alone variable", + Target); + end if; return; elsif Target_Root /= Expr_Root then - Error_Msg_NE - ("source of borrow must be variable &", - Expr, Target); + if Emit_Messages then + Error_Msg_NE + ("source of borrow must be variable &", + Expr, Target); + end if; return; end if; end if; @@ -1220,7 +1225,9 @@ package body Sem_SPARK is Check_Expression (Expr, Move); else - Error_Msg_N ("expression not allowed as source of move", Expr); + if Emit_Messages then + Error_Msg_N ("expression not allowed as source of move", Expr); + end if; return; end if; @@ -1253,7 +1260,7 @@ package body Sem_SPARK is begin Check_Parameter_Or_Global (Expr => Actual, - Typ => Underlying_Type (Etype (Formal)), + Typ => Retysp (Etype (Formal)), Kind => Ekind (Formal), Subp => Subp, Global_Var => False); @@ -1287,7 +1294,15 @@ package body Sem_SPARK is begin Inside_Procedure_Call := True; Check_Params (Call); - Check_Globals (Get_Called_Entity (Call)); + if Ekind (Get_Called_Entity (Call)) = E_Subprogram_Type then + if Emit_Messages then + Error_Msg_N + ("call through access to subprogram is not allowed in SPARK", + Call); + end if; + else + Check_Globals (Get_Called_Entity (Call)); + end if; Inside_Procedure_Call := False; Update_Params (Call); @@ -1322,8 +1337,10 @@ package body Sem_SPARK is and then Is_Anonymous_Access_Type (Etype (Spec_Id)) and then not Is_Traversal_Function (Spec_Id) then - Error_Msg_N ("anonymous access type for result only allowed for " - & "traveral functions", Spec_Id); + if Emit_Messages then + Error_Msg_N ("anonymous access type for result only allowed for " + & "traversal functions", Spec_Id); + end if; return; end if; @@ -1585,7 +1602,10 @@ package body Sem_SPARK is begin if not Is_Subpath_Expression (Expr) then - Error_Msg_N ("name expected here for move/borrow/observe", Expr); + if Emit_Messages then + Error_Msg_N + ("name expected here for move/borrow/observe", Expr); + end if; return; end if; @@ -1617,7 +1637,15 @@ package body Sem_SPARK is when N_Function_Call => Read_Params (Expr); - Check_Globals (Get_Called_Entity (Expr)); + if Ekind (Get_Called_Entity (Expr)) = E_Subprogram_Type then + if Emit_Messages then + Error_Msg_N + ("call through access to subprogram is not allowed in " + & "SPARK", Expr); + end if; + else + Check_Globals (Get_Called_Entity (Expr)); + end if; when N_Op_Concat => Read_Expression (Left_Opnd (Expr)); @@ -1664,9 +1692,10 @@ package body Sem_SPARK is -- There can be only one element for a value of deep type -- in order to avoid aliasing. - if not (Box_Present (Assoc)) + if not Box_Present (Assoc) and then Is_Deep (Etype (Expression (Assoc))) and then not Is_Singleton_Choice (CL) + and then Emit_Messages then Error_Msg_F ("singleton choice required to prevent aliasing", @@ -1725,11 +1754,16 @@ package body Sem_SPARK is (Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Loop_Entry or else - Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update); + Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update + or else + Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Image); Read_Expression (Prefix (Expr)); if Get_Attribute_Id (Attribute_Name (Expr)) = Attribute_Update + or else (Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Image + and then Is_Type_Name (Prefix (Expr))) then Read_Expression_List (Expressions (Expr)); end if; @@ -1761,7 +1795,9 @@ package body Sem_SPARK is -- Read mode. if Mode /= Read then - Error_Msg_N ("name expected here for move/borrow/observe", Expr); + if Emit_Messages then + Error_Msg_N ("name expected here for move/borrow/observe", Expr); + end if; return; end if; @@ -1804,6 +1840,13 @@ package body Sem_SPARK is end if; return; + when N_Delta_Constraint => + Read_Expression (Delta_Expression (Expr)); + if Present (Range_Constraint (Expr)) then + Read_Expression (Range_Constraint (Expr)); + end if; + return; + when others => null; end case; @@ -1934,8 +1977,7 @@ package body Sem_SPARK is raise Program_Error; when others => - Error_Msg_Name_1 := Aname; - Error_Msg_N ("attribute % not allowed in SPARK", Expr); + null; end case; end; @@ -1999,7 +2041,7 @@ package body Sem_SPARK is when N_Delta_Aggregate | N_Target_Name => - Error_Msg_N ("unsupported construct in SPARK", Expr); + null; -- Procedure calls are handled in Check_Node @@ -2330,16 +2372,16 @@ package body Sem_SPARK is KeyO := Perm_Tree_Maps.Get_First_Key (Component (Orig_Tree)); while KeyO.Present loop + CompN := Perm_Tree_Maps.Get + (Component (New_Tree), KeyO.K); + CompO := Perm_Tree_Maps.Get + (Component (Orig_Tree), KeyO.K); pragma Assert (CompO /= null); Check_Is_Less_Restrictive_Tree (CompN, CompO, E); KeyO := Perm_Tree_Maps.Get_Next_Key (Component (Orig_Tree)); - CompN := Perm_Tree_Maps.Get - (Component (New_Tree), KeyO.K); - CompO := Perm_Tree_Maps.Get - (Component (Orig_Tree), KeyO.K); end loop; end; @@ -2362,12 +2404,15 @@ package body Sem_SPARK is Expl : Node_Id) is begin - Error_Msg_Node_2 := Loop_Id; - Error_Msg_N ("insufficient permission for & when exiting loop &", E); - Perm_Mismatch (Exp_Perm => Perm, - Act_Perm => Found_Perm, - N => Loop_Id, - Expl => Expl); + if Emit_Messages then + Error_Msg_Node_2 := Loop_Id; + Error_Msg_N + ("insufficient permission for & when exiting loop &", E); + Perm_Mismatch (Exp_Perm => Perm, + Act_Perm => Found_Perm, + N => Loop_Id, + Expl => Expl); + end if; end Perm_Error_Loop_Exit; -- Local variables @@ -2543,6 +2588,7 @@ package body Sem_SPARK is | N_Package_Instantiation | N_Package_Renaming_Declaration | N_Procedure_Instantiation + | N_Raise_xxx_Error | N_Record_Representation_Clause | N_Subprogram_Declaration | N_Subprogram_Renaming_Declaration @@ -2745,7 +2791,7 @@ package body Sem_SPARK is Prag_Id : constant Pragma_Id := Get_Pragma_Id (Prag); Arg1 : constant Node_Id := First (Pragma_Argument_Associations (Prag)); - Arg2 : Node_Id; + Arg2 : Node_Id := Empty; begin if Present (Arg1) then @@ -2903,17 +2949,20 @@ package body Sem_SPARK is -- function. if No (Root) then - if Nkind (Expr) = N_Function_Call then - Error_Msg_N - ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr); - Error_Msg_N - ("\function called must be a traversal function", Expr); - else - Error_Msg_N - ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr); - Error_Msg_N - ("\expression must be part of stand-alone object or parameter", - Expr); + if Emit_Messages then + if Nkind (Expr) = N_Function_Call then + Error_Msg_N + ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr); + Error_Msg_N + ("\function called must be a traversal function", Expr); + else + Error_Msg_N + ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr); + Error_Msg_N + ("\expression must be part of stand-alone object or " & + "parameter", + Expr); + end if; end if; Status := Error; @@ -2958,7 +3007,9 @@ package body Sem_SPARK is if No (Get_Root_Object (Target, Through_Traversal => False)) then - Error_Msg_N ("illegal target for assignment", Target); + if Emit_Messages then + Error_Msg_N ("illegal target for assignment", Target); + end if; return; end if; @@ -3064,7 +3115,7 @@ package body Sem_SPARK is if Is_Anonymous_Access_Type (Return_Typ) then pragma Assert (Is_Traversal_Function (Subp)); - if Nkind (Expr) /= N_Null then + if Nkind (Expr) /= N_Null and then Emit_Messages then declare Expr_Root : constant Entity_Id := Get_Root_Object (Expr); @@ -3089,9 +3140,11 @@ package body Sem_SPARK is Check_Expression (Expr, Move); else - Error_Msg_N - ("expression not allowed as source of move", - Expr); + if Emit_Messages then + Error_Msg_N + ("expression not allowed as source of move", + Expr); + end if; return; end if; @@ -3114,14 +3167,14 @@ package body Sem_SPARK is Subp : constant Entity_Id := Return_Applies_To (Return_Statement_Entity (Stmt)); Decls : constant List_Id := Return_Object_Declarations (Stmt); - Decl : constant Node_Id := Last (Decls); + Decl : constant Node_Id := Last_Non_Pragma (Decls); Obj : constant Entity_Id := Defining_Identifier (Decl); Perm : Perm_Kind; begin -- SPARK RM 3.10(5): return statement of traversal function - if Is_Traversal_Function (Subp) then + if Is_Traversal_Function (Subp) and then Emit_Messages then Error_Msg_N ("extended return cannot apply to a traversal function", Stmt); @@ -3254,7 +3307,7 @@ package body Sem_SPARK is | N_Selective_Accept | N_Timed_Entry_Call => - Error_Msg_N ("unsupported construct in SPARK", Stmt); + null; -- The following nodes are never generated in GNATprove mode @@ -3270,12 +3323,12 @@ package body Sem_SPARK is ---------------- procedure Check_Type (Typ : Entity_Id) is - Check_Typ : constant Entity_Id := Underlying_Type (Typ); + Check_Typ : constant Entity_Id := Retysp (Typ); begin case Type_Kind'(Ekind (Check_Typ)) is when Access_Kind => - case Access_Kind'(Ekind (Underlying_Type (Check_Typ))) is + case Access_Kind'(Ekind (Check_Typ)) is when E_Access_Type | E_Anonymous_Access_Type => @@ -3283,18 +3336,26 @@ package body Sem_SPARK is when E_Access_Subtype => Check_Type (Base_Type (Check_Typ)); when E_Access_Attribute_Type => - Error_Msg_N ("access attribute not allowed in SPARK", - Check_Typ); + if Emit_Messages then + Error_Msg_N ("access attribute not allowed in SPARK", + Check_Typ); + end if; when E_Allocator_Type => - Error_Msg_N ("missing type resolution", Check_Typ); + if Emit_Messages then + Error_Msg_N ("missing type resolution", Check_Typ); + end if; when E_General_Access_Type => - Error_Msg_NE - ("general access type & not allowed in SPARK", - Check_Typ, Check_Typ); + if Emit_Messages then + Error_Msg_NE + ("general access type & not allowed in SPARK", + Check_Typ, Check_Typ); + end if; when Access_Subprogram_Kind => - Error_Msg_NE - ("access to subprogram type & not allowed in SPARK", - Check_Typ, Check_Typ); + if Emit_Messages then + Error_Msg_NE + ("access to subprogram type & not allowed in SPARK", + Check_Typ, Check_Typ); + end if; end case; when E_Array_Type @@ -3307,9 +3368,11 @@ package body Sem_SPARK is and then (Is_Tagged_Type (Check_Typ) or else Is_Class_Wide_Type (Check_Typ)) then - Error_Msg_NE - ("tagged type & cannot be owning in SPARK", - Check_Typ, Check_Typ); + if Emit_Messages then + Error_Msg_NE + ("tagged type & cannot be owning in SPARK", + Check_Typ, Check_Typ); + end if; else declare @@ -3317,7 +3380,12 @@ package body Sem_SPARK is begin Comp := First_Component_Or_Discriminant (Check_Typ); while Present (Comp) loop - Check_Type (Etype (Comp)); + + -- Ignore components which are not visible in SPARK + + if Component_Is_Visible_In_SPARK (Comp) then + Check_Type (Etype (Comp)); + end if; Next_Component_Or_Discriminant (Comp); end loop; end; @@ -3333,14 +3401,14 @@ package body Sem_SPARK is => null; - -- The following should not arise as underlying types + -- Do not check type whose full view is not SPARK when E_Private_Type | E_Private_Subtype | E_Limited_Private_Type | E_Limited_Private_Subtype => - raise Program_Error; + null; end case; end Check_Type; @@ -3526,7 +3594,8 @@ package body Sem_SPARK is pragma Assert (Nkind (N) = N_Selected_Component); declare Comp : constant Entity_Id := - Entity (Selector_Name (N)); + Original_Record_Component + (Entity (Selector_Name (N))); D : constant Perm_Tree_Access := Perm_Tree_Maps.Get (Component (C.Tree_Access), Comp); @@ -3577,7 +3646,9 @@ package body Sem_SPARK is is begin if not Is_Subpath_Expression (Expr) then - Error_Msg_N ("name expected here for path", Expr); + if Emit_Messages then + Error_Msg_N ("name expected here for path", Expr); + end if; return Empty; end if; @@ -3630,7 +3701,9 @@ package body Sem_SPARK is Attribute_Loop_Entry or else Get_Attribute_Id (Attribute_Name (Expr)) = - Attribute_Update); + Attribute_Update + or else Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Image); return Empty; when others => @@ -3750,22 +3823,27 @@ package body Sem_SPARK is function Is_Deep (Typ : Entity_Id) return Boolean is begin - case Type_Kind'(Ekind (Underlying_Type (Typ))) is + case Type_Kind'(Ekind (Retysp (Typ))) is when Access_Kind => return True; when E_Array_Type | E_Array_Subtype => - return Is_Deep (Component_Type (Underlying_Type (Typ))); + return Is_Deep (Component_Type (Retysp (Typ))); when Record_Kind => declare Comp : Entity_Id; begin - Comp := First_Component_Or_Discriminant (Typ); + Comp := First_Component_Or_Discriminant (Retysp (Typ)); while Present (Comp) loop - if Is_Deep (Etype (Comp)) then + + -- Ignore components not visible in SPARK + + if Component_Is_Visible_In_SPARK (Comp) + and then Is_Deep (Etype (Comp)) + then return True; end if; Next_Component_Or_Discriminant (Comp); @@ -3783,14 +3861,14 @@ package body Sem_SPARK is => return False; - -- The following should not arise as underlying types + -- Ignore full view of types if it is not in SPARK when E_Private_Type | E_Private_Subtype | E_Limited_Private_Type | E_Limited_Private_Subtype => - raise Program_Error; + return False; end case; end Is_Deep; @@ -3910,8 +3988,10 @@ package body Sem_SPARK is when N_Selected_Component => if Nkind (Expr_Elt) /= N_Selected_Component - or else Entity (Selector_Name (Prefix_Elt)) - /= Entity (Selector_Name (Expr_Elt)) + or else Original_Record_Component + (Entity (Selector_Name (Prefix_Elt))) + /= Original_Record_Component + (Entity (Selector_Name (Expr_Elt))) then return False; end if; @@ -3962,7 +4042,10 @@ package body Sem_SPARK is Attribute_Update or else Get_Attribute_Id (Attribute_Name (Expr)) = - Attribute_Loop_Entry)) + Attribute_Loop_Entry + or else + Get_Attribute_Id (Attribute_Name (Expr)) = + Attribute_Image)) or else Nkind (Expr) = N_Op_Concat; end Is_Subpath_Expression; @@ -3985,7 +4068,7 @@ package body Sem_SPARK is -- and the function's first parameter is of an access type. - and then Is_Access_Type (Etype (First_Formal (E))); + and then Is_Access_Type (Retysp (Etype (First_Formal (E)))); end Is_Traversal_Function; -------------------------------- @@ -4363,14 +4446,16 @@ package body Sem_SPARK is begin Set_Root_Object (N, Root, Is_Deref); - if Is_Deref then - Error_Msg_NE - ("insufficient permission on dereference from &", N, Root); - else - Error_Msg_NE ("insufficient permission for &", N, Root); - end if; + if Emit_Messages then + if Is_Deref then + Error_Msg_NE + ("insufficient permission on dereference from &", N, Root); + else + Error_Msg_NE ("insufficient permission for &", N, Root); + end if; - Perm_Mismatch (N, Perm, Found_Perm, Expl, Forbidden_Perm); + Perm_Mismatch (N, Perm, Found_Perm, Expl, Forbidden_Perm); + end if; end Perm_Error; ------------------------------- @@ -4385,10 +4470,12 @@ package body Sem_SPARK is Expl : Node_Id) is begin - Error_Msg_Node_2 := Subp; - Error_Msg_NE ("insufficient permission for & when returning from &", - Subp, E); - Perm_Mismatch (Subp, Perm, Found_Perm, Expl); + if Emit_Messages then + Error_Msg_Node_2 := Subp; + Error_Msg_NE ("insufficient permission for & when returning from &", + Subp, E); + Perm_Mismatch (Subp, Perm, Found_Perm, Expl); + end if; end Perm_Error_Subprogram_End; ------------------ @@ -4429,7 +4516,9 @@ package body Sem_SPARK is Var := Key.K; Borrowed := Get (Current_Borrowers, Var); - if Is_Prefix_Or_Almost (Pref => Borrowed, Expr => Expr) then + if Is_Prefix_Or_Almost (Pref => Borrowed, Expr => Expr) + and then Emit_Messages + then Error_Msg_Sloc := Sloc (Borrowed); Error_Msg_N ("object was borrowed #", Expr); end if; @@ -4465,7 +4554,9 @@ package body Sem_SPARK is Var := Key.K; Observed := Get (Current_Observers, Var); - if Is_Prefix_Or_Almost (Pref => Observed, Expr => Expr) then + if Is_Prefix_Or_Almost (Pref => Observed, Expr => Expr) + and then Emit_Messages + then Error_Msg_Sloc := Sloc (Observed); Error_Msg_N ("object was observed #", Expr); end if; @@ -4543,6 +4634,7 @@ package body Sem_SPARK is if Is_Deep (Expr_Type) and then not Inside_Procedure_Call and then Present (Get_Root_Object (Expr)) + and then Emit_Messages then Error_Msg_N ("illegal move during elaboration", Expr); end if; @@ -4587,7 +4679,7 @@ package body Sem_SPARK is -- Forbidden during elaboration if Inside_Elaboration then - if not Inside_Procedure_Call then + if not Inside_Procedure_Call and then Emit_Messages then Error_Msg_N ("illegal borrow during elaboration", Expr); end if; @@ -4606,7 +4698,7 @@ package body Sem_SPARK is -- Forbidden during elaboration if Inside_Elaboration then - if not Inside_Procedure_Call then + if not Inside_Procedure_Call and then Emit_Messages then Error_Msg_N ("illegal observe during elaboration", Expr); end if; @@ -4803,7 +4895,7 @@ package body Sem_SPARK is while Present (Formal) loop Return_Parameter_Or_Global (Id => Formal, - Typ => Underlying_Type (Etype (Formal)), + Typ => Retysp (Etype (Formal)), Kind => Ekind (Formal), Subp => Subp, Global_Var => False); @@ -4876,6 +4968,7 @@ package body Sem_SPARK is E : Entity_Id; Expl : Node_Id) is + Check_Ty : constant Entity_Id := Retysp (E); begin -- Shallow extensions are set to RW @@ -4894,7 +4987,7 @@ package body Sem_SPARK is -- precision. when Entire_Object => - case Ekind (E) is + case Ekind (Check_Ty) is when E_Array_Type | E_Array_Subtype => @@ -4908,7 +5001,8 @@ package body Sem_SPARK is Permission => Read_Write, Children_Permission => Read_Write)); begin - Set_Perm_Extensions_Move (C, Component_Type (E), Expl); + Set_Perm_Extensions_Move + (C, Component_Type (Check_Ty), Expl); T.all.Tree := (Kind => Array_Component, Is_Node_Deep => Is_Node_Deep (T), Explanation => Expl, @@ -4923,17 +5017,36 @@ package body Sem_SPARK is Hashtbl : Perm_Tree_Maps.Instance; begin - Comp := First_Component_Or_Discriminant (E); + Comp := First_Component_Or_Discriminant (Check_Ty); while Present (Comp) loop - C := new Perm_Tree_Wrapper' - (Tree => - (Kind => Entire_Object, - Is_Node_Deep => Is_Deep (Etype (Comp)), - Explanation => Expl, - Permission => Read_Write, - Children_Permission => Read_Write)); - Set_Perm_Extensions_Move (C, Etype (Comp), Expl); - Perm_Tree_Maps.Set (Hashtbl, Comp, C); + + -- Unfold components which are visible in SPARK + + if Component_Is_Visible_In_SPARK (Comp) then + C := new Perm_Tree_Wrapper' + (Tree => + (Kind => Entire_Object, + Is_Node_Deep => Is_Deep (Etype (Comp)), + Explanation => Expl, + Permission => Read_Write, + Children_Permission => Read_Write)); + Set_Perm_Extensions_Move (C, Etype (Comp), Expl); + + -- Hidden components are never deep + + else + C := new Perm_Tree_Wrapper' + (Tree => + (Kind => Entire_Object, + Is_Node_Deep => False, + Explanation => Expl, + Permission => Read_Write, + Children_Permission => Read_Write)); + Set_Perm_Extensions (C, Read_Write, Expl => Expl); + end if; + + Perm_Tree_Maps.Set + (Hashtbl, Original_Record_Component (Comp), C); Next_Component_Or_Discriminant (Comp); end loop; @@ -4955,7 +5068,8 @@ package body Sem_SPARK is Set_Perm_Extensions (T, No_Access, Expl); when Array_Component => - Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E), Expl); + Set_Perm_Extensions_Move + (Get_Elem (T), Component_Type (Check_Ty), Expl); when Record_Component => declare @@ -4963,11 +5077,23 @@ package body Sem_SPARK is Comp : Entity_Id; begin - Comp := First_Component_Or_Discriminant (E); + Comp := First_Component_Or_Discriminant (Check_Ty); while Present (Comp) loop - C := Perm_Tree_Maps.Get (Component (T), Comp); + C := Perm_Tree_Maps.Get + (Component (T), Original_Record_Component (Comp)); pragma Assert (C /= null); - Set_Perm_Extensions_Move (C, Etype (Comp), Expl); + + -- Move visible components + + if Component_Is_Visible_In_SPARK (Comp) then + Set_Perm_Extensions_Move (C, Etype (Comp), Expl); + + -- Hidden components are never deep + + else + Set_Perm_Extensions (C, Read_Write, Expl => Expl); + end if; + Next_Component_Or_Discriminant (Comp); end loop; end; @@ -5073,7 +5199,9 @@ package body Sem_SPARK is if Kind (C) = Record_Component then declare - Comp : constant Entity_Id := Entity (Selector_Name (N)); + Comp : constant Entity_Id := + Original_Record_Component + (Entity (Selector_Name (N))); D : constant Perm_Tree_Access := Perm_Tree_Maps.Get (Component (C), Comp); pragma Assert (D /= null); @@ -5102,11 +5230,14 @@ package body Sem_SPARK is begin Comp := - First_Component_Or_Discriminant (Etype (Prefix (N))); + First_Component_Or_Discriminant + (Retysp (Etype (Prefix (N)))); while Present (Comp) loop if Perm /= None - and then Comp = Entity (Selector_Name (N)) + and then Original_Record_Component (Comp) = + Original_Record_Component + (Entity (Selector_Name (N))) then P := Perm; else @@ -5116,15 +5247,22 @@ package body Sem_SPARK is D := new Perm_Tree_Wrapper' (Tree => (Kind => Entire_Object, - Is_Node_Deep => Is_Deep (Etype (Comp)), + Is_Node_Deep => + -- Hidden components are never deep + Component_Is_Visible_In_SPARK (Comp) + and then Is_Deep (Etype (Comp)), Explanation => Expl, Permission => P, Children_Permission => Child_P)); - Perm_Tree_Maps.Set (Hashtbl, Comp, D); + Perm_Tree_Maps.Set + (Hashtbl, Original_Record_Component (Comp), D); -- Store the tree to return for this component - if Comp = Entity (Selector_Name (N)) then + if Original_Record_Component (Comp) = + Original_Record_Component + (Entity (Selector_Name (N))) + then D_This := D; end if; @@ -5380,14 +5518,6 @@ package body Sem_SPARK is -- Functions cannot have outputs in SPARK elsif Ekind (Subp) = E_Function then - if Kind = E_Out_Parameter then - Error_Msg_N ("function with OUT parameter is not " - & "allowed in SPARK", Id); - else - Error_Msg_N ("function with `IN OUT` parameter is not " - & "allowed in SPARK", Id); - end if; - return; -- Deep types define a borrow or a move @@ -5424,7 +5554,7 @@ package body Sem_SPARK is while Present (Formal) loop Setup_Parameter_Or_Global (Id => Formal, - Typ => Underlying_Type (Etype (Formal)), + Typ => Retysp (Etype (Formal)), Kind => Ekind (Formal), Subp => Subp, Global_Var => False, @@ -5457,11 +5587,12 @@ package body Sem_SPARK is while Present (Comp) loop Setup_Parameter_Or_Global (Id => Comp, - Typ => Underlying_Type (Etype (Comp)), + Typ => Retysp (Etype (Comp)), Kind => Kind, Subp => Subp, Global_Var => False, Expl => Comp); + Next_Component_Or_Discriminant (Comp); end loop; end Setup_Protected_Components; diff --git a/gcc/ada/sem_spark.ads b/gcc/ada/sem_spark.ads index ee4126a..0e8b29b 100644 --- a/gcc/ada/sem_spark.ads +++ b/gcc/ada/sem_spark.ads @@ -132,12 +132,34 @@ -- get read-write permission, which can be specified using the node's -- Children_Permission field. +-- The implementation is done as a generic, so that GNATprove can instantiate +-- it with suitable formal arguments that depend on the SPARK_Mode boundary +-- as well as the two-phase architecture of GNATprove (which runs the GNAT +-- front end twice, once for global generation and once for analysis). + with Types; use Types; +generic + with function Retysp (X : Entity_Id) return Entity_Id; + -- Return the representative type in SPARK for a type. + + with function Component_Is_Visible_In_SPARK (C : Entity_Id) return Boolean; + -- Return whether a component is visible in SPARK. No aliasing check is + -- performed for a component that is visible. + + with function Emit_Messages return Boolean; + -- Return True when error messages should be emitted. + package Sem_SPARK is procedure Check_Safe_Pointers (N : Node_Id); -- The entry point of this package. It analyzes a node and reports errors -- when there are violations of ownership rules. + function Is_Deep (Typ : Entity_Id) return Boolean; + -- A function that can tell whether a type is deep. Returns True if the + -- type passed as argument is deep. + + function Is_Traversal_Function (E : Entity_Id) return Boolean; + end Sem_SPARK; -- cgit v1.1 From 708fb956d9b625c150aadf9fb6394651ef054b5a Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 11 Jul 2019 08:03:14 +0000 Subject: [Ada] Avoid spurious warning on assertions with Loop_Entry When the Loop_Entry attribute is used inside a loop invariant or another assertion where it is allowed, it may lead to spurious warnings on conditions that are detected to be always valid. Now fixed. 2019-07-11 Yannick Moy gcc/ada/ * sem_eval.adb (Is_Same_Value): Add special case for rewritten Loop_Entry attribute. gcc/testsuite/ * gnat.dg/loop_entry1.adb: New testcase. From-SVN: r273403 --- gcc/ada/ChangeLog | 5 ++++ gcc/ada/sem_eval.adb | 49 ++++++++++++++++++++++++++++------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gnat.dg/loop_entry1.adb | 13 ++++++++++ 4 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/loop_entry1.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 95c898b..15b90e3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Yannick Moy + + * sem_eval.adb (Is_Same_Value): Add special case for rewritten + Loop_Entry attribute. + 2019-07-11 Claire Dross * gnat1drv.adb: SPARK checking rules for pointer aliasing are diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index e140fa7..734c961 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -986,6 +986,13 @@ package body Sem_Eval is Lf : constant Node_Id := Compare_Fixup (L); Rf : constant Node_Id := Compare_Fixup (R); + function Is_Rewritten_Loop_Entry (N : Node_Id) return Boolean; + -- An attribute reference to Loop_Entry may have been rewritten into + -- its prefix as a way to avoid generating a constant for that + -- attribute when the corresponding pragma is ignored. These nodes + -- should be ignored when deciding if they can be equal to one + -- another. + function Is_Same_Subscript (L, R : List_Id) return Boolean; -- L, R are the Expressions values from two attribute nodes for First -- or Last attributes. Either may be set to No_List if no expressions @@ -993,6 +1000,19 @@ package body Sem_Eval is -- expressions represent the same subscript (note one case is where -- one subscript is missing and the other is explicitly set to 1). + ----------------------------- + -- Is_Rewritten_Loop_Entry -- + ----------------------------- + + function Is_Rewritten_Loop_Entry (N : Node_Id) return Boolean is + Orig_N : constant Node_Id := Original_Node (N); + begin + return Orig_N /= N + and then Nkind (Orig_N) = N_Attribute_Reference + and then Get_Attribute_Id (Attribute_Name (Orig_N)) = + Attribute_Loop_Entry; + end Is_Rewritten_Loop_Entry; + ----------------------- -- Is_Same_Subscript -- ----------------------- @@ -1018,23 +1038,32 @@ package body Sem_Eval is -- Start of processing for Is_Same_Value begin - -- Values are the same if they refer to the same entity and the - -- entity is non-volatile. This does not however apply to Float - -- types, since we may have two NaN values and they should never - -- compare equal. + -- Loop_Entry nodes rewritten into their prefix inside ignored + -- pragmas should never lead to a decision of equality. - -- If the entity is a discriminant, the two expressions may be bounds - -- of components of objects of the same discriminated type. The - -- values of the discriminants are not static, and therefore the - -- result is unknown. + if Is_Rewritten_Loop_Entry (Lf) + or else Is_Rewritten_Loop_Entry (Rf) + then + return False; - -- It would be better to comment individual branches of this test ??? + -- Values are the same if they refer to the same entity and the + -- entity is nonvolatile. - if Nkind_In (Lf, N_Identifier, N_Expanded_Name) + elsif Nkind_In (Lf, N_Identifier, N_Expanded_Name) and then Nkind_In (Rf, N_Identifier, N_Expanded_Name) and then Entity (Lf) = Entity (Rf) + + -- If the entity is a discriminant, the two expressions may be + -- bounds of components of objects of the same discriminated type. + -- The values of the discriminants are not static, and therefore + -- the result is unknown. + and then Ekind (Entity (Lf)) /= E_Discriminant and then Present (Entity (Lf)) + + -- This does not however apply to Float types, since we may have + -- two NaN values and they should never compare equal. + and then not Is_Floating_Point_Type (Etype (L)) and then not Is_Volatile_Reference (L) and then not Is_Volatile_Reference (R) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index baef966..f4a6d05 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-11 Yannick Moy + + * gnat.dg/loop_entry1.adb: New testcase. + 2019-07-11 Ed Schonberg * gnat.dg/prot8.adb, gnat.dg/prot8.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/loop_entry1.adb b/gcc/testsuite/gnat.dg/loop_entry1.adb new file mode 100644 index 0000000..39cb8d0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_entry1.adb @@ -0,0 +1,13 @@ +-- { dg-do compile } +-- { dg-options "-gnatwc" } + +procedure Loop_Entry1 (X, Y : in out Integer) is +begin + while X < Y loop + pragma Loop_Invariant + (X >= X'Loop_Entry and then Y <= Y'Loop_Entry); + + X := X + 1; + Y := Y - 1; + end loop; +end Loop_Entry1; -- cgit v1.1 From d99ef225ac0722ab011cd39386fed4e346311edb Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 11 Jul 2019 08:03:19 +0000 Subject: [Ada] Flip the meaning of debug switch -gnatdF 2019-07-11 Yannick Moy gcc/ada/ * debug.adb: Flip meaning of debug switch -gnatdF. From-SVN: r273404 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/debug.adb | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 15b90e3..a5273a8 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,9 @@ 2019-07-11 Yannick Moy + * debug.adb: Flip meaning of debug switch -gnatdF. + +2019-07-11 Yannick Moy + * sem_eval.adb (Is_Same_Value): Add special case for rewritten Loop_Entry attribute. diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb index 6df3d6f..6a5d0ea 100644 --- a/gcc/ada/debug.adb +++ b/gcc/ada/debug.adb @@ -602,10 +602,11 @@ package body Debug is -- dE Apply compile time elaboration checking for with relations between -- predefined units. Normally no checks are made. - -- dF Perform the new SPARK checking rules for pointer aliasing. This is - -- only activated in GNATprove mode and on SPARK code. These rules are - -- not yet part of the official SPARK language, but are expected to be - -- included in a future version of SPARK. + -- dF Disable the new SPARK checking rules for pointer aliasing. This is + -- only activated as part of GNATprove mode and on SPARK code. Now + -- that pointer support is part of the official SPARK language, this + -- switch allows reverting to the previous version of GNATprove + -- rejecting pointers. -- dG Generate all warnings. Normally Errout suppresses warnings on -- units that are not part of the main extended source, and also -- cgit v1.1 From 8b727104817f1b0c2a03013ed397e99f8673405c Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Thu, 11 Jul 2019 08:03:24 +0000 Subject: [Ada] Avoid spurious errors on dimensionality checking in GNATprove In the special GNATprove mode of the frontend, automatic inlining is performed, which may lead to spurious errors on dimensionality checking. Avoid performing this checking on inlined code, which has already been checked for dimensionality errors. There is no impact on compilation. 2019-07-11 Yannick Moy gcc/ada/ * sem_res.adb (Resolve_Call): Do not perform dimensionality checking on inlined bodies. From-SVN: r273405 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_res.adb | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a5273a8..59f20c4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-11 Yannick Moy + * sem_res.adb (Resolve_Call): Do not perform dimensionality + checking on inlined bodies. + +2019-07-11 Yannick Moy + * debug.adb: Flip meaning of debug switch -gnatdF. 2019-07-11 Yannick Moy diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 730f173..4ca74f8 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -6949,7 +6949,9 @@ package body Sem_Res is -- Check the dimensions of the actuals in the call. For function calls, -- propagate the dimensions from the returned type to N. - Analyze_Dimension_Call (N, Nam); + if not In_Inlined_Body then + Analyze_Dimension_Call (N, Nam); + end if; -- All done, evaluate call and deal with elaboration issues -- cgit v1.1 From 929d520369a92d26bb734d79588ffde8aba6e8e8 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Thu, 11 Jul 2019 08:03:28 +0000 Subject: [Ada] Minor refactoring 2019-07-11 Piotr Trojanek gcc/ada/ * checks.adb: Fix typo in comment. * sem.adb (Semantics): Avoid repeated calls to In_Extended_Main_Source_Unit by reusing an already-cached result. * sem_util.adb (First_Global): Fix style. From-SVN: r273406 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/checks.adb | 2 +- gcc/ada/sem.adb | 2 +- gcc/ada/sem_util.adb | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 59f20c4..e3fd0a1 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-11 Piotr Trojanek + + * checks.adb: Fix typo in comment. + * sem.adb (Semantics): Avoid repeated calls to + In_Extended_Main_Source_Unit by reusing an already-cached + result. + * sem_util.adb (First_Global): Fix style. + 2019-07-11 Yannick Moy * sem_res.adb (Resolve_Call): Do not perform dimensionality diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 984bb15..73f7edc 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -7056,7 +7056,7 @@ package body Checks is Convert_And_Check_Range; end if; - -- Note that at this stage we now that the Target_Base_Type is not in + -- Note that at this stage we know that the Target_Base_Type is not in -- the range of the Source_Base_Type (since even the Target_Type itself -- is not in this range). It could still be the case that Source_Type is -- in range of the target base type since we have not checked that case. diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb index fa3ed48..2f8f6a4 100644 --- a/gcc/ada/sem.adb +++ b/gcc/ada/sem.adb @@ -1579,7 +1579,7 @@ package body Sem is and then Nkind (Unit (Comp_Unit)) in N_Proper_Body and then (Nkind (Unit (Comp_Unit)) /= N_Subprogram_Body or else not Acts_As_Spec (Comp_Unit)) - and then not In_Extended_Main_Source_Unit (Comp_Unit) + and then not Ext_Main_Source_Unit then null; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 04d981a6..f18eb0f 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -8703,6 +8703,8 @@ package body Sem_Util is Global : Node_Id := Empty; Body_Id : Entity_Id; + -- Start of processing for First_Global + begin pragma Assert (Nam_In (Global_Mode, Name_In_Out, Name_Input, -- cgit v1.1 From 674dbc204d3b572186df85803b086ddb9a790837 Mon Sep 17 00:00:00 2001 From: Piotr Trojanek Date: Thu, 11 Jul 2019 08:03:33 +0000 Subject: [Ada] Use high-level wrappers for Lib.Units.Table 2019-07-11 Piotr Trojanek gcc/ada/ * lib-writ.adb (Ensure_System_Dependency, Up_To_Date_ALI_File_Exists, Write_ALI): Replace low-level access to table with a high-level query. From-SVN: r273407 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/lib-writ.adb | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e3fd0a1..7c09238 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,11 @@ 2019-07-11 Piotr Trojanek + * lib-writ.adb (Ensure_System_Dependency, + Up_To_Date_ALI_File_Exists, Write_ALI): Replace low-level access + to table with a high-level query. + +2019-07-11 Piotr Trojanek + * checks.adb: Fix typo in comment. * sem.adb (Semantics): Avoid repeated calls to In_Extended_Main_Source_Unit by reusing an already-cached diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb index 31ef8e2..987afcb 100644 --- a/gcc/ada/lib-writ.adb +++ b/gcc/ada/lib-writ.adb @@ -143,7 +143,7 @@ package body Lib.Writ is -- Nothing to do if we already compiled System for Unum in Units.First .. Last_Unit loop - if Units.Table (Unum).Source_Index = System_Source_File_Index then + if Source_Index (Unum) = System_Source_File_Index then return; end if; end loop; @@ -431,7 +431,7 @@ package body Lib.Writ is Id := First_Sdep_Entry; for J in 1 .. Num_Sdep loop - Sind := Units.Table (Sdep_Table (J)).Source_Index; + Sind := Source_Index (Sdep_Table (J)); while Sdep.Table (Id).Sfile /= File_Name (Sind) loop if Id = Sdep.Last then @@ -1563,7 +1563,7 @@ package body Lib.Writ is for J in 1 .. Num_Sdep loop Unum := Sdep_Table (J); Units.Table (Unum).Dependency_Num := J; - Sind := Units.Table (Unum).Source_Index; + Sind := Source_Index (Unum); Write_Info_Initiate ('D'); Write_Info_Char (' '); -- cgit v1.1 From 491b0b4015a70071a05e0faa5c2082c43a51a0d3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 11 Jul 2019 10:31:19 +0200 Subject: re PR target/91124 (gcc.target/i386/avx512vl-vpshldvd-2.c etc. FAIL) PR target/91124 * config/i386/i386-builtin-types.def (V32HI_FTYPE_V32HI_V32HI_V32HI_INT, V16HI_FTYPE_V16HI_V16HI_V16HI_INT, V8HI_FTYPE_V8HI_V8HI_V8HI_INT, V8SI_FTYPE_V8SI_V8SI_V8SI_INT, V4DI_FTYPE_V4DI_V4DI_V4DI_INT, V8DI_FTYPE_V8DI_V8DI_V8DI_INT, V16SI_FTYPE_V16SI_V16SI_V16SI_INT, V2DI_FTYPE_V2DI_V2DI_V2DI_INT, V4SI_FTYPE_V4SI_V4SI_V4SI_INT): Remove. * config/i386/i386-builtin.def (__builtin_ia32_vpshrdv_v32hi_mask, __builtin_ia32_vpshrdv_v32hi_maskz, __builtin_ia32_vpshrdv_v16hi_mask, __builtin_ia32_vpshrdv_v16hi_maskz, __builtin_ia32_vpshrdv_v8hi_mask, __builtin_ia32_vpshrdv_v8hi_maskz, __builtin_ia32_vpshrdv_v16si_mask, __builtin_ia32_vpshrdv_v16si_maskz, __builtin_ia32_vpshrdv_v8si_mask, __builtin_ia32_vpshrdv_v8si_maskz, __builtin_ia32_vpshrdv_v4si_mask, __builtin_ia32_vpshrdv_v4si_maskz, __builtin_ia32_vpshrdv_v8di_mask, __builtin_ia32_vpshrdv_v8di_maskz, __builtin_ia32_vpshrdv_v4di_mask, __builtin_ia32_vpshrdv_v4di_maskz, __builtin_ia32_vpshrdv_v2di_mask, __builtin_ia32_vpshrdv_v2di_maskz, __builtin_ia32_vpshldv_v32hi_mask, __builtin_ia32_vpshldv_v32hi_maskz, __builtin_ia32_vpshldv_v16hi_mask, __builtin_ia32_vpshldv_v16hi_maskz, __builtin_ia32_vpshldv_v8hi_mask, __builtin_ia32_vpshldv_v8hi_maskz, __builtin_ia32_vpshldv_v16si_mask, __builtin_ia32_vpshldv_v16si_maskz, __builtin_ia32_vpshldv_v8si_mask, __builtin_ia32_vpshldv_v8si_maskz, __builtin_ia32_vpshldv_v4si_mask, __builtin_ia32_vpshldv_v4si_maskz, __builtin_ia32_vpshldv_v8di_mask, __builtin_ia32_vpshldv_v8di_maskz, __builtin_ia32_vpshldv_v4di_mask, __builtin_ia32_vpshldv_v4di_maskz, __builtin_ia32_vpshldv_v2di_mask, __builtin_ia32_vpshldv_v2di_maskz, __builtin_ia32_vpdpbusd_v16si_mask, __builtin_ia32_vpdpbusd_v16si_maskz, __builtin_ia32_vpdpbusd_v8si_mask, __builtin_ia32_vpdpbusd_v8si_maskz, __builtin_ia32_vpdpbusd_v4si_mask, __builtin_ia32_vpdpbusd_v4si_maskz, __builtin_ia32_vpdpbusds_v16si_mask, __builtin_ia32_vpdpbusds_v16si_maskz, __builtin_ia32_vpdpbusds_v8si_mask, __builtin_ia32_vpdpbusds_v8si_maskz, __builtin_ia32_vpdpbusds_v4si_mask, __builtin_ia32_vpdpbusds_v4si_maskz, __builtin_ia32_vpdpwssd_v16si_mask, __builtin_ia32_vpdpwssd_v16si_maskz, __builtin_ia32_vpdpwssd_v8si_mask, __builtin_ia32_vpdpwssd_v8si_maskz, __builtin_ia32_vpdpwssd_v4si_mask, __builtin_ia32_vpdpwssd_v4si_maskz, __builtin_ia32_vpdpwssds_v16si_mask, __builtin_ia32_vpdpwssds_v16si_maskz, __builtin_ia32_vpdpwssds_v8si_mask, __builtin_ia32_vpdpwssds_v8si_maskz, __builtin_ia32_vpdpwssds_v4si_mask, __builtin_ia32_vpdpwssds_v4si_maskz): Use *_USI, *_UHI or *_UQI suffixed types rather than *_INT. * config/i386/i386-expand.c (ix86_expand_args_builtin): Don't handle V32HI_FTYPE_V32HI_V32HI_V32HI_INT, V16HI_FTYPE_V16HI_V16HI_V16HI_INT, V8HI_FTYPE_V8HI_V8HI_V8HI_INT, V8SI_FTYPE_V8SI_V8SI_V8SI_INT, V4DI_FTYPE_V4DI_V4DI_V4DI_INT, V8DI_FTYPE_V8DI_V8DI_V8DI_INT, V16SI_FTYPE_V16SI_V16SI_V16SI_INT, V2DI_FTYPE_V2DI_V2DI_V2DI_INT and V4SI_FTYPE_V4SI_V4SI_V4SI_INT. From-SVN: r273408 --- gcc/ChangeLog | 55 +++++++++++++++ gcc/config/i386/i386-builtin-types.def | 9 --- gcc/config/i386/i386-builtin.def | 120 ++++++++++++++++----------------- gcc/config/i386/i386-expand.c | 9 --- 4 files changed, 115 insertions(+), 78 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f171853..a02213d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,58 @@ +2019-07-11 Jakub Jelinek + + PR target/91124 + * config/i386/i386-builtin-types.def + (V32HI_FTYPE_V32HI_V32HI_V32HI_INT, + V16HI_FTYPE_V16HI_V16HI_V16HI_INT, V8HI_FTYPE_V8HI_V8HI_V8HI_INT, + V8SI_FTYPE_V8SI_V8SI_V8SI_INT, V4DI_FTYPE_V4DI_V4DI_V4DI_INT, + V8DI_FTYPE_V8DI_V8DI_V8DI_INT, V16SI_FTYPE_V16SI_V16SI_V16SI_INT, + V2DI_FTYPE_V2DI_V2DI_V2DI_INT, V4SI_FTYPE_V4SI_V4SI_V4SI_INT): Remove. + * config/i386/i386-builtin.def (__builtin_ia32_vpshrdv_v32hi_mask, + __builtin_ia32_vpshrdv_v32hi_maskz, __builtin_ia32_vpshrdv_v16hi_mask, + __builtin_ia32_vpshrdv_v16hi_maskz, __builtin_ia32_vpshrdv_v8hi_mask, + __builtin_ia32_vpshrdv_v8hi_maskz, __builtin_ia32_vpshrdv_v16si_mask, + __builtin_ia32_vpshrdv_v16si_maskz, __builtin_ia32_vpshrdv_v8si_mask, + __builtin_ia32_vpshrdv_v8si_maskz, __builtin_ia32_vpshrdv_v4si_mask, + __builtin_ia32_vpshrdv_v4si_maskz, __builtin_ia32_vpshrdv_v8di_mask, + __builtin_ia32_vpshrdv_v8di_maskz, __builtin_ia32_vpshrdv_v4di_mask, + __builtin_ia32_vpshrdv_v4di_maskz, __builtin_ia32_vpshrdv_v2di_mask, + __builtin_ia32_vpshrdv_v2di_maskz, __builtin_ia32_vpshldv_v32hi_mask, + __builtin_ia32_vpshldv_v32hi_maskz, __builtin_ia32_vpshldv_v16hi_mask, + __builtin_ia32_vpshldv_v16hi_maskz, __builtin_ia32_vpshldv_v8hi_mask, + __builtin_ia32_vpshldv_v8hi_maskz, __builtin_ia32_vpshldv_v16si_mask, + __builtin_ia32_vpshldv_v16si_maskz, __builtin_ia32_vpshldv_v8si_mask, + __builtin_ia32_vpshldv_v8si_maskz, __builtin_ia32_vpshldv_v4si_mask, + __builtin_ia32_vpshldv_v4si_maskz, __builtin_ia32_vpshldv_v8di_mask, + __builtin_ia32_vpshldv_v8di_maskz, __builtin_ia32_vpshldv_v4di_mask, + __builtin_ia32_vpshldv_v4di_maskz, __builtin_ia32_vpshldv_v2di_mask, + __builtin_ia32_vpshldv_v2di_maskz, __builtin_ia32_vpdpbusd_v16si_mask, + __builtin_ia32_vpdpbusd_v16si_maskz, __builtin_ia32_vpdpbusd_v8si_mask, + __builtin_ia32_vpdpbusd_v8si_maskz, __builtin_ia32_vpdpbusd_v4si_mask, + __builtin_ia32_vpdpbusd_v4si_maskz, + __builtin_ia32_vpdpbusds_v16si_mask, + __builtin_ia32_vpdpbusds_v16si_maskz, + __builtin_ia32_vpdpbusds_v8si_mask, + __builtin_ia32_vpdpbusds_v8si_maskz, + __builtin_ia32_vpdpbusds_v4si_mask, + __builtin_ia32_vpdpbusds_v4si_maskz, + __builtin_ia32_vpdpwssd_v16si_mask, + __builtin_ia32_vpdpwssd_v16si_maskz, __builtin_ia32_vpdpwssd_v8si_mask, + __builtin_ia32_vpdpwssd_v8si_maskz, __builtin_ia32_vpdpwssd_v4si_mask, + __builtin_ia32_vpdpwssd_v4si_maskz, + __builtin_ia32_vpdpwssds_v16si_mask, + __builtin_ia32_vpdpwssds_v16si_maskz, + __builtin_ia32_vpdpwssds_v8si_mask, + __builtin_ia32_vpdpwssds_v8si_maskz, + __builtin_ia32_vpdpwssds_v4si_mask, + __builtin_ia32_vpdpwssds_v4si_maskz): Use *_USI, *_UHI or *_UQI + suffixed types rather than *_INT. + * config/i386/i386-expand.c (ix86_expand_args_builtin): Don't handle + V32HI_FTYPE_V32HI_V32HI_V32HI_INT, V16HI_FTYPE_V16HI_V16HI_V16HI_INT, + V8HI_FTYPE_V8HI_V8HI_V8HI_INT, V8SI_FTYPE_V8SI_V8SI_V8SI_INT, + V4DI_FTYPE_V4DI_V4DI_V4DI_INT, V8DI_FTYPE_V8DI_V8DI_V8DI_INT, + V16SI_FTYPE_V16SI_V16SI_V16SI_INT, V2DI_FTYPE_V2DI_V2DI_V2DI_INT + and V4SI_FTYPE_V4SI_V4SI_V4SI_INT. + 2019-07-11 Aldy Hernandez * tree-vrp.c (intersect_ranges): If we know the intersection is diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index 221c0e7..38fea5c 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -1252,17 +1252,8 @@ DEF_FUNCTION_TYPE (V8HI, V8HI, V8HI, INT, V8HI, INT) DEF_FUNCTION_TYPE (V4SI, V4SI, V4SI, INT, V4SI, INT) DEF_FUNCTION_TYPE (V2DI, V2DI, V2DI, INT, V2DI, INT) DEF_FUNCTION_TYPE (V32HI, V32HI, V32HI, V32HI) -DEF_FUNCTION_TYPE (V32HI, V32HI, V32HI, V32HI, INT) -DEF_FUNCTION_TYPE (V16HI, V16HI, V16HI, V16HI, INT) -DEF_FUNCTION_TYPE (V8HI, V8HI, V8HI, V8HI, INT) -DEF_FUNCTION_TYPE (V8SI, V8SI, V8SI, V8SI, INT) -DEF_FUNCTION_TYPE (V4SI, V4SI, V4SI, V4SI, INT) DEF_FUNCTION_TYPE (V8DI, V8DI, V8DI, V8DI) -DEF_FUNCTION_TYPE (V8DI, V8DI, V8DI, V8DI, INT) -DEF_FUNCTION_TYPE (V4DI, V4DI, V4DI, V4DI, INT) DEF_FUNCTION_TYPE (V16SI, V16SI, V16SI, V16SI) -DEF_FUNCTION_TYPE (V16SI, V16SI, V16SI, V16SI, INT) -DEF_FUNCTION_TYPE (V2DI, V2DI, V2DI, V2DI, INT) # BITALG builtins DEF_FUNCTION_TYPE (V4DI, V4DI) diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index ef45311..6ac820e 100644 --- a/gcc/config/i386/i386-builtin.def +++ b/gcc/config/i386/i386-builtin.def @@ -2528,60 +2528,60 @@ BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshl BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshld_v2di_mask, "__builtin_ia32_vpshld_v2di_mask", IX86_BUILTIN_VPSHLDV2DI_MASK, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_INT_V2DI_INT) BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v32hi, "__builtin_ia32_vpshrdv_v32hi", IX86_BUILTIN_VPSHRDVV32HI, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshrdv_v32hi_mask, "__builtin_ia32_vpshrdv_v32hi_mask", IX86_BUILTIN_VPSHRDVV32HI_MASK, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshrdv_v32hi_maskz, "__builtin_ia32_vpshrdv_v32hi_maskz", IX86_BUILTIN_VPSHRDVV32HI_MASKZ, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshrdv_v32hi_mask, "__builtin_ia32_vpshrdv_v32hi_mask", IX86_BUILTIN_VPSHRDVV32HI_MASK, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_USI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshrdv_v32hi_maskz, "__builtin_ia32_vpshrdv_v32hi_maskz", IX86_BUILTIN_VPSHRDVV32HI_MASKZ, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_USI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v16hi, "__builtin_ia32_vpshrdv_v16hi", IX86_BUILTIN_VPSHRDVV16HI, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v16hi_mask, "__builtin_ia32_vpshrdv_v16hi_mask", IX86_BUILTIN_VPSHRDVV16HI_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v16hi_maskz, "__builtin_ia32_vpshrdv_v16hi_maskz", IX86_BUILTIN_VPSHRDVV16HI_MASKZ, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v16hi_mask, "__builtin_ia32_vpshrdv_v16hi_mask", IX86_BUILTIN_VPSHRDVV16HI_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v16hi_maskz, "__builtin_ia32_vpshrdv_v16hi_maskz", IX86_BUILTIN_VPSHRDVV16HI_MASKZ, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_UHI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8hi, "__builtin_ia32_vpshrdv_v8hi", IX86_BUILTIN_VPSHRDVV8HI, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8hi_mask, "__builtin_ia32_vpshrdv_v8hi_mask", IX86_BUILTIN_VPSHRDVV8HI_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8hi_maskz, "__builtin_ia32_vpshrdv_v8hi_maskz", IX86_BUILTIN_VPSHRDVV8HI_MASKZ, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8hi_mask, "__builtin_ia32_vpshrdv_v8hi_mask", IX86_BUILTIN_VPSHRDVV8HI_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8hi_maskz, "__builtin_ia32_vpshrdv_v8hi_maskz", IX86_BUILTIN_VPSHRDVV8HI_MASKZ, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v16si, "__builtin_ia32_vpshrdv_v16si", IX86_BUILTIN_VPSHRDVV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v16si_mask, "__builtin_ia32_vpshrdv_v16si_mask", IX86_BUILTIN_VPSHRDVV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v16si_maskz, "__builtin_ia32_vpshrdv_v16si_maskz", IX86_BUILTIN_VPSHRDVV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v16si_mask, "__builtin_ia32_vpshrdv_v16si_mask", IX86_BUILTIN_VPSHRDVV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v16si_maskz, "__builtin_ia32_vpshrdv_v16si_maskz", IX86_BUILTIN_VPSHRDVV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8si, "__builtin_ia32_vpshrdv_v8si", IX86_BUILTIN_VPSHRDVV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8si_mask, "__builtin_ia32_vpshrdv_v8si_mask", IX86_BUILTIN_VPSHRDVV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8si_maskz, "__builtin_ia32_vpshrdv_v8si_maskz", IX86_BUILTIN_VPSHRDVV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8si_mask, "__builtin_ia32_vpshrdv_v8si_mask", IX86_BUILTIN_VPSHRDVV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v8si_maskz, "__builtin_ia32_vpshrdv_v8si_maskz", IX86_BUILTIN_VPSHRDVV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4si, "__builtin_ia32_vpshrdv_v4si", IX86_BUILTIN_VPSHRDVV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4si_mask, "__builtin_ia32_vpshrdv_v4si_mask", IX86_BUILTIN_VPSHRDVV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4si_maskz, "__builtin_ia32_vpshrdv_v4si_maskz", IX86_BUILTIN_VPSHRDVV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4si_mask, "__builtin_ia32_vpshrdv_v4si_mask", IX86_BUILTIN_VPSHRDVV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4si_maskz, "__builtin_ia32_vpshrdv_v4si_maskz", IX86_BUILTIN_VPSHRDVV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v8di, "__builtin_ia32_vpshrdv_v8di", IX86_BUILTIN_VPSHRDVV8DI, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v8di_mask, "__builtin_ia32_vpshrdv_v8di_mask", IX86_BUILTIN_VPSHRDVV8DI_MASK, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v8di_maskz, "__builtin_ia32_vpshrdv_v8di_maskz", IX86_BUILTIN_VPSHRDVV8DI_MASKZ, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v8di_mask, "__builtin_ia32_vpshrdv_v8di_mask", IX86_BUILTIN_VPSHRDVV8DI_MASK, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshrdv_v8di_maskz, "__builtin_ia32_vpshrdv_v8di_maskz", IX86_BUILTIN_VPSHRDVV8DI_MASKZ, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4di, "__builtin_ia32_vpshrdv_v4di", IX86_BUILTIN_VPSHRDVV4DI, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4di_mask, "__builtin_ia32_vpshrdv_v4di_mask", IX86_BUILTIN_VPSHRDVV4DI_MASK, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4di_maskz, "__builtin_ia32_vpshrdv_v4di_maskz", IX86_BUILTIN_VPSHRDVV4DI_MASKZ, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4di_mask, "__builtin_ia32_vpshrdv_v4di_mask", IX86_BUILTIN_VPSHRDVV4DI_MASK, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v4di_maskz, "__builtin_ia32_vpshrdv_v4di_maskz", IX86_BUILTIN_VPSHRDVV4DI_MASKZ, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v2di, "__builtin_ia32_vpshrdv_v2di", IX86_BUILTIN_VPSHRDVV2DI, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v2di_mask, "__builtin_ia32_vpshrdv_v2di_mask", IX86_BUILTIN_VPSHRDVV2DI_MASK, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v2di_maskz, "__builtin_ia32_vpshrdv_v2di_maskz", IX86_BUILTIN_VPSHRDVV2DI_MASKZ, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v2di_mask, "__builtin_ia32_vpshrdv_v2di_mask", IX86_BUILTIN_VPSHRDVV2DI_MASK, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshrdv_v2di_maskz, "__builtin_ia32_vpshrdv_v2di_maskz", IX86_BUILTIN_VPSHRDVV2DI_MASKZ, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v32hi, "__builtin_ia32_vpshldv_v32hi", IX86_BUILTIN_VPSHLDVV32HI, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshldv_v32hi_mask, "__builtin_ia32_vpshldv_v32hi_mask", IX86_BUILTIN_VPSHLDVV32HI_MASK, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshldv_v32hi_maskz, "__builtin_ia32_vpshldv_v32hi_maskz", IX86_BUILTIN_VPSHLDVV32HI_MASKZ, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshldv_v32hi_mask, "__builtin_ia32_vpshldv_v32hi_mask", IX86_BUILTIN_VPSHLDVV32HI_MASK, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_USI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_vpshldv_v32hi_maskz, "__builtin_ia32_vpshldv_v32hi_maskz", IX86_BUILTIN_VPSHLDVV32HI_MASKZ, UNKNOWN, (int) V32HI_FTYPE_V32HI_V32HI_V32HI_USI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v16hi, "__builtin_ia32_vpshldv_v16hi", IX86_BUILTIN_VPSHLDVV16HI, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v16hi_mask, "__builtin_ia32_vpshldv_v16hi_mask", IX86_BUILTIN_VPSHLDVV16HI_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v16hi_maskz, "__builtin_ia32_vpshldv_v16hi_maskz", IX86_BUILTIN_VPSHLDVV16HI_MASKZ, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v16hi_mask, "__builtin_ia32_vpshldv_v16hi_mask", IX86_BUILTIN_VPSHLDVV16HI_MASK, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v16hi_maskz, "__builtin_ia32_vpshldv_v16hi_maskz", IX86_BUILTIN_VPSHLDVV16HI_MASKZ, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI_V16HI_UHI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8hi, "__builtin_ia32_vpshldv_v8hi", IX86_BUILTIN_VPSHLDVV8HI, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8hi_mask, "__builtin_ia32_vpshldv_v8hi_mask", IX86_BUILTIN_VPSHLDVV8HI_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8hi_maskz, "__builtin_ia32_vpshldv_v8hi_maskz", IX86_BUILTIN_VPSHLDVV8HI_MASKZ, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8hi_mask, "__builtin_ia32_vpshldv_v8hi_mask", IX86_BUILTIN_VPSHLDVV8HI_MASK, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8hi_maskz, "__builtin_ia32_vpshldv_v8hi_maskz", IX86_BUILTIN_VPSHLDVV8HI_MASKZ, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v16si, "__builtin_ia32_vpshldv_v16si", IX86_BUILTIN_VPSHLDVV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v16si_mask, "__builtin_ia32_vpshldv_v16si_mask", IX86_BUILTIN_VPSHLDVV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v16si_maskz, "__builtin_ia32_vpshldv_v16si_maskz", IX86_BUILTIN_VPSHLDVV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v16si_mask, "__builtin_ia32_vpshldv_v16si_mask", IX86_BUILTIN_VPSHLDVV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v16si_maskz, "__builtin_ia32_vpshldv_v16si_maskz", IX86_BUILTIN_VPSHLDVV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8si, "__builtin_ia32_vpshldv_v8si", IX86_BUILTIN_VPSHLDVV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8si_mask, "__builtin_ia32_vpshldv_v8si_mask", IX86_BUILTIN_VPSHLDVV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8si_maskz, "__builtin_ia32_vpshldv_v8si_maskz", IX86_BUILTIN_VPSHLDVV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8si_mask, "__builtin_ia32_vpshldv_v8si_mask", IX86_BUILTIN_VPSHLDVV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v8si_maskz, "__builtin_ia32_vpshldv_v8si_maskz", IX86_BUILTIN_VPSHLDVV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4si, "__builtin_ia32_vpshldv_v4si", IX86_BUILTIN_VPSHLDVV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4si_mask, "__builtin_ia32_vpshldv_v4si_mask", IX86_BUILTIN_VPSHLDVV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4si_maskz, "__builtin_ia32_vpshldv_v4si_maskz", IX86_BUILTIN_VPSHLDVV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4si_mask, "__builtin_ia32_vpshldv_v4si_mask", IX86_BUILTIN_VPSHLDVV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4si_maskz, "__builtin_ia32_vpshldv_v4si_maskz", IX86_BUILTIN_VPSHLDVV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v8di, "__builtin_ia32_vpshldv_v8di", IX86_BUILTIN_VPSHLDVV8DI, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v8di_mask, "__builtin_ia32_vpshldv_v8di_mask", IX86_BUILTIN_VPSHLDVV8DI_MASK, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v8di_maskz, "__builtin_ia32_vpshldv_v8di_maskz", IX86_BUILTIN_VPSHLDVV8DI_MASKZ, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v8di_mask, "__builtin_ia32_vpshldv_v8di_mask", IX86_BUILTIN_VPSHLDVV8DI_MASK, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2, 0, CODE_FOR_vpshldv_v8di_maskz, "__builtin_ia32_vpshldv_v8di_maskz", IX86_BUILTIN_VPSHLDVV8DI_MASKZ, UNKNOWN, (int) V8DI_FTYPE_V8DI_V8DI_V8DI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4di, "__builtin_ia32_vpshldv_v4di", IX86_BUILTIN_VPSHLDVV4DI, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4di_mask, "__builtin_ia32_vpshldv_v4di_mask", IX86_BUILTIN_VPSHLDVV4DI_MASK, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4di_maskz, "__builtin_ia32_vpshldv_v4di_maskz", IX86_BUILTIN_VPSHLDVV4DI_MASKZ, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4di_mask, "__builtin_ia32_vpshldv_v4di_mask", IX86_BUILTIN_VPSHLDVV4DI_MASK, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v4di_maskz, "__builtin_ia32_vpshldv_v4di_maskz", IX86_BUILTIN_VPSHLDVV4DI_MASKZ, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_V4DI_UQI) BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v2di, "__builtin_ia32_vpshldv_v2di", IX86_BUILTIN_VPSHLDVV2DI, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v2di_mask, "__builtin_ia32_vpshldv_v2di_mask", IX86_BUILTIN_VPSHLDVV2DI_MASK, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_INT) -BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v2di_maskz, "__builtin_ia32_vpshldv_v2di_maskz", IX86_BUILTIN_VPSHLDVV2DI_MASKZ, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_INT) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v2di_mask, "__builtin_ia32_vpshldv_v2di_mask", IX86_BUILTIN_VPSHLDVV2DI_MASK, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpshldv_v2di_maskz, "__builtin_ia32_vpshldv_v2di_maskz", IX86_BUILTIN_VPSHLDVV2DI_MASKZ, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI_UQI) /* GFNI */ BDESC (OPTION_MASK_ISA_GFNI | OPTION_MASK_ISA_AVX512F, 0, CODE_FOR_vgf2p8affineinvqb_v64qi, "__builtin_ia32_vgf2p8affineinvqb_v64qi", IX86_BUILTIN_VGF2P8AFFINEINVQB512, UNKNOWN, (int) V64QI_FTYPE_V64QI_V64QI_INT) @@ -2606,44 +2606,44 @@ BDESC (OPTION_MASK_ISA_GFNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vgf2p8mulb_v /* VNNI */ BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si, "__builtin_ia32_vpdpbusd_v16si", IX86_BUILTIN_VPDPBUSDV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si_mask, "__builtin_ia32_vpdpbusd_v16si_mask", IX86_BUILTIN_VPDPBUSDV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si_maskz, "__builtin_ia32_vpdpbusd_v16si_maskz", IX86_BUILTIN_VPDPBUSDV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si_mask, "__builtin_ia32_vpdpbusd_v16si_mask", IX86_BUILTIN_VPDPBUSDV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusd_v16si_maskz, "__builtin_ia32_vpdpbusd_v16si_maskz", IX86_BUILTIN_VPDPBUSDV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si, "__builtin_ia32_vpdpbusd_v8si", IX86_BUILTIN_VPDPBUSDV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si_mask, "__builtin_ia32_vpdpbusd_v8si_mask", IX86_BUILTIN_VPDPBUSDV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si_maskz, "__builtin_ia32_vpdpbusd_v8si_maskz", IX86_BUILTIN_VPDPBUSDV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si_mask, "__builtin_ia32_vpdpbusd_v8si_mask", IX86_BUILTIN_VPDPBUSDV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v8si_maskz, "__builtin_ia32_vpdpbusd_v8si_maskz", IX86_BUILTIN_VPDPBUSDV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si, "__builtin_ia32_vpdpbusd_v4si", IX86_BUILTIN_VPDPBUSDV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si_mask, "__builtin_ia32_vpdpbusd_v4si_mask", IX86_BUILTIN_VPDPBUSDV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si_maskz, "__builtin_ia32_vpdpbusd_v4si_maskz", IX86_BUILTIN_VPDPBUSDV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si_mask, "__builtin_ia32_vpdpbusd_v4si_mask", IX86_BUILTIN_VPDPBUSDV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusd_v4si_maskz, "__builtin_ia32_vpdpbusd_v4si_maskz", IX86_BUILTIN_VPDPBUSDV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si, "__builtin_ia32_vpdpbusds_v16si", IX86_BUILTIN_VPDPBUSDSV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si_mask, "__builtin_ia32_vpdpbusds_v16si_mask", IX86_BUILTIN_VPDPBUSDSV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si_maskz, "__builtin_ia32_vpdpbusds_v16si_maskz", IX86_BUILTIN_VPDPBUSDSV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si_mask, "__builtin_ia32_vpdpbusds_v16si_mask", IX86_BUILTIN_VPDPBUSDSV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpbusds_v16si_maskz, "__builtin_ia32_vpdpbusds_v16si_maskz", IX86_BUILTIN_VPDPBUSDSV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si, "__builtin_ia32_vpdpbusds_v8si", IX86_BUILTIN_VPDPBUSDSV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si_mask, "__builtin_ia32_vpdpbusds_v8si_mask", IX86_BUILTIN_VPDPBUSDSV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si_maskz, "__builtin_ia32_vpdpbusds_v8si_maskz", IX86_BUILTIN_VPDPBUSDSV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si_mask, "__builtin_ia32_vpdpbusds_v8si_mask", IX86_BUILTIN_VPDPBUSDSV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v8si_maskz, "__builtin_ia32_vpdpbusds_v8si_maskz", IX86_BUILTIN_VPDPBUSDSV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si, "__builtin_ia32_vpdpbusds_v4si", IX86_BUILTIN_VPDPBUSDSV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si_mask, "__builtin_ia32_vpdpbusds_v4si_mask", IX86_BUILTIN_VPDPBUSDSV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si_maskz, "__builtin_ia32_vpdpbusds_v4si_maskz", IX86_BUILTIN_VPDPBUSDSV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si_mask, "__builtin_ia32_vpdpbusds_v4si_mask", IX86_BUILTIN_VPDPBUSDSV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpbusds_v4si_maskz, "__builtin_ia32_vpdpbusds_v4si_maskz", IX86_BUILTIN_VPDPBUSDSV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si, "__builtin_ia32_vpdpwssd_v16si", IX86_BUILTIN_VPDPWSSDV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si_mask, "__builtin_ia32_vpdpwssd_v16si_mask", IX86_BUILTIN_VPDPWSSDV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si_maskz, "__builtin_ia32_vpdpwssd_v16si_maskz", IX86_BUILTIN_VPDPWSSDV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si_mask, "__builtin_ia32_vpdpwssd_v16si_mask", IX86_BUILTIN_VPDPWSSDV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssd_v16si_maskz, "__builtin_ia32_vpdpwssd_v16si_maskz", IX86_BUILTIN_VPDPWSSDV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si, "__builtin_ia32_vpdpwssd_v8si", IX86_BUILTIN_VPDPWSSDV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si_mask, "__builtin_ia32_vpdpwssd_v8si_mask", IX86_BUILTIN_VPDPWSSDV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si_maskz, "__builtin_ia32_vpdpwssd_v8si_maskz", IX86_BUILTIN_VPDPWSSDV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si_mask, "__builtin_ia32_vpdpwssd_v8si_mask", IX86_BUILTIN_VPDPWSSDV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v8si_maskz, "__builtin_ia32_vpdpwssd_v8si_maskz", IX86_BUILTIN_VPDPWSSDV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si, "__builtin_ia32_vpdpwssd_v4si", IX86_BUILTIN_VPDPWSSDV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si_mask, "__builtin_ia32_vpdpwssd_v4si_mask", IX86_BUILTIN_VPDPWSSDV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si_maskz, "__builtin_ia32_vpdpwssd_v4si_maskz", IX86_BUILTIN_VPDPWSSDV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si_mask, "__builtin_ia32_vpdpwssd_v4si_mask", IX86_BUILTIN_VPDPWSSDV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssd_v4si_maskz, "__builtin_ia32_vpdpwssd_v4si_maskz", IX86_BUILTIN_VPDPWSSDV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si, "__builtin_ia32_vpdpwssds_v16si", IX86_BUILTIN_VPDPWSSDSV16SI, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si_mask, "__builtin_ia32_vpdpwssds_v16si_mask", IX86_BUILTIN_VPDPWSSDSV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si_maskz, "__builtin_ia32_vpdpwssds_v16si_maskz", IX86_BUILTIN_VPDPWSSDSV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si_mask, "__builtin_ia32_vpdpwssds_v16si_mask", IX86_BUILTIN_VPDPWSSDSV16SI_MASK, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) +BDESC (OPTION_MASK_ISA_AVX512VNNI, 0, CODE_FOR_vpdpwssds_v16si_maskz, "__builtin_ia32_vpdpwssds_v16si_maskz", IX86_BUILTIN_VPDPWSSDSV16SI_MASKZ, UNKNOWN, (int) V16SI_FTYPE_V16SI_V16SI_V16SI_UHI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si, "__builtin_ia32_vpdpwssds_v8si", IX86_BUILTIN_VPDPWSSDSV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si_mask, "__builtin_ia32_vpdpwssds_v8si_mask", IX86_BUILTIN_VPDPWSSDSV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si_maskz, "__builtin_ia32_vpdpwssds_v8si_maskz", IX86_BUILTIN_VPDPWSSDSV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si_mask, "__builtin_ia32_vpdpwssds_v8si_mask", IX86_BUILTIN_VPDPWSSDSV8SI_MASK, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v8si_maskz, "__builtin_ia32_vpdpwssds_v8si_maskz", IX86_BUILTIN_VPDPWSSDSV8SI_MASKZ, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_V8SI_UQI) BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si, "__builtin_ia32_vpdpwssds_v4si", IX86_BUILTIN_VPDPWSSDSV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si_mask, "__builtin_ia32_vpdpwssds_v4si_mask", IX86_BUILTIN_VPDPWSSDSV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) -BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si_maskz, "__builtin_ia32_vpdpwssds_v4si_maskz", IX86_BUILTIN_VPDPWSSDSV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_INT) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si_mask, "__builtin_ia32_vpdpwssds_v4si_mask", IX86_BUILTIN_VPDPWSSDSV4SI_MASK, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) +BDESC (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpdpwssds_v4si_maskz, "__builtin_ia32_vpdpwssds_v4si_maskz", IX86_BUILTIN_VPDPWSSDSV4SI_MASKZ, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI_UQI) /* VPCLMULQDQ */ BDESC (OPTION_MASK_ISA_VPCLMULQDQ | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_vpclmulqdq_v2di, "__builtin_ia32_vpclmulqdq_v2di", IX86_BUILTIN_VPCLMULQDQ2, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_INT) diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 5d3b74a..0519da8 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -9573,15 +9573,6 @@ ix86_expand_args_builtin (const struct builtin_description *d, case USI_FTYPE_V32HI_V32HI_INT_USI: case UHI_FTYPE_V16HI_V16HI_INT_UHI: case UQI_FTYPE_V8HI_V8HI_INT_UQI: - case V32HI_FTYPE_V32HI_V32HI_V32HI_INT: - case V16HI_FTYPE_V16HI_V16HI_V16HI_INT: - case V8HI_FTYPE_V8HI_V8HI_V8HI_INT: - case V8SI_FTYPE_V8SI_V8SI_V8SI_INT: - case V4DI_FTYPE_V4DI_V4DI_V4DI_INT: - case V8DI_FTYPE_V8DI_V8DI_V8DI_INT: - case V16SI_FTYPE_V16SI_V16SI_V16SI_INT: - case V2DI_FTYPE_V2DI_V2DI_V2DI_INT: - case V4SI_FTYPE_V4SI_V4SI_V4SI_INT: nargs = 4; mask_pos = 1; nargs_constant = 1; -- cgit v1.1 From 946732df902dbb23dd44abe97fea41e154e6e5f9 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 11 Jul 2019 10:31:51 +0200 Subject: re PR target/91124 (gcc.target/i386/avx512vl-vpshldvd-2.c etc. FAIL) PR target/91124 * config/i386/sse.md (sse2_cvtpd2dq): Change into ... (sse2_cvtpd2dq): ... this. Remove mask substitution macros. (sse2_cvtpd2dq_mask, sse2_cvtpd2dq_mask_1): New define_insns. (ufix_notruncv2dfv2si2): Change into ... (ufix_notruncv2dfv2si2): ... this. Remove mask substitution macros. (ufix_notruncv2dfv2si2_mask, ufix_notruncv2dfv2si2_mask_1): New define_insns. (ufix_truncv2dfv2si2): Change into ... (ufix_truncv2dfv2si2): ... this. Remove mask substitution macros. (ufix_truncv2dfv2si2_mask, ufix_truncv2dfv2si2_mask_1): New define_insns. (sse2_cvttpd2dq): Change into ... (sse2_cvttpd2dq): ... this. Remove mask substitution macros. (sse2_cvttpd2dq_mask, sse2_cvttpd2dq_mask_1): New define_insns. (*sse2_cvtpd2dq): Change into ... (*sse2_cvtpd2dq): ... this. Remove mask substitution macros. Add "C" constraint to const0_operand. (*sse2_cvtpd2dq_mask, *sse2_cvtpd2dq_mask_1): New define_insns. (sse2_cvtpd2ps_mask): Adjust expand to match *sse2_cvtpd2ps_mask changes. From-SVN: r273409 --- gcc/ChangeLog | 22 ++++++ gcc/config/i386/sse.md | 200 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 202 insertions(+), 20 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a02213d..364466b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,28 @@ 2019-07-11 Jakub Jelinek PR target/91124 + * config/i386/sse.md (sse2_cvtpd2dq): Change into ... + (sse2_cvtpd2dq): ... this. Remove mask substitution macros. + (sse2_cvtpd2dq_mask, sse2_cvtpd2dq_mask_1): New define_insns. + (ufix_notruncv2dfv2si2): Change into ... + (ufix_notruncv2dfv2si2): ... this. Remove mask substitution macros. + (ufix_notruncv2dfv2si2_mask, ufix_notruncv2dfv2si2_mask_1): New + define_insns. + (ufix_truncv2dfv2si2): Change into ... + (ufix_truncv2dfv2si2): ... this. Remove mask substitution macros. + (ufix_truncv2dfv2si2_mask, ufix_truncv2dfv2si2_mask_1): New + define_insns. + (sse2_cvttpd2dq): Change into ... + (sse2_cvttpd2dq): ... this. Remove mask substitution macros. + (sse2_cvttpd2dq_mask, sse2_cvttpd2dq_mask_1): New define_insns. + (*sse2_cvtpd2dq): Change into ... + (*sse2_cvtpd2dq): ... this. Remove mask substitution macros. + Add "C" constraint to const0_operand. + (*sse2_cvtpd2dq_mask, *sse2_cvtpd2dq_mask_1): New define_insns. + (sse2_cvtpd2ps_mask): Adjust expand to match *sse2_cvtpd2ps_mask + changes. + + PR target/91124 * config/i386/i386-builtin-types.def (V32HI_FTYPE_V32HI_V32HI_V32HI_INT, V16HI_FTYPE_V16HI_V16HI_V16HI_INT, V8HI_FTYPE_V8HI_V8HI_V8HI_INT, diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 3ce2239..12d6dc0 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -5927,16 +5927,16 @@ (set_attr "btver2_decode" "vector") (set_attr "mode" "OI")]) -(define_insn "sse2_cvtpd2dq" +(define_insn "sse2_cvtpd2dq" [(set (match_operand:V4SI 0 "register_operand" "=v") (vec_concat:V4SI (unspec:V2SI [(match_operand:V2DF 1 "vector_operand" "vBm")] UNSPEC_FIX_NOTRUNC) (const_vector:V2SI [(const_int 0) (const_int 0)])))] - "TARGET_SSE2 && " + "TARGET_SSE2" { if (TARGET_AVX) - return "vcvtpd2dq{x}\t{%1, %0|%0, %1}"; + return "vcvtpd2dq{x}\t{%1, %0|%0, %1}"; else return "cvtpd2dq\t{%1, %0|%0, %1}"; } @@ -5949,6 +5949,38 @@ (set_attr "athlon_decode" "vector") (set_attr "bdver1_decode" "double")]) +(define_insn "sse2_cvtpd2dq_mask" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "vm")] + UNSPEC_FIX_NOTRUNC) + (vec_select:V2SI + (match_operand:V4SI 2 "nonimm_or_0_operand" "0C") + (parallel [(const_int 0) (const_int 1)])) + (match_operand:QI 3 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvtpd2dq{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +(define_insn "*sse2_cvtpd2dq_mask_1" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "vm")] + UNSPEC_FIX_NOTRUNC) + (const_vector:V2SI [(const_int 0) (const_int 0)]) + (match_operand:QI 2 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvtpd2dq{x}\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + ;; For ufix_notrunc* insn patterns (define_mode_attr pd2udqsuff [(V8DF "") (V4DF "{y}")]) @@ -5964,15 +5996,49 @@ (set_attr "prefix" "evex") (set_attr "mode" "")]) -(define_insn "ufix_notruncv2dfv2si2" +(define_insn "ufix_notruncv2dfv2si2" [(set (match_operand:V4SI 0 "register_operand" "=v") (vec_concat:V4SI (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "vm")] - UNSPEC_UNSIGNED_FIX_NOTRUNC) + UNSPEC_UNSIGNED_FIX_NOTRUNC) (const_vector:V2SI [(const_int 0) (const_int 0)])))] "TARGET_AVX512VL" - "vcvtpd2udq{x}\t{%1, %0|%0, %1}" + "vcvtpd2udq{x}\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +(define_insn "ufix_notruncv2dfv2si2_mask" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (unspec:V2SI + [(match_operand:V2DF 1 "nonimmediate_operand" "vm")] + UNSPEC_UNSIGNED_FIX_NOTRUNC) + (vec_select:V2SI + (match_operand:V4SI 2 "nonimm_or_0_operand" "0C") + (parallel [(const_int 0) (const_int 1)])) + (match_operand:QI 3 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvtpd2udq{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +(define_insn "*ufix_notruncv2dfv2si2_mask_1" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (unspec:V2SI + [(match_operand:V2DF 1 "nonimmediate_operand" "vm")] + UNSPEC_UNSIGNED_FIX_NOTRUNC) + (const_vector:V2SI [(const_int 0) (const_int 0)]) + (match_operand:QI 2 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvtpd2udq{x}\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}" [(set_attr "type" "ssecvt") (set_attr "prefix" "evex") (set_attr "mode" "TI")]) @@ -5987,13 +6053,43 @@ (set_attr "prefix" "evex") (set_attr "mode" "OI")]) -(define_insn "ufix_truncv2dfv2si2" +(define_insn "ufix_truncv2dfv2si2" [(set (match_operand:V4SI 0 "register_operand" "=v") (vec_concat:V4SI (unsigned_fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "vm")) (const_vector:V2SI [(const_int 0) (const_int 0)])))] "TARGET_AVX512VL" - "vcvttpd2udq{x}\t{%1, %0|%0, %1}" + "vcvttpd2udq{x}\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +(define_insn "ufix_truncv2dfv2si2_mask" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (unsigned_fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "vm")) + (vec_select:V2SI + (match_operand:V4SI 2 "nonimm_or_0_operand" "0C") + (parallel [(const_int 0) (const_int 1)])) + (match_operand:QI 3 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvttpd2udq{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +(define_insn "*ufix_truncv2dfv2si2_mask_1" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (unsigned_fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "vm")) + (const_vector:V2SI [(const_int 0) (const_int 0)]) + (match_operand:QI 2 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvttpd2udq{x}\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}" [(set_attr "type" "ssecvt") (set_attr "prefix" "evex") (set_attr "mode" "TI")]) @@ -6138,15 +6234,15 @@ "TARGET_AVX" "operands[2] = CONST0_RTX (V4SImode);") -(define_insn "sse2_cvttpd2dq" +(define_insn "sse2_cvttpd2dq" [(set (match_operand:V4SI 0 "register_operand" "=v") (vec_concat:V4SI (fix:V2SI (match_operand:V2DF 1 "vector_operand" "vBm")) (const_vector:V2SI [(const_int 0) (const_int 0)])))] - "TARGET_SSE2 && " + "TARGET_SSE2" { if (TARGET_AVX) - return "vcvttpd2dq{x}\t{%1, %0|%0, %1}"; + return "vcvttpd2dq{x}\t{%1, %0|%0, %1}"; else return "cvttpd2dq\t{%1, %0|%0, %1}"; } @@ -6157,6 +6253,36 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) +(define_insn "sse2_cvttpd2dq_mask" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "vm")) + (vec_select:V2SI + (match_operand:V4SI 2 "nonimm_or_0_operand" "0C") + (parallel [(const_int 0) (const_int 1)])) + (match_operand:QI 3 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvttpd2dq{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +(define_insn "*sse2_cvttpd2dq_mask_1" + [(set (match_operand:V4SI 0 "register_operand" "=v") + (vec_concat:V4SI + (vec_merge:V2SI + (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "vm")) + (const_vector:V2SI [(const_int 0) (const_int 0)]) + (match_operand:QI 2 "register_operand" "Yk")) + (const_vector:V2SI [(const_int 0) (const_int 0)])))] + "TARGET_AVX512VL" + "vcvttpd2dq{x}\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + (define_insn "sse2_cvtsd2ss" [(set (match_operand:V4SF 0 "register_operand" "=x,x,v") (vec_merge:V4SF @@ -6276,26 +6402,28 @@ (define_expand "sse2_cvtpd2ps_mask" [(set (match_operand:V4SF 0 "register_operand") - (vec_merge:V4SF - (vec_concat:V4SF + (vec_concat:V4SF + (vec_merge:V2SF (float_truncate:V2SF (match_operand:V2DF 1 "vector_operand")) - (match_dup 4)) - (match_operand:V4SF 2 "register_operand") - (match_operand:QI 3 "register_operand")))] + (vec_select:V2SF + (match_operand:V4SF 2 "nonimm_or_0_operand") + (parallel [(const_int 0) (const_int 1)])) + (match_operand:QI 3 "register_operand")) + (match_dup 4)))] "TARGET_SSE2" "operands[4] = CONST0_RTX (V2SFmode);") -(define_insn "*sse2_cvtpd2ps" +(define_insn "*sse2_cvtpd2ps" [(set (match_operand:V4SF 0 "register_operand" "=v") (vec_concat:V4SF (float_truncate:V2SF (match_operand:V2DF 1 "vector_operand" "vBm")) - (match_operand:V2SF 2 "const0_operand")))] - "TARGET_SSE2 && " + (match_operand:V2SF 2 "const0_operand" "C")))] + "TARGET_SSE2" { if (TARGET_AVX) - return "vcvtpd2ps{x}\t{%1, %0|%0, %1}"; + return "vcvtpd2ps{x}\t{%1, %0|%0, %1}"; else return "cvtpd2ps\t{%1, %0|%0, %1}"; } @@ -6307,6 +6435,38 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "V4SF")]) +(define_insn "*sse2_cvtpd2ps_mask" + [(set (match_operand:V4SF 0 "register_operand" "=v") + (vec_concat:V4SF + (vec_merge:V2SF + (float_truncate:V2SF + (match_operand:V2DF 1 "nonimmediate_operand" "vm")) + (vec_select:V2SF + (match_operand:V4SF 2 "nonimm_or_0_operand" "0C") + (parallel [(const_int 0) (const_int 1)])) + (match_operand:QI 3 "register_operand" "Yk")) + (match_operand:V2SF 4 "const0_operand" "C")))] + "TARGET_AVX512VL" + "vcvtpd2ps{x}\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V4SF")]) + +(define_insn "*sse2_cvtpd2ps_mask_1" + [(set (match_operand:V4SF 0 "register_operand" "=v") + (vec_concat:V4SF + (vec_merge:V2SF + (float_truncate:V2SF + (match_operand:V2DF 1 "nonimmediate_operand" "vm")) + (match_operand:V2SF 3 "const0_operand" "C") + (match_operand:QI 2 "register_operand" "Yk")) + (match_operand:V2SF 4 "const0_operand" "C")))] + "TARGET_AVX512VL" + "vcvtpd2ps{x}\t{%1, %0%{%2%}%{z%}|%0%{%2%}%{z%}, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V4SF")]) + ;; For _cvtps2pd insn pattern (define_mode_attr sf2dfmode [(V8DF "V8SF") (V4DF "V4SF")]) -- cgit v1.1 From e617512f4af4e8f3342e3ba944fae093eaa9c4da Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Thu, 11 Jul 2019 20:36:48 +0200 Subject: rs6000: Handle Modula-2 in the traceback table This patch recognises Modula-2 as language for the traceback table, fixing the problem shown in https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00848.html . * config/rs6000/rs6000-logue.c (rs6000_output_function_epilogue): Handle Modula-2. From-SVN: r273411 --- gcc/ChangeLog | 5 +++++ gcc/config/rs6000/rs6000-logue.c | 2 ++ 2 files changed, 7 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 364466b..891ac3f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-11 Segher Boessenkool + + * config/rs6000/rs6000-logue.c (rs6000_output_function_epilogue): + Handle Modula-2. + 2019-07-11 Jakub Jelinek PR target/91124 diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index acc11df..c1948e3 100644 --- a/gcc/config/rs6000/rs6000-logue.c +++ b/gcc/config/rs6000/rs6000-logue.c @@ -5252,6 +5252,8 @@ rs6000_output_function_epilogue (FILE *file) i = 1; else if (! strcmp (language_string, "GNU Ada")) i = 3; + else if (! strcmp (language_string, "GNU Modula-2")) + i = 8; else if (lang_GNU_CXX () || ! strcmp (language_string, "GNU Objective-C++")) i = 9; -- cgit v1.1 From 998175f6465a95fe812c0bc793600115393bb315 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Thu, 11 Jul 2019 20:51:23 +0200 Subject: rs6000: Adjust comment for the Modula-2 traceback lang * config/rs6000/rs6000-logue.c: Add Modula-2 to comment. From-SVN: r273413 --- gcc/ChangeLog | 4 ++++ gcc/config/rs6000/rs6000-logue.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 891ac3f..aa9e05c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2019-07-11 Segher Boessenkool + * config/rs6000/rs6000-logue.c: Add Modula-2 to comment. + +2019-07-11 Segher Boessenkool + * config/rs6000/rs6000-logue.c (rs6000_output_function_epilogue): Handle Modula-2. diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c index c1948e3..ebfe533 100644 --- a/gcc/config/rs6000/rs6000-logue.c +++ b/gcc/config/rs6000/rs6000-logue.c @@ -5237,7 +5237,7 @@ rs6000_output_function_epilogue (FILE *file) /* Language type. Unfortunately, there does not seem to be any official way to discover the language being compiled, so we use language_string. - C is 0. Fortran is 1. Ada is 3. C++ is 9. + C is 0. Fortran is 1. Ada is 3. Modula-2 is 8. C++ is 9. Java is 13. Objective-C is 14. Objective-C++ isn't assigned a number, so for now use 9. LTO, Go, D, and JIT aren't assigned numbers either, so for now use 0. */ -- cgit v1.1 From 4c98bdadcb67e12c63882587d96ab6335711f009 Mon Sep 17 00:00:00 2001 From: Sunil K Pandey Date: Thu, 11 Jul 2019 19:09:37 +0000 Subject: i386: Add AVX512 unaligned intrinsics __m512i _mm512_loadu_epi64( void * sa); void _mm512_storeu_epi64(void * d, __m512i a); __m512i _mm512_loadu_epi32( void * sa); void _mm512_storeu_epi32(void * d, __m512i a); void _mm256_storeu_epi64(void * d, __m256i a); void _mm_storeu_epi64(void * d, __m128i a); void _mm256_storeu_epi32(void * d, __m256i a); void _mm_storeu_epi32(void * d, __m128i a); Tested on x86-64. 2019-07-11 Sunil K Pandey gcc/ PR target/90980 * config/i386/avx512fintrin.h (_mm512_loadu_epi64): New. (_mm512_storeu_epi64): Likewise. (_mm512_loadu_epi32): Likewise. (_mm512_storeu_epi32): Likewise. * config/i386/avx512vlintrin.h (_mm256_storeu_epi64): New. (_mm_storeu_epi64): Likewise. (_mm256_storeu_epi32): Likewise. (_mm_storeu_epi32): Likewise. gcc/testsuite/ PR target/90980 * gcc.target/i386/pr90980-1.c: New test. * gcc.target/i386/pr90980-2.c: Likewise. * gcc.target/i386/pr90980-3.c: Likewise. From-SVN: r273416 --- gcc/ChangeLog | 12 ++++++++++++ gcc/config/i386/avx512fintrin.h | 28 ++++++++++++++++++++++++++++ gcc/config/i386/avx512vlintrin.h | 28 ++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/gcc.target/i386/pr90980-1.c | 17 +++++++++++++++++ gcc/testsuite/gcc.target/i386/pr90980-2.c | 17 +++++++++++++++++ gcc/testsuite/gcc.target/i386/pr90980-3.c | 20 ++++++++++++++++++++ 7 files changed, 129 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr90980-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr90980-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr90980-3.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa9e05c..235cc53 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2019-07-11 Sunil K Pandey + + PR target/90980 + * config/i386/avx512fintrin.h (_mm512_loadu_epi64): New. + (_mm512_storeu_epi64): Likewise. + (_mm512_loadu_epi32): Likewise. + (_mm512_storeu_epi32): Likewise. + * config/i386/avx512vlintrin.h (_mm256_storeu_epi64): New. + (_mm_storeu_epi64): Likewise. + (_mm256_storeu_epi32): Likewise. + (_mm_storeu_epi32): Likewise. + 2019-07-11 Segher Boessenkool * config/rs6000/rs6000-logue.c: Add Modula-2 to comment. diff --git a/gcc/config/i386/avx512fintrin.h b/gcc/config/i386/avx512fintrin.h index e35eedb..454fd3d 100644 --- a/gcc/config/i386/avx512fintrin.h +++ b/gcc/config/i386/avx512fintrin.h @@ -6352,6 +6352,13 @@ _mm_mask_store_sd (double *__P, __mmask8 __U, __m128d __A) extern __inline __m512i __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_epi64 (void const *__P) +{ + return *(__m512i_u *) __P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm512_mask_loadu_epi64 (__m512i __W, __mmask8 __U, void const *__P) { return (__m512i) __builtin_ia32_loaddqudi512_mask ((const long long *) __P, @@ -6371,6 +6378,13 @@ _mm512_maskz_loadu_epi64 (__mmask8 __U, void const *__P) extern __inline void __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_epi64 (void *__P, __m512i __A) +{ + *(__m512i_u *) __P = (__m512i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm512_mask_storeu_epi64 (void *__P, __mmask8 __U, __m512i __A) { __builtin_ia32_storedqudi512_mask ((long long *) __P, (__v8di) __A, @@ -6386,6 +6400,13 @@ _mm512_loadu_si512 (void const *__P) extern __inline __m512i __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_loadu_epi32 (void const *__P) +{ + return *(__m512i_u *) __P; +} + +extern __inline __m512i +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm512_mask_loadu_epi32 (__m512i __W, __mmask16 __U, void const *__P) { return (__m512i) __builtin_ia32_loaddqusi512_mask ((const int *) __P, @@ -6412,6 +6433,13 @@ _mm512_storeu_si512 (void *__P, __m512i __A) extern __inline void __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_storeu_epi32 (void *__P, __m512i __A) +{ + *(__m512i_u *) __P = (__m512i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm512_mask_storeu_epi32 (void *__P, __mmask16 __U, __m512i __A) { __builtin_ia32_storedqusi512_mask ((int *) __P, (__v16si) __A, diff --git a/gcc/config/i386/avx512vlintrin.h b/gcc/config/i386/avx512vlintrin.h index 3eaf817..bd8746d 100644 --- a/gcc/config/i386/avx512vlintrin.h +++ b/gcc/config/i386/avx512vlintrin.h @@ -757,6 +757,13 @@ _mm_maskz_loadu_epi64 (__mmask8 __U, void const *__P) extern __inline void __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_epi64 (void *__P, __m256i __A) +{ + *(__m256i_u *) __P = (__m256i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_storedqudi256_mask ((long long *) __P, @@ -766,6 +773,13 @@ _mm256_mask_storeu_epi64 (void *__P, __mmask8 __U, __m256i __A) extern __inline void __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_epi64 (void *__P, __m128i __A) +{ + *(__m128i_u *) __P = (__m128i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm_mask_storeu_epi64 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_storedqudi128_mask ((long long *) __P, @@ -813,6 +827,13 @@ _mm_maskz_loadu_epi32 (__mmask8 __U, void const *__P) extern __inline void __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_storeu_epi32 (void *__P, __m256i __A) +{ + *(__m256i_u *) __P = (__m256i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A) { __builtin_ia32_storedqusi256_mask ((int *) __P, @@ -822,6 +843,13 @@ _mm256_mask_storeu_epi32 (void *__P, __mmask8 __U, __m256i __A) extern __inline void __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_storeu_epi32 (void *__P, __m128i __A) +{ + *(__m128i_u *) __P = (__m128i_u) __A; +} + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm_mask_storeu_epi32 (void *__P, __mmask8 __U, __m128i __A) { __builtin_ia32_storedqusi128_mask ((int *) __P, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f4a6d05..cfc96b0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-07-11 Sunil K Pandey + + PR target/90980 + * gcc.target/i386/pr90980-1.c: New test. + * gcc.target/i386/pr90980-2.c: Likewise. + * gcc.target/i386/pr90980-3.c: Likewise. + 2019-07-11 Yannick Moy * gnat.dg/loop_entry1.adb: New testcase. diff --git a/gcc/testsuite/gcc.target/i386/pr90980-1.c b/gcc/testsuite/gcc.target/i386/pr90980-1.c new file mode 100644 index 0000000..72a30dc --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr90980-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=skylake-avx512 -O2" } */ +/* { dg-final { scan-assembler-times "(?:vmovups|vmovdqu)\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*\\)(?:\n|\[ \\t\]+#)" 2 } } */ + +#include + +int *a; +long long *b; +volatile __m128i xx; +volatile __m128i xx1; + +void extern +avx512vl_test (void) +{ + _mm_storeu_epi32 (a, xx); + _mm_storeu_epi64 (b, xx1); +} diff --git a/gcc/testsuite/gcc.target/i386/pr90980-2.c b/gcc/testsuite/gcc.target/i386/pr90980-2.c new file mode 100644 index 0000000..b1980e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr90980-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=skylake-avx512 -O2" } */ +/* { dg-final { scan-assembler-times "vmovdqu\[0-9\]*\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*\\)(?:\n|\[ \\t\]+#)" 2 } } */ + +#include + +int *a; +long long *b; +volatile __m256i yy; +volatile __m256i yy1; + +void extern +avx512vl_test (void) +{ + _mm256_storeu_epi32 (a, yy); + _mm256_storeu_epi64 (b, yy1); +} diff --git a/gcc/testsuite/gcc.target/i386/pr90980-3.c b/gcc/testsuite/gcc.target/i386/pr90980-3.c new file mode 100644 index 0000000..d839ee0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr90980-3.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-march=skylake-avx512 -O2" } */ +/* { dg-final { scan-assembler-times "vmovdqu64\[ \\t\]+\[^\{\n\]*\\)\[^\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */ +/* { dg-final { scan-assembler-times "vmovdqu64\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*\\)(?:\n|\[ \\t\]+#)" 2 } } */ + +#include + +int *a; +long long *b; +volatile __m512i zz; +volatile __m512i zz1; + +void extern +avx512f_test (void) +{ + zz = _mm512_loadu_epi32 (a); + _mm512_storeu_epi32 (a, zz); + zz1 = _mm512_loadu_epi64 (b); + _mm512_storeu_epi64 (b, zz1); +} -- cgit v1.1 From bee60edc26944d6993b3bfdca3a811d7a8c04e0f Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 11 Jul 2019 23:01:25 +0200 Subject: ChangeLog: Fix whitespace. * ChangeLog: Fix whitespace. * testsuite/ChangeLog: Ditto. From-SVN: r273424 --- gcc/ChangeLog | 307 ++++++++++++++++++++++++------------------------ gcc/testsuite/ChangeLog | 248 +++++++++++++++++++------------------- 2 files changed, 276 insertions(+), 279 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 235cc53..3d92250 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1699,7 +1699,8 @@ * gimple-match.h (gimple_match_cond::any_else): Same. * gimple-ssa-backprop.c: Same. * gimple-ssa-sprintf.c: Same. - * gimple-ssa-store-merging.c (store_operand_info::store_operand_info): Same. + * gimple-ssa-store-merging.c (store_operand_info::store_operand_info): + Same. (store_immediate_info::store_immediate_info): Same. (merged_store_group::apply_stores): Same. (get_location_for_stmts): Same. @@ -1816,7 +1817,7 @@ Make static. (gimple_match_op::resimplify): New. * tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Valueize - according to availability. Use gimple_match_op::resimplify. + according to availability. Use gimple_match_op::resimplify. 2019-07-09 Eric Botcazou @@ -2206,8 +2207,8 @@ 2019-07-04 Martin Liska - * tree-ssa-loop-niter.c (get_upper_bound_based_on_builtin_expr_with_prob): - New function. + * tree-ssa-loop-niter.c + (get_upper_bound_based_on_builtin_expr_with_prob): New function. (estimate_numbers_of_iterations): Support __builtin_expect_with_probability for analysis of # of loop iterations. @@ -2861,7 +2862,7 @@ 2019-07-01 Vladislav Ivanishin - * gdbhooks.py (GdbPrettyPrinters.add_printer_for_types): Reorder + * gdbhooks.py (GdbPrettyPrinters.add_printer_for_types): Reorder parameter names to match usage (no functional change). (GdbPrettyPrinters.add_printer_for_regex): Ditto. @@ -3048,7 +3049,7 @@ * config/arc/arc.h: Change movmem to cpymem in comment. * config/arc/arc.md (movmemsi): Change movmem to cpymem. * config/arm/arm-protos.h: Change movmem to cpymem in names. - * config/arm/arm.c (arm_movmemqi_unaligned, arm_gen_movmemqi, + * config/arm/arm.c (arm_movmemqi_unaligned, arm_gen_movmemqi, gen_movmem_ldrd_strd, thumb_expand_movmemqi) Change movmem to cpymem. * config/arm/arm.md (movmemqi): Change movmem to cpymem. * config/arm/thumb1.md (movmem12b, movmem8b): Change movmem to cpymem. @@ -3073,7 +3074,7 @@ expand_setmem_epilogue_via_loop, expand_set_or_cpymem_prologue, expand_small_cpymem_or_setmem, expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves, - expand_set_or_cpymem_constant_prologue, + expand_set_or_cpymem_constant_prologue, ix86_expand_set_or_cpymem): Change movmem to cpymem. * config/i386/i386-protos.h: Change movmem to cpymem. * config/i386/i386.h: Change movmem to cpymem in comment. @@ -3104,9 +3105,9 @@ * config/pa/pa.c (compute_movmem_length): Change movmem to cpymem. (pa_adjust_insn_length): Change call to compute_movmem_length. * config/pa/pa.md (movmemsi, movmemsi_prereload, movmemsi_postreload, - movmemdi, movmemdi_prereload, + movmemdi, movmemdi_prereload, movmemdi_postreload): Change movmem to cpymem. - * config/pdp11/pdp11.md (movmemhi, movmemhi1, + * config/pdp11/pdp11.md (movmemhi, movmemhi1, movmemhi_nocc, UNSPEC_MOVMEM): Change movmem to cpymem. * config/riscv/riscv.c: Change movmem to cpymem in comment. * config/riscv/riscv.h: Change movmem to cpymem. @@ -3131,7 +3132,7 @@ * doc/md.texi: Change movmem to cpymem and update description to match. * doc/rtl.texi: Change movmem to cpymem. * target.def (use_by_pieces_infrastructure_p): Change movmem to cpymem. - * doc/tm.texi: Regenerate. + * doc/tm.texi: Regenerate. 2019-06-27 Bill Schmidt @@ -3210,7 +3211,8 @@ * dojump.c (do_jump_by_parts_greater_rtx): Likewise. * early-remat.c (early_remat::record_equiv_candidates): Likewise. * emit-rtl.c (try_split): Likewise. - * graphite-scop-detection.c (assign_parameter_index_in_region): Likewise. + * graphite-scop-detection.c (assign_parameter_index_in_region): + Likewise. * ipa-cp.c (cgraph_edge_brings_all_agg_vals_for_node): Likewise. * ira-color.c (setup_profitable_hard_regs): Likewise. * ira.c (rtx_moveable_p): Likewise. @@ -3367,13 +3369,6 @@ * bb-reorder.c (connect_better_edge_p): Add missing else statement in the middle of if-else statements. -/home/marxin/Programming/gcc/gcc/bb-reorder.c:1031:2: warning: Value stored to 'is_better_edge' is never read - is_better_edge = true; - ^ ~~~~ -/home/marxin/Programming/gcc/gcc/bb-reorder.c:1034:2: warning: Value stored to 'is_better_edge' is never read - is_better_edge = false; - ^ ~~~~~ - 2019-06-25 Hongtao Liu H.J. Lu Olga Makhotina @@ -3523,7 +3518,7 @@ (df_update_exit_block_uses): Likewise. 2019-06-25 Kwok Cheung Yeung - Andrew Stubbs + Andrew Stubbs * config.gcc (thread_file): Set to gcn for AMD GCN. * config/gcn/gcn.c (gcn_emutls_var_init): New function. @@ -4013,7 +4008,7 @@ 2019-06-18 Iain Sandoe - * config/darwin.c: Strip trailing whitespace. + * config/darwin.c: Strip trailing whitespace. 2019-06-18 Iain Sandoe @@ -4545,10 +4540,10 @@ 2019-06-12 Przemyslaw Wirkus - * config/arm/iterators.md (VABAL): New int iterator. - * config/arm/neon.md (sadv16qi): New define_expand. - * config/arm/unspecs.md ("unspec"): Define UNSPEC_VABAL_S, UNSPEC_VABAL_U - values. + * config/arm/iterators.md (VABAL): New int iterator. + * config/arm/neon.md (sadv16qi): New define_expand. + * config/arm/unspecs.md ("unspec"): Define UNSPEC_VABAL_S, + UNSPEC_VABAL_U values. 2019-06-12 Martin Liska @@ -4797,8 +4792,7 @@ (gimple_stringops_transform): Likewise. (gimple_find_values_to_profile): Set number of counters for HIST_TYPE_SINGLE_VALUE. - * value-prof.h (get_most_common_single_value): - New. + * value-prof.h (get_most_common_single_value): New. 2019-06-10 Martin Liska @@ -4882,7 +4876,7 @@ (types_same_for_odr): Remove. (types_odr_comparable): Remove. (odr_vtable_hasher::equal): Remove. - (odr_vtable_hash_type, odr_vtable_hash): Remove. + (odr_vtable_hash_type, odr_vtable_hash): Remove. (add_type_duplicate): Do not synchronize vtable and name hashtables. (get_odr_type): Do not use vtable hash. (dump_odr_type): Remove commented out code. @@ -5593,7 +5587,8 @@ 2019-06-03 Kyrylo Tkachov * config/aarch64/iterators.md (MAX_OPP): New code attr. - * config/aarch64/aarch64-simd.md (*aarch64_abd_3): Rename to... + * config/aarch64/aarch64-simd.md (*aarch64_abd_3): + Rename to... (aarch64_abd_3): ... This. (sadv16qi): Add TARGET_DOTPROD expansion. @@ -5674,7 +5669,7 @@ NOTE_INSN_DELETED_LABEL check. 2019-05-31 Prachi Godbole - Robert Suchanek + Robert Suchanek * config/mips/mips.c (mips_expand_builtin_insn): Swap the 1st and 3rd operands of the fmadd/fmsub/maddv builtin. @@ -5840,7 +5835,7 @@ 2019-05-30 Sam Tebbs - * aarch64/aarch64.c (aarch64_post_cfi_startproc): Add + * aarch64/aarch64.c (aarch64_post_cfi_startproc): Add cfun->is_thunk check. 2019-05-30 Jakub Jelinek @@ -5969,8 +5964,9 @@ * config/aarch64/iterators.md (pauth_hint_num_a): Replace UNSPEC_PACI1716 and UNSPEC_AUTI1716 with UNSPEC_PACIA1716 and UNSPEC_AUTIA1716 respectively. - * config/aarch64/iterators.md (pauth_hint_num_a): Rename to pauth_hint_num - and add UNSPEC_PACIBSP, UNSPEC_AUTIBSP, UNSPEC_PACIB1716, UNSPEC_AUTIB1716. + * config/aarch64/iterators.md (pauth_hint_num_a): Rename to + pauth_hint_num and add UNSPEC_PACIBSP, UNSPEC_AUTIBSP, + UNSPEC_PACIB1716, UNSPEC_AUTIB1716. * doc/invoke.texi (-mbranch-protection): Add b-key type. * config/aarch64/aarch64-bti-insert.c (aarch64_pac_insn_p): Rename UNSPEC_PACISP to UNSPEC_PACIASP and UNSPEC_PACIBSP. @@ -6317,8 +6313,8 @@ 2019-05-23 Iain Sandoe - * config/i386/darwin.h: Reject -mfentry*. - * doc/sourcebuild.texi: Document mfentry target support. + * config/i386/darwin.h: Reject -mfentry*. + * doc/sourcebuild.texi: Document mfentry target support. 2019-05-23 Bill Schmidt @@ -6455,7 +6451,7 @@ decl. 2019-05-22 Kwok Cheung Yeung - Andrew Stubbs + Andrew Stubbs * config.gcc (gcc_cv_initfini_array): Set for AMD GCN. * config/gcn/gcn-run.c (init_array_kernel, fini_array_kernel): New. @@ -6733,8 +6729,6 @@ (altivec_expand_builtin): Likewise. (rs6000_get_function_versions_dispatcher): Quote target_clones. -Fix test-suite. - 2019-05-20 Jakub Jelinek PR c++/59813 @@ -7005,120 +6999,120 @@ Fix test-suite. 2019-05-16 Martin Sebor - * builtins.c (expand_builtin_atomic_always_lock_free): Quote - identifiers, keywords, operators, and types in diagnostics. Correct - quoting, spelling, and sentence capitalization issues. - (expand_builtin_atomic_is_lock_free): Same. - (fold_builtin_next_arg): Same. - * cfgexpand.c (expand_one_var): Same. - (tree_conflicts_with_clobbers_p): Same. - (expand_asm_stmt): Same. - (verify_loop_structure): Same. - * cgraphunit.c (process_function_and_variable_attributes): Same. - * collect-utils.c (collect_execute): Same. - * collect2.c (maybe_run_lto_and_relink): Same. - (is_lto_object_file): Same. - (scan_prog_file): Same. - * convert.c (convert_to_real_1): Same. - * dwarf2out.c (dwarf2out_begin_prologue): Same. - * except.c (verify_eh_tree): Same. - * gcc.c (execute): Same. - (eval_spec_function): Same. - (run_attempt): Same. - (driver::set_up_specs): Same. - (compare_debug_auxbase_opt_spec_function): Same. - * gcov-tool.c (unlink_gcda_file): Same. - (do_merge): Same. - (do_rewrite): Same. - * gcse.c (gcse_or_cprop_is_too_expensive): Same. - * gimplify.c (gimplify_asm_expr): Same. - (gimplify_adjust_omp_clauses): Same. - * hsa-gen.c (gen_hsa_addr_insns): Same. - (gen_hsa_insns_for_load): Same. - (gen_hsa_cmp_insn_from_gimple): Same. - (gen_hsa_insns_for_operation_assignment): Same. - (gen_get_level): Same. - (gen_hsa_alloca): Same. - (omp_simple_builtin::generate): Same. - (gen_hsa_atomic_for_builtin): Same. - (gen_hsa_insns_for_call): Same. - * input.c (dump_location_info): Same. - * ipa-devirt.c (compare_virtual_tables): Same. - * ira.c (ira_setup_eliminable_regset): Same. - * lra-assigns.c (lra_assign): Same. - * lra-constraints.c (lra_constraints): Same. - * lto-streamer-in.c (lto_input_mode_table): Same. - * lto-wrapper.c (get_options_from_collect_gcc_options): Same. - (merge_and_complain): Same. - (compile_offload_image): Same. - (compile_images_for_offload_targets): Same. - (debug_objcopy): Same. - (run_gcc): Same. - (main): Same. - * opts.c (print_specific_help): Same. - (parse_no_sanitize_attribute): Same. - (print_help): Same. - (handle_param): Same. - * plugin.c (add_new_plugin): Same. - (parse_plugin_arg_opt): Same. - (try_init_one_plugin): Same. - * print-rtl.c (debug_bb_n_slim): Quote identifiers, keywords, - operators, and types in diagnostics. Correct quoting and spelling - issues. - * read-rtl-function.c (parse_edge_flag_token): Same. - (function_reader::parse_enum_value): Same. - * reg-stack.c (check_asm_stack_operands): Same. - * regcprop.c (validate_value_data): Same. - * sched-rgn.c (make_pass_sched_fusion): Same. - * stmt.c (check_unique_operand_names): Same. - * targhooks.c (default_target_option_pragma_parse): Same. - * tlink.c (recompile_files): Same. - * toplev.c (process_options): Same. - (do_compile): Same. - * trans-mem.c (diagnose_tm_1): Same. - (ipa_tm_scan_irr_block): Same. - (ipa_tm_diagnose_transaction): Same. - * tree-cfg.c (verify_address): Same. Use get_tree_code_name to - format a tree code name in a diagnostic. - (verify_types_in_gimple_min_lval): Same. - (verify_types_in_gimple_reference): Same. - (verify_gimple_call): Same. - (verify_gimple_assign_unary): Same. - (verify_gimple_assign_binary): Same. - (verify_gimple_assign_ternary): Same. - (verify_gimple_assign_single): Same. - (verify_gimple_switch): Same. - (verify_gimple_label): Same. - (verify_gimple_phi): Same. - (verify_gimple_in_seq): Same. - (verify_eh_throw_stmt_node): Same. - (collect_subblocks): Same. - (gimple_verify_flow_info): Same. - (do_warn_unused_result): Same. - * tree-inline.c (expand_call_inline): Same. - * tree-into-ssa.c (update_ssa): Same. - * tree.c (tree_int_cst_elt_check_failed): Same. - (tree_vec_elt_check_failed): Same. - (omp_clause_operand_check_failed): Same. - (verify_type_variant): Same. - (verify_type): Same. - * value-prof.c (verify_histograms): Same. - * varasm.c (assemble_start_function): Same. + * builtins.c (expand_builtin_atomic_always_lock_free): Quote + identifiers, keywords, operators, and types in diagnostics. Correct + quoting, spelling, and sentence capitalization issues. + (expand_builtin_atomic_is_lock_free): Same. + (fold_builtin_next_arg): Same. + * cfgexpand.c (expand_one_var): Same. + (tree_conflicts_with_clobbers_p): Same. + (expand_asm_stmt): Same. + (verify_loop_structure): Same. + * cgraphunit.c (process_function_and_variable_attributes): Same. + * collect-utils.c (collect_execute): Same. + * collect2.c (maybe_run_lto_and_relink): Same. + (is_lto_object_file): Same. + (scan_prog_file): Same. + * convert.c (convert_to_real_1): Same. + * dwarf2out.c (dwarf2out_begin_prologue): Same. + * except.c (verify_eh_tree): Same. + * gcc.c (execute): Same. + (eval_spec_function): Same. + (run_attempt): Same. + (driver::set_up_specs): Same. + (compare_debug_auxbase_opt_spec_function): Same. + * gcov-tool.c (unlink_gcda_file): Same. + (do_merge): Same. + (do_rewrite): Same. + * gcse.c (gcse_or_cprop_is_too_expensive): Same. + * gimplify.c (gimplify_asm_expr): Same. + (gimplify_adjust_omp_clauses): Same. + * hsa-gen.c (gen_hsa_addr_insns): Same. + (gen_hsa_insns_for_load): Same. + (gen_hsa_cmp_insn_from_gimple): Same. + (gen_hsa_insns_for_operation_assignment): Same. + (gen_get_level): Same. + (gen_hsa_alloca): Same. + (omp_simple_builtin::generate): Same. + (gen_hsa_atomic_for_builtin): Same. + (gen_hsa_insns_for_call): Same. + * input.c (dump_location_info): Same. + * ipa-devirt.c (compare_virtual_tables): Same. + * ira.c (ira_setup_eliminable_regset): Same. + * lra-assigns.c (lra_assign): Same. + * lra-constraints.c (lra_constraints): Same. + * lto-streamer-in.c (lto_input_mode_table): Same. + * lto-wrapper.c (get_options_from_collect_gcc_options): Same. + (merge_and_complain): Same. + (compile_offload_image): Same. + (compile_images_for_offload_targets): Same. + (debug_objcopy): Same. + (run_gcc): Same. + (main): Same. + * opts.c (print_specific_help): Same. + (parse_no_sanitize_attribute): Same. + (print_help): Same. + (handle_param): Same. + * plugin.c (add_new_plugin): Same. + (parse_plugin_arg_opt): Same. + (try_init_one_plugin): Same. + * print-rtl.c (debug_bb_n_slim): Quote identifiers, keywords, + operators, and types in diagnostics. Correct quoting and spelling + issues. + * read-rtl-function.c (parse_edge_flag_token): Same. + (function_reader::parse_enum_value): Same. + * reg-stack.c (check_asm_stack_operands): Same. + * regcprop.c (validate_value_data): Same. + * sched-rgn.c (make_pass_sched_fusion): Same. + * stmt.c (check_unique_operand_names): Same. + * targhooks.c (default_target_option_pragma_parse): Same. + * tlink.c (recompile_files): Same. + * toplev.c (process_options): Same. + (do_compile): Same. + * trans-mem.c (diagnose_tm_1): Same. + (ipa_tm_scan_irr_block): Same. + (ipa_tm_diagnose_transaction): Same. + * tree-cfg.c (verify_address): Same. Use get_tree_code_name to + format a tree code name in a diagnostic. + (verify_types_in_gimple_min_lval): Same. + (verify_types_in_gimple_reference): Same. + (verify_gimple_call): Same. + (verify_gimple_assign_unary): Same. + (verify_gimple_assign_binary): Same. + (verify_gimple_assign_ternary): Same. + (verify_gimple_assign_single): Same. + (verify_gimple_switch): Same. + (verify_gimple_label): Same. + (verify_gimple_phi): Same. + (verify_gimple_in_seq): Same. + (verify_eh_throw_stmt_node): Same. + (collect_subblocks): Same. + (gimple_verify_flow_info): Same. + (do_warn_unused_result): Same. + * tree-inline.c (expand_call_inline): Same. + * tree-into-ssa.c (update_ssa): Same. + * tree.c (tree_int_cst_elt_check_failed): Same. + (tree_vec_elt_check_failed): Same. + (omp_clause_operand_check_failed): Same. + (verify_type_variant): Same. + (verify_type): Same. + * value-prof.c (verify_histograms): Same. + * varasm.c (assemble_start_function): Same. 2019-05-16 Martin Sebor - * config/i386/i386-expand.c (get_element_number): Quote keywords - and other internal names in diagnostics. Adjust other diagnostic - formatting issues noted by -Wformat-diag. - * config/i386/i386-features.c - (ix86_mangle_function_version_assembler_name): Same. - * config/i386/i386-options.c (ix86_handle_abi_attribute): Same. - * config/i386/i386.c (ix86_function_type_abi): Same. - (ix86_function_ms_hook_prologue): Same. - (classify_argument): Same. - (ix86_expand_prologue): Same. - (ix86_md_asm_adjust): Same. - (ix86_memmodel_check): Same. + * config/i386/i386-expand.c (get_element_number): Quote keywords + and other internal names in diagnostics. Adjust other diagnostic + formatting issues noted by -Wformat-diag. + * config/i386/i386-features.c + (ix86_mangle_function_version_assembler_name): Same. + * config/i386/i386-options.c (ix86_handle_abi_attribute): Same. + * config/i386/i386.c (ix86_function_type_abi): Same. + (ix86_function_ms_hook_prologue): Same. + (classify_argument): Same. + (ix86_expand_prologue): Same. + (ix86_md_asm_adjust): Same. + (ix86_memmodel_check): Same. 2019-05-17 Dragan Mladjenovic @@ -8859,8 +8853,8 @@ Fix test-suite. PR target/89952 * config/s390/s390.c (s390_restore_gprs_from_fprs): Restore GPRs - from FPRs in reverse order. Generate REG_CFA_DEF_CFA note also - for restored hard frame pointer. + from FPRs in reverse order. Generate REG_CFA_DEF_CFA note also + for restored hard frame pointer. (s390_sched_dependencies_evaluation): Implement new target hook. (TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK): New macro definition. @@ -9229,7 +9223,7 @@ Fix test-suite. * config/microblaze/microblaze.c (microblaze_expand_block_move): Treat size and alignment as unsigned. - + 2019-04-15 Richard Biener PR debug/90074 @@ -14217,7 +14211,8 @@ Fix test-suite. (_mm256_mask_fixupimm_ps): Ditto. (_mm_mask_fixupimm_pd): Ditto. (_mm_mask_fixupimm_ps): Ditto. - * config/i386/i386-builtin-types.def: Add new types and remove useless ones. + * config/i386/i386-builtin-types.def: Add new types and remove + useless ones. * config/i386/i386-builtin.def: Update builtin definitions. * config/i386/i386.c: Handle new builtin types and remove useless ones. * config/i386/sse.md: Update VFIXUPIMM* patterns. @@ -14336,10 +14331,12 @@ Fix test-suite. 2019-01-16 Tamar Christina - * config/arm/arm-protos.h (neon_vcmla_lane_prepare_operands): Remove patternmode. + * config/arm/arm-protos.h (neon_vcmla_lane_prepare_operands): + Remove patternmode. * config/arm/arm.c (neon_vcmla_lane_prepare_operands): Likewise. - * config/arm/neon.md (neon_vcmla_lane, neon_vcmla_laneq, - neon_vcmlaq_lane): Remove endianness conversion. + * config/arm/neon.md (neon_vcmla_lane, + neon_vcmla_laneq, neon_vcmlaq_lane): + Remove endianness conversion. 2019-01-16 Martin Liska diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cfc96b0..6c40496 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1816,8 +1816,8 @@ 2019-06-12 Przemyslaw Wirkus - * gcc.target/arm/ssadv16qi.c: New test. - * gcc.target/arm/usadv16qi.c: Likewise. + * gcc.target/arm/ssadv16qi.c: New test. + * gcc.target/arm/usadv16qi.c: Likewise. 2019-06-12 Jakub Jelinek @@ -3100,123 +3100,123 @@ 2019-05-16 Martin Sebor - * c-c++-common/Wbool-operation-1.c: Adjust text of expected diagnostics. - * c-c++-common/Wvarargs-2.c: Same. - * c-c++-common/Wvarargs.c: Same. - * c-c++-common/pr51768.c: Same. - * c-c++-common/tm/inline-asm.c: Same. - * c-c++-common/tm/safe-1.c: Same. - * g++.dg/asm-qual-1.C: Same. - * g++.dg/asm-qual-3.C: Same. - * g++.dg/conversion/dynamic1.C: Same. - * g++.dg/cpp0x/constexpr-89599.C: Same. - * g++.dg/cpp0x/constexpr-cast.C: Same. - * g++.dg/cpp0x/constexpr-shift1.C: Same. - * g++.dg/cpp0x/lambda/lambda-conv11.C: Same. - * g++.dg/cpp0x/nullptr04.C: Same. - * g++.dg/cpp0x/static_assert12.C: Same. - * g++.dg/cpp0x/static_assert8.C: Same. - * g++.dg/cpp1y/lambda-conv1.C: Same. - * g++.dg/cpp1y/pr79393-3.C: Same. - * g++.dg/cpp1y/static_assert1.C: Same. - * g++.dg/cpp1z/constexpr-if4.C: Same. - * g++.dg/cpp1z/constexpr-if5.C: Same. - * g++.dg/cpp1z/constexpr-if9.C: Same. - * g++.dg/eh/goto2.C: Same. - * g++.dg/eh/goto3.C: Same. - * g++.dg/expr/static_cast8.C: Same. - * g++.dg/ext/flexary5.C: Same. - * g++.dg/ext/utf-array-short-wchar.C: Same. - * g++.dg/ext/utf-array.C: Same. - * g++.dg/ext/utf8-2.C: Same. - * g++.dg/gomp/loop-4.C: Same. - * g++.dg/gomp/macro-4.C: Same. - * g++.dg/gomp/udr-1.C: Same. - * g++.dg/init/initializer-string-too-long.C: Same. - * g++.dg/other/offsetof9.C: Same. - * g++.dg/ubsan/pr63956.C: Same. - * g++.dg/warn/Wbool-operation-1.C: Same. - * g++.dg/warn/Wtype-limits-Wextra.C: Same. - * g++.dg/warn/Wtype-limits.C: Same. - * g++.dg/wrappers/pr88680.C: Same. - * g++.old-deja/g++.mike/eh55.C: Same. - * gcc.dg/Wsign-compare-1.c: Same. - * gcc.dg/Wtype-limits-Wextra.c: Same. - * gcc.dg/Wtype-limits.c: Same. - * gcc.dg/Wunknownprag.c: Same. - * gcc.dg/Wunsuffixed-float-constants-1.c: Same. - * gcc.dg/asm-6.c: Same. - * gcc.dg/asm-qual-1.c: Same. - * gcc.dg/cast-1.c: Same. - * gcc.dg/cast-2.c: Same. - * gcc.dg/cast-3.c: Same. - * gcc.dg/cpp/source_date_epoch-2.c: Same. - * gcc.dg/debug/pr85252.c: Same. - * gcc.dg/dfp/cast-bad.c: Same. - * gcc.dg/format/gcc_diag-1.c: Same. - * gcc.dg/format/gcc_diag-11.c: Same. - * gcc.dg/gcc_diag-11.c: Same. - * gcc.dg/gnu-cond-expr-2.c: Same. - * gcc.dg/gnu-cond-expr-3.c: Same. - * gcc.dg/gomp/macro-4.c: Same. - * gcc.dg/init-bad-1.c: Same. - * gcc.dg/init-bad-2.c: Same. - * gcc.dg/init-bad-3.c: Same. - * gcc.dg/pr27528.c: Same. - * gcc.dg/pr48552-1.c: Same. - * gcc.dg/pr48552-2.c: Same. - * gcc.dg/pr59846.c: Same. - * gcc.dg/pr61096-1.c: Same. - * gcc.dg/pr8788-1.c: Same. - * gcc.dg/pr90082.c: Same. - * gcc.dg/simd-2.c: Same. - * gcc.dg/spellcheck-params-2.c: Same. - * gcc.dg/spellcheck-params.c: Same. - * gcc.dg/strlenopt-49.c: Same. - * gcc.dg/tm/pr52141.c: Same. - * gcc.dg/torture/pr51106-1.c: Same. - * gcc.dg/torture/pr51106-2.c: Same. - * gcc.dg/utf-array-short-wchar.c: Same. - * gcc.dg/utf-array.c: Same. - * gcc.dg/utf8-2.c: Same. - * gcc.dg/warn-sprintf-no-nul.c: Same. - * gcc.target/i386/asm-flag-0.c: Same. - * gcc.target/i386/inline_error.c: Same. - * gcc.target/i386/pr30848.c: Same. - * gcc.target/i386/pr39082-1.c: Same. - * gcc.target/i386/pr39678.c: Same. - * gcc.target/i386/pr57756.c: Same. - * gcc.target/i386/pr68843-1.c: Same. - * gcc.target/i386/pr79804.c: Same. - * gcc.target/i386/pr82673.c: Same. - * obj-c++.dg/class-protocol-1.mm: Same. - * obj-c++.dg/exceptions-3.mm: Same. - * obj-c++.dg/exceptions-4.mm: Same. - * obj-c++.dg/exceptions-5.mm: Same. - * obj-c++.dg/exceptions-6.mm: Same. - * obj-c++.dg/method-12.mm: Same. - * obj-c++.dg/method-13.mm: Same. - * obj-c++.dg/method-6.mm: Same. - * obj-c++.dg/method-7.mm: Same. - * obj-c++.dg/method-9.mm: Same. - * obj-c++.dg/method-lookup-1.mm: Same. - * obj-c++.dg/proto-lossage-4.mm: Same. - * obj-c++.dg/protocol-qualifier-2.mm: Same. - * objc.dg/call-super-2.m: Same. - * objc.dg/class-protocol-1.m: Same. - * objc.dg/desig-init-1.m: Same. - * objc.dg/exceptions-3.m: Same. - * objc.dg/exceptions-4.m: Same. - * objc.dg/exceptions-5.m: Same. - * objc.dg/exceptions-6.m: Same. - * objc.dg/method-19.m: Same. - * objc.dg/method-2.m: Same. - * objc.dg/method-5.m: Same. - * objc.dg/method-6.m: Same. - * objc.dg/method-7.m: Same. - * objc.dg/method-lookup-1.m: Same. - * objc.dg/proto-hier-1.m: Same. - * objc.dg/proto-lossage-4.m: Same. + * c-c++-common/Wbool-operation-1.c: Adjust text of expected diagnostics. + * c-c++-common/Wvarargs-2.c: Same. + * c-c++-common/Wvarargs.c: Same. + * c-c++-common/pr51768.c: Same. + * c-c++-common/tm/inline-asm.c: Same. + * c-c++-common/tm/safe-1.c: Same. + * g++.dg/asm-qual-1.C: Same. + * g++.dg/asm-qual-3.C: Same. + * g++.dg/conversion/dynamic1.C: Same. + * g++.dg/cpp0x/constexpr-89599.C: Same. + * g++.dg/cpp0x/constexpr-cast.C: Same. + * g++.dg/cpp0x/constexpr-shift1.C: Same. + * g++.dg/cpp0x/lambda/lambda-conv11.C: Same. + * g++.dg/cpp0x/nullptr04.C: Same. + * g++.dg/cpp0x/static_assert12.C: Same. + * g++.dg/cpp0x/static_assert8.C: Same. + * g++.dg/cpp1y/lambda-conv1.C: Same. + * g++.dg/cpp1y/pr79393-3.C: Same. + * g++.dg/cpp1y/static_assert1.C: Same. + * g++.dg/cpp1z/constexpr-if4.C: Same. + * g++.dg/cpp1z/constexpr-if5.C: Same. + * g++.dg/cpp1z/constexpr-if9.C: Same. + * g++.dg/eh/goto2.C: Same. + * g++.dg/eh/goto3.C: Same. + * g++.dg/expr/static_cast8.C: Same. + * g++.dg/ext/flexary5.C: Same. + * g++.dg/ext/utf-array-short-wchar.C: Same. + * g++.dg/ext/utf-array.C: Same. + * g++.dg/ext/utf8-2.C: Same. + * g++.dg/gomp/loop-4.C: Same. + * g++.dg/gomp/macro-4.C: Same. + * g++.dg/gomp/udr-1.C: Same. + * g++.dg/init/initializer-string-too-long.C: Same. + * g++.dg/other/offsetof9.C: Same. + * g++.dg/ubsan/pr63956.C: Same. + * g++.dg/warn/Wbool-operation-1.C: Same. + * g++.dg/warn/Wtype-limits-Wextra.C: Same. + * g++.dg/warn/Wtype-limits.C: Same. + * g++.dg/wrappers/pr88680.C: Same. + * g++.old-deja/g++.mike/eh55.C: Same. + * gcc.dg/Wsign-compare-1.c: Same. + * gcc.dg/Wtype-limits-Wextra.c: Same. + * gcc.dg/Wtype-limits.c: Same. + * gcc.dg/Wunknownprag.c: Same. + * gcc.dg/Wunsuffixed-float-constants-1.c: Same. + * gcc.dg/asm-6.c: Same. + * gcc.dg/asm-qual-1.c: Same. + * gcc.dg/cast-1.c: Same. + * gcc.dg/cast-2.c: Same. + * gcc.dg/cast-3.c: Same. + * gcc.dg/cpp/source_date_epoch-2.c: Same. + * gcc.dg/debug/pr85252.c: Same. + * gcc.dg/dfp/cast-bad.c: Same. + * gcc.dg/format/gcc_diag-1.c: Same. + * gcc.dg/format/gcc_diag-11.c: Same. + * gcc.dg/gcc_diag-11.c: Same. + * gcc.dg/gnu-cond-expr-2.c: Same. + * gcc.dg/gnu-cond-expr-3.c: Same. + * gcc.dg/gomp/macro-4.c: Same. + * gcc.dg/init-bad-1.c: Same. + * gcc.dg/init-bad-2.c: Same. + * gcc.dg/init-bad-3.c: Same. + * gcc.dg/pr27528.c: Same. + * gcc.dg/pr48552-1.c: Same. + * gcc.dg/pr48552-2.c: Same. + * gcc.dg/pr59846.c: Same. + * gcc.dg/pr61096-1.c: Same. + * gcc.dg/pr8788-1.c: Same. + * gcc.dg/pr90082.c: Same. + * gcc.dg/simd-2.c: Same. + * gcc.dg/spellcheck-params-2.c: Same. + * gcc.dg/spellcheck-params.c: Same. + * gcc.dg/strlenopt-49.c: Same. + * gcc.dg/tm/pr52141.c: Same. + * gcc.dg/torture/pr51106-1.c: Same. + * gcc.dg/torture/pr51106-2.c: Same. + * gcc.dg/utf-array-short-wchar.c: Same. + * gcc.dg/utf-array.c: Same. + * gcc.dg/utf8-2.c: Same. + * gcc.dg/warn-sprintf-no-nul.c: Same. + * gcc.target/i386/asm-flag-0.c: Same. + * gcc.target/i386/inline_error.c: Same. + * gcc.target/i386/pr30848.c: Same. + * gcc.target/i386/pr39082-1.c: Same. + * gcc.target/i386/pr39678.c: Same. + * gcc.target/i386/pr57756.c: Same. + * gcc.target/i386/pr68843-1.c: Same. + * gcc.target/i386/pr79804.c: Same. + * gcc.target/i386/pr82673.c: Same. + * obj-c++.dg/class-protocol-1.mm: Same. + * obj-c++.dg/exceptions-3.mm: Same. + * obj-c++.dg/exceptions-4.mm: Same. + * obj-c++.dg/exceptions-5.mm: Same. + * obj-c++.dg/exceptions-6.mm: Same. + * obj-c++.dg/method-12.mm: Same. + * obj-c++.dg/method-13.mm: Same. + * obj-c++.dg/method-6.mm: Same. + * obj-c++.dg/method-7.mm: Same. + * obj-c++.dg/method-9.mm: Same. + * obj-c++.dg/method-lookup-1.mm: Same. + * obj-c++.dg/proto-lossage-4.mm: Same. + * obj-c++.dg/protocol-qualifier-2.mm: Same. + * objc.dg/call-super-2.m: Same. + * objc.dg/class-protocol-1.m: Same. + * objc.dg/desig-init-1.m: Same. + * objc.dg/exceptions-3.m: Same. + * objc.dg/exceptions-4.m: Same. + * objc.dg/exceptions-5.m: Same. + * objc.dg/exceptions-6.m: Same. + * objc.dg/method-19.m: Same. + * objc.dg/method-2.m: Same. + * objc.dg/method-5.m: Same. + * objc.dg/method-6.m: Same. + * objc.dg/method-7.m: Same. + * objc.dg/method-lookup-1.m: Same. + * objc.dg/proto-hier-1.m: Same. + * objc.dg/proto-lossage-4.m: Same. 2019-05-17 Dragan Mladjenovic @@ -3329,7 +3329,7 @@ 2019-05-15 Janne Blomqvist PR fortran/90461 - * gfortran.dg/open_errors_2.f90: Add -std=f2008, adjust line number. + * gfortran.dg/open_errors_2.f90: Add -std=f2008, adjust line number. * gfortran.dg/open_errors_3.f90: New test. 2019-05-15 H.J. Lu @@ -4057,10 +4057,10 @@ 2019-04-29 Vladislav Ivanishin - * gcc.dg/uninit-25-gimple.c: New test. - * gcc.dg/uninit-25.c: New test. - * gcc.dg/uninit-26.c: New test. - * gcc.dg/uninit-27-gimple.c: New test. + * gcc.dg/uninit-25-gimple.c: New test. + * gcc.dg/uninit-25.c: New test. + * gcc.dg/uninit-26.c: New test. + * gcc.dg/uninit-27-gimple.c: New test. 2019-04-29 Richard Biener -- cgit v1.1 From a8b9ee6feb54764859c6f113983255a6dec897d6 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 11 Jul 2019 21:37:33 +0000 Subject: compiler: ensure evaluation order in type hash/eq functions The type hash and equality functions are generated after the order_evaluations pass. They may contain shortcut operators and Set_and_use_temporary_expressions (e.g. from lowering a Binary_exprssion) that need to be ordered. Run order_evaluations and remove_shortcuts on these functions. (The hash functions may be fine, but to be on the safe side we run on them anyway. We do need to run on the equality functions.) A Set_and_use_temporary_expression is effectively an assignment, so it needs to be ordered. Otherwise if we insert a temporary statement before it, we may get wrong evaluation order. A test case is CL 185818. Fixes golang/go#33062. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/185817 From-SVN: r273425 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.h | 4 ++++ gcc/go/gofrontend/gogo.cc | 18 ++++++++++++++++++ gcc/go/gofrontend/gogo.h | 8 ++++++++ gcc/go/gofrontend/types.cc | 4 ++++ 5 files changed, 35 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 7b3f874..28fc223 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -ec754ff4617d564d3dc377121ea9ac5e55f6535a +70ceba5e95716653b9f829a457a44a829175d4da The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 2c6a080..3b65e7a 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -1628,6 +1628,10 @@ class Set_and_use_temporary_expression : public Expression } bool + do_must_eval_in_order() const + { return true; } + + bool do_is_addressable() const { return true; } diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 234a4f4..f9a18bc 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -4097,6 +4097,15 @@ Gogo::order_evaluations() this->traverse(&order_eval); } +// Order evaluations in a block. + +void +Gogo::order_block(Block* block) +{ + Order_eval order_eval(this); + block->traverse(&order_eval); +} + // A traversal class used to find a single shortcut operator within an // expression. @@ -4306,6 +4315,15 @@ Gogo::remove_shortcuts() this->traverse(&shortcuts); } +// Turn shortcut operators into explicit if statements in a block. + +void +Gogo::remove_shortcuts_in_block(Block* block) +{ + Shortcuts shortcuts(this); + block->traverse(&shortcuts); +} + // Traversal to flatten parse tree after order of evaluation rules are applied. class Flatten : public Traverse diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index cb8e25f..6ffdc59 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -749,10 +749,18 @@ class Gogo void remove_shortcuts(); + // Turn short-cut operators into explicit if statements in a block. + void + remove_shortcuts_in_block(Block*); + // Use temporary variables to force order of evaluation. void order_evaluations(); + // Order evaluations in a block. + void + order_block(Block*); + // Add write barriers as needed. void add_write_barriers(); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index cc65bd8..b46525d 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -2098,6 +2098,8 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, int64_t size, Block* b = gogo->finish_block(bloc); gogo->add_block(b, bloc); gogo->lower_block(hash_fn, b); + gogo->order_block(b); + gogo->remove_shortcuts_in_block(b); gogo->finish_function(bloc); Named_object *equal_fn = gogo->start_function(equal_name, equal_fntype, @@ -2119,6 +2121,8 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, int64_t size, b = gogo->finish_block(bloc); gogo->add_block(b, bloc); gogo->lower_block(equal_fn, b); + gogo->order_block(b); + gogo->remove_shortcuts_in_block(b); gogo->finish_function(bloc); // Build the function descriptors for the type descriptor to refer to. -- cgit v1.1 From e63f834983bfbcfc88520993ad3442134c9f8dbd Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 12 Jul 2019 00:16:23 +0000 Subject: Daily bump. From-SVN: r273429 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index bc314b8..3a2691b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190711 +20190712 -- cgit v1.1 From 3362737705972ba59976909b9dbff31615a1021a Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Fri, 12 Jul 2019 05:07:35 +0000 Subject: Add hint if the fallthrough target of current BB isn't the one placed closely next. 2019-07-12 Kewen Lin * gcc/cfgrtl.c (print_rtl_with_bb): Emit a hint if the fallthrough target of current basic block isn't the placed right next. From-SVN: r273430 --- gcc/ChangeLog | 6 ++++++ gcc/cfgrtl.c | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d92250..d4eaa49 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-12 Kewen Lin + + * gcc/cfgrtl.c (print_rtl_with_bb): Emit a hint if the + fallthrough target of current basic block isn't the placed + right next. + 2019-07-11 Sunil K Pandey PR target/90980 diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 4853ce4..bdef400 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -2198,7 +2198,7 @@ print_rtl_with_bb (FILE *outf, const rtx_insn *rtx_first, dump_flags_t flags) if (df) df_dump_start (outf); - if (flags & TDF_BLOCKS) + if (cfun->curr_properties & PROP_cfg) { FOR_EACH_BB_REVERSE_FN (bb, cfun) { @@ -2206,16 +2206,19 @@ print_rtl_with_bb (FILE *outf, const rtx_insn *rtx_first, dump_flags_t flags) start[INSN_UID (BB_HEAD (bb))] = bb; end[INSN_UID (BB_END (bb))] = bb; - for (x = BB_HEAD (bb); x != NULL_RTX; x = NEXT_INSN (x)) + if (flags & TDF_BLOCKS) { - enum bb_state state = IN_MULTIPLE_BB; + for (x = BB_HEAD (bb); x != NULL_RTX; x = NEXT_INSN (x)) + { + enum bb_state state = IN_MULTIPLE_BB; - if (in_bb_p[INSN_UID (x)] == NOT_IN_BB) - state = IN_ONE_BB; - in_bb_p[INSN_UID (x)] = state; + if (in_bb_p[INSN_UID (x)] == NOT_IN_BB) + state = IN_ONE_BB; + in_bb_p[INSN_UID (x)] = state; - if (x == BB_END (bb)) - break; + if (x == BB_END (bb)) + break; + } } } } @@ -2249,16 +2252,36 @@ print_rtl_with_bb (FILE *outf, const rtx_insn *rtx_first, dump_flags_t flags) if (flags & TDF_DETAILS) df_dump_insn_bottom (tmp_rtx, outf); - if (flags & TDF_BLOCKS) + bb = end[INSN_UID (tmp_rtx)]; + if (bb != NULL) { - bb = end[INSN_UID (tmp_rtx)]; - if (bb != NULL) + if (flags & TDF_BLOCKS) { dump_bb_info (outf, bb, 0, dump_flags, false, true); if (df && (flags & TDF_DETAILS)) df_dump_bottom (bb, outf); putc ('\n', outf); } + /* Emit a hint if the fallthrough target of current basic block + isn't the one placed right next. */ + else if (EDGE_COUNT (bb->succs) > 0) + { + gcc_assert (BB_END (bb) == tmp_rtx); + const rtx_insn *ninsn = NEXT_INSN (tmp_rtx); + /* Bypass intervening deleted-insn notes and debug insns. */ + while (ninsn + && !NONDEBUG_INSN_P (ninsn) + && !start[INSN_UID (ninsn)]) + ninsn = NEXT_INSN (ninsn); + edge e = find_fallthru_edge (bb->succs); + if (e && ninsn) + { + basic_block dest = e->dest; + if (start[INSN_UID (ninsn)] != dest) + fprintf (outf, "%s ; pc falls through to BB %d\n", + print_rtx_head, dest->index); + } + } } } -- cgit v1.1 From 1fdd6f0412922eb7438cbbadbb805fce8cc77485 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 12 Jul 2019 09:49:51 +0200 Subject: tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER. * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER. * tree.c (omp_clause_num_ops, omp_clause_code_name): Add order clause entries. (walk_tree_1): Handle OMP_CLAUSE_ORDER. * tree-pretty-print.c (dump_omp_clause): Likewise. * gimplify.c (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses): Likewise. * omp-low.c (scan_sharing_clauses): Likewise. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Likewise. c-family/ * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_ORDER. * c-omp.c (c_omp_split_clauses): Handle splitting of OMP_CLAUSE_ORDER. c/ * c-parser.c (c_parser_omp_clause_name): Handle order clause. (c_parser_omp_clause_order): New function. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ORDER. (OMP_SIMD_CLAUSE_MASK, OMP_FOR_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_ORDER. * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_ORDER. cp/ * parser.c (cp_parser_omp_clause_name): Handle order clause. (cp_parser_omp_clause_order): New function. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ORDER. (OMP_SIMD_CLAUSE_MASK, OMP_FOR_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_ORDER. * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_ORDER. * pt.c (tsubst_omp_clauses): Likewise. testsuite/ * c-c++-common/gomp/order-1.c: New test. * c-c++-common/gomp/order-2.c: New test. From-SVN: r273431 --- gcc/ChangeLog | 13 +++++++ gcc/c-family/ChangeLog | 7 +++- gcc/c-family/c-omp.c | 18 ++++++++++ gcc/c-family/c-pragma.h | 1 + gcc/c/ChangeLog | 9 +++++ gcc/c/c-parser.c | 50 ++++++++++++++++++++++++-- gcc/c/c-typeck.c | 28 +++++++++++++++ gcc/cp/ChangeLog | 10 ++++++ gcc/cp/parser.c | 60 +++++++++++++++++++++++++++++-- gcc/cp/pt.c | 1 + gcc/cp/semantics.c | 19 ++++++++++ gcc/gimplify.c | 2 ++ gcc/omp-low.c | 2 ++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/c-c++-common/gomp/order-1.c | 53 +++++++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/order-2.c | 57 +++++++++++++++++++++++++++++ gcc/tree-core.h | 3 ++ gcc/tree-nested.c | 2 ++ gcc/tree-pretty-print.c | 4 +++ gcc/tree.c | 5 ++- 20 files changed, 342 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/order-1.c create mode 100644 gcc/testsuite/c-c++-common/gomp/order-2.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d4eaa49..34fb0da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2019-07-12 Jakub Jelinek + + * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER. + * tree.c (omp_clause_num_ops, omp_clause_code_name): Add + order clause entries. + (walk_tree_1): Handle OMP_CLAUSE_ORDER. + * tree-pretty-print.c (dump_omp_clause): Likewise. + * gimplify.c (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses): + Likewise. + * omp-low.c (scan_sharing_clauses): Likewise. + * tree-nested.c (convert_nonlocal_omp_clauses, + convert_local_omp_clauses): Likewise. + 2019-07-12 Kewen Lin * gcc/cfgrtl.c (print_rtl_with_bb): Emit a hint if the diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index bbad47f..b84e1f5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,7 +1,12 @@ +2019-07-12 Jakub Jelinek + + * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_ORDER. + * c-omp.c (c_omp_split_clauses): Handle splitting of OMP_CLAUSE_ORDER. + 2019-07-09 Martin Sebor PR c++/61339 - * c-opts.c (handle_deferred_opts): : Change class-key of PODs to struct + * c-opts.c (handle_deferred_opts): Change class-key of PODs to struct and others to class. * c-pretty-print.h: Same. diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 583305e..fc08e93 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -1632,6 +1632,24 @@ c_omp_split_clauses (location_t loc, enum tree_code code, } s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; + /* order clauses are allowed on for and simd. */ + case OMP_CLAUSE_ORDER: + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) + { + if (code == OMP_SIMD) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_ORDER); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; + cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c; + s = C_OMP_CLAUSE_SPLIT_SIMD; + } + else + s = C_OMP_CLAUSE_SPLIT_FOR; + } + else + s = C_OMP_CLAUSE_SPLIT_SIMD; + break; /* Reduction is allowed on simd, for, parallel, sections, taskloop and teams. Duplicate it on all of them, but omit on for or sections if parallel is present (unless inscan, in that case diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index ed65036..4239ada 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -114,6 +114,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_NUM_TASKS, PRAGMA_OMP_CLAUSE_NUM_TEAMS, PRAGMA_OMP_CLAUSE_NUM_THREADS, + PRAGMA_OMP_CLAUSE_ORDER, PRAGMA_OMP_CLAUSE_ORDERED, PRAGMA_OMP_CLAUSE_PARALLEL, PRAGMA_OMP_CLAUSE_PRIORITY, diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index bb0573e..c58680c 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2019-07-12 Jakub Jelinek + + * c-parser.c (c_parser_omp_clause_name): Handle order clause. + (c_parser_omp_clause_order): New function. + (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ORDER. + (OMP_SIMD_CLAUSE_MASK, OMP_FOR_CLAUSE_MASK): Add + PRAGMA_OMP_CLAUSE_ORDER. + * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_ORDER. + 2019-07-10 Richard Biener * gimple-parser.c (c_parser_gimple_postfix_expression): Support diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 3fa7e68..1f83c24 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -11789,6 +11789,8 @@ c_parser_omp_clause_name (c_parser *parser) case 'o': if (!strcmp ("ordered", p)) result = PRAGMA_OMP_CLAUSE_ORDERED; + else if (!strcmp ("order", p)) + result = PRAGMA_OMP_CLAUSE_ORDER; break; case 'p': if (!strcmp ("parallel", p)) @@ -13467,6 +13469,44 @@ c_parser_oacc_clause_wait (c_parser *parser, tree list) return list; } + +/* OpenMP 5.0: + order ( concurrent ) */ + +static tree +c_parser_omp_clause_order (c_parser *parser, tree list) +{ + location_t loc = c_parser_peek_token (parser)->location; + tree c; + const char *p; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + if (!c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_error (parser, "expected %"); + goto out_err; + } + p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "concurrent") != 0) + { + c_parser_error (parser, "expected %"); + goto out_err; + } + c_parser_consume_token (parser); + parens.skip_until_found_close (parser); + /* check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order"); */ + c = build_omp_clause (loc, OMP_CLAUSE_ORDER); + OMP_CLAUSE_CHAIN (c) = list; + return c; + + out_err: + parens.skip_until_found_close (parser); + return list; +} + + /* OpenMP 2.5: ordered @@ -15092,6 +15132,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_num_threads (parser, clauses); c_name = "num_threads"; break; + case PRAGMA_OMP_CLAUSE_ORDER: + clauses = c_parser_omp_clause_order (parser, clauses); + c_name = "order"; + break; case PRAGMA_OMP_CLAUSE_ORDERED: clauses = c_parser_omp_clause_ordered (parser, clauses); c_name = "ordered"; @@ -17221,7 +17265,8 @@ omp_split_clauses (location_t loc, enum tree_code code, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) static tree c_parser_omp_simd (location_t loc, c_parser *parser, @@ -17277,7 +17322,8 @@ c_parser_omp_simd (location_t loc, c_parser *parser, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) static tree c_parser_omp_for (location_t loc, c_parser *parser, diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 6419ca9..e4ce03d 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -13667,6 +13667,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) tree last_iterators = NULL_TREE; bool last_iterators_remove = false; tree *nogroup_seen = NULL; + tree *order_clause = NULL; /* 1 if normal/task reduction has been seen, -1 if inscan reduction has been seen, -2 if mixed inscan/normal reduction diagnosed. */ int reduction_seen = 0; @@ -14631,6 +14632,25 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_ORDER: + if (ordered_clause) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% clause must not be used together " + "with %"); + remove = true; + break; + } + else if (order_clause) + { + /* Silently remove duplicates. */ + remove = true; + break; + } + order_clause = pc; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_NUM_TEAMS: @@ -14683,6 +14703,14 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_ORDERED: ordered_clause = c; + if (order_clause) + { + error_at (OMP_CLAUSE_LOCATION (*order_clause), + "% clause must not be used together " + "with %"); + *order_clause = OMP_CLAUSE_CHAIN (*order_clause); + order_clause = NULL; + } pc = &OMP_CLAUSE_CHAIN (c); continue; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bc788c1..a18959d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2019-07-12 Jakub Jelinek + + * parser.c (cp_parser_omp_clause_name): Handle order clause. + (cp_parser_omp_clause_order): New function. + (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ORDER. + (OMP_SIMD_CLAUSE_MASK, OMP_FOR_CLAUSE_MASK): Add + PRAGMA_OMP_CLAUSE_ORDER. + * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_ORDER. + * pt.c (tsubst_omp_clauses): Likewise. + 2019-07-10 Paolo Carlini * decl.c (get_type_quals, diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1281410..c46740a 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -32528,6 +32528,8 @@ cp_parser_omp_clause_name (cp_parser *parser) case 'o': if (!strcmp ("ordered", p)) result = PRAGMA_OMP_CLAUSE_ORDERED; + else if (!strcmp ("order", p)) + result = PRAGMA_OMP_CLAUSE_ORDER; break; case 'p': if (!strcmp ("parallel", p)) @@ -33919,6 +33921,50 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list, return list; } +/* OpenMP 5.0: + order ( concurrent ) */ + +static tree +cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location) +{ + tree c, id; + const char *p; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + cp_parser_error (parser, "expected %"); + goto out_err; + } + else + { + id = cp_lexer_peek_token (parser->lexer)->u.value; + p = IDENTIFIER_POINTER (id); + } + if (strcmp (p, "concurrent") != 0) + { + cp_parser_error (parser, "expected %"); + goto out_err; + } + cp_lexer_consume_token (parser->lexer); + if (!parens.require_close (parser)) + goto out_err; + + /* check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order", location); */ + c = build_omp_clause (location, OMP_CLAUSE_ORDER); + OMP_CLAUSE_CHAIN (c) = list; + return c; + + out_err: + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; +} + /* OpenMP 2.5: ordered @@ -35510,7 +35556,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, c_name = "mergeable"; break; case PRAGMA_OMP_CLAUSE_NOWAIT: - clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location); + clauses = cp_parser_omp_clause_nowait (parser, clauses, + token->location); c_name = "nowait"; break; case PRAGMA_OMP_CLAUSE_NUM_TASKS: @@ -35523,6 +35570,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, token->location); c_name = "num_threads"; break; + case PRAGMA_OMP_CLAUSE_ORDER: + clauses = cp_parser_omp_clause_order (parser, clauses, + token->location); + c_name = "order"; + break; case PRAGMA_OMP_CLAUSE_ORDERED: clauses = cp_parser_omp_clause_ordered (parser, clauses, token->location); @@ -37560,7 +37612,8 @@ cp_omp_split_clauses (location_t loc, enum tree_code code, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) static tree cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok, @@ -37620,7 +37673,8 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) static tree cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c0a0487..e23c0aa 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16422,6 +16422,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_INDEPENDENT: case OMP_CLAUSE_AUTO: case OMP_CLAUSE_SEQ: diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index aadfaff..1a21705 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6127,6 +6127,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bool branch_seen = false; bool copyprivate_seen = false; bool ordered_seen = false; + bool order_seen = false; bool schedule_seen = false; bool oacc_async = false; tree last_iterators = NULL_TREE; @@ -7600,6 +7601,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) ordered_seen = true; break; + case OMP_CLAUSE_ORDER: + if (order_seen) + remove = true; + else + order_seen = true; + break; + case OMP_CLAUSE_INBRANCH: case OMP_CLAUSE_NOTINBRANCH: if (branch_seen) @@ -7775,6 +7783,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "% clause", "ordered"); pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_ORDER: + if (ordered_seen) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% clause must not be used together " + "with %"); + *pc = OMP_CLAUSE_CHAIN (c); + continue; + } + pc = &OMP_CLAUSE_CHAIN (c); + continue; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) { diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 146a86c..ca7ad33 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9263,6 +9263,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: break; @@ -10223,6 +10224,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_SIMD: case OMP_CLAUSE_HINT: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_IS_DEVICE_PTR: case OMP_CLAUSE_ASYNC: diff --git a/gcc/omp-low.c b/gcc/omp-low.c index a855c5b..052ffc9 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1402,6 +1402,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE_SIMD: case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_ASYNC: case OMP_CLAUSE_WAIT: case OMP_CLAUSE_GANG: @@ -1595,6 +1596,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE_SIMD: case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_NONTEMPORAL: case OMP_CLAUSE_ASYNC: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6c40496..ed3165e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-12 Jakub Jelinek + + * c-c++-common/gomp/order-1.c: New test. + * c-c++-common/gomp/order-2.c: New test. + 2019-07-11 Sunil K Pandey PR target/90980 diff --git a/gcc/testsuite/c-c++-common/gomp/order-1.c b/gcc/testsuite/c-c++-common/gomp/order-1.c new file mode 100644 index 0000000..da4b73d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/order-1.c @@ -0,0 +1,53 @@ +void +f1 (int *a) +{ + int i; + #pragma omp for order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp simd order ( concurrent ) + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp for simd order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; +} + +void +f2 (int *a) +{ + int i; + #pragma omp parallel for order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp parallel for simd order (concurrent) + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp teams distribute parallel for order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp teams distribute parallel for simd order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp teams + { + #pragma omp distribute parallel for order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp distribute parallel for simd order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; + } + #pragma omp taskloop simd order (concurrent) + for (i = 0; i < 128; i++) + a[i]++; +} + +void +f3 (int *a) +{ + int i; + #pragma omp for order(concurrent) order(concurrent) order(concurrent) + for (i = 0; i < 128; i++) + a[i]++; +} diff --git a/gcc/testsuite/c-c++-common/gomp/order-2.c b/gcc/testsuite/c-c++-common/gomp/order-2.c new file mode 100644 index 0000000..1a9adb0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/order-2.c @@ -0,0 +1,57 @@ +void +f1 (int *a) +{ + int i; + #pragma omp for order /* { dg-error "expected" } */ + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp for simd order : /* { dg-error "expected" } */ + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp simd order ( foobar ) /* { dg-error "expected" } */ + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp for simd order( concurrent /* { dg-error "expected" } */ + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp for simd order( concurrent : foo )/* { dg-error "expected" } */ + for (i = 0; i < 128; i++) + a[i]++; +} + +void +f2 (int *a) +{ + int i; + #pragma omp teams + #pragma omp distribute order(concurrent) /* { dg-error "'order' is not valid for '#pragma omp distribute'" } */ + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp taskloop order (concurrent) /* { dg-error "'order' is not valid for '#pragma omp taskloop'" } */ + for (i = 0; i < 128; i++) + a[i]++; + #pragma omp for order(concurrent) ordered /* { dg-error "'order' clause must not be used together with 'ordered'" } */ + for (i = 0; i < 128; i++) + { + #pragma omp ordered + a[i]++; + } + #pragma omp for ordered order(concurrent) /* { dg-error "'order' clause must not be used together with 'ordered'" } */ + for (i = 0; i < 128; i++) + { + #pragma omp ordered + a[i]++; + } + #pragma omp for ordered (1) order(concurrent) /* { dg-error "'order' clause must not be used together with 'ordered'" } */ + for (i = 0; i < 128; i++) + { + #pragma omp ordered depend (sink: i - 1) + #pragma omp ordered depend (source) + } + #pragma omp for order(concurrent)ordered (1) /* { dg-error "'order' clause must not be used together with 'ordered'" } */ + for (i = 0; i < 128; i++) + { + #pragma omp ordered depend (sink: i - 1) + #pragma omp ordered depend (source) + } +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index b5dde47..8ac07e8 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -448,6 +448,9 @@ enum omp_clause_code { /* OpenMP clause: defaultmap (tofrom: scalar). */ OMP_CLAUSE_DEFAULTMAP, + /* OpenMP clause: order (concurrent). */ + OMP_CLAUSE_ORDER, + /* Internally used only clause, holding SIMD uid. */ OMP_CLAUSE__SIMDUID_, diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index e703cd9..1527456 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1343,6 +1343,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_SEQ: case OMP_CLAUSE_INDEPENDENT: case OMP_CLAUSE_AUTO: @@ -2073,6 +2074,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_SEQ: case OMP_CLAUSE_INDEPENDENT: case OMP_CLAUSE_AUTO: diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 742c284..a75f97a 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -1040,6 +1040,10 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) pp_right_paren (pp); break; + case OMP_CLAUSE_ORDER: + pp_string (pp, "order(concurrent)"); + break; + case OMP_CLAUSE__SIMDUID_: pp_string (pp, "_simduid_("); dump_generic_node (pp, OMP_CLAUSE__SIMDUID__DECL (clause), diff --git a/gcc/tree.c b/gcc/tree.c index a609963..751370b 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -342,7 +342,8 @@ unsigned const char omp_clause_num_ops[] = 0, /* OMP_CLAUSE_THREADS */ 0, /* OMP_CLAUSE_SIMD */ 1, /* OMP_CLAUSE_HINT */ - 0, /* OMP_CLAUSE_DEFALTMAP */ + 0, /* OMP_CLAUSE_DEFAULTMAP */ + 0, /* OMP_CLAUSE_ORDER */ 1, /* OMP_CLAUSE__SIMDUID_ */ 0, /* OMP_CLAUSE__SIMT_ */ 0, /* OMP_CLAUSE_INDEPENDENT */ @@ -424,6 +425,7 @@ const char * const omp_clause_code_name[] = "simd", "hint", "defaultmap", + "order", "_simduid_", "_simt_", "independent", @@ -12340,6 +12342,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_ORDER: case OMP_CLAUSE_AUTO: case OMP_CLAUSE_SEQ: case OMP_CLAUSE_TILE: -- cgit v1.1 From d281492de84960b5885f88fffeeb226650f5141d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 12 Jul 2019 07:54:23 +0000 Subject: Support multiple operand counts for .md @ patterns This patch extends the support for "@..." pattern names so that the patterns can have different numbers of operands. This allows things like binary and ternary operations to be handled in a consistent way, a bit like optabs. The generators assert that the number of operands passed is correct for the underlying instruction. Also, replace_operands_with_dups iterated over the old rtx format even after having decided to do a replacement, which broke with match_operator. 2019-07-12 Richard Sandiford gcc/ * doc/md.texi: Document that @ patterns can have different numbers of operands. * genemit.c (handle_overloaded_gen): Handle this case. * genopinit.c (handle_overloaded_gen): Likewise. * gensupport.c (replace_operands_with_dups): Iterate over the new rtx's format rather than the old one's. From-SVN: r273432 --- gcc/ChangeLog | 9 ++++++++ gcc/doc/md.texi | 9 ++++++++ gcc/genemit.c | 65 +++++++++++++++++++++++++++++--------------------------- gcc/genopinit.c | 62 +++++++++++++++++++++++++++++++---------------------- gcc/gensupport.c | 2 ++ 5 files changed, 91 insertions(+), 56 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34fb0da..0894db7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-12 Richard Sandiford + + * doc/md.texi: Document that @ patterns can have different + numbers of operands. + * genemit.c (handle_overloaded_gen): Handle this case. + * genopinit.c (handle_overloaded_gen): Likewise. + * gensupport.c (replace_operands_with_dups): Iterate over + the new rtx's format rather than the old one's. + 2019-07-12 Jakub Jelinek * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index b1fcc38..af216da 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -11381,4 +11381,13 @@ name and same types of iterator. For example: would produce a single set of functions that handles both @code{INTEGER_MODES} and @code{FLOAT_MODES}. +It is also possible for these @samp{@@} patterns to have different +numbers of operands from each other. For example, patterns with +a binary rtl code might take three operands (one output and two inputs) +while patterns with a ternary rtl code might take four operands (one +output and three inputs). This combination would produce separate +@samp{maybe_gen_@var{name}} and @samp{gen_@var{name}} functions for +each operand count, but it would still produce a single +@samp{maybe_code_for_@var{name}} and a single @samp{code_for_@var{name}}. + @end ifset diff --git a/gcc/genemit.c b/gcc/genemit.c index 83f86a3..3ff8197 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -811,42 +811,45 @@ handle_overloaded_code_for (overloaded_name *oname) static void handle_overloaded_gen (overloaded_name *oname) { + unsigned HOST_WIDE_INT seen = 0; /* All patterns must have the same number of operands. */ - pattern_stats stats; - get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1)); for (overloaded_instance *instance = oname->first_instance->next; instance; instance = instance->next) { - pattern_stats stats2; - get_pattern_stats (&stats2, XVEC (instance->insn, 1)); - if (stats.num_generator_args != stats2.num_generator_args) - fatal_at (get_file_location (instance->insn), - "inconsistent number of operands for '%s'; " - "this instance has %d, but previous instances had %d", - oname->name, stats2.num_generator_args, - stats.num_generator_args); + pattern_stats stats; + get_pattern_stats (&stats, XVEC (instance->insn, 1)); + unsigned HOST_WIDE_INT mask + = HOST_WIDE_INT_1U << stats.num_generator_args; + if (seen & mask) + continue; + + seen |= mask; + + /* Print the function prototype. */ + printf ("\nrtx\nmaybe_gen_%s (", oname->name); + print_overload_arguments (oname); + for (int i = 0; i < stats.num_generator_args; ++i) + printf (", rtx x%d", i); + printf (")\n{\n"); + + /* Use maybe_code_for_*, instead of duplicating the selection + logic here. */ + printf (" insn_code code = maybe_code_for_%s (", oname->name); + for (unsigned int i = 0; i < oname->arg_types.length (); ++i) + printf ("%sarg%d", i == 0 ? "" : ", ", i); + printf (");\n" + " if (code != CODE_FOR_nothing)\n" + " {\n" + " gcc_assert (insn_data[code].n_generator_args == %d);\n" + " return GEN_FCN (code) (", stats.num_generator_args); + for (int i = 0; i < stats.num_generator_args; ++i) + printf ("%sx%d", i == 0 ? "" : ", ", i); + printf (");\n" + " }\n" + " else\n" + " return NULL_RTX;\n" + "}\n"); } - - /* Print the function prototype. */ - printf ("\nrtx\nmaybe_gen_%s (", oname->name); - print_overload_arguments (oname); - for (int i = 0; i < stats.num_generator_args; ++i) - printf (", rtx x%d", i); - printf (")\n{\n"); - - /* Use maybe_code_for_*, instead of duplicating the selection logic here. */ - printf (" insn_code code = maybe_code_for_%s (", oname->name); - for (unsigned int i = 0; i < oname->arg_types.length (); ++i) - printf ("%sarg%d", i == 0 ? "" : ", ", i); - printf (");\n" - " if (code != CODE_FOR_nothing)\n" - " return GEN_FCN (code) ("); - for (int i = 0; i < stats.num_generator_args; ++i) - printf ("%sx%d", i == 0 ? "" : ", ", i); - printf (");\n" - " else\n" - " return NULL_RTX;\n" - "}\n"); } int diff --git a/gcc/genopinit.c b/gcc/genopinit.c index ea4c3ce..1dd1d82 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -134,31 +134,43 @@ handle_overloaded_code_for (FILE *file, overloaded_name *oname) static void handle_overloaded_gen (FILE *file, overloaded_name *oname) { - pattern_stats stats; - get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1)); - - fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name); - for (unsigned int i = 0; i < oname->arg_types.length (); ++i) - fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]); - for (int i = 0; i < stats.num_generator_args; ++i) - fprintf (file, ", rtx"); - fprintf (file, ");\n"); - - fprintf (file, "inline rtx\ngen_%s (", oname->name); - for (unsigned int i = 0; i < oname->arg_types.length (); ++i) - fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i); - for (int i = 0; i < stats.num_generator_args; ++i) - fprintf (file, ", rtx x%d", i); - fprintf (file, ")\n{\n rtx res = maybe_gen_%s (", oname->name); - for (unsigned int i = 0; i < oname->arg_types.length (); ++i) - fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i); - for (int i = 0; i < stats.num_generator_args; ++i) - fprintf (file, ", x%d", i); - fprintf (file, - ");\n" - " gcc_assert (res);\n" - " return res;\n" - "}\n"); + unsigned HOST_WIDE_INT seen = 0; + for (overloaded_instance *instance = oname->first_instance->next; + instance; instance = instance->next) + { + pattern_stats stats; + get_pattern_stats (&stats, XVEC (instance->insn, 1)); + unsigned HOST_WIDE_INT mask + = HOST_WIDE_INT_1U << stats.num_generator_args; + if (seen & mask) + continue; + + seen |= mask; + + fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name); + for (unsigned int i = 0; i < oname->arg_types.length (); ++i) + fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]); + for (int i = 0; i < stats.num_generator_args; ++i) + fprintf (file, ", rtx"); + fprintf (file, ");\n"); + + fprintf (file, "inline rtx\ngen_%s (", oname->name); + for (unsigned int i = 0; i < oname->arg_types.length (); ++i) + fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", + oname->arg_types[i], i); + for (int i = 0; i < stats.num_generator_args; ++i) + fprintf (file, ", rtx x%d", i); + fprintf (file, ")\n{\n rtx res = maybe_gen_%s (", oname->name); + for (unsigned int i = 0; i < oname->arg_types.length (); ++i) + fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i); + for (int i = 0; i < stats.num_generator_args; ++i) + fprintf (file, ", x%d", i); + fprintf (file, + ");\n" + " gcc_assert (res);\n" + " return res;\n" + "}\n"); + } } int diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 0ad9995..1aab711 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -500,12 +500,14 @@ replace_operands_with_dups (rtx x) { newx = rtx_alloc (MATCH_DUP); XINT (newx, 0) = XINT (x, 0); + x = newx; } else if (GET_CODE (x) == MATCH_OPERATOR) { newx = rtx_alloc (MATCH_OP_DUP); XINT (newx, 0) = XINT (x, 0); XVEC (newx, 1) = XVEC (x, 2); + x = newx; } else newx = shallow_copy_rtx (x); -- cgit v1.1 From e7ba492a04d0bfef9752cbb16fcce3ffc31bf99f Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 12 Jul 2019 08:14:34 +0000 Subject: [arch64] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. No behavioural change except for dropping the unused SVE divide permutations. 2019-07-12 Richard Sandiford gcc/ * config/aarch64/aarch64.md (*compare_condjump) (loadwb_pair_, loadwb_pair_) (storewb_pair_, storewb_pair_) (*ands_compare0): Fix ambiguous uses of .md attributes. * config/aarch64/aarch64-simd.md (*aarch64_get_lane_extend): Likewise. (*aarch64_get_lane_zero_extend): Likewise. * config/aarch64/aarch64-sve.md (while_ult): Likewise. (*cond__any): Fix SVE_I/SVE_SDI typo. From-SVN: r273433 --- gcc/ChangeLog | 13 +++++++++++++ gcc/config/aarch64/aarch64-simd.md | 37 +++++++++++++++++++------------------ gcc/config/aarch64/aarch64-sve.md | 2 +- gcc/config/aarch64/aarch64.md | 29 +++++++++++++++-------------- 4 files changed, 48 insertions(+), 33 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0894db7..66e715f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,18 @@ 2019-07-12 Richard Sandiford + * config/aarch64/aarch64.md (*compare_condjump) + (loadwb_pair_, loadwb_pair_) + (storewb_pair_, storewb_pair_) + (*ands_compare0): Fix ambiguous uses of .md attributes. + * config/aarch64/aarch64-simd.md + (*aarch64_get_lane_extend): Likewise. + (*aarch64_get_lane_zero_extend): Likewise. + * config/aarch64/aarch64-sve.md + (while_ult): Likewise. + (*cond__any): Fix SVE_I/SVE_SDI typo. + +2019-07-12 Richard Sandiford + * doc/md.texi: Document that @ patterns can have different numbers of operands. * genemit.c (handle_overloaded_gen): Handle this case. diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 0c2600f..d480e43 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -3135,30 +3135,31 @@ (define_insn "*aarch64_get_lane_extend" [(set (match_operand:GPI 0 "register_operand" "=r") (sign_extend:GPI - (vec_select: + (vec_select: (match_operand:VDQQH 1 "register_operand" "w") (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] "TARGET_SIMD" { - operands[2] = aarch64_endian_lane_rtx (mode, INTVAL (operands[2])); + operands[2] = aarch64_endian_lane_rtx (mode, + INTVAL (operands[2])); return "smov\\t%0, %1.[%2]"; } - [(set_attr "type" "neon_to_gp")] -) - -(define_insn "*aarch64_get_lane_zero_extend" - [(set (match_operand:GPI 0 "register_operand" "=r") - (zero_extend:GPI - (vec_select: - (match_operand:VDQQH 1 "register_operand" "w") - (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] - "TARGET_SIMD" - { - operands[2] = aarch64_endian_lane_rtx (mode, - INTVAL (operands[2])); - return "umov\\t%w0, %1.[%2]"; - } - [(set_attr "type" "neon_to_gp")] + [(set_attr "type" "neon_to_gp")] +) + +(define_insn "*aarch64_get_lane_zero_extend" + [(set (match_operand:GPI 0 "register_operand" "=r") + (zero_extend:GPI + (vec_select: + (match_operand:VDQQH 1 "register_operand" "w") + (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] + "TARGET_SIMD" + { + operands[2] = aarch64_endian_lane_rtx (mode, + INTVAL (operands[2])); + return "umov\\t%w0, %1.[%2]"; + } + [(set_attr "type" "neon_to_gp")] ) ;; Lane extraction of a value, neither sign nor zero extension diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index c4670b6..e489afb 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -1363,7 +1363,7 @@ ;; don't have an unnecessary PTRUE. "&& !CONSTANT_P (operands[1])" { - operands[1] = CONSTM1_RTX (mode); + operands[1] = CONSTM1_RTX (mode); } ) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 4d559c4..d1b2c20 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -567,14 +567,14 @@ ;; sub x0, x1, #(CST & 0xfff000) ;; subs x0, x0, #(CST & 0x000fff) ;; b .Label -(define_insn_and_split "*compare_condjump" +(define_insn_and_split "*compare_condjump" [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r") (match_operand:GPI 1 "aarch64_imm24" "n")) (label_ref:P (match_operand 2 "" "")) (pc)))] - "!aarch64_move_imm (INTVAL (operands[1]), mode) - && !aarch64_plus_operand (operands[1], mode) + "!aarch64_move_imm (INTVAL (operands[1]), mode) + && !aarch64_plus_operand (operands[1], mode) && !reload_completed" "#" "&& true" @@ -582,11 +582,12 @@ { HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff; HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000; - rtx tmp = gen_reg_rtx (mode); - emit_insn (gen_add3 (tmp, operands[0], GEN_INT (-hi_imm))); - emit_insn (gen_add3_compare0 (tmp, tmp, GEN_INT (-lo_imm))); + rtx tmp = gen_reg_rtx (mode); + emit_insn (gen_add3 (tmp, operands[0], GEN_INT (-hi_imm))); + emit_insn (gen_add3_compare0 (tmp, tmp, GEN_INT (-lo_imm))); rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM); - rtx cmp_rtx = gen_rtx_fmt_ee (, mode, cc_reg, const0_rtx); + rtx cmp_rtx = gen_rtx_fmt_ee (, mode, + cc_reg, const0_rtx); emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2])); DONE; } @@ -1505,8 +1506,8 @@ (mem:GPI (plus:P (match_dup 1) (match_operand:P 5 "const_int_operand" "n"))))])] "INTVAL (operands[5]) == GET_MODE_SIZE (mode)" - "ldp\\t%2, %3, [%1], %4" - [(set_attr "type" "load_")] + "ldp\\t%2, %3, [%1], %4" + [(set_attr "type" "load_")] ) (define_insn "loadwb_pair_" @@ -1520,7 +1521,7 @@ (mem:GPF (plus:P (match_dup 1) (match_operand:P 5 "const_int_operand" "n"))))])] "INTVAL (operands[5]) == GET_MODE_SIZE (mode)" - "ldp\\t%2, %3, [%1], %4" + "ldp\\t%2, %3, [%1], %4" [(set_attr "type" "neon_load1_2reg")] ) @@ -1553,8 +1554,8 @@ (match_operand:P 5 "const_int_operand" "n"))) (match_operand:GPI 3 "register_operand" "r"))])] "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (mode)" - "stp\\t%2, %3, [%0, %4]!" - [(set_attr "type" "store_")] + "stp\\t%2, %3, [%0, %4]!" + [(set_attr "type" "store_")] ) (define_insn "storewb_pair_" @@ -1569,7 +1570,7 @@ (match_operand:P 5 "const_int_operand" "n"))) (match_operand:GPF 3 "register_operand" "w"))])] "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (mode)" - "stp\\t%2, %3, [%0, %4]!" + "stp\\t%2, %3, [%0, %4]!" [(set_attr "type" "neon_store1_2reg")] ) @@ -4782,7 +4783,7 @@ [(set_attr "type" "alus_imm")] ) -(define_insn "*ands_compare0" +(define_insn "*ands_compare0" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r")) -- cgit v1.1 From e067f9924bad423bf6265b75414d3160e6cf660a Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 12 Jul 2019 09:35:21 +0000 Subject: cfgexpand.c (expand_gimple_stmt_1): If the statement doesn't have location... * cfgexpand.c (expand_gimple_stmt_1) : If the statement doesn't have location, set the current location to the function's end From-SVN: r273434 --- gcc/ChangeLog | 5 +++++ gcc/cfgexpand.c | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 66e715f..e75e1ec 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-12 Eric Botcazou + + * cfgexpand.c (expand_gimple_stmt_1) : If the statement + doesn't have location, set the current location to the function's end. + 2019-07-12 Richard Sandiford * config/aarch64/aarch64.md (*compare_condjump) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index d0c1d31..33af991 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -3714,6 +3714,12 @@ expand_gimple_stmt_1 (gimple *stmt) { op0 = gimple_return_retval (as_a (stmt)); + /* If a return doesn't have a location, it very likely represents + multiple user returns so we cannot let it inherit the location + of the last statement of the previous basic block in RTL. */ + if (!gimple_has_location (stmt)) + set_curr_insn_location (cfun->function_end_locus); + if (op0 && op0 != error_mark_node) { tree result = DECL_RESULT (current_function_decl); -- cgit v1.1 From 831e688af50c5f77a2daa3cd3bfd0f27d54d5d72 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 12 Jul 2019 10:03:10 +0000 Subject: fold-const.h (get_array_ctor_element_at_index): Adjust. 2019-07-12 Richard Biener * fold-const.h (get_array_ctor_element_at_index): Adjust. * fold-const.c (get_array_ctor_element_at_index): Add ctor_idx output parameter informing the caller where in the constructor the element was (not) found. Add early exit for when the ctor is sorted. * gimple-fold.c (fold_array_ctor_reference): Support constant folding across multiple array elements. * gcc.dg/tree-ssa/vector-7.c: New testcase. From-SVN: r273435 --- gcc/ChangeLog | 10 ++++ gcc/fold-const.c | 36 ++++++++++--- gcc/fold-const.h | 3 +- gcc/gimple-fold.c | 91 +++++++++++++++++++++++++++++--- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/tree-ssa/vector-7.c | 39 ++++++++++++++ 6 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vector-7.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e75e1ec..bd47ddd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-07-12 Richard Biener + + * fold-const.h (get_array_ctor_element_at_index): Adjust. + * fold-const.c (get_array_ctor_element_at_index): Add + ctor_idx output parameter informing the caller where in + the constructor the element was (not) found. Add early exit + for when the ctor is sorted. + * gimple-fold.c (fold_array_ctor_reference): Support constant + folding across multiple array elements. + 2019-07-12 Eric Botcazou * cfgexpand.c (expand_gimple_stmt_1) : If the statement diff --git a/gcc/fold-const.c b/gcc/fold-const.c index edb23fd..74544bf 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11839,10 +11839,15 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type, } /* Gets the element ACCESS_INDEX from CTOR, which must be a CONSTRUCTOR - of an array (or vector). */ + of an array (or vector). *CTOR_IDX if non-NULL is updated with the + constructor element index of the value returned. If the element is + not found NULL_TREE is returned and *CTOR_IDX is updated to + the index of the element after the ACCESS_INDEX position (which + may be outside of the CTOR array). */ tree -get_array_ctor_element_at_index (tree ctor, offset_int access_index) +get_array_ctor_element_at_index (tree ctor, offset_int access_index, + unsigned *ctor_idx) { tree index_type = NULL_TREE; offset_int low_bound = 0; @@ -11869,7 +11874,7 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index) TYPE_SIGN (index_type)); offset_int max_index; - unsigned HOST_WIDE_INT cnt; + unsigned cnt; tree cfield, cval; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval) @@ -11897,11 +11902,26 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index) max_index = index; } - /* Do we have match? */ - if (wi::cmpu (access_index, index) >= 0 - && wi::cmpu (access_index, max_index) <= 0) - return cval; - } + /* Do we have match? */ + if (wi::cmpu (access_index, index) >= 0) + { + if (wi::cmpu (access_index, max_index) <= 0) + { + if (ctor_idx) + *ctor_idx = cnt; + return cval; + } + } + else if (in_gimple_form) + /* We're past the element we search for. Note during parsing + the elements might not be sorted. + ??? We should use a binary search and a flag on the + CONSTRUCTOR as to whether elements are sorted in declaration + order. */ + break; + } + if (ctor_idx) + *ctor_idx = cnt; return NULL_TREE; } diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 2a69bf9..eab2b47 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -67,7 +67,8 @@ extern tree fold_build_call_array_loc (location_t, tree, tree, int, tree *); #define fold_build_call_array_initializer(T1,T2,N,T4)\ fold_build_call_array_initializer_loc (UNKNOWN_LOCATION, T1, T2, N, T4) extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *); -extern tree get_array_ctor_element_at_index (tree, offset_int); +extern tree get_array_ctor_element_at_index (tree, offset_int, + unsigned * = NULL); extern bool fold_convertible_p (const_tree, const_tree); #define fold_convert(T1,T2)\ fold_convert_loc (UNKNOWN_LOCATION, T1, T2) diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 118718a..be83620 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -6716,14 +6716,13 @@ fold_array_ctor_reference (tree type, tree ctor, elt_size = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor)))); /* When TYPE is non-null, verify that it specifies a constant-sized - accessed not larger than size of array element. Avoid division + access of a multiple of the array element size. Avoid division by zero below when ELT_SIZE is zero, such as with the result of an initializer for a zero-length array or an empty struct. */ if (elt_size == 0 || (type && (!TYPE_SIZE_UNIT (type) - || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST - || elt_size < wi::to_offset (TYPE_SIZE_UNIT (type))))) + || TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST))) return NULL_TREE; /* Compute the array index we look for. */ @@ -6734,10 +6733,88 @@ fold_array_ctor_reference (tree type, tree ctor, /* And offset within the access. */ inner_offset = offset % (elt_size.to_uhwi () * BITS_PER_UNIT); - /* See if the array field is large enough to span whole access. We do not - care to fold accesses spanning multiple array indexes. */ - if (inner_offset + size > elt_size.to_uhwi () * BITS_PER_UNIT) - return NULL_TREE; + if (size > elt_size.to_uhwi () * BITS_PER_UNIT) + { + /* native_encode_expr constraints. */ + if (size > MAX_BITSIZE_MODE_ANY_MODE + || size % BITS_PER_UNIT != 0 + || inner_offset % BITS_PER_UNIT != 0) + return NULL_TREE; + + unsigned ctor_idx; + tree val = get_array_ctor_element_at_index (ctor, access_index, + &ctor_idx); + if (!val && ctor_idx >= CONSTRUCTOR_NELTS (ctor)) + return build_zero_cst (type); + + /* native-encode adjacent ctor elements. */ + unsigned char buf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT]; + unsigned bufoff = 0; + offset_int index = 0; + offset_int max_index = access_index; + constructor_elt *elt = CONSTRUCTOR_ELT (ctor, ctor_idx); + if (!val) + val = build_zero_cst (TREE_TYPE (TREE_TYPE (ctor))); + else if (!CONSTANT_CLASS_P (val)) + return NULL_TREE; + if (!elt->index) + ; + else if (TREE_CODE (elt->index) == RANGE_EXPR) + { + index = wi::to_offset (TREE_OPERAND (elt->index, 0)); + max_index = wi::to_offset (TREE_OPERAND (elt->index, 1)); + } + else + index = max_index = wi::to_offset (elt->index); + index = wi::umax (index, access_index); + do + { + int len = native_encode_expr (val, buf + bufoff, + elt_size.to_uhwi (), + inner_offset / BITS_PER_UNIT); + if (len != elt_size - inner_offset / BITS_PER_UNIT) + return NULL_TREE; + inner_offset = 0; + bufoff += len; + + access_index += 1; + if (wi::cmpu (access_index, index) == 0) + val = elt->value; + else if (wi::cmpu (access_index, max_index) > 0) + { + ctor_idx++; + if (ctor_idx >= CONSTRUCTOR_NELTS (ctor)) + { + val = build_zero_cst (TREE_TYPE (TREE_TYPE (ctor))); + ++max_index; + } + else + { + elt = CONSTRUCTOR_ELT (ctor, ctor_idx); + index = 0; + max_index = access_index; + if (!elt->index) + ; + else if (TREE_CODE (elt->index) == RANGE_EXPR) + { + index = wi::to_offset (TREE_OPERAND (elt->index, 0)); + max_index = wi::to_offset (TREE_OPERAND (elt->index, 1)); + } + else + index = max_index = wi::to_offset (elt->index); + index = wi::umax (index, access_index); + if (wi::cmpu (access_index, index) == 0) + val = elt->value; + else + val = build_zero_cst (TREE_TYPE (TREE_TYPE (ctor))); + } + } + } + while (bufoff < size / BITS_PER_UNIT); + *suboff += size; + return native_interpret_expr (type, buf, size / BITS_PER_UNIT); + } + if (tree val = get_array_ctor_element_at_index (ctor, access_index)) { if (!size && TREE_CODE (val) != CONSTRUCTOR) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ed3165e..dfda37f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-12 Richard Biener + + * gcc.dg/tree-ssa/vector-7.c: New testcase. + 2019-07-12 Jakub Jelinek * c-c++-common/gomp/order-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-7.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-7.c new file mode 100644 index 0000000..ebfe15d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-7.c @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fdump-tree-optimized" } */ + +typedef __INT8_TYPE__ v16qi __attribute__((vector_size(16),may_alias,aligned(1))); +typedef __INT32_TYPE__ v4si __attribute__((vector_size(16),may_alias,aligned(1))); + +const __INT32_TYPE__ x[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; +const __INT8_TYPE__ y[32] + = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; +const __INT32_TYPE__ z[8] = { [3] = 3, [1] = 1 }; + +int +main() +{ + v4si v1 = *(v4si *)(x + 1); + for (unsigned i = 0; i < 4; ++i) + if (v1[i] != (v4si) { 2, 3, 4, 5 }[i]) + __builtin_abort (); + v4si v2 = *(v4si *)z; + for (unsigned i = 0; i < 4; ++i) + if (v2[i] != (v4si) { 0, 1, 0, 3 }[i]) + __builtin_abort (); + v4si v3 = *(v4si *)(y + 1); + for (unsigned i = 0; i < 4; ++i) + if (v3[i] != +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + (v4si) { 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f01 }[i] +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + (v4si) { 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d }[i] +#else + v3[i] +#endif + ) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ -- cgit v1.1 From 49dbd6a0325f510af43b05bc0b91426779b4ed59 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 12 Jul 2019 10:15:39 +0000 Subject: re PR rtl-optimization/91136 (incorrect move of instruction to delay slot causes application crash in exception handling) PR rtl-optimization/91136 * df-core.c (ACCESSING REFS): Fix typos in comment. * resource.c (mark_target_live_reg): Add artificial defs that occur at the beginning of the block to the initial set of live registers. From-SVN: r273436 --- gcc/ChangeLog | 7 +++++++ gcc/df-core.c | 6 +++--- gcc/resource.c | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bd47ddd..7f01af3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-12 Eric Botcazou + + PR rtl-optimization/91136 + * df-core.c (ACCESSING REFS): Fix typos in comment. + * resource.c (mark_target_live_reg): Add artificial defs that occur at + the beginning of the block to the initial set of live registers. + 2019-07-12 Richard Biener * fold-const.h (get_array_ctor_element_at_index): Adjust. diff --git a/gcc/df-core.c b/gcc/df-core.c index 44848aa..be19aba 100644 --- a/gcc/df-core.c +++ b/gcc/df-core.c @@ -298,12 +298,12 @@ There are 4 ways to obtain access to refs: Artificial defs and uses occur both at the beginning and ends of blocks. - For blocks that area at the destination of eh edges, the + For blocks that are at the destination of eh edges, the artificial uses and defs occur at the beginning. The defs relate to the registers specified in EH_RETURN_DATA_REGNO and the uses - relate to the registers specified in ED_USES. Logically these + relate to the registers specified in EH_USES. Logically these defs and uses should really occur along the eh edge, but there is - no convenient way to do this. Artificial edges that occur at the + no convenient way to do this. Artificial defs that occur at the beginning of the block have the DF_REF_AT_TOP flag set. Artificial uses occur at the end of all blocks. These arise from diff --git a/gcc/resource.c b/gcc/resource.c index f8a23ed..c4bcfd7 100644 --- a/gcc/resource.c +++ b/gcc/resource.c @@ -987,9 +987,13 @@ mark_target_live_regs (rtx_insn *insns, rtx target_maybe_return, struct resource { regset regs_live = DF_LR_IN (BASIC_BLOCK_FOR_FN (cfun, b)); rtx_insn *start_insn, *stop_insn; + df_ref def; /* Compute hard regs live at start of block. */ REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live); + FOR_EACH_ARTIFICIAL_DEF (def, b) + if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) + SET_HARD_REG_BIT (current_live_regs, DF_REF_REGNO (def)); /* Get starting and ending insn, handling the case where each might be a SEQUENCE. */ -- cgit v1.1 From 72ab1c51b607dd5446ee24ff9fce9178d6b811cb Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 12 Jul 2019 10:33:52 +0000 Subject: Relax vector_builder::elt sanity check I'd made it a precondition of vector_builder::elt that the encoding must have been fully populated and that all implicit elements are therefore defined. But for one of the AArch64 patches I'm working on, it'd be convenient to be able to look back at previous elements while building up the encoding. This patch therefore makes the assert specific to implicit elements only. 2019-07-12 Richard Sandiford gcc/ * vector-builder.h (vector_builder::elt): Allow already-supplied elements to be read back before building is complete. From-SVN: r273440 --- gcc/ChangeLog | 5 +++++ gcc/vector-builder.h | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f01af3..43b5248 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-12 Richard Sandiford + + * vector-builder.h (vector_builder::elt): Allow already-supplied + elements to be read back before building is complete. + 2019-07-12 Eric Botcazou PR rtl-optimization/91136 diff --git a/gcc/vector-builder.h b/gcc/vector-builder.h index 9f95b01..aac8a87 100644 --- a/gcc/vector-builder.h +++ b/gcc/vector-builder.h @@ -199,14 +199,15 @@ template T vector_builder::elt (unsigned int i) const { - /* This only makes sense if the encoding has been fully populated. */ - gcc_checking_assert (encoded_nelts () <= this->length ()); - /* First handle elements that are already present in the underlying vector, regardless of whether they're part of the encoding or not. */ if (i < this->length ()) return (*this)[i]; + /* Extrapolation is only possible if the encoding has been fully + populated. */ + gcc_checking_assert (encoded_nelts () <= this->length ()); + /* Identify the pattern that contains element I and work out the index of the last encoded element for that pattern. */ unsigned int pattern = i % m_npatterns; -- cgit v1.1 From fdc1f34302906036637445455a53a09f25a4acfd Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Fri, 12 Jul 2019 13:50:49 +0000 Subject: introduce try/finally/else in gimplefe for gcc/c/ChangeLog * gimple-parser.c (c_parser_gimple_try_stmt): New. (c_parser_compound_statement): Call it. for gcc/testsuite/ChangeLog * gcc.dg/gimplefe-43.c: New. From-SVN: r273443 --- gcc/c/ChangeLog | 5 ++++ gcc/c/gimple-parser.c | 61 ++++++++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/gimplefe-43.c | 25 ++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/gimplefe-43.c (limited to 'gcc') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index c58680c..927fa91 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2019-07-12 Alexandre Oliva + + * gimple-parser.c (c_parser_gimple_try_stmt): New. + (c_parser_compound_statement): Call it. + 2019-07-12 Jakub Jelinek * c-parser.c (c_parser_omp_clause_name): Handle order clause. diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index a0ea721..4970ae1 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -117,6 +117,7 @@ static struct c_expr c_parser_gimple_postfix_expression_after_primary static void c_parser_gimple_declaration (gimple_parser &); static void c_parser_gimple_goto_stmt (gimple_parser &, location_t, tree, gimple_seq *); +static void c_parser_gimple_try_stmt (gimple_parser &, gimple_seq *); static void c_parser_gimple_if_stmt (gimple_parser &, gimple_seq *); static void c_parser_gimple_switch_stmt (gimple_parser &, gimple_seq *); static void c_parser_gimple_return_stmt (gimple_parser &, gimple_seq *); @@ -407,6 +408,9 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) { + case RID_AT_TRY: + c_parser_gimple_try_stmt (parser, seq); + break; case RID_IF: c_parser_gimple_if_stmt (parser, seq); break; @@ -448,6 +452,14 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) c_parser_gimple_label (parser, seq); break; } + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_token (parser)->id_kind == C_ID_ID + && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), + "try") == 0) + { + c_parser_gimple_try_stmt (parser, seq); + break; + } /* Basic block specification. __BB (index, ...) */ if ((cfun->curr_properties & PROP_cfg) @@ -2092,6 +2104,55 @@ c_parser_gimple_paren_condition (gimple_parser &parser) return cond; } +/* Parse gimple try statement. + + try-statement: + try { ... } finally { ... } + try { ... } finally { ... } else { ... } + + This could support try/catch as well, but it's not implemented yet. + */ + +static void +c_parser_gimple_try_stmt (gimple_parser &parser, gimple_seq *seq) +{ + gimple_seq tryseq = NULL; + c_parser_consume_token (parser); + c_parser_gimple_compound_statement (parser, &tryseq); + + if ((c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_AT_FINALLY) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_token (parser)->id_kind == C_ID_ID + && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), + "finally") == 0)) + { + gimple_seq finseq = NULL; + c_parser_consume_token (parser); + c_parser_gimple_compound_statement (parser, &finseq); + + if (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_ELSE) + { + gimple_seq elsseq = NULL; + c_parser_consume_token (parser); + c_parser_gimple_compound_statement (parser, &elsseq); + + geh_else *stmt = gimple_build_eh_else (finseq, elsseq); + finseq = NULL; + gimple_seq_add_stmt_without_update (&finseq, stmt); + } + + gtry *stmt = gimple_build_try (tryseq, finseq, GIMPLE_TRY_FINALLY); + gimple_seq_add_stmt_without_update (seq, stmt); + } + else if (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_AT_CATCH) + c_parser_error (parser, "% is not supported"); + else + c_parser_error (parser, "expected % or %"); +} + /* Parse gimple if-else statement. if-statement: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dfda37f..c235200 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-12 Alexandre Oliva + + * gcc.dg/gimplefe-43.c: New. + 2019-07-12 Richard Biener * gcc.dg/tree-ssa/vector-7.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/gimplefe-43.c b/gcc/testsuite/gcc.dg/gimplefe-43.c new file mode 100644 index 0000000..5fd66e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-43.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ + +void __GIMPLE foo() +{ + try + { + try + { + ; + } + finally + { + ; + } + else + { + ; + } + } + finally + { + ; + } +} -- cgit v1.1 From b847405adee3059762816ab009bc4a5281b5b911 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Fri, 12 Jul 2019 13:51:00 +0000 Subject: allow EH to escape from GIMPLE_EH_ELSE ELSE block The only preexisting use of GIMPLE_EH_ELSE, for transactional memory commits, did not allow exceptions to escape from the ELSE path. The trick it uses to allow the ELSE path to see the propagating exception does not work very well if the exception cleanup raises further exceptions: the ELSE block is configured to handle exceptions in itself. This confuses the heck out of CFG and EH cleanups. Basing the lowering context for the ELSE block on outer_state, rather than this_state, gets us the expected enclosing handler. for gcc/ChangeLog * tree-eh.c (honor_protect_cleanup_actions): Use outer_ rather than this_state as the lowering context for the ELSE seq in a GIMPLE_EH_ELSE. for gcc/testsuite/ChangeLog * gcc.dg/gimplefe-44.c: New. From-SVN: r273444 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 2 ++ gcc/testsuite/gcc.dg/gimplefe-44.c | 33 +++++++++++++++++++++++++++++++++ gcc/tree-eh.c | 13 ++++++++----- 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/gimplefe-44.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 43b5248..2d1d29f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-12 Alexandre Oliva + + * tree-eh.c (honor_protect_cleanup_actions): Use outer_ + rather than this_state as the lowering context for the ELSE + seq in a GIMPLE_EH_ELSE. + 2019-07-12 Richard Sandiford * vector-builder.h (vector_builder::elt): Allow already-supplied diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c235200..debec92 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2019-07-12 Alexandre Oliva + * gcc.dg/gimplefe-44.c: New. + * gcc.dg/gimplefe-43.c: New. 2019-07-12 Richard Biener diff --git a/gcc/testsuite/gcc.dg/gimplefe-44.c b/gcc/testsuite/gcc.dg/gimplefe-44.c new file mode 100644 index 0000000..a9a92b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-44.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-fexceptions -fgimple -fdump-tree-eh-eh" } */ + +void __GIMPLE foo() +{ + try + { + try + { + extern void might_throw1 (); + might_throw1 (); + } + finally + { + extern void might_throw2 (); + might_throw2 (); + } + else + { + extern void might_throw3 (); + might_throw3 (); + } + } + finally + { + extern void might_throw4 (); + might_throw4 (); + } +} + +/* { dg-final { scan-tree-dump ".LP 1. might_throw1" "eh" } } */ +/* { dg-final { scan-tree-dump ".LP 2. might_throw2" "eh" } } */ +/* { dg-final { scan-tree-dump ".LP 2. might_throw3" "eh" } } */ diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index fb7d202..5bb07e4 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -996,11 +996,14 @@ honor_protect_cleanup_actions (struct leh_state *outer_state, gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else)); finally = gimple_eh_else_e_body (eh_else); - /* Let the ELSE see the exception that's being processed. */ - eh_region save_ehp = this_state->ehp_region; - this_state->ehp_region = this_state->cur_region; - lower_eh_constructs_1 (this_state, &finally); - this_state->ehp_region = save_ehp; + /* Let the ELSE see the exception that's being processed, but + since the cleanup is outside the try block, process it with + outer_state, otherwise it may be used as a cleanup for + itself, and Bad Things (TM) ensue. */ + eh_region save_ehp = outer_state->ehp_region; + outer_state->ehp_region = this_state->cur_region; + lower_eh_constructs_1 (outer_state, &finally); + outer_state->ehp_region = save_ehp; } else { -- cgit v1.1 From cf91b5997dec281e4b784c163d76d5be3e8569f6 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 12 Jul 2019 14:36:50 +0000 Subject: re PR tree-optimization/91145 (ICE: in vect_build_slp_tree_2, at tree-vect-slp.c:1143 with -march=skylake-avx512 -O3) 2019-07-12 Richard Biener PR tree-optimization/91145 * tree-vect-slp.c (vect_build_slp_tree_2): Fix reduction chain check. * gcc.dg/torture/pr91145.c: New testcase. From-SVN: r273445 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 6 +++++- gcc/testsuite/gcc.dg/torture/pr91145.c | 16 ++++++++++++++++ gcc/tree-vect-slp.c | 3 ++- 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr91145.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d1d29f..84fee9e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-12 Richard Biener + + PR tree-optimization/91145 + * tree-vect-slp.c (vect_build_slp_tree_2): Fix reduction + chain check. + 2019-07-12 Alexandre Oliva * tree-eh.c (honor_protect_cleanup_actions): Use outer_ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index debec92..e948a71 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,7 +1,11 @@ +2019-07-12 Richard Biener + + PR tree-optimization/91145 + * gcc.dg/torture/pr91145.c: New testcase. + 2019-07-12 Alexandre Oliva * gcc.dg/gimplefe-44.c: New. - * gcc.dg/gimplefe-43.c: New. 2019-07-12 Richard Biener diff --git a/gcc/testsuite/gcc.dg/torture/pr91145.c b/gcc/testsuite/gcc.dg/torture/pr91145.c new file mode 100644 index 0000000..7d62ad1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr91145.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=skylake-avx512" { target x86_64-*-* i?86-*-* } } */ + +int a, c; +unsigned b, e; +extern unsigned d[100]; + +void f() +{ + for (int g = 0; g < 70; g++) + { + + b += d[g] - c; + e -= g ^ a; + } +} diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index d172c3a..31f4519 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -1140,7 +1140,8 @@ vect_build_slp_tree_2 (vec_info *vinfo, FOR_EACH_VEC_ELT (stmts, i, other_info) { /* But for reduction chains only check on the first stmt. */ - if (REDUC_GROUP_FIRST_ELEMENT (other_info) + if (!STMT_VINFO_DATA_REF (other_info) + && REDUC_GROUP_FIRST_ELEMENT (other_info) && REDUC_GROUP_FIRST_ELEMENT (other_info) != stmt_info) continue; if (STMT_VINFO_DEF_TYPE (other_info) != def_type) -- cgit v1.1 From c3a7a7b8abb7e356c34c9bccde895d76c514e2dd Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 12 Jul 2019 09:40:39 -0600 Subject: c6x.c (c6x_section_type): Clear SECTION_NOTYPE for the ".far" section. * config/c6x/c6x.c (c6x_section_type): Clear SECTION_NOTYPE for the ".far" section. From-SVN: r273447 --- gcc/ChangeLog | 5 +++++ gcc/config/c6x/c6x.c | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 84fee9e..4f32256 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-12 Jeff Law + + * config/c6x/c6x.c (c6x_section_type): Clear SECTION_NOTYPE + for the ".far" section. + 2019-07-12 Richard Biener PR tree-optimization/91145 diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c index 93841e4..f6c9bbf 100644 --- a/gcc/config/c6x/c6x.c +++ b/gcc/config/c6x/c6x.c @@ -1083,6 +1083,14 @@ c6x_section_type_flags (tree decl, const char *name, int reloc) flags |= default_section_type_flags (decl, name, reloc); + /* The ".far" section will be declared with @nobits elsewhere. + But when declared via this path it will not have the @nobits + flag because of SECTION_NOTYPE. This causes linker warnings + due to the mismatched attribute. Clearing SECTION_NOTYPE + for the ".far" section is sufficient to fix this problem. */ + if (strcmp (name, ".far") == 0) + flags &= ~SECTION_NOTYPE; + return flags; } -- cgit v1.1 From b9ef6a2e04bfd01329902781818ef80c52cd8b97 Mon Sep 17 00:00:00 2001 From: Jiangning Liu Date: Fri, 12 Jul 2019 16:28:43 +0000 Subject: re PR tree-optimization/89430 (A missing ifcvt optimization to generate csel) 2019-07-12 Jiangning Liu PR tree-optimization/89430 * tree-ssa-phiopt.c (cond_store_replacement): Support conditional store elimination for local variable without address escape. PR tree-optimization/89430 * gcc.dg/tree-ssa/pr89430-1.c: New test. * gcc.dg/tree-ssa/pr89430-2.c: New test. * gcc.dg/tree-ssa/pr89430-3.c: New test. * gcc.dg/tree-ssa/pr89430-4.c: New test. * gcc.dg/tree-ssa/pr89430-5.c: New test. * gcc.dg/tree-ssa/pr89430-6.c: New test. From-SVN: r273449 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 10 ++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c | 12 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c | 14 ++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c | 12 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c | 14 ++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c | 16 ++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c | 19 +++++++++++++++++++ gcc/tree-ssa-phiopt.c | 24 ++++++++++++++++++++---- 9 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4f32256..8923216 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-12 Jiangning Liu + + PR tree-optimization/89430 + * tree-ssa-phiopt.c (cond_store_replacement): Support conditional + store elimination for local variable without address escape. + 2019-07-12 Jeff Law * config/c6x/c6x.c (c6x_section_type): Clear SECTION_NOTYPE diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e948a71..7181308 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2019-07-08 Jiangning Liu + + PR tree-optimization/89430 + * gcc.dg/tree-ssa/pr89430-1.c: New test. + * gcc.dg/tree-ssa/pr89430-2.c: New test. + * gcc.dg/tree-ssa/pr89430-3.c: New test. + * gcc.dg/tree-ssa/pr89430-4.c: New test. + * gcc.dg/tree-ssa/pr89430-5.c: New test. + * gcc.dg/tree-ssa/pr89430-6.c: New test. + 2019-07-12 Richard Biener PR tree-optimization/91145 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c new file mode 100644 index 0000000..8ee1850 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cselim-details" } */ + +unsigned test(unsigned k, unsigned b) { + unsigned a[2]; + if (b < a[k]) { + a[k] = b; + } + return a[0]+a[1]; +} + +/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c new file mode 100644 index 0000000..9b96875 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cselim-details" } */ + +int c; +unsigned test(unsigned k, unsigned b) { + unsigned a[2]; + a[k] = c; + if (b < a[k]) { + a[k] = b; + } + return a[0]+a[1]; +} + +/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c new file mode 100644 index 0000000..0fac9f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-3.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cselim-details" } */ + +unsigned a[2]; +unsigned test(unsigned k, unsigned b) { + if (b < a[k]) { + a[k] = b; + } + return a[0]+a[1]; +} + +/* { dg-final { scan-tree-dump-not "Conditional store replacement" "cselim" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c new file mode 100644 index 0000000..54b8c11 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cselim-details" } */ + +int *p; +unsigned test(unsigned k, unsigned b) { + unsigned a[2]; + p = a; + if (b < a[k]) { + a[k] = b; + } + return a[0]+a[1]; +} + +/* { dg-final { scan-tree-dump-not "Conditional store replacement" "cselim" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c new file mode 100644 index 0000000..b2d0411 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cselim-details" } */ + +int test(int b, int k) { + struct { + int data[2]; + } a; + + if (b < a.data[k]) { + a.data[k] = b; + } + + return a.data[0] + a.data[1]; +} + +/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c new file mode 100644 index 0000000..8d3c4f7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr89430-6.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cselim-details" } */ + +int test(int b, int k) { + typedef struct { + int x; + } SS; + struct { + SS data[2]; + } a; + + if (b < a.data[k].x) { + a.data[k].x = b; + } + + return a.data[0].x + a.data[1].x; +} + +/* { dg-final { scan-tree-dump "Conditional store replacement" "cselim" } } */ diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 7088ff9..a514ed8 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -2196,7 +2196,8 @@ get_non_trapping (void) We check that MIDDLE_BB contains only one store, that that store doesn't trap (not via NOTRAP, but via checking if an access to the same - memory location dominates us) and that the store has a "simple" RHS. */ + memory location dominates us, or the store is to a local addressable + object) and that the store has a "simple" RHS. */ static bool cond_store_replacement (basic_block middle_bb, basic_block join_bb, @@ -2218,8 +2219,9 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb, locus = gimple_location (assign); lhs = gimple_assign_lhs (assign); rhs = gimple_assign_rhs1 (assign); - if (TREE_CODE (lhs) != MEM_REF - || TREE_CODE (TREE_OPERAND (lhs, 0)) != SSA_NAME + if ((TREE_CODE (lhs) != MEM_REF + && TREE_CODE (lhs) != ARRAY_REF + && TREE_CODE (lhs) != COMPONENT_REF) || !is_gimple_reg_type (TREE_TYPE (lhs))) return false; @@ -2227,7 +2229,13 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb, TREE_THIS_NOTRAP here, but in that case we also could move stores, whose value is not available readily, which we want to avoid. */ if (!nontrap->contains (lhs)) - return false; + { + /* If LHS is a local variable without address-taken, we could + always safely move down the store. */ + tree base = get_base_address (lhs); + if (!auto_var_p (base) || TREE_ADDRESSABLE (base)) + return false; + } /* Now we've checked the constraints, so do the transformation: 1) Remove the single store. */ @@ -2280,6 +2288,14 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb, else gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "\nConditional store replacement happened!"); + fprintf (dump_file, "\nReplaced the store with a load."); + fprintf (dump_file, "\nInserted a new PHI statement in joint block:\n"); + print_gimple_stmt (dump_file, new_stmt, 0, TDF_VOPS|TDF_MEMSYMS); + } + return true; } -- cgit v1.1 From d132c59b10ac8ee35d2e48c0b598160d5bdabf46 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 12 Jul 2019 16:56:57 +0000 Subject: tree-ssa-alias.c (same_tmr_indexing_p): Break out from ... * tree-ssa-alias.c (same_tmr_indexing_p): Break out from ... (indirect_refs_may_alias_p): ... here. (nonoverlapping_component_refs_since_match_p): Support also non-trivial mem refs in the access paths. * gcc.dg/tree-ssa/alias-access-path-9.c: New testcase. From-SVN: r273451 --- gcc/ChangeLog | 8 ++++ gcc/testsuite/ChangeLog | 4 ++ .../gcc.dg/tree-ssa/alias-access-path-9.c | 44 ++++++++++++++++++++++ gcc/tree-ssa-alias.c | 43 ++++++++++----------- 4 files changed, 76 insertions(+), 23 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-9.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8923216..37b5eaf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-12 Jan Hubicka + + * tree-ssa-alias.c (same_tmr_indexing_p): Break out from ... + (indirect_refs_may_alias_p): ... here. + (nonoverlapping_component_refs_since_match_p): Support also non-trivial + mem refs in the access paths. + 2019-07-12 Jiangning Liu PR tree-optimization/89430 @@ -21,6 +28,7 @@ rather than this_state as the lowering context for the ELSE seq in a GIMPLE_EH_ELSE. +>>>>>>> .r273450 2019-07-12 Richard Sandiford * vector-builder.h (vector_builder::elt): Allow already-supplied diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7181308..4d6eb0f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-12 Jan Hubicka + + * gcc.dg/tree-ssa/alias-access-path-9.c: New testcase. + 2019-07-08 Jiangning Liu PR tree-optimization/89430 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-9.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-9.c new file mode 100644 index 0000000..fdc4789 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-9.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ + +/* This testcase tests nonoverlapping_component_refs_since_match_p in presence + of non-trivial mem-refs. */ +struct a {int a,b;}; +struct b {struct a a[10];}; +struct c {int c; struct b b;} c, *cptr; + +void +set_a(struct a *a, int p) +{ + a->a=p; +} +void +set_b(struct a *a, int p) +{ + a->b=p; +} +int +get_a(struct a *a) +{ + return a->a; +} + +int +test(int i, int j) +{ + struct b *bptr = &c.b; + set_a (&bptr->a[i], 123); + set_b (&bptr->a[j], 124); + return get_a (&bptr->a[i]); +} + +int +test2(int i, int j) +{ + struct b *bptr = &cptr->b; + set_a (&bptr->a[i], 125); + set_b (&bptr->a[j], 126); + return get_a (&bptr->a[i]); +} +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre1"} } */ +/* { dg-final { scan-tree-dump-times "return 125" 1 "fre1"} } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 54e3a54..e1ea307 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1265,20 +1265,6 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, component_refs1.safe_push (ref1); ref1 = TREE_OPERAND (ref1, 0); } - if (TREE_CODE (ref1) == MEM_REF && ref1 != match1) - { - if (!integer_zerop (TREE_OPERAND (ref1, 1))) - { - ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias; - return -1; - } - } - /* TODO: Handle TARGET_MEM_REF later. */ - if (TREE_CODE (ref1) == TARGET_MEM_REF && ref1 != match1) - { - ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias; - return -1; - } /* Create the stack of handled components for REF2. */ while (handled_component_p (ref2) && ref2 != match2) @@ -1290,20 +1276,31 @@ nonoverlapping_component_refs_since_match_p (tree match1, tree ref1, component_refs2.safe_push (ref2); ref2 = TREE_OPERAND (ref2, 0); } - if (TREE_CODE (ref2) == MEM_REF && ref2 != match2) - { - if (!integer_zerop (TREE_OPERAND (ref2, 1))) - { - ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias; - return -1; - } - } - if (TREE_CODE (ref2) == TARGET_MEM_REF && ref2 != match2) + + bool mem_ref1 = TREE_CODE (ref1) == MEM_REF && ref1 != match1; + bool mem_ref2 = TREE_CODE (ref2) == MEM_REF && ref2 != match2; + + /* If only one of access path starts with MEM_REF check that offset is 0 + so the addresses stays the same after stripping it. + TODO: In this case we may walk the other access path until we get same + offset. + + If both starts with MEM_REF, offset has to be same. */ + if ((mem_ref1 && !mem_ref2 && !integer_zerop (TREE_OPERAND (ref1, 1))) + || (mem_ref2 && !mem_ref1 && !integer_zerop (TREE_OPERAND (ref2, 1))) + || (mem_ref1 && mem_ref2 + && !tree_int_cst_equal (TREE_OPERAND (ref1, 1), + TREE_OPERAND (ref2, 1)))) { ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias; return -1; } + /* TARGET_MEM_REF are never wrapped in handled components, so we do not need + to handle them here at all. */ + gcc_checking_assert (TREE_CODE (ref1) != TARGET_MEM_REF + && TREE_CODE (ref2) != TARGET_MEM_REF); + /* Pop the stacks in parallel and examine the COMPONENT_REFs of the same rank. This is sufficient because we start from the same DECL and you cannot reference several fields at a time with COMPONENT_REFs (unlike -- cgit v1.1 From 5dd47cb75dac4583dc38e9c1df2fde89fd459a08 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 12 Jul 2019 17:36:45 +0000 Subject: invoke.texi (ssa-name-def-chain-limit): Document new --param. gcc/ChangeLog: * doc/invoke.texi (ssa-name-def-chain-limit): Document new --param. * params.def (PARAM_SSA_NAME_DEF_CHAIN_LIMIT): Add new --param. * tree-vrp.c (vrp_prop::check_mem_ref): Use PARAM_SSA_NAME_DEF_CHAIN_LIMIT. gcc/testsuite/ChangeLog: * gcc.dg/Warray-bounds-43.c: New test. From-SVN: r273454 --- gcc/ChangeLog | 8 +- gcc/doc/invoke.texi | 7 ++ gcc/params.def | 6 ++ gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/Warray-bounds-43.c | 133 ++++++++++++++++++++++++++++++++ gcc/tree-vrp.c | 3 +- 6 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-43.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 37b5eaf..685c779 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-12 Martin Sebor + + * doc/invoke.texi (ssa-name-def-chain-limit): Document new --param. + * params.def (PARAM_SSA_NAME_DEF_CHAIN_LIMIT): Add new --param. + * tree-vrp.c (vrp_prop::check_mem_ref): Use + PARAM_SSA_NAME_DEF_CHAIN_LIMIT. + 2019-07-12 Jan Hubicka * tree-ssa-alias.c (same_tmr_indexing_p): Break out from ... @@ -28,7 +35,6 @@ rather than this_state as the lowering context for the ELSE seq in a GIMPLE_EH_ELSE. ->>>>>>> .r273450 2019-07-12 Richard Sandiford * vector-builder.h (vector_builder::elt): Allow already-supplied diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 0c20cb6..b4e71f2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -12225,6 +12225,13 @@ before the loop versioning pass considers it too big to copy, discounting any instructions in inner loops that directly benefit from versioning. +@item ssa-name-def-chain-limit +The maximum number of SSA_NAME assignments to follow in determining +a property of a variable such as its value. This limits the number +of iterations or recursive calls GCC performs when optimizing certain +statements or when determining their validity prior to issuing +diagnostics. + @end table @end table diff --git a/gcc/params.def b/gcc/params.def index 4567c17..c56055d 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -1437,6 +1437,12 @@ DEFPARAM(PARAM_HASH_TABLE_VERIFICATION_LIMIT, "each searched element.", 10, 0, 0) +DEFPARAM(PARAM_SSA_NAME_DEF_CHAIN_LIMIT, + "ssa-name-def-chain-limit", + "The maximum number of SSA_NAME assignments to follow in determining " + "a value.", + 512, 0, 0) + /* Local variables: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4d6eb0f..73fe739 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-12 Martin Sebor + + * gcc.dg/Warray-bounds-43.c: New test. + 2019-07-12 Jan Hubicka * gcc.dg/tree-ssa/alias-access-path-9.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-43.c b/gcc/testsuite/gcc.dg/Warray-bounds-43.c new file mode 100644 index 0000000..8892921 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-43.c @@ -0,0 +1,133 @@ +/* Test to verify that --param ssa_name_def_chain_limit can be used to + limit the maximum number of SSA_NAME assignments the warning follows. + { dg-do compile } + { dg-options "-O2 -Wall --param ssa-name-def-chain-limit=4" } */ + +#define NOIPA __attribute__ ((noipa)) + +const char a0[] = ""; +const char a1[] = "1"; +const char a2[] = "12"; +const char a3[] = "123"; +const char a4[] = "1234"; +const char a5[] = "12345"; +const char a6[] = "123456"; +const char a7[] = "1234567"; +const char a8[] = "12345678"; +const char a9[] = "123456789"; + +void f (const char*, ...); + +int i0, i1, i2, i3, i4, i5, i6, i7, i8; + +NOIPA int g2 (int i) +{ + if (i < 1) i = 1; + + const char *p0 = a9; + const char *p1 = p0 + i; + const char *p2 = p1 + i; + + f (p0, p1, p2); + + return p2[8]; // { dg-warning "\\\[-Warray-bounds]" } +} + +NOIPA int g3 (int i) +{ + if (i < 1) i = 1; + + const char *p0 = a9; + const char *p1 = p0 + i; + const char *p2 = p1 + i; + const char *p3 = p2 + i; + + f (p0, p1, p2, p3); + + return p3[7]; // { dg-warning "\\\[-Warray-bounds]" } +} + +NOIPA int g4 (int i) +{ + if (i < 1) i = 1; + + const char *p0 = a9; + const char *p1 = p0 + i; + const char *p2 = p1 + i; + const char *p3 = p2 + i; + const char *p4 = p3 + i; + + f (p0, p1, p2, p3, p4); + + return p4[6]; // { dg-warning "\\\[-Warray-bounds]" } +} + +NOIPA int g5 (int i) +{ + if (i < 1) i = 1; + + const char *p0 = a9; + const char *p1 = p0 + i; + const char *p2 = p1 + i; + const char *p3 = p2 + i; + const char *p4 = p3 + i; + const char *p5 = p4 + i; + + f (p0, p1, p2, p3, p4, p5); + + return p5[5]; +} + +NOIPA int g6 (int i) +{ + if (i < 1) i = 1; + + const char *p0 = a9; + const char *p1 = p0 + i; + const char *p2 = p1 + i; + const char *p3 = p2 + i; + const char *p4 = p3 + i; + const char *p5 = p4 + i; + const char *p6 = p5 + i; + + f (p0, p1, p2, p3, p4, p5, p6); + + return p6[4]; +} + +NOIPA int g7 (int i) +{ + if (i < 1) i = 1; + + const char *p0 = a9; + const char *p1 = p0 + i; + const char *p2 = p1 + i; + const char *p3 = p2 + i; + const char *p4 = p3 + i; + const char *p5 = p4 + i; + const char *p6 = p5 + i; + const char *p7 = p6 + i; + + f (p0, p1, p2, p3, p4, p5, p6, p7); + + return p7[3]; +} + +NOIPA int g8 (int i) +{ + if (i < 1) i = 1; + + const char *p0 = a9; + const char *p1 = p0 + i; + const char *p2 = p1 + i; + const char *p3 = p2 + i; + const char *p4 = p3 + i; + const char *p5 = p4 + i; + const char *p6 = p5 + i; + const char *p7 = p6 + i; + const char *p8 = p7 + i; + + f (p0, p1, p2, p3, p4, p5, p6, p7, p8); + + return p8[2]; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 594ee9a..b79dfb2 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -4492,7 +4492,8 @@ vrp_prop::check_mem_ref (location_t location, tree ref, The loop computes the range of the final offset for expressions such as (A + i0 + ... + iN)[CSTOFF] where i0 through iN are SSA_NAMEs in some range. */ - while (TREE_CODE (arg) == SSA_NAME) + const unsigned limit = PARAM_VALUE (PARAM_SSA_NAME_DEF_CHAIN_LIMIT); + for (unsigned n = 0; TREE_CODE (arg) == SSA_NAME && n < limit; ++n) { gimple *def = SSA_NAME_DEF_STMT (arg); if (!is_gimple_assign (def)) -- cgit v1.1 From 61fba2674fb10a8b8b2ae6b5ec965fd1fd738395 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Fri, 12 Jul 2019 18:38:33 +0000 Subject: [Darwin, testsuite] Remove unused test. During GCC-9, the codegen for unreachable switch case statements changed such that the (undefined) behaviour of reaching such statements is directed to one of the existing switch cases. This means that the testcase which deals with the old behaviour can no longer work (and there is nothing to test with it). The [Darwin-specific] test is now redundant and can be removed. gcc/testsuite/ 2019-07-12 Iain Sandoe * gcc.dg/pr57438-2.c: Remove. From-SVN: r273457 --- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/pr57438-2.c | 23 ----------------------- 2 files changed, 4 insertions(+), 23 deletions(-) delete mode 100644 gcc/testsuite/gcc.dg/pr57438-2.c (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 73fe739..1c9db4b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-12 Iain Sandoe + + * gcc.dg/pr57438-2.c: Remove. + 2019-07-12 Martin Sebor * gcc.dg/Warray-bounds-43.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr57438-2.c b/gcc/testsuite/gcc.dg/pr57438-2.c deleted file mode 100644 index f3ff1dc..0000000 --- a/gcc/testsuite/gcc.dg/pr57438-2.c +++ /dev/null @@ -1,23 +0,0 @@ -/* { dg-do compile { target *-*-darwin* } } */ -/* { dg-options "--param case-values-threshold=3 -O2" } */ -/* { dg-additional-options "-funwind-tables" { target powerpc*-*-darwin* } } - -/* This is testing that a trailing local label is followed by a - nop where required. */ - -int foo (int x) -{ - switch (x) - { - case 0: - return 10; - case 3: - return -1; - case 5: - return 29; - default: - __builtin_unreachable(); - } -} - -/* { dg-final { scan-assembler "nop\\nLFE.*" { target { *-*-darwin* } } } } */ -- cgit v1.1 From d64c6837a72def74a510429cc33e279c355829b7 Mon Sep 17 00:00:00 2001 From: Bill Seurer Date: Fri, 12 Jul 2019 21:57:07 +0000 Subject: [PATCH] Fix typo in test case. The test case has a typo in the big endian section that reversed two digits. Fix committed as obvious. 2019-07-12 Bill Seurer * gcc.dg/tree-ssa/vector-7.c: Fix typo. From-SVN: r273459 --- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/tree-ssa/vector-7.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1c9db4b..9f136fc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-12 Bill Seurer + + * gcc.dg/tree-ssa/vector-7.c: Fix typo. + 2019-07-12 Iain Sandoe * gcc.dg/pr57438-2.c: Remove. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-7.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-7.c index ebfe15d..b8ad684 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vector-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-7.c @@ -25,7 +25,7 @@ main() for (unsigned i = 0; i < 4; ++i) if (v3[i] != #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - (v4si) { 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f01 }[i] + (v4si) { 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10 }[i] #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ (v4si) { 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d }[i] #else -- cgit v1.1 From bf85a0385f07887c35c32d62cf9d015b4ae58d22 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 13 Jul 2019 00:16:24 +0000 Subject: Daily bump. From-SVN: r273463 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3a2691b..1a8e551 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190712 +20190713 -- cgit v1.1 From 704686049d5eb2d54fe62585d2c17c5ef00dbb83 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 13 Jul 2019 08:25:04 +0200 Subject: gimplify.c (struct gimplify_omp_ctx): Add order_concurrent member. * gimplify.c (struct gimplify_omp_ctx): Add order_concurrent member. (omp_notice_threadprivate_variable): Diagnose threadprivate variable uses inside of order(concurrent) constructs. (gimplify_scan_omp_clauses): Set ctx->order_concurrent if OMP_CLAUSE_ORDER is seen. * omp-low.c (struct omp_context): Add order_concurrent member. (scan_sharing_clauses): Set ctx->order_concurrent if OMP_CLAUSE_ORDER is seen. (check_omp_nesting_restrictions): Diagnose ordered or atomic inside of simd order(concurrent). Diagnose constructs not allowed inside of for order(concurrent). (setjmp_or_longjmp_p): Add a context and TREE_PUBLIC check to avoid complaining about static double setjmp (double); or class static methods or non-global namespace setjmps. (omp_runtime_api_call): New function. (scan_omp_1_stmt): Diagnose OpenMP runtime API calls inside of order(concurrent) loops. * c-c++-common/gomp/order-3.c: New test. * c-c++-common/gomp/order-4.c: New test. From-SVN: r273464 --- gcc/ChangeLog | 20 +++ gcc/gimplify.c | 24 +++- gcc/omp-low.c | 165 ++++++++++++++++++++++- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/c-c++-common/gomp/order-3.c | 212 ++++++++++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/order-4.c | 29 ++++ 6 files changed, 444 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/order-3.c create mode 100644 gcc/testsuite/c-c++-common/gomp/order-4.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 685c779..1c6f4ad 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2019-07-13 Jakub Jelinek + + * gimplify.c (struct gimplify_omp_ctx): Add order_concurrent member. + (omp_notice_threadprivate_variable): Diagnose threadprivate variable + uses inside of order(concurrent) constructs. + (gimplify_scan_omp_clauses): Set ctx->order_concurrent if + OMP_CLAUSE_ORDER is seen. + * omp-low.c (struct omp_context): Add order_concurrent member. + (scan_sharing_clauses): Set ctx->order_concurrent if + OMP_CLAUSE_ORDER is seen. + (check_omp_nesting_restrictions): Diagnose ordered or atomic inside + of simd order(concurrent). Diagnose constructs not allowed inside of + for order(concurrent). + (setjmp_or_longjmp_p): Add a context and TREE_PUBLIC check to avoid + complaining about static double setjmp (double); or class static + methods or non-global namespace setjmps. + (omp_runtime_api_call): New function. + (scan_omp_1_stmt): Diagnose OpenMP runtime API calls inside of + order(concurrent) loops. + 2019-07-12 Martin Sebor * doc/invoke.texi (ssa-name-def-chain-limit): Document new --param. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index ca7ad33..66df5c5 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -222,6 +222,7 @@ struct gimplify_omp_ctx bool distribute; bool target_firstprivatize_array_bases; bool add_safelen1; + bool order_concurrent; int defaultmap[4]; }; @@ -7025,14 +7026,24 @@ omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl, struct gimplify_omp_ctx *octx; for (octx = ctx; octx; octx = octx->outer_context) - if ((octx->region_type & ORT_TARGET) != 0) + if ((octx->region_type & ORT_TARGET) != 0 + || octx->order_concurrent) { n = splay_tree_lookup (octx->variables, (splay_tree_key)decl); if (n == NULL) { - error ("threadprivate variable %qE used in target region", - DECL_NAME (decl)); - error_at (octx->location, "enclosing target region"); + if (octx->order_concurrent) + { + error ("threadprivate variable %qE used in a region with" + " % clause", DECL_NAME (decl)); + error_at (octx->location, "enclosing region"); + } + else + { + error ("threadprivate variable %qE used in target region", + DECL_NAME (decl)); + error_at (octx->location, "enclosing target region"); + } splay_tree_insert (octx->variables, (splay_tree_key)decl, 0); } if (decl2) @@ -9263,11 +9274,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: - case OMP_CLAUSE_ORDER: case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: break; + case OMP_CLAUSE_ORDER: + ctx->order_concurrent = true; + break; + case OMP_CLAUSE_DEFAULTMAP: enum gimplify_defaultmap_kind gdmkmin, gdmkmax; switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)) diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 052ffc9..01cf728 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -150,6 +150,9 @@ struct omp_context /* True in the second simd loop of for simd with inscan reductions. */ bool for_simd_scan_phase; + + /* True if there is order(concurrent) clause on the construct. */ + bool order_concurrent; }; static splay_tree all_contexts; @@ -1390,6 +1393,10 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) } break; + case OMP_CLAUSE_ORDER: + ctx->order_concurrent = true; + break; + case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_COLLAPSE: @@ -1402,7 +1409,6 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE_SIMD: case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_DEFAULTMAP: - case OMP_CLAUSE_ORDER: case OMP_CLAUSE_ASYNC: case OMP_CLAUSE_WAIT: case OMP_CLAUSE_GANG: @@ -2669,9 +2675,20 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR) ctx = ctx->outer; if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) { c = NULL_TREE; + if (ctx->order_concurrent + && (gimple_code (stmt) == GIMPLE_OMP_ORDERED + || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD + || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)) + { + error_at (gimple_location (stmt), + "OpenMP constructs other than % or" + " % may not be nested inside a region with" + " the % clause"); + return false; + } if (gimple_code (stmt) == GIMPLE_OMP_ORDERED) { c = gimple_omp_ordered_clauses (as_a (stmt)); @@ -2717,6 +2734,18 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) return false; } } + else if (ctx->order_concurrent + && gimple_code (stmt) != GIMPLE_OMP_PARALLEL + && (gimple_code (stmt) != GIMPLE_OMP_FOR + || gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_SIMD) + && gimple_code (stmt) != GIMPLE_OMP_SCAN) + { + error_at (gimple_location (stmt), + "OpenMP constructs other than % or" + " % may not be nested inside a region with" + " the % clause"); + return false; + } } switch (gimple_code (stmt)) { @@ -3323,12 +3352,123 @@ setjmp_or_longjmp_p (const_tree fndecl) return true; tree declname = DECL_NAME (fndecl); - if (!declname) + if (!declname + || (DECL_CONTEXT (fndecl) != NULL_TREE + && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL) + || !TREE_PUBLIC (fndecl)) return false; + const char *name = IDENTIFIER_POINTER (declname); return !strcmp (name, "setjmp") || !strcmp (name, "longjmp"); } +/* Return true if FNDECL is an omp_* runtime API call. */ + +static bool +omp_runtime_api_call (const_tree fndecl) +{ + tree declname = DECL_NAME (fndecl); + if (!declname + || (DECL_CONTEXT (fndecl) != NULL_TREE + && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL) + || !TREE_PUBLIC (fndecl)) + return false; + + const char *name = IDENTIFIER_POINTER (declname); + if (strncmp (name, "omp_", 4) != 0) + return false; + + static const char *omp_runtime_apis[] = + { + /* This array has 3 sections. First omp_* calls that don't + have any suffixes. */ + "target_alloc", + "target_associate_ptr", + "target_disassociate_ptr", + "target_free", + "target_is_present", + "target_memcpy", + "target_memcpy_rect", + NULL, + /* Now omp_* calls that are available as omp_* and omp_*_. */ + "capture_affinity", + "destroy_lock", + "destroy_nest_lock", + "display_affinity", + "get_active_level", + "get_affinity_format", + "get_cancellation", + "get_default_device", + "get_dynamic", + "get_initial_device", + "get_level", + "get_max_active_levels", + "get_max_task_priority", + "get_max_threads", + "get_nested", + "get_num_devices", + "get_num_places", + "get_num_procs", + "get_num_teams", + "get_num_threads", + "get_partition_num_places", + "get_place_num", + "get_proc_bind", + "get_team_num", + "get_thread_limit", + "get_thread_num", + "get_wtick", + "get_wtime", + "in_final", + "in_parallel", + "init_lock", + "init_nest_lock", + "is_initial_device", + "pause_resource", + "pause_resource_all", + "set_affinity_format", + "set_lock", + "set_nest_lock", + "test_lock", + "test_nest_lock", + "unset_lock", + "unset_nest_lock", + NULL, + /* And finally calls available as omp_*, omp_*_ and omp_*_8_. */ + "get_ancestor_thread_num", + "get_partition_place_nums", + "get_place_num_procs", + "get_place_proc_ids", + "get_schedule", + "get_team_size", + "set_default_device", + "set_dynamic", + "set_max_active_levels", + "set_nested", + "set_num_threads", + "set_schedule" + }; + + int mode = 0; + for (unsigned i = 0; i < ARRAY_SIZE (omp_runtime_apis); i++) + { + if (omp_runtime_apis[i] == NULL) + { + mode++; + continue; + } + size_t len = strlen (omp_runtime_apis[i]); + if (strncmp (name + 4, omp_runtime_apis[i], len) == 0 + && (name[4 + len] == '\0' + || (mode > 0 + && name[4 + len] == '_' + && (name[4 + len + 1] == '\0' + || (mode > 1 + && strcmp (name + 4 + len + 1, "8_") == 0))))) + return true; + } + return false; +} /* Helper function for scan_omp. @@ -3354,10 +3494,10 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, tree fndecl = gimple_call_fndecl (stmt); if (fndecl) { - if (setjmp_or_longjmp_p (fndecl) - && ctx + if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_SIMD + && setjmp_or_longjmp_p (fndecl)) { remove = true; error_at (gimple_location (stmt), @@ -3378,6 +3518,19 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, default: break; } + else if (ctx) + { + omp_context *octx = ctx; + if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN && ctx->outer) + octx = ctx->outer; + if (octx->order_concurrent && omp_runtime_api_call (fndecl)) + { + remove = true; + error_at (gimple_location (stmt), + "OpenMP runtime API call %qD in a region with " + "% clause", fndecl); + } + } } } if (remove) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9f136fc..dccf6ee 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-13 Jakub Jelinek + + * c-c++-common/gomp/order-3.c: New test. + * c-c++-common/gomp/order-4.c: New test. + 2019-07-12 Bill Seurer * gcc.dg/tree-ssa/vector-7.c: Fix typo. diff --git a/gcc/testsuite/c-c++-common/gomp/order-3.c b/gcc/testsuite/c-c++-common/gomp/order-3.c new file mode 100644 index 0000000..225d0cc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/order-3.c @@ -0,0 +1,212 @@ +void foo (void); +int v; +#ifdef __cplusplus +extern "C" { +#endif +int omp_get_thread_num (void); +int omp_get_num_threads (void); +int omp_target_is_present (const void *, int); +int omp_get_cancellation (void); +#ifdef __cplusplus +} +#endif + +void +f1 (int *a) +{ + int i; + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp parallel /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + foo (); + } + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp simd /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp critical /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + foo (); + } + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + foo (); + } + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + v++; + } + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic read + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + } + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ + } + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ +} + +void +f2 (int *a) +{ + int i; + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp parallel /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + foo (); + } + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp simd /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp critical /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + foo (); + } + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + foo (); + } + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + v++; + } + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic read + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + } + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ + } + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ +} + +void +f3 (int *a) +{ + int i; + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp parallel + foo (); + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp simd + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + foo (); + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + foo (); + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + v++; + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic read + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + #pragma omp task /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + a[i]++; + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp taskloop /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/order-4.c b/gcc/testsuite/c-c++-common/gomp/order-4.c new file mode 100644 index 0000000..f916772 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/order-4.c @@ -0,0 +1,29 @@ +int t; +#pragma omp threadprivate(t) + +void +f1 (void) +{ + int i; + #pragma omp simd order(concurrent) /* { dg-error "enclosing region" } */ + for (i = 0; i < 64; i++) + t++; /* { dg-error "threadprivate variable 't' used in a region with 'order\\(concurrent\\)' clause" } */ +} + +void +f2 (void) +{ + int i; + #pragma omp for simd order(concurrent) /* { dg-error "enclosing region" } */ + for (i = 0; i < 64; i++) /* { dg-error "enclosing region" "" { target c++ } } */ + t++; /* { dg-error "threadprivate variable 't' used in a region with 'order\\(concurrent\\)' clause" } */ +} + +void +f3 (void) +{ + int i; + #pragma omp for order(concurrent) /* { dg-error "enclosing region" } */ + for (i = 0; i < 64; i++) + t++; /* { dg-error "threadprivate variable 't' used in a region with 'order\\(concurrent\\)' clause" } */ +} -- cgit v1.1 From 1a888209de88d4a4a1f415beb28e5a94b95e088f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 13 Jul 2019 08:29:46 +0200 Subject: re PR c/91149 (GCC 9 and later incorrectly rejects OpenMP task reduction-modifier on target parallel combined construct) PR c/91149 * c-omp.c (c_omp_split_clauses): Fix a pasto in OMP_CLAUSE_REDUCTION_TASK handling. * c-c++-common/gomp/reduction-task-3.c: New test. From-SVN: r273465 --- gcc/c-family/ChangeLog | 6 ++++++ gcc/c-family/c-omp.c | 2 +- gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/c-c++-common/gomp/reduction-task-3.c | 12 ++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/reduction-task-3.c (limited to 'gcc') diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index b84e1f5..d360759 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2019-07-13 Jakub Jelinek + + PR c/91149 + * c-omp.c (c_omp_split_clauses): Fix a pasto in + OMP_CLAUSE_REDUCTION_TASK handling. + 2019-07-12 Jakub Jelinek * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_ORDER. diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index fc08e93..dc59bd2 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -1667,7 +1667,7 @@ c_omp_split_clauses (location_t loc, enum tree_code code, } else if (code != OMP_SECTIONS && (mask & (OMP_CLAUSE_MASK_1 - << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0 + << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0 && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dccf6ee..22cd660 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2019-07-13 Jakub Jelinek + PR c/91149 + * c-c++-common/gomp/reduction-task-3.c: New test. + * c-c++-common/gomp/order-3.c: New test. * c-c++-common/gomp/order-4.c: New test. diff --git a/gcc/testsuite/c-c++-common/gomp/reduction-task-3.c b/gcc/testsuite/c-c++-common/gomp/reduction-task-3.c new file mode 100644 index 0000000..bde2ccb --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/reduction-task-3.c @@ -0,0 +1,12 @@ +/* PR c/91149 */ + +int r; + +void +foo (void) +{ + #pragma omp parallel reduction(task, +: r) + r++; + #pragma omp target parallel reduction(task, +: r) + r++; +} -- cgit v1.1 From f2b29269c407f10718bc935b3dd5c7e8641b6847 Mon Sep 17 00:00:00 2001 From: Prathamesh Kulkarni Date: Sat, 13 Jul 2019 08:28:33 +0000 Subject: re PR target/90723 (pr88598-2.c segfaults with -msve-vector-bits=256) 2019-07-15 Prathamesh Kulkarni PR target/90723 * recog.h (temporary_volatile_ok): New class. * config/aarch64/aarch64.c (aarch64_emit_sve_pred_move): Set volatile_ok temporarily to true using temporary_volatile_ok. * expr.c (emit_block_move_via_cpymem): Likewise. * optabs.c (maybe_legitimize_operand): Likewise. From-SVN: r273466 --- gcc/ChangeLog | 9 +++++++++ gcc/config/aarch64/aarch64.c | 1 + gcc/expr.c | 10 ++-------- gcc/optabs.c | 10 ++++------ gcc/recog.h | 17 +++++++++++++++++ 5 files changed, 33 insertions(+), 14 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1c6f4ad..f41e07a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-14 Prathamesh Kulkarni + + PR target/90723 + * recog.h (temporary_volatile_ok): New class. + * config/aarch64/aarch64.c (aarch64_emit_sve_pred_move): Set + volatile_ok temporarily to true using temporary_volatile_ok. + * expr.c (emit_block_move_via_cpymem): Likewise. + * optabs.c (maybe_legitimize_operand): Likewise. + 2019-07-13 Jakub Jelinek * gimplify.c (struct gimplify_omp_ctx): Add order_concurrent member. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index e4e9e3f..5bf182c 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3457,6 +3457,7 @@ aarch64_emit_sve_pred_move (rtx dest, rtx pred, rtx src) create_output_operand (&ops[0], dest, mode); create_input_operand (&ops[1], pred, GET_MODE(pred)); create_input_operand (&ops[2], src, mode); + temporary_volatile_ok v (true); expand_insn (code_for_aarch64_pred_mov (mode), 3, ops); } diff --git a/gcc/expr.c b/gcc/expr.c index ff1f224..20e3f9c 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1732,8 +1732,6 @@ emit_block_move_via_cpymem (rtx x, rtx y, rtx size, unsigned int align, unsigned HOST_WIDE_INT max_size, unsigned HOST_WIDE_INT probable_max_size) { - int save_volatile_ok = volatile_ok; - if (expected_align < align) expected_align = align; if (expected_size != -1) @@ -1745,7 +1743,7 @@ emit_block_move_via_cpymem (rtx x, rtx y, rtx size, unsigned int align, } /* Since this is a move insn, we don't care about volatility. */ - volatile_ok = 1; + temporary_volatile_ok v (true); /* Try the most limited insn first, because there's no point including more than one in the machine description unless @@ -1809,14 +1807,10 @@ emit_block_move_via_cpymem (rtx x, rtx y, rtx size, unsigned int align, create_fixed_operand (&ops[8], NULL); } if (maybe_expand_insn (code, nops, ops)) - { - volatile_ok = save_volatile_ok; - return true; - } + return true; } } - volatile_ok = save_volatile_ok; return false; } diff --git a/gcc/optabs.c b/gcc/optabs.c index 193cd91..4b39ff6 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -7202,17 +7202,15 @@ maybe_legitimize_operand (enum insn_code icode, unsigned int opno, class expand_operand *op) { machine_mode mode, imode; - bool old_volatile_ok, result; mode = op->mode; switch (op->type) { case EXPAND_FIXED: - old_volatile_ok = volatile_ok; - volatile_ok = true; - result = maybe_legitimize_operand_same_code (icode, opno, op); - volatile_ok = old_volatile_ok; - return result; + { + temporary_volatile_ok v (true); + return maybe_legitimize_operand_same_code (icode, opno, op); + } case EXPAND_OUTPUT: gcc_assert (mode != VOIDmode); diff --git a/gcc/recog.h b/gcc/recog.h index 75cbbdc..e09b27c 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -186,6 +186,23 @@ skip_alternative (const char *p) /* Nonzero means volatile operands are recognized. */ extern int volatile_ok; +/* RAII class for temporarily setting volatile_ok. */ + +class temporary_volatile_ok +{ +public: + temporary_volatile_ok (int value) : save_volatile_ok (volatile_ok) + { + volatile_ok = value; + } + + ~temporary_volatile_ok () { volatile_ok = save_volatile_ok; } + +private: + temporary_volatile_ok (const temporary_volatile_ok &); + int save_volatile_ok; +}; + /* Set by constrain_operands to the number of the alternative that matched. */ extern int which_alternative; -- cgit v1.1 From 544a74f051255994fe03d1b4081ee66e9ae14489 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Sat, 13 Jul 2019 12:03:29 +0000 Subject: * Makefile.rtl: Use g-sercom__linux.adb for all linuxes. From-SVN: r273467 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/Makefile.rtl | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7c09238..efd9d2f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-13 Andreas Schwab + + * Makefile.rtl: Use g-sercom__linux.adb for all linuxes. + 2019-07-11 Piotr Trojanek * lib-writ.adb (Ensure_System_Dependency, diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 80ba46d..daee19a 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2460,7 +2460,6 @@ ifeq ($(strip $(filter-out riscv% linux%,$(target_cpu) $(target_os))),) s-tasinf.adb Date: Sat, 13 Jul 2019 17:57:21 +0200 Subject: rs6000: Shut up -Wformat-diag somewhat We currently get lot of build warnings like /home/segher/src/gcc/gcc/config/rs6000/rs6000-c.c:7039:12: warning: misspelled term 'builtin function' in format; use 'built-in function' instead [-Wformat-diag] 7039 | error ("builtin function %qs not supported in this compiler " | ^~~~~~~~~~~~~~~~ That would print something like builtin function '__builtin_example' not supported in this compiler Changing that to "built-in" as suggested only makes this worse. Instead, let's just remove the whole "builtin function" phrase. PR target/91148 * config/rs6000/rs6000.c (rs6000_invalid_builtin): Remove superfluous "builtin function" phrasing. gcc/testsuite/ * gcc.target/powerpc/bfp/scalar-cmp-exp-eq-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-cmp-exp-gt-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-cmp-exp-lt-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-extract-exp-1.c: Adjust. * gcc.target/powerpc/bfp/scalar-extract-exp-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-extract-exp-4.c: Adjust. * gcc.target/powerpc/bfp/scalar-extract-sig-1.c: Adjust. * gcc.target/powerpc/bfp/scalar-extract-sig-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-extract-sig-4.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-1.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-10.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-4.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-5.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-7.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-8.c: Adjust. * gcc.target/powerpc/bfp/scalar-test-data-class-11.c: Adjust. * gcc.target/powerpc/bfp/scalar-test-data-class-6.c: Adjust. * gcc.target/powerpc/bfp/scalar-test-data-class-7.c: Adjust. * gcc.target/powerpc/bfp/scalar-test-neg-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-test-neg-3.c: Adjust. * gcc.target/powerpc/bfp/scalar-test-neg-5.c: Adjust. * gcc.target/powerpc/bfp/vec-extract-exp-2.c: Adjust. * gcc.target/powerpc/bfp/vec-extract-exp-3.c: Adjust. * gcc.target/powerpc/bfp/vec-extract-sig-2.c: Adjust. * gcc.target/powerpc/bfp/vec-extract-sig-3.c: Adjust. * gcc.target/powerpc/bfp/vec-insert-exp-2.c: Adjust. * gcc.target/powerpc/bfp/vec-insert-exp-3.c: Adjust. * gcc.target/powerpc/bfp/vec-insert-exp-6.c: Adjust. * gcc.target/powerpc/bfp/vec-insert-exp-7.c: Adjust. * gcc.target/powerpc/bfp/vec-test-data-class-2.c: Adjust. * gcc.target/powerpc/bfp/vec-test-data-class-3.c: Adjust. * gcc.target/powerpc/byte-in-either-range-1.c: Adjust. * gcc.target/powerpc/byte-in-range-1.c: Adjust. * gcc.target/powerpc/byte-in-set-1.c: Adjust. * gcc.target/powerpc/byte-in-set-2.c: Adjust. * gcc.target/powerpc/cmpb-3.c: Adjust. * gcc.target/powerpc/crypto-builtin-2.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-1.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-11.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-16.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-21.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-26.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-31.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-36.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-41.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-46.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-51.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-56.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-6.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-61.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-66.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-71.c: Adjust. * gcc.target/powerpc/dfp/dtstsfi-76.c: Adjust. * gcc.target/powerpc/vsu/vec-all-nez-7.c: Adjust. * gcc.target/powerpc/vsu/vec-any-eqz-7.c: Adjust. * gcc.target/powerpc/vsu/vec-cmpnez-7.c: Adjust. * gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c: Adjust. * gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c: Adjust. * gcc.target/powerpc/vsu/vec-xl-len-12.c: Adjust. * gcc.target/powerpc/vsu/vec-xl-len-13.c: Adjust. * gcc.target/powerpc/vsu/vec-xlx-7.c: Adjust. * gcc.target/powerpc/vsu/vec-xrx-7.c: Adjust. * gcc.target/powerpc/vsu/vec-xst-len-12.c: Adjust. * gcc.target/powerpc/vsu/vec-xst-len-13.c: Adjust. From-SVN: r273468 --- gcc/ChangeLog | 8 ++- gcc/config/rs6000/rs6000.c | 51 +++++++--------- gcc/testsuite/ChangeLog | 70 ++++++++++++++++++++++ .../gcc.target/powerpc/bfp/scalar-cmp-exp-eq-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-cmp-exp-gt-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-cmp-exp-lt-2.c | 2 +- .../powerpc/bfp/scalar-cmp-exp-unordered-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-extract-exp-1.c | 2 +- .../gcc.target/powerpc/bfp/scalar-extract-exp-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-extract-exp-4.c | 2 +- .../gcc.target/powerpc/bfp/scalar-extract-sig-1.c | 2 +- .../gcc.target/powerpc/bfp/scalar-extract-sig-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-extract-sig-4.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-1.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-10.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-4.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-5.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-7.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-8.c | 2 +- .../powerpc/bfp/scalar-test-data-class-11.c | 2 +- .../powerpc/bfp/scalar-test-data-class-6.c | 2 +- .../powerpc/bfp/scalar-test-data-class-7.c | 2 +- .../gcc.target/powerpc/bfp/scalar-test-neg-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-test-neg-3.c | 2 +- .../gcc.target/powerpc/bfp/scalar-test-neg-5.c | 2 +- .../gcc.target/powerpc/bfp/vec-extract-exp-2.c | 2 +- .../gcc.target/powerpc/bfp/vec-extract-exp-3.c | 2 +- .../gcc.target/powerpc/bfp/vec-extract-sig-2.c | 2 +- .../gcc.target/powerpc/bfp/vec-extract-sig-3.c | 2 +- .../gcc.target/powerpc/bfp/vec-insert-exp-2.c | 2 +- .../gcc.target/powerpc/bfp/vec-insert-exp-3.c | 2 +- .../gcc.target/powerpc/bfp/vec-insert-exp-6.c | 2 +- .../gcc.target/powerpc/bfp/vec-insert-exp-7.c | 2 +- .../gcc.target/powerpc/bfp/vec-test-data-class-2.c | 2 +- .../gcc.target/powerpc/bfp/vec-test-data-class-3.c | 2 +- .../gcc.target/powerpc/byte-in-either-range-1.c | 2 +- gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c | 2 +- gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c | 2 +- gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c | 2 +- gcc/testsuite/gcc.target/powerpc/cmpb-3.c | 2 +- .../gcc.target/powerpc/crypto-builtin-2.c | 14 ++--- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-1.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-11.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-16.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-21.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-26.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-31.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-36.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-41.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-46.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-51.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-56.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-6.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-61.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-66.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-71.c | 2 +- gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-76.c | 2 +- .../gcc.target/powerpc/vsu/vec-all-nez-7.c | 2 +- .../gcc.target/powerpc/vsu/vec-any-eqz-7.c | 2 +- .../gcc.target/powerpc/vsu/vec-cmpnez-7.c | 2 +- .../gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c | 2 +- .../gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c | 2 +- .../gcc.target/powerpc/vsu/vec-xl-len-12.c | 2 +- .../gcc.target/powerpc/vsu/vec-xl-len-13.c | 2 +- gcc/testsuite/gcc.target/powerpc/vsu/vec-xlx-7.c | 2 +- gcc/testsuite/gcc.target/powerpc/vsu/vec-xrx-7.c | 2 +- .../gcc.target/powerpc/vsu/vec-xst-len-12.c | 2 +- .../gcc.target/powerpc/vsu/vec-xst-len-13.c | 2 +- 69 files changed, 170 insertions(+), 103 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f41e07a..2f83c26 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,10 @@ -2019-07-14 Prathamesh Kulkarni +2019-07-13 Segher Boessenkool + + PR target/91148 + * config/rs6000/rs6000.c (rs6000_invalid_builtin): Remove superfluous + "builtin function" phrasing. + +2019-07-13 Prathamesh Kulkarni PR target/90723 * recog.h (temporary_volatile_ok): New class. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 39fa6ec..827894c 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -14785,62 +14785,53 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode) gcc_assert (name != NULL); if ((fnmask & RS6000_BTM_CELL) != 0) - error ("builtin function %qs is only valid for the cell processor", name); + error ("%qs is only valid for the cell processor", name); else if ((fnmask & RS6000_BTM_VSX) != 0) - error ("builtin function %qs requires the %qs option", name, "-mvsx"); + error ("%qs requires the %qs option", name, "-mvsx"); else if ((fnmask & RS6000_BTM_HTM) != 0) - error ("builtin function %qs requires the %qs option", name, "-mhtm"); + error ("%qs requires the %qs option", name, "-mhtm"); else if ((fnmask & RS6000_BTM_ALTIVEC) != 0) - error ("builtin function %qs requires the %qs option", name, "-maltivec"); + error ("%qs requires the %qs option", name, "-maltivec"); else if ((fnmask & (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) == (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) - error ("builtin function %qs requires the %qs and %qs options", - name, "-mhard-dfp", "-mpower8-vector"); + error ("%qs requires the %qs and %qs options", name, "-mhard-dfp", + "-mpower8-vector"); else if ((fnmask & RS6000_BTM_DFP) != 0) - error ("builtin function %qs requires the %qs option", name, "-mhard-dfp"); + error ("%qs requires the %qs option", name, "-mhard-dfp"); else if ((fnmask & RS6000_BTM_P8_VECTOR) != 0) - error ("builtin function %qs requires the %qs option", name, - "-mpower8-vector"); + error ("%qs requires the %qs option", name, "-mpower8-vector"); else if ((fnmask & (RS6000_BTM_P9_VECTOR | RS6000_BTM_64BIT)) == (RS6000_BTM_P9_VECTOR | RS6000_BTM_64BIT)) - error ("builtin function %qs requires the %qs and %qs options", - name, "-mcpu=power9", "-m64"); + error ("%qs requires the %qs and %qs options", name, "-mcpu=power9", + "-m64"); else if ((fnmask & RS6000_BTM_P9_VECTOR) != 0) - error ("builtin function %qs requires the %qs option", name, - "-mcpu=power9"); + error ("%qs requires the %qs option", name, "-mcpu=power9"); else if ((fnmask & (RS6000_BTM_P9_MISC | RS6000_BTM_64BIT)) == (RS6000_BTM_P9_MISC | RS6000_BTM_64BIT)) - error ("builtin function %qs requires the %qs and %qs options", - name, "-mcpu=power9", "-m64"); + error ("%qs requires the %qs and %qs options", name, "-mcpu=power9", + "-m64"); else if ((fnmask & RS6000_BTM_P9_MISC) == RS6000_BTM_P9_MISC) - error ("builtin function %qs requires the %qs option", name, - "-mcpu=power9"); + error ("%qs requires the %qs option", name, "-mcpu=power9"); else if ((fnmask & RS6000_BTM_LDBL128) == RS6000_BTM_LDBL128) { if (!TARGET_HARD_FLOAT) - error ("builtin function %qs requires the %qs option", name, - "-mhard-float"); + error ("%qs requires the %qs option", name, "-mhard-float"); else - error ("builtin function %qs requires the %qs option", name, + error ("%qs requires the %qs option", name, TARGET_IEEEQUAD ? "-mabi=ibmlongdouble" : "-mlong-double-128"); } else if ((fnmask & RS6000_BTM_HARD_FLOAT) != 0) - error ("builtin function %qs requires the %qs option", name, - "-mhard-float"); + error ("%qs requires the %qs option", name, "-mhard-float"); else if ((fnmask & RS6000_BTM_FLOAT128_HW) != 0) - error ("builtin function %qs requires ISA 3.0 IEEE 128-bit floating point", - name); + error ("%qs requires ISA 3.0 IEEE 128-bit floating point", name); else if ((fnmask & RS6000_BTM_FLOAT128) != 0) - error ("builtin function %qs requires the %qs option", name, - "%<-mfloat128%>"); + error ("%qs requires the %qs option", name, "%<-mfloat128%>"); else if ((fnmask & (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64)) == (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64)) - error ("builtin function %qs requires the %qs (or newer), and " - "%qs or %qs options", + error ("%qs requires the %qs (or newer), and %qs or %qs options", name, "-mcpu=power7", "-m64", "-mpowerpc64"); else - error ("builtin function %qs is not supported with the current options", - name); + error ("%qs is not supported with the current options", name); } /* Target hook for early folding of built-ins, shamelessly stolen diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 22cd660..4cdb328 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,73 @@ +2019-07-13 Segher Boessenkool + + PR target/91148 + * gcc.target/powerpc/bfp/scalar-cmp-exp-eq-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-cmp-exp-gt-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-cmp-exp-lt-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-extract-exp-1.c: Adjust. + * gcc.target/powerpc/bfp/scalar-extract-exp-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-extract-exp-4.c: Adjust. + * gcc.target/powerpc/bfp/scalar-extract-sig-1.c: Adjust. + * gcc.target/powerpc/bfp/scalar-extract-sig-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-extract-sig-4.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-1.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-10.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-4.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-5.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-7.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-8.c: Adjust. + * gcc.target/powerpc/bfp/scalar-test-data-class-11.c: Adjust. + * gcc.target/powerpc/bfp/scalar-test-data-class-6.c: Adjust. + * gcc.target/powerpc/bfp/scalar-test-data-class-7.c: Adjust. + * gcc.target/powerpc/bfp/scalar-test-neg-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-test-neg-3.c: Adjust. + * gcc.target/powerpc/bfp/scalar-test-neg-5.c: Adjust. + * gcc.target/powerpc/bfp/vec-extract-exp-2.c: Adjust. + * gcc.target/powerpc/bfp/vec-extract-exp-3.c: Adjust. + * gcc.target/powerpc/bfp/vec-extract-sig-2.c: Adjust. + * gcc.target/powerpc/bfp/vec-extract-sig-3.c: Adjust. + * gcc.target/powerpc/bfp/vec-insert-exp-2.c: Adjust. + * gcc.target/powerpc/bfp/vec-insert-exp-3.c: Adjust. + * gcc.target/powerpc/bfp/vec-insert-exp-6.c: Adjust. + * gcc.target/powerpc/bfp/vec-insert-exp-7.c: Adjust. + * gcc.target/powerpc/bfp/vec-test-data-class-2.c: Adjust. + * gcc.target/powerpc/bfp/vec-test-data-class-3.c: Adjust. + * gcc.target/powerpc/byte-in-either-range-1.c: Adjust. + * gcc.target/powerpc/byte-in-range-1.c: Adjust. + * gcc.target/powerpc/byte-in-set-1.c: Adjust. + * gcc.target/powerpc/byte-in-set-2.c: Adjust. + * gcc.target/powerpc/cmpb-3.c: Adjust. + * gcc.target/powerpc/crypto-builtin-2.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-1.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-11.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-16.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-21.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-26.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-31.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-36.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-41.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-46.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-51.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-56.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-6.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-61.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-66.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-71.c: Adjust. + * gcc.target/powerpc/dfp/dtstsfi-76.c: Adjust. + * gcc.target/powerpc/vsu/vec-all-nez-7.c: Adjust. + * gcc.target/powerpc/vsu/vec-any-eqz-7.c: Adjust. + * gcc.target/powerpc/vsu/vec-cmpnez-7.c: Adjust. + * gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c: Adjust. + * gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c: Adjust. + * gcc.target/powerpc/vsu/vec-xl-len-12.c: Adjust. + * gcc.target/powerpc/vsu/vec-xl-len-13.c: Adjust. + * gcc.target/powerpc/vsu/vec-xlx-7.c: Adjust. + * gcc.target/powerpc/vsu/vec-xrx-7.c: Adjust. + * gcc.target/powerpc/vsu/vec-xst-len-12.c: Adjust. + * gcc.target/powerpc/vsu/vec-xst-len-13.c: Adjust. + 2019-07-13 Jakub Jelinek PR c/91149 diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-2.c index 6d713d2..604dbbc 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-eq-2.c @@ -11,5 +11,5 @@ compare_exponents_eq (double *exponent1_p, double *exponent2_p) double exponent1 = *exponent1_p; double exponent2 = *exponent2_p; - return __builtin_vec_scalar_cmp_exp_eq (exponent1, exponent2); /* { dg-error "builtin function '__builtin_vsx_scalar_cmp_exp_dp_eq' requires" } */ + return __builtin_vec_scalar_cmp_exp_eq (exponent1, exponent2); /* { dg-error "'__builtin_vsx_scalar_cmp_exp_dp_eq' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-2.c index f3d8f04..2f01b87 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-gt-2.c @@ -11,5 +11,5 @@ compare_exponents_gt (double *exponent1_p, double *exponent2_p) double exponent1 = *exponent1_p; double exponent2 = *exponent2_p; - return __builtin_vec_scalar_cmp_exp_gt (exponent1, exponent2); /* { dg-error "builtin function '__builtin_vsx_scalar_cmp_exp_dp_gt' requires" } */ + return __builtin_vec_scalar_cmp_exp_gt (exponent1, exponent2); /* { dg-error "'__builtin_vsx_scalar_cmp_exp_dp_gt' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-2.c index 0dd210a..75969c2 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-lt-2.c @@ -11,5 +11,5 @@ compare_exponents_lt (double *exponent1_p, double *exponent2_p) double exponent1 = *exponent1_p; double exponent2 = *exponent2_p; - return __builtin_vec_scalar_cmp_exp_lt (exponent1, exponent2); /* { dg-error "builtin function '__builtin_vsx_scalar_cmp_exp_dp_lt' requires" } */ + return __builtin_vec_scalar_cmp_exp_lt (exponent1, exponent2); /* { dg-error "'__builtin_vsx_scalar_cmp_exp_dp_lt' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-2.c index 6987991..f59b4a3 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-cmp-exp-unordered-2.c @@ -11,5 +11,5 @@ compare_exponents_unordered (double *exponent1_p, double *exponent2_p) double exponent1 = *exponent1_p; double exponent2 = *exponent2_p; - return __builtin_vec_scalar_cmp_exp_unordered (exponent1, exponent2); /* { dg-error "builtin function '__builtin_vsx_scalar_cmp_exp_dp_unordered' requires" } */ + return __builtin_vec_scalar_cmp_exp_unordered (exponent1, exponent2); /* { dg-error "'__builtin_vsx_scalar_cmp_exp_dp_unordered' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-1.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-1.c index d77d84c..9737762 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-1.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-1.c @@ -11,7 +11,7 @@ get_exponent (double *p) { double source = *p; - return __builtin_vec_scalar_extract_exp (source); /* { dg-error "builtin function '__builtin_vsx_scalar_extract_exp' requires" } */ + return __builtin_vec_scalar_extract_exp (source); /* { dg-error "'__builtin_vsx_scalar_extract_exp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c index 3f4d97b..b04462f 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c @@ -14,7 +14,7 @@ get_exponent (double *p) { double source = *p; - return scalar_extract_exp (source); /* { dg-error "builtin function '__builtin_vec_scalar_extract_exp' not supported in this compiler configuration" } */ + return scalar_extract_exp (source); /* { dg-error "'__builtin_vec_scalar_extract_exp' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c index b3d4910..850ff62 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-4.c @@ -11,7 +11,7 @@ get_exponent (__ieee128 *p) { __ieee128 source = *p; - return __builtin_vec_scalar_extract_exp (source); /* { dg-error "builtin function '__builtin_vsx_scalar_extract_expq' requires" } */ + return __builtin_vec_scalar_extract_exp (source); /* { dg-error "'__builtin_vsx_scalar_extract_expq' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-1.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-1.c index b87e6d46..f12eed3 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-1.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-1.c @@ -11,5 +11,5 @@ get_significand (double *p) { double source = *p; - return __builtin_vec_scalar_extract_sig (source); /* { dg-error "builtin function '__builtin_vsx_scalar_extract_sig' requires" } */ + return __builtin_vec_scalar_extract_sig (source); /* { dg-error "'__builtin_vsx_scalar_extract_sig' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c index 4a9819c..c912879 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c @@ -12,5 +12,5 @@ get_significand (double *p) { double source = *p; - return __builtin_vec_scalar_extract_sig (source); /* { dg-error "builtin function '__builtin_vec_scalar_extract_sig' not supported in this compiler configuration" } */ + return __builtin_vec_scalar_extract_sig (source); /* { dg-error "'__builtin_vec_scalar_extract_sig' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c index cf8f14c..32a53c6 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-4.c @@ -11,5 +11,5 @@ get_significand (__ieee128 *p) { __ieee128 source = *p; - return __builtin_vec_scalar_extract_sig (source); /* { dg-error "builtin function '__builtin_vsx_scalar_extract_sigq' requires" } */ + return __builtin_vec_scalar_extract_sig (source); /* { dg-error "'__builtin_vsx_scalar_extract_sigq' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-1.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-1.c index a913899..8260b10 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-1.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-1.c @@ -13,5 +13,5 @@ insert_exponent (unsigned long long int *significand_p, unsigned long long int significand = *significand_p; unsigned long long int exponent = *exponent_p; - return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "builtin function '__builtin_vsx_scalar_insert_exp' requires" } */ + return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vsx_scalar_insert_exp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c index 196a6f6..769d3b0 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-10.c @@ -13,5 +13,5 @@ insert_exponent (__ieee128 *significand_p, __ieee128 significand = *significand_p; unsigned long long int exponent = *exponent_p; - return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "builtin function '__builtin_vsx_scalar_insert_exp_qp' requires" } */ + return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vsx_scalar_insert_exp_qp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c index 9cab364..af27099 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c @@ -16,5 +16,5 @@ insert_exponent (unsigned long long int *significand_p, unsigned long long int significand = *significand_p; unsigned long long int exponent = *exponent_p; - return scalar_insert_exp (significand, exponent); /* { dg-error "builtin function '__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ + return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-4.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-4.c index a248703..1699c67 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-4.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-4.c @@ -13,5 +13,5 @@ insert_exponent (double *significand_p, double significand = *significand_p; unsigned long long int exponent = *exponent_p; - return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "builtin function '__builtin_vsx_scalar_insert_exp_dp' requires" } */ + return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vsx_scalar_insert_exp_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c index a6605b9..05b98d9 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c @@ -16,5 +16,5 @@ insert_exponent (double *significand_p, double significand = *significand_p; unsigned long long int exponent = *exponent_p; - return scalar_insert_exp (significand, exponent); /* { dg-error "builtin function '__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ + return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c index 3f6a3ff..2e03e15 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-7.c @@ -13,5 +13,5 @@ insert_exponent (unsigned __int128 *significand_p, unsigned __int128 significand = *significand_p; unsigned long long int exponent = *exponent_p; - return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "builtin function '__builtin_vsx_scalar_insert_exp_q' requires" } */ + return __builtin_vec_scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vsx_scalar_insert_exp_q' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c index 2bb4f5e..d1a0a8b 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c @@ -16,5 +16,5 @@ insert_exponent (unsigned __int128 *significand_p, /* { dg-error "'__int128' is unsigned __int128 significand = *significand_p; /* { dg-error "'__int128' is not supported on this target" } */ unsigned long long int exponent = *exponent_p; - return scalar_insert_exp (significand, exponent); /* { dg-error "builtin function '__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ + return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c index 1ed3fd2..7c6fca2 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-11.c @@ -10,5 +10,5 @@ test_data_class (__ieee128 *p) { __ieee128 source = *p; - return __builtin_vec_scalar_test_data_class (source, 3); /* { dg-error "builtin function '__builtin_vsx_scalar_test_data_class_qp' requires" } */ + return __builtin_vec_scalar_test_data_class (source, 3); /* { dg-error "'__builtin_vsx_scalar_test_data_class_qp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-6.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-6.c index 9fae5ff..7fb6601 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-6.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-6.c @@ -10,5 +10,5 @@ test_data_class (double *p) { double source = *p; - return __builtin_vec_scalar_test_data_class (source, 3); /* { dg-error "builtin function '__builtin_vsx_scalar_test_data_class_dp' requires" } */ + return __builtin_vec_scalar_test_data_class (source, 3); /* { dg-error "'__builtin_vsx_scalar_test_data_class_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-7.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-7.c index f3e8a20..02e9ec5 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-7.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-data-class-7.c @@ -10,5 +10,5 @@ test_data_class (float *p) { float source = *p; - return __builtin_vec_scalar_test_data_class (source, 3); /* { dg-error "builtin function '__builtin_vsx_scalar_test_data_class_sp' requires" } */ + return __builtin_vec_scalar_test_data_class (source, 3); /* { dg-error "'__builtin_vsx_scalar_test_data_class_sp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c index 6bdf1d6..7d2b4de 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-2.c @@ -10,5 +10,5 @@ test_neg (float *p) { float source = *p; - return __builtin_vec_scalar_test_neg_sp (source); /* { dg-error "builtin function '__builtin_vsx_scalar_test_neg_sp' requires" } */ + return __builtin_vec_scalar_test_neg_sp (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_sp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c index 681b3d7..b503dfa 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-3.c @@ -10,5 +10,5 @@ test_neg (double *p) { double source = *p; - return __builtin_vec_scalar_test_neg_dp (source); /* { dg-error "builtin function '__builtin_vsx_scalar_test_neg_dp' requires" } */ + return __builtin_vec_scalar_test_neg_dp (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c index b234ab9..bab8604 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-test-neg-5.c @@ -10,5 +10,5 @@ test_neg (__ieee128 *p) { __ieee128 source = *p; - return __builtin_vec_scalar_test_neg_qp (source); /* { dg-error "builtin function '__builtin_vsx_scalar_test_neg_qp' requires" } */ + return __builtin_vec_scalar_test_neg_qp (source); /* { dg-error "'__builtin_vsx_scalar_test_neg_qp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-2.c index e27e053..86d0260 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-2.c @@ -9,5 +9,5 @@ get_exponents (__vector double *p) { __vector double source = *p; - return __builtin_vec_extract_exp (source); /* { dg-error "builtin function '__builtin_vsx_extract_exp_dp' requires" } */ + return __builtin_vec_extract_exp (source); /* { dg-error "'__builtin_vsx_extract_exp_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-3.c index c2d48f8..e909a26 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-3.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-exp-3.c @@ -9,5 +9,5 @@ get_exponents (__vector float *p) { __vector float source = *p; - return __builtin_vec_extract_exp (source); /* { dg-error "builtin function '__builtin_vsx_extract_exp_sp' requires" } */ + return __builtin_vec_extract_exp (source); /* { dg-error "'__builtin_vsx_extract_exp_sp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-2.c index 0ef4b3c..eab6673 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-2.c @@ -9,5 +9,5 @@ get_significands (__vector double *p) { __vector double source = *p; - return __builtin_vec_extract_sig (source); /* { dg-error "builtin function '__builtin_vsx_extract_sig_dp' requires" } */ + return __builtin_vec_extract_sig (source); /* { dg-error "'__builtin_vsx_extract_sig_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-3.c index 4727fc3..ab1967b 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-3.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-extract-sig-3.c @@ -9,5 +9,5 @@ get_significands (__vector float *p) { __vector float source = *p; - return __builtin_vec_extract_sig (source); /* { dg-error "builtin function '__builtin_vsx_extract_sig_sp' requires" } */ + return __builtin_vec_extract_sig (source); /* { dg-error "'__builtin_vsx_extract_sig_sp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-2.c index 4f33fd2..6aa6b40 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-2.c @@ -11,5 +11,5 @@ make_floats (__vector unsigned int *significands_p, __vector unsigned int significands = *significands_p; __vector unsigned int exponents = *exponents_p; - return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "builtin function '__builtin_vsx_insert_exp_sp' requires" } */ + return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "'__builtin_vsx_insert_exp_sp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-3.c index 097f0da..ab4c2f1 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-3.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-3.c @@ -11,5 +11,5 @@ make_doubles (__vector unsigned long long int *significands_p, __vector unsigned long long int significands = *significands_p; __vector unsigned long long int exponents = *exponents_p; - return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "builtin function '__builtin_vsx_insert_exp_dp' requires" } */ + return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "'__builtin_vsx_insert_exp_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-6.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-6.c index 01595cd..70ed82b 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-6.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-6.c @@ -11,5 +11,5 @@ make_floats (__vector float *significands_p, __vector float significands = *significands_p; __vector unsigned int exponents = *exponents_p; - return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "builtin function '__builtin_vsx_insert_exp_sp' requires" } */ + return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "'__builtin_vsx_insert_exp_sp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-7.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-7.c index 3401630..eb5dda4 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-7.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-insert-exp-7.c @@ -11,5 +11,5 @@ make_doubles (__vector double *significands_p, __vector double significands = *significands_p; __vector unsigned long long int exponents = *exponents_p; - return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "builtin function '__builtin_vsx_insert_exp_dp' requires" } */ + return __builtin_vec_insert_exp (significands, exponents); /* { dg-error "'__builtin_vsx_insert_exp_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-2.c index 1ade5fb..f53efdc 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-2.c @@ -9,5 +9,5 @@ get_data_class_flags (__vector double *p) { __vector double source = *p; - return __builtin_vec_test_data_class (source, 0x37); /* { dg-error "builtin function '__builtin_vsx_test_data_class_dp' requires" } */ + return __builtin_vec_test_data_class (source, 0x37); /* { dg-error "'__builtin_vsx_test_data_class_dp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-3.c b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-3.c index a4f804e..5ec7019 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-3.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/vec-test-data-class-3.c @@ -9,5 +9,5 @@ get_data_class_flags (__vector float *p) { __vector float source = *p; - return __builtin_vec_test_data_class (source, 0x37); /* { dg-error "builtin function '__builtin_vsx_test_data_class_sp' requires" } */ + return __builtin_vec_test_data_class (source, 0x37); /* { dg-error "'__builtin_vsx_test_data_class_sp' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c b/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c index 6e11285..e67fb66 100644 --- a/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c +++ b/gcc/testsuite/gcc.target/powerpc/byte-in-either-range-1.c @@ -17,5 +17,5 @@ test_byte_in_either_range (unsigned char b, range_encoding = ((first_hi_bound << 24) | (first_lo_bound << 16) | (second_hi_bound << 8) | second_lo_bound); - return __builtin_byte_in_either_range (b, range_encoding); /* { dg-error "builtin function '__builtin_scalar_byte_in_either_range' requires" } */ + return __builtin_byte_in_either_range (b, range_encoding); /* { dg-error "'__builtin_scalar_byte_in_either_range' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c b/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c index bd4a9d3..4f4ad8f 100644 --- a/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c +++ b/gcc/testsuite/gcc.target/powerpc/byte-in-range-1.c @@ -10,6 +10,6 @@ test_byte_in_range (unsigned char b, unsigned char low_range, unsigned char high_range) { unsigned int range_encoding = (high_range << 8) | low_range; - return __builtin_byte_in_range (b, range_encoding); /* { dg-error "builtin function '__builtin_scalar_byte_in_range' requires" } */ + return __builtin_byte_in_range (b, range_encoding); /* { dg-error "'__builtin_scalar_byte_in_range' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c b/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c index 3d3247a..a369dc1 100644 --- a/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c +++ b/gcc/testsuite/gcc.target/powerpc/byte-in-set-1.c @@ -9,5 +9,5 @@ int test_byte_in_set (unsigned char b, unsigned long long set_members) { - return __builtin_byte_in_set (b, set_members); /* { dg-error "builtin function '__builtin_scalar_byte_in_set' requires" } */ + return __builtin_byte_in_set (b, set_members); /* { dg-error "'__builtin_scalar_byte_in_set' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c index a858841..a741010 100644 --- a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c +++ b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c @@ -11,5 +11,5 @@ int test_byte_in_set (unsigned char b, unsigned long long set_members) { - return __builtin_byte_in_set (b, set_members); /* { dg-error "builtin function '__builtin_byte_in_set' not supported in this compiler configuration" } */ + return __builtin_byte_in_set (b, set_members); /* { dg-error "'__builtin_byte_in_set' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb-3.c b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c index 70de475..0fa8eb1 100644 --- a/gcc/testsuite/gcc.target/powerpc/cmpb-3.c +++ b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c @@ -8,7 +8,7 @@ void abort (); long long int do_compare (long long int a, long long int b) { - return __builtin_cmpb (a, b); /* { dg-error "builtin function '__builtin_cmpb' not supported in this compiler configuration" } */ + return __builtin_cmpb (a, b); /* { dg-error "'__builtin_cmpb' not supported in this compiler configuration" } */ } void expect (long long int pattern, long long int value) diff --git a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c index a3389ff..4066b12 100644 --- a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c +++ b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-2.c @@ -5,21 +5,21 @@ void use_builtins_d (__vector unsigned long long *p, __vector unsigned long long *q, __vector unsigned long long *r, __vector unsigned long long *s) { - p[0] = __builtin_crypto_vcipher (q[0], r[0]); /* { dg-error "builtin function '__builtin_crypto_vcipher' is not supported with the current options" } */ - p[1] = __builtin_crypto_vcipherlast (q[1], r[1]); /* { dg-error "builtin function '__builtin_crypto_vcipherlast' is not supported with the current options" } */ - p[2] = __builtin_crypto_vncipher (q[2], r[2]); /* { dg-error "builtin function '__builtin_crypto_vncipher' is not supported with the current options" } */ - p[3] = __builtin_crypto_vncipherlast (q[3], r[3]); /* { dg-error "builtin function '__builtin_crypto_vncipherlast' is not supported with the current options" } */ + p[0] = __builtin_crypto_vcipher (q[0], r[0]); /* { dg-error "'__builtin_crypto_vcipher' is not supported with the current options" } */ + p[1] = __builtin_crypto_vcipherlast (q[1], r[1]); /* { dg-error "'__builtin_crypto_vcipherlast' is not supported with the current options" } */ + p[2] = __builtin_crypto_vncipher (q[2], r[2]); /* { dg-error "'__builtin_crypto_vncipher' is not supported with the current options" } */ + p[3] = __builtin_crypto_vncipherlast (q[3], r[3]); /* { dg-error "'__builtin_crypto_vncipherlast' is not supported with the current options" } */ p[4] = __builtin_crypto_vpermxor (q[4], r[4], s[4]); p[5] = __builtin_crypto_vpmsumd (q[5], r[5]); - p[6] = __builtin_crypto_vshasigmad (q[6], 1, 15); /* { dg-error "builtin function '__builtin_crypto_vshasigmad' is not supported with the current options" } */ - p[7] = __builtin_crypto_vsbox (q[7]); /* { dg-error "builtin function '__builtin_crypto_vsbox' is not supported with the current options" } */ + p[6] = __builtin_crypto_vshasigmad (q[6], 1, 15); /* { dg-error "'__builtin_crypto_vshasigmad' is not supported with the current options" } */ + p[7] = __builtin_crypto_vsbox (q[7]); /* { dg-error "'__builtin_crypto_vsbox' is not supported with the current options" } */ } void use_builtins_w (__vector unsigned int *p, __vector unsigned int *q, __vector unsigned int *r, __vector unsigned int *s) { p[0] = __builtin_crypto_vpermxor (q[0], r[0], s[0]); p[1] = __builtin_crypto_vpmsumw (q[1], r[1]); - p[2] = __builtin_crypto_vshasigmaw (q[2], 1, 15); /* { dg-error "builtin function '__builtin_crypto_vshasigmaw' is not supported with the current options" } */ + p[2] = __builtin_crypto_vshasigmaw (q[2], 1, 15); /* { dg-error "'__builtin_crypto_vshasigmaw' is not supported with the current options" } */ } void use_builtins_h (__vector unsigned short *p, __vector unsigned short *q, __vector unsigned short *r, __vector unsigned short *s) diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-1.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-1.c index 62e2f7f..e660b74 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-1.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-1.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_lt (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_lt_dd' requires" } */ + return __builtin_dfp_dtstsfi_lt (5, source); /* { dg-error "'__builtin_dtstsfi_lt_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-11.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-11.c index bdbf85c..92145f0 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-11.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-11.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_lt_dd (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_lt_dd' requires" } */ + return __builtin_dfp_dtstsfi_lt_dd (5, source); /* { dg-error "'__builtin_dtstsfi_lt_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-16.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-16.c index a2f4c4f..62dc52d 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-16.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-16.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_lt_td (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_lt_td' requires" } */ + return __builtin_dfp_dtstsfi_lt_td (5, source); /* { dg-error "'__builtin_dtstsfi_lt_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-21.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-21.c index a881b71..a8e435b 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-21.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-21.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_gt (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_gt_dd' requires" } */ + return __builtin_dfp_dtstsfi_gt (5, source); /* { dg-error "'__builtin_dtstsfi_gt_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-26.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-26.c index d69a094..40790f4 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-26.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-26.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_gt (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_gt_td' requires" } */ + return __builtin_dfp_dtstsfi_gt (5, source); /* { dg-error "'__builtin_dtstsfi_gt_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-31.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-31.c index d921b8f..a7f3908 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-31.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-31.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_gt_dd (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_gt_dd' requires" } */ + return __builtin_dfp_dtstsfi_gt_dd (5, source); /* { dg-error "'__builtin_dtstsfi_gt_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-36.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-36.c index 046c78b..1b48867 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-36.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-36.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_gt_td (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_gt_td' requires" } */ + return __builtin_dfp_dtstsfi_gt_td (5, source); /* { dg-error "'__builtin_dtstsfi_gt_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-41.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-41.c index 7460c0c..640e6c8 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-41.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-41.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_eq (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_eq_dd' requires" } */ + return __builtin_dfp_dtstsfi_eq (5, source); /* { dg-error "'__builtin_dtstsfi_eq_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-46.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-46.c index 2072f11..6557a63 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-46.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-46.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_eq (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_eq_td' requires" } */ + return __builtin_dfp_dtstsfi_eq (5, source); /* { dg-error "'__builtin_dtstsfi_eq_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-51.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-51.c index cf0b4ad..801c8c7 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-51.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-51.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_eq_dd (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_eq_dd' requires" } */ + return __builtin_dfp_dtstsfi_eq_dd (5, source); /* { dg-error "'__builtin_dtstsfi_eq_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-56.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-56.c index cac7c4d..589adeb 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-56.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-56.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_eq_td (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_eq_td' requires" } */ + return __builtin_dfp_dtstsfi_eq_td (5, source); /* { dg-error "'__builtin_dtstsfi_eq_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-6.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-6.c index dfa8039..873ad9f 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-6.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-6.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_lt (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_lt_td' requires" } */ + return __builtin_dfp_dtstsfi_lt (5, source); /* { dg-error "'__builtin_dtstsfi_lt_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-61.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-61.c index ad7aced..3b2867c 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-61.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-61.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_ov (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_ov_dd' requires" } */ + return __builtin_dfp_dtstsfi_ov (5, source); /* { dg-error "'__builtin_dtstsfi_ov_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-66.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-66.c index ee9b56a..2b6d30a 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-66.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-66.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_ov (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_ov_td' requires" } */ + return __builtin_dfp_dtstsfi_ov (5, source); /* { dg-error "'__builtin_dtstsfi_ov_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-71.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-71.c index bcdac7a..8fe0b6a 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-71.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-71.c @@ -9,6 +9,6 @@ int doTestBCDSignificance (_Decimal64 *p) { _Decimal64 source = *p; - return __builtin_dfp_dtstsfi_ov_dd (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_ov_dd' requires" } */ + return __builtin_dfp_dtstsfi_ov_dd (5, source); /* { dg-error "'__builtin_dtstsfi_ov_dd' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-76.c b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-76.c index a618067..dccc388 100644 --- a/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-76.c +++ b/gcc/testsuite/gcc.target/powerpc/dfp/dtstsfi-76.c @@ -9,7 +9,7 @@ int doTestBCDSignificance (_Decimal128 *p) { _Decimal128 source = *p; - return __builtin_dfp_dtstsfi_ov_td (5, source); /* { dg-error "builtin function '__builtin_dtstsfi_ov_td' requires" } */ + return __builtin_dfp_dtstsfi_ov_td (5, source); /* { dg-error "'__builtin_dtstsfi_ov_td' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c index 980893f..c2b237e 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c @@ -11,5 +11,5 @@ test_all_not_equal_and_not_zero (vector unsigned short *arg1_p, vector unsigned short arg_1 = *arg1_p; vector unsigned short arg_2 = *arg2_p; - return __builtin_vec_vcmpnez_p (__CR6_LT, arg_1, arg_2); /* { dg-error "builtin function '__builtin_vec_vcmpnez_p' not supported in this compiler configuration" } */ + return __builtin_vec_vcmpnez_p (__CR6_LT, arg_1, arg_2); /* { dg-error "'__builtin_vec_vcmpnez_p' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c index 9fdbd5f..afd3526 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c @@ -10,5 +10,5 @@ test_any_equal (vector unsigned int *arg1_p, vector unsigned int *arg2_p) vector unsigned int arg_1 = *arg1_p; vector unsigned int arg_2 = *arg2_p; - return __builtin_vec_vcmpnez_p (__CR6_LT_REV, arg_1, arg_2); /* { dg-error "builtin function '__builtin_vec_vcmpnez_p' not supported in this compiler configuration" } */ + return __builtin_vec_vcmpnez_p (__CR6_LT_REV, arg_1, arg_2); /* { dg-error "'__builtin_vec_vcmpnez_p' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c index bc906f7..811b32f 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cmpnez-7.c @@ -10,5 +10,5 @@ fetch_data (vector unsigned int *arg1_p, vector unsigned int *arg2_p) vector unsigned int arg_1 = *arg1_p; vector unsigned int arg_2 = *arg2_p; - return __builtin_vec_vcmpnez (arg_1, arg_2); /* { dg-error "builtin function '__builtin_altivec_vcmpnezw' requires the '-mcpu=power9' option" } */ + return __builtin_vec_vcmpnez (arg_1, arg_2); /* { dg-error "'__builtin_altivec_vcmpnezw' requires the '-mcpu=power9' option" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c index 3364354..6ee066d 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cntlz-lsbb-2.c @@ -9,5 +9,5 @@ count_leading_zero_byte_bits (vector unsigned char *arg1_p) { vector unsigned char arg_1 = *arg1_p; - return __builtin_vec_vclzlsbb (arg_1); /* { dg-error "builtin function '__builtin_altivec_vclzlsbb_v16qi' requires the '-mcpu=power9' option" } */ + return __builtin_vec_vclzlsbb (arg_1); /* { dg-error "'__builtin_altivec_vclzlsbb_v16qi' requires the '-mcpu=power9' option" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c index dfad174..ecd0add 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-cnttz-lsbb-2.c @@ -9,5 +9,5 @@ count_trailing_zero_byte_bits (vector unsigned char *arg1_p) { vector unsigned char arg_1 = *arg1_p; - return __builtin_vec_vctzlsbb (arg_1); /* { dg-error "builtin function '__builtin_altivec_vctzlsbb_v16qi' requires the '-mcpu=power9' option" } */ + return __builtin_vec_vctzlsbb (arg_1); /* { dg-error "'__builtin_altivec_vctzlsbb_v16qi' requires the '-mcpu=power9' option" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-12.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-12.c index 96a04d2..92b0d0dd 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-12.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-12.c @@ -11,5 +11,5 @@ __vector float fetch_data (float *address, size_t length) { - return __builtin_vec_lxvl (address, length); /* { dg-error "builtin function '__builtin_vsx_lxvl' requires" } */ + return __builtin_vec_lxvl (address, length); /* { dg-error "'__builtin_vsx_lxvl' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c index 04f213a9..4808c4d 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c @@ -13,5 +13,5 @@ __vector float fetch_data (float *address, size_t length) { - return __builtin_vec_lxvl (address, length); /* { dg-error "builtin function '__builtin_vec_lxvl' not supported in this compiler configuration" } */ + return __builtin_vec_lxvl (address, length); /* { dg-error "'__builtin_vec_lxvl' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xlx-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xlx-7.c index 25cd01c..c6f7b5c 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xlx-7.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xlx-7.c @@ -10,5 +10,5 @@ fetch_data (unsigned int offset, vector signed int *datap) { vector signed int data = *datap; - return __builtin_vec_vextulx (offset, data); /* { dg-error "builtin function '__builtin_altivec_vextuwlx' requires" } */ + return __builtin_vec_vextulx (offset, data); /* { dg-error "'__builtin_altivec_vextuwlx' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xrx-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xrx-7.c index 3a27213..fd6b5be 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xrx-7.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xrx-7.c @@ -10,5 +10,5 @@ fetch_data (unsigned short offset, vector signed short *datap) { vector signed short data = *datap; - return __builtin_vec_vexturx (offset, data); /* { dg-error "builtin function '__builtin_altivec_vextuhrx' requires" } */ + return __builtin_vec_vexturx (offset, data); /* { dg-error "'__builtin_altivec_vextuhrx' requires" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c index 992d7b5..0a0b0cb 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c @@ -13,5 +13,5 @@ store_data (vector double *datap, double *address, size_t length) { vector double data = *datap; - __builtin_vec_stxvl (data, address, length); /* { dg-error "builtin function '__builtin_vec_stxvl' not supported in this compiler configuration" } */ + __builtin_vec_stxvl (data, address, length); /* { dg-error "'__builtin_vec_stxvl' not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-13.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-13.c index 37b20b0..2a6a7da 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-13.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-13.c @@ -14,5 +14,5 @@ store_data (vector double *datap, double *address, size_t length) { vector double data = *datap; - __builtin_vec_stxvl (data, address, length); /* { dg-error "builtin function '__builtin_altivec_stxvl' requires" } */ + __builtin_vec_stxvl (data, address, length); /* { dg-error "'__builtin_altivec_stxvl' requires" } */ } -- cgit v1.1 From e2bc581fca97845eb2a36578468739273442794d Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sat, 13 Jul 2019 20:46:40 +0200 Subject: tree-ssa-alias.c (component_ref_to_zero_sized_trailing_array_p): Break out from ... * tree-ssa-alias.c (component_ref_to_zero_sized_trailing_array_p): Break out from ... (aliasing_component_refs_walk): Break out from ... (aliasing_component_refs_p): ... here. From-SVN: r273469 --- gcc/ChangeLog | 7 ++ gcc/tree-ssa-alias.c | 205 +++++++++++++++++++++++++++------------------------ 2 files changed, 114 insertions(+), 98 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f83c26..fc43ac2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-13 Jan Hubicka + + * tree-ssa-alias.c (component_ref_to_zero_sized_trailing_array_p): + Break out from ... + (aliasing_component_refs_walk): Break out from ... + (aliasing_component_refs_p): ... here. + 2019-07-13 Segher Boessenkool PR target/91148 diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index e1ea307..d6e3976 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -895,6 +895,97 @@ aliasing_matching_component_refs_p (tree match1, tree ref1, return true; } +/* Return true if REF is reference to zero sized trailing array. I.e. + struct foo {int bar; int array[0];} *fooptr; + fooptr->array. */ + +static bool +component_ref_to_zero_sized_trailing_array_p (tree ref) +{ + return (TREE_CODE (ref) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE + && (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (ref, 1))) + || integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (ref, 1))))) + && array_at_struct_end_p (ref)); +} + +/* Worker for aliasing_component_refs_p. Most parameters match parameters of + aliasing_component_refs_p. + + Walk access path REF2 and try to find type matching TYPE1 + (which is a start of possibly aliasing access path REF1). + If match is found, try to disambiguate. + + Return 0 for sucessful disambiguation. + Return 1 if match was found but disambiguation failed + Return -1 if there is no match. + In this case MAYBE_MATCH is set to 0 if there is no type matching TYPE1 + in access patch REF2 and -1 if we are not sure. */ + +static int +aliasing_component_refs_walk (tree ref1, tree type1, tree base1, + poly_int64 offset1, poly_int64 max_size1, + tree end_struct_ref1, + tree ref2, tree base2, + poly_int64 offset2, poly_int64 max_size2, + bool *maybe_match) +{ + tree ref = ref2; + int same_p; + + while (true) + { + /* We walk from inner type to the outer types. If type we see is + already too large to be part of type1, terminate the search. */ + int cmp = compare_type_sizes (type1, TREE_TYPE (ref)); + + if (cmp < 0 + && (!end_struct_ref1 + || compare_type_sizes (TREE_TYPE (end_struct_ref1), + TREE_TYPE (ref)) < 0)) + break; + /* If types may be of same size, see if we can decide about their + equality. */ + if (cmp == 0) + { + same_p = same_type_for_tbaa (TREE_TYPE (ref), type1); + if (same_p == 1) + break; + /* In case we can't decide whether types are same try to + continue looking for the exact match. + Remember however that we possibly saw a match + to bypass the access path continuations tests we do later. */ + if (same_p == -1) + *maybe_match = true; + } + if (!handled_component_p (ref)) + break; + ref = TREE_OPERAND (ref, 0); + } + if (same_p == 1) + { + /* We assume that arrays can overlap by multiple of their elements + size as tested in gcc.dg/torture/alias-2.c. + This partial overlap happen only when both arrays are bases of + the access and not contained within another component ref. + To be safe we also assume partial overlap for VLAs. */ + if (TREE_CODE (TREE_TYPE (base1)) == ARRAY_TYPE + && (!TYPE_SIZE (TREE_TYPE (base1)) + || TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) != INTEGER_CST + || ref == base2)) + /* Setting maybe_match to true triggers + nonoverlapping_component_refs_p test later that still may do + useful disambiguation. */ + *maybe_match = true; + else + return aliasing_matching_component_refs_p (base1, ref1, + offset1, max_size1, + ref, ref2, + offset2, max_size2); + } + return -1; +} + /* Determine if the two component references REF1 and REF2 which are based on access types TYPE1 and TYPE2 and of which at least one is based on an indirect reference may alias. @@ -919,7 +1010,6 @@ aliasing_component_refs_p (tree ref1, disambiguating q->i and p->a.j. */ tree base1, base2; tree type1, type2; - int same_p1 = 0, same_p2 = 0; bool maybe_match = false; tree end_struct_ref1 = NULL, end_struct_ref2 = NULL; @@ -938,11 +1028,7 @@ aliasing_component_refs_p (tree ref1, Because we compare sizes of arrays just by sizes of their elements, we only need to care about zero sized array fields here. */ - if (TREE_CODE (base1) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (base1, 1))) == ARRAY_TYPE - && (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1))) - || integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1))))) - && array_at_struct_end_p (base1)) + if (component_ref_to_zero_sized_trailing_array_p (base1)) { gcc_checking_assert (!end_struct_ref1); end_struct_ref1 = base1; @@ -956,11 +1042,7 @@ aliasing_component_refs_p (tree ref1, base2 = ref2; while (handled_component_p (base2)) { - if (TREE_CODE (base2) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (base2, 1))) == ARRAY_TYPE - && (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1))) - || integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1))))) - && array_at_struct_end_p (base2)) + if (component_ref_to_zero_sized_trailing_array_p (base2)) { gcc_checking_assert (!end_struct_ref2); end_struct_ref2 = base2; @@ -984,57 +1066,13 @@ aliasing_component_refs_p (tree ref1, || (end_struct_ref2 && compare_type_sizes (TREE_TYPE (end_struct_ref2), type1) >= 0)) { - tree ref = ref2; - while (true) - { - /* We walk from inner type to the outer types. If type we see is - already too large to be part of type1, terminate the search. */ - int cmp = compare_type_sizes (type1, TREE_TYPE (ref)); - - if (cmp < 0 - && (!end_struct_ref1 - || compare_type_sizes (TREE_TYPE (end_struct_ref1), - TREE_TYPE (ref)) < 0)) - break; - /* If types may be of same size, see if we can decide about their - equality. */ - if (cmp == 0) - { - same_p2 = same_type_for_tbaa (TREE_TYPE (ref), type1); - if (same_p2 == 1) - break; - /* In case we can't decide whether types are same try to - continue looking for the exact match. - Remember however that we possibly saw a match - to bypass the access path continuations tests we do later. */ - if (same_p2 == -1) - maybe_match = true; - } - if (!handled_component_p (ref)) - break; - ref = TREE_OPERAND (ref, 0); - } - if (same_p2 == 1) - { - /* We assume that arrays can overlap by multiple of their elements - size as tested in gcc.dg/torture/alias-2.c. - This partial overlap happen only when both arrays are bases of - the access and not contained within another component ref. - To be safe we also assume partial overlap for VLAs. */ - if (TREE_CODE (TREE_TYPE (base1)) == ARRAY_TYPE - && (!TYPE_SIZE (TREE_TYPE (base1)) - || TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) != INTEGER_CST - || ref == base2)) - /* Setting maybe_match to true triggers - nonoverlapping_component_refs_p test later that still may do - useful disambiguation. */ - maybe_match = true; - else - return aliasing_matching_component_refs_p (base1, ref1, - offset1, max_size1, - ref, ref2, - offset2, max_size2); - } + int res = aliasing_component_refs_walk (ref1, type1, base1, + offset1, max_size1, + end_struct_ref1, + ref2, base2, offset2, max_size2, + &maybe_match); + if (res != -1) + return res; } /* If we didn't find a common base, try the other way around. */ @@ -1042,42 +1080,13 @@ aliasing_component_refs_p (tree ref1, || (end_struct_ref1 && compare_type_sizes (TREE_TYPE (end_struct_ref1), type1) <= 0)) { - tree ref = ref1; - while (true) - { - int cmp = compare_type_sizes (type2, TREE_TYPE (ref)); - if (cmp < 0 - && (!end_struct_ref2 - || compare_type_sizes (TREE_TYPE (end_struct_ref2), - TREE_TYPE (ref)) < 0)) - break; - /* If types may be of same size, see if we can decide about their - equality. */ - if (cmp == 0) - { - same_p1 = same_type_for_tbaa (TREE_TYPE (ref), type2); - if (same_p1 == 1) - break; - if (same_p1 == -1) - maybe_match = true; - } - if (!handled_component_p (ref)) - break; - ref = TREE_OPERAND (ref, 0); - } - if (same_p1 == 1) - { - if (TREE_CODE (TREE_TYPE (base2)) == ARRAY_TYPE - && (!TYPE_SIZE (TREE_TYPE (base2)) - || TREE_CODE (TYPE_SIZE (TREE_TYPE (base2))) != INTEGER_CST - || ref == base1)) - maybe_match = true; - else - return aliasing_matching_component_refs_p (ref, ref1, - offset1, max_size1, - base2, ref2, - offset2, max_size2); - } + int res = aliasing_component_refs_walk (ref2, type2, base2, + offset2, max_size2, + end_struct_ref2, + ref1, base1, offset1, max_size1, + &maybe_match); + if (res != -1) + return res; } /* In the following code we make an assumption that the types in access -- cgit v1.1 From 8028dd3f2f36e73440bb78d8d81a7eaaf71513be Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sat, 13 Jul 2019 21:21:43 +0000 Subject: [Darwin, PPC, testsuite] Require stabs support for a test. The test fails if the assembler doesn't support stabs. 2019-07-13 Iain Sandoe * gcc.target/powerpc/stabs-attrib-vect-darwin.c: Require stabs support. From-SVN: r273470 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c | 1 + 2 files changed, 6 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4cdb328..d92ffc6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-13 Iain Sandoe + + * gcc.target/powerpc/stabs-attrib-vect-darwin.c: Require stabs + support. + 2019-07-13 Segher Boessenkool PR target/91148 diff --git a/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c b/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c index 3c52287..5c7acf1 100644 --- a/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c +++ b/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c @@ -1,5 +1,6 @@ /* Test Attribute Vector associated with vector type stabs. */ /* { dg-do compile { target powerpc*-*-darwin* } } */ +/* { dg-require-effective-target stabs } */ /* { dg-options "-gstabs+ -fno-eliminate-unused-debug-types -faltivec" } */ int main () -- cgit v1.1 From 0d67fe7e009324fbff6c554d590c8c9330fc211a Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 14 Jul 2019 00:16:17 +0000 Subject: Daily bump. From-SVN: r273474 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1a8e551..7c107ea 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190713 +20190714 -- cgit v1.1 From d67dfb85ba4f89f5f3045f2483005c290bc18108 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sun, 14 Jul 2019 10:24:38 +0200 Subject: rs6000: Shut up -Wformat-diag a little more PR target/91148 * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): Remove superfluous "builtin function" phrasing. gcc/testsuite/ * gcc.target/powerpc/bfp/scalar-extract-exp-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-extract-sig-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-2.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-5.c: Adjust. * gcc.target/powerpc/bfp/scalar-insert-exp-8.c: Adjust. * gcc.target/powerpc/byte-in-set-2.c: Adjust. * gcc.target/powerpc/cmpb-3.c: Adjust. * gcc.target/powerpc/vsu/vec-all-nez-7.c: Adjust. * gcc.target/powerpc/vsu/vec-any-eqz-7.c: Adjust. * gcc.target/powerpc/vsu/vec-xl-len-13.c: Adjust. * gcc.target/powerpc/vsu/vec-xst-len-12.c: Adjust. From-SVN: r273475 --- gcc/ChangeLog | 6 ++++++ gcc/config/rs6000/rs6000-c.c | 3 +-- gcc/testsuite/ChangeLog | 15 +++++++++++++++ .../gcc.target/powerpc/bfp/scalar-extract-exp-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-extract-sig-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-2.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-5.c | 2 +- .../gcc.target/powerpc/bfp/scalar-insert-exp-8.c | 2 +- gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c | 2 +- gcc/testsuite/gcc.target/powerpc/cmpb-3.c | 2 +- gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c | 2 +- gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c | 2 +- gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c | 2 +- gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c | 2 +- 14 files changed, 33 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fc43ac2..9376ab4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-14 Segher Boessenkool + + PR target/91148 + * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): Remove + superfluous "builtin function" phrasing. + 2019-07-13 Jan Hubicka * tree-ssa-alias.c (component_ref_to_zero_sized_trailing_array_p): diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 7854082..7f0cdc7 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -7036,8 +7036,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, name, internal_name); } else - error ("builtin function %qs not supported in this compiler " - "configuration", name); + error ("%qs is not supported in this compiler configuration", name); /* If an error-representing result tree was returned from altivec_build_resolved_builtin above, use it. */ return (result != NULL) ? result : error_mark_node; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d92ffc6..8993a818 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2019-07-14 Segher Boessenkool + + PR target/91148 + * gcc.target/powerpc/bfp/scalar-extract-exp-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-extract-sig-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-2.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-5.c: Adjust. + * gcc.target/powerpc/bfp/scalar-insert-exp-8.c: Adjust. + * gcc.target/powerpc/byte-in-set-2.c: Adjust. + * gcc.target/powerpc/cmpb-3.c: Adjust. + * gcc.target/powerpc/vsu/vec-all-nez-7.c: Adjust. + * gcc.target/powerpc/vsu/vec-any-eqz-7.c: Adjust. + * gcc.target/powerpc/vsu/vec-xl-len-13.c: Adjust. + * gcc.target/powerpc/vsu/vec-xst-len-12.c: Adjust. + 2019-07-13 Iain Sandoe * gcc.target/powerpc/stabs-attrib-vect-darwin.c: Require stabs diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c index b04462f..9221806 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-exp-2.c @@ -14,7 +14,7 @@ get_exponent (double *p) { double source = *p; - return scalar_extract_exp (source); /* { dg-error "'__builtin_vec_scalar_extract_exp' not supported in this compiler configuration" } */ + return scalar_extract_exp (source); /* { dg-error "'__builtin_vec_scalar_extract_exp' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c index c912879..e24d4bd 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-extract-sig-2.c @@ -12,5 +12,5 @@ get_significand (double *p) { double source = *p; - return __builtin_vec_scalar_extract_sig (source); /* { dg-error "'__builtin_vec_scalar_extract_sig' not supported in this compiler configuration" } */ + return __builtin_vec_scalar_extract_sig (source); /* { dg-error "'__builtin_vec_scalar_extract_sig' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c index af27099..feb9431 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-2.c @@ -16,5 +16,5 @@ insert_exponent (unsigned long long int *significand_p, unsigned long long int significand = *significand_p; unsigned long long int exponent = *exponent_p; - return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ + return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c index 05b98d9..0e5683d 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-5.c @@ -16,5 +16,5 @@ insert_exponent (double *significand_p, double significand = *significand_p; unsigned long long int exponent = *exponent_p; - return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ + return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c index d1a0a8b..bd68f77 100644 --- a/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c +++ b/gcc/testsuite/gcc.target/powerpc/bfp/scalar-insert-exp-8.c @@ -16,5 +16,5 @@ insert_exponent (unsigned __int128 *significand_p, /* { dg-error "'__int128' is unsigned __int128 significand = *significand_p; /* { dg-error "'__int128' is not supported on this target" } */ unsigned long long int exponent = *exponent_p; - return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' not supported in this compiler configuration" } */ + return scalar_insert_exp (significand, exponent); /* { dg-error "'__builtin_vec_scalar_insert_exp' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c index a741010..9a80c27 100644 --- a/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c +++ b/gcc/testsuite/gcc.target/powerpc/byte-in-set-2.c @@ -11,5 +11,5 @@ int test_byte_in_set (unsigned char b, unsigned long long set_members) { - return __builtin_byte_in_set (b, set_members); /* { dg-error "'__builtin_byte_in_set' not supported in this compiler configuration" } */ + return __builtin_byte_in_set (b, set_members); /* { dg-error "'__builtin_byte_in_set' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/cmpb-3.c b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c index 0fa8eb1..de111a8 100644 --- a/gcc/testsuite/gcc.target/powerpc/cmpb-3.c +++ b/gcc/testsuite/gcc.target/powerpc/cmpb-3.c @@ -8,7 +8,7 @@ void abort (); long long int do_compare (long long int a, long long int b) { - return __builtin_cmpb (a, b); /* { dg-error "'__builtin_cmpb' not supported in this compiler configuration" } */ + return __builtin_cmpb (a, b); /* { dg-error "'__builtin_cmpb' is not supported in this compiler configuration" } */ } void expect (long long int pattern, long long int value) diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c index c2b237e..0f9badd 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-all-nez-7.c @@ -11,5 +11,5 @@ test_all_not_equal_and_not_zero (vector unsigned short *arg1_p, vector unsigned short arg_1 = *arg1_p; vector unsigned short arg_2 = *arg2_p; - return __builtin_vec_vcmpnez_p (__CR6_LT, arg_1, arg_2); /* { dg-error "'__builtin_vec_vcmpnez_p' not supported in this compiler configuration" } */ + return __builtin_vec_vcmpnez_p (__CR6_LT, arg_1, arg_2); /* { dg-error "'__builtin_vec_vcmpnez_p' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c index afd3526..c69dfa6 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-any-eqz-7.c @@ -10,5 +10,5 @@ test_any_equal (vector unsigned int *arg1_p, vector unsigned int *arg2_p) vector unsigned int arg_1 = *arg1_p; vector unsigned int arg_2 = *arg2_p; - return __builtin_vec_vcmpnez_p (__CR6_LT_REV, arg_1, arg_2); /* { dg-error "'__builtin_vec_vcmpnez_p' not supported in this compiler configuration" } */ + return __builtin_vec_vcmpnez_p (__CR6_LT_REV, arg_1, arg_2); /* { dg-error "'__builtin_vec_vcmpnez_p' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c index 4808c4d..9de6424 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xl-len-13.c @@ -13,5 +13,5 @@ __vector float fetch_data (float *address, size_t length) { - return __builtin_vec_lxvl (address, length); /* { dg-error "'__builtin_vec_lxvl' not supported in this compiler configuration" } */ + return __builtin_vec_lxvl (address, length); /* { dg-error "'__builtin_vec_lxvl' is not supported in this compiler configuration" } */ } diff --git a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c index 0a0b0cb..3a51132 100644 --- a/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c +++ b/gcc/testsuite/gcc.target/powerpc/vsu/vec-xst-len-12.c @@ -13,5 +13,5 @@ store_data (vector double *datap, double *address, size_t length) { vector double data = *datap; - __builtin_vec_stxvl (data, address, length); /* { dg-error "'__builtin_vec_stxvl' not supported in this compiler configuration" } */ + __builtin_vec_stxvl (data, address, length); /* { dg-error "'__builtin_vec_stxvl' is not supported in this compiler configuration" } */ } -- cgit v1.1 From a20f263ba1a76af40eb4e6734529739a2a30ed65 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sun, 14 Jul 2019 13:57:10 +0200 Subject: ipa-fnsummary.c (ipa_dump_hints): Do not dump array_index. * ipa-fnsummary.c (ipa_dump_hints): Do not dump array_index. (ipa_fn_summary::~ipa_fn_summary): Do not destroy array_index. (ipa_fn_summary_t::duplicate): Do not duplicate array_index. (array_index_predicate): Remove. (analyze_function_body): Account cost for variable ofsetted array indexing. (estimate_node_size_and_time): Do not compute array index hint. (ipa_merge_fn_summary_after_inlining): Do not merge array index hint. (inline_read_section): Do not read array index hint. (ipa_fn_summary_write): Do not write array index hint. * doc/invoke.texi (ipa-cp-array-index-hint-bonus): Remove. * ipa-cp.c (hint_time_bonus): Remove. * ipa-fnsummary.h (ipa_hints_vals): Remove array_index. (ipa_fnsummary): Remove array_index. * ipa-inline.c (want_inline_small_function_p): Do not use array_index. (edge_badness): Likewise. * params.def (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS): Remove. From-SVN: r273479 --- gcc/ChangeLog | 21 ++++++++++ gcc/doc/invoke.texi | 6 --- gcc/ipa-cp.c | 2 - gcc/ipa-fnsummary.c | 109 +++++++++++++++------------------------------------- gcc/ipa-fnsummary.h | 11 ++---- gcc/ipa-inline.c | 3 -- gcc/params.def | 6 --- 7 files changed, 54 insertions(+), 104 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9376ab4..9b5cc7a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2019-07-14 Jan Hubicka + + * ipa-fnsummary.c (ipa_dump_hints): Do not dump array_index. + (ipa_fn_summary::~ipa_fn_summary): Do not destroy array_index. + (ipa_fn_summary_t::duplicate): Do not duplicate array_index. + (array_index_predicate): Remove. + (analyze_function_body): Account cost for variable ofsetted array + indexing. + (estimate_node_size_and_time): Do not compute array index hint. + (ipa_merge_fn_summary_after_inlining): Do not merge array index hint. + (inline_read_section): Do not read array index hint. + (ipa_fn_summary_write): Do not write array index hint. + * doc/invoke.texi (ipa-cp-array-index-hint-bonus): Remove. + * ipa-cp.c (hint_time_bonus): Remove. + * ipa-fnsummary.h (ipa_hints_vals): Remove array_index. + (ipa_fnsummary): Remove array_index. + * ipa-inline.c (want_inline_small_function_p): Do not use + array_index. + (edge_badness): Likewise. + * params.def (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS): Remove. + 2019-07-14 Segher Boessenkool PR target/91148 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b4e71f2..758aef3 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -11895,12 +11895,6 @@ of iterations of a loop known, it adds a bonus of @option{ipa-cp-loop-hint-bonus} to the profitability score of the candidate. -@item ipa-cp-array-index-hint-bonus -When IPA-CP determines that a cloning candidate would make the index of -an array access known, it adds a bonus of -@option{ipa-cp-array-index-hint-bonus} to the profitability -score of the candidate. - @item ipa-max-aa-steps During its analysis of function bodies, IPA-CP employs alias analysis in order to track values pointed to by function parameters. In order diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 0fd3650..b20a6d0 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -2607,8 +2607,6 @@ hint_time_bonus (ipa_hints hints) int result = 0; if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride)) result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS); - if (hints & INLINE_HINT_array_index) - result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS); return result; } diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 0998621..78eb8cb 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -134,11 +134,6 @@ ipa_dump_hints (FILE *f, ipa_hints hints) hints &= ~INLINE_HINT_declared_inline; fprintf (f, " declared_inline"); } - if (hints & INLINE_HINT_array_index) - { - hints &= ~INLINE_HINT_array_index; - fprintf (f, " array_index"); - } if (hints & INLINE_HINT_known_hot) { hints &= ~INLINE_HINT_known_hot; @@ -549,8 +544,6 @@ ipa_fn_summary::~ipa_fn_summary () edge_predicate_pool.remove (loop_iterations); if (loop_stride) edge_predicate_pool.remove (loop_stride); - if (array_index) - edge_predicate_pool.remove (array_index); vec_free (conds); vec_free (size_time_table); } @@ -703,8 +696,6 @@ ipa_fn_summary_t::duplicate (cgraph_node *src, possible_truths); remap_hint_predicate_after_duplication (&info->loop_stride, possible_truths); - remap_hint_predicate_after_duplication (&info->array_index, - possible_truths); /* If inliner or someone after inliner will ever start producing non-trivial clones, we will get trouble with lack of information @@ -727,12 +718,6 @@ ipa_fn_summary_t::duplicate (cgraph_node *src, info->loop_stride = NULL; set_hint_predicate (&info->loop_stride, p); } - if (info->array_index) - { - predicate p = *info->array_index; - info->array_index = NULL; - set_hint_predicate (&info->array_index, p); - } } if (!dst->global.inlined_to) ipa_update_overall_fn_summary (dst); @@ -894,11 +879,6 @@ ipa_dump_fn_summary (FILE *f, struct cgraph_node *node) fprintf (f, " loop stride:"); s->loop_stride->dump (f, s->conds); } - if (s->array_index) - { - fprintf (f, " array index:"); - s->array_index->dump (f, s->conds); - } fprintf (f, " calls:\n"); dump_ipa_call_summary (f, 4, node, s); fprintf (f, "\n"); @@ -1824,27 +1804,6 @@ predicate_for_phi_result (class ipa_fn_summary *summary, gphi *phi, nonconstant_names[SSA_NAME_VERSION (gimple_phi_result (phi))] = *p; } -/* Return predicate specifying when array index in access OP becomes non-constant. */ - -static predicate -array_index_predicate (ipa_fn_summary *info, - vec< predicate> nonconstant_names, tree op) -{ - predicate p = false; - while (handled_component_p (op)) - { - if (TREE_CODE (op) == ARRAY_REF || TREE_CODE (op) == ARRAY_RANGE_REF) - { - if (TREE_CODE (TREE_OPERAND (op, 1)) == SSA_NAME) - p = p.or_with (info->conds, - nonconstant_names[SSA_NAME_VERSION - (TREE_OPERAND (op, 1))]); - } - op = TREE_OPERAND (op, 0); - } - return p; -} - /* For a typical usage of __builtin_expect (a nonconstant_names = vNULL; int nblocks, n; int *order; - predicate array_index = true; gimple *fix_builtin_expect_stmt; gcc_assert (my_function && my_function->cfg); @@ -2146,26 +2104,6 @@ analyze_function_body (struct cgraph_node *node, bool early) this_time); } - if (gimple_assign_load_p (stmt) && nonconstant_names.exists ()) - { - predicate this_array_index; - this_array_index = - array_index_predicate (info, nonconstant_names, - gimple_assign_rhs1 (stmt)); - if (this_array_index != false) - array_index &= this_array_index; - } - if (gimple_store_p (stmt) && nonconstant_names.exists ()) - { - predicate this_array_index; - this_array_index = - array_index_predicate (info, nonconstant_names, - gimple_get_lhs (stmt)); - if (this_array_index != false) - array_index &= this_array_index; - } - - if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt)) { @@ -2273,14 +2211,40 @@ analyze_function_body (struct cgraph_node *node, bool early) if (dump_file) fprintf (dump_file, " fp_expression set\n"); } + } - gcc_assert (time >= 0); - gcc_assert (size >= 0); + /* Account cost of address calculations in the statements. */ + for (unsigned int i = 0; i < gimple_num_ops (stmt); i++) + { + for (tree op = gimple_op (stmt, i); + op && handled_component_p (op); + op = TREE_OPERAND (op, 0)) + if ((TREE_CODE (op) == ARRAY_REF + || TREE_CODE (op) == ARRAY_RANGE_REF) + && TREE_CODE (TREE_OPERAND (op, 1)) == SSA_NAME) + { + predicate p = bb_predicate; + if (fbi.info) + p = p & will_be_nonconstant_expr_predicate + (&fbi, info, TREE_OPERAND (op, 1), + nonconstant_names); + if (p != false) + { + time += freq; + size += 1; + if (dump_file) + fprintf (dump_file, + "\t\tAccounting address calculation.\n"); + info->account_size_time (ipa_fn_summary::size_scale, + freq, + bb_predicate, + p); + } + } } + } } - set_hint_predicate (&ipa_fn_summaries->get_create (node)->array_index, - array_index); free (order); if (nonconstant_names.exists () && !early) @@ -2783,9 +2747,6 @@ estimate_node_size_and_time (struct cgraph_node *node, if (info->loop_stride && !info->loop_stride->evaluate (possible_truths)) hints |= INLINE_HINT_loop_stride; - if (info->array_index - && !info->array_index->evaluate (possible_truths)) - hints |= INLINE_HINT_array_index; if (info->scc_no) hints |= INLINE_HINT_in_scc; if (DECL_DECLARED_INLINE_P (node->decl)) @@ -3106,9 +3067,6 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge) remap_hint_predicate (info, callee_info, &callee_info->loop_stride, operand_map, offset_map, clause, &toplev_predicate); - remap_hint_predicate (info, callee_info, - &callee_info->array_index, - operand_map, offset_map, clause, &toplev_predicate); ipa_call_summary *s = ipa_call_summaries->get (edge); inline_update_callee_summaries (edge->callee, s->loop_depth); @@ -3366,9 +3324,6 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data, p.stream_in (&ib); if (info) set_hint_predicate (&info->loop_stride, p); - p.stream_in (&ib); - if (info) - set_hint_predicate (&info->array_index, p); for (e = node->callees; e; e = e->next_callee) read_ipa_call_summary (&ib, e, info != NULL); for (e = node->indirect_calls; e; e = e->next_callee) @@ -3517,10 +3472,6 @@ ipa_fn_summary_write (void) info->loop_stride->stream_out (ob); else streamer_write_uhwi (ob, 0); - if (info->array_index) - info->array_index->stream_out (ob); - else - streamer_write_uhwi (ob, 0); for (edge = cnode->callees; edge; edge = edge->next_callee) write_ipa_call_summary (ob, edge); for (edge = cnode->indirect_calls; edge; edge = edge->next_callee) diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h index 55bc341..173d3f2 100644 --- a/gcc/ipa-fnsummary.h +++ b/gcc/ipa-fnsummary.h @@ -48,11 +48,8 @@ enum ipa_hints_vals { if functions are in different modules, inlining may not be so important. Set by simple_edge_hints in ipa-inline-analysis.c. */ INLINE_HINT_cross_module = 64, - /* If array indexes of loads/stores become known there may be room for - further optimization. */ - INLINE_HINT_array_index = 128, /* We know that the callee is hot by profile. */ - INLINE_HINT_known_hot = 256 + INLINE_HINT_known_hot = 128 }; typedef int ipa_hints; @@ -97,7 +94,7 @@ public: fp_expressions (false), estimated_stack_size (false), stack_frame_offset (false), time (0), size (0), conds (NULL), size_time_table (NULL), loop_iterations (NULL), loop_stride (NULL), - array_index (NULL), growth (0), scc_no (0) + growth (0), scc_no (0) { } @@ -111,7 +108,7 @@ public: stack_frame_offset (s.stack_frame_offset), time (s.time), size (s.size), conds (s.conds), size_time_table (s.size_time_table), loop_iterations (s.loop_iterations), loop_stride (s.loop_stride), - array_index (s.array_index), growth (s.growth), scc_no (s.scc_no) + growth (s.growth), scc_no (s.scc_no) {} /* Default constructor. */ @@ -157,8 +154,6 @@ public: /* Predicate on when some loop in the function becomes to have known stride. */ predicate * GTY((skip)) loop_stride; - /* Predicate on when some array indexes become constants. */ - predicate * GTY((skip)) array_index; /* Estimated growth for inlining all copies of the function before start of small functions inlining. This value will get out of date as the callers are duplicated, but diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 939d86e..e730066 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -807,7 +807,6 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) || (!(hints & (INLINE_HINT_indirect_call | INLINE_HINT_known_hot | INLINE_HINT_loop_iterations - | INLINE_HINT_array_index | INLINE_HINT_loop_stride)) && !(big_speedup = big_speedup_p (e))))) { @@ -833,7 +832,6 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) && !(hints & INLINE_HINT_known_hot) && growth >= ((hints & (INLINE_HINT_indirect_call | INLINE_HINT_loop_iterations - | INLINE_HINT_array_index | INLINE_HINT_loop_stride)) ? MAX (MAX_INLINE_INSNS_AUTO, MAX_INLINE_INSNS_SINGLE) @@ -1227,7 +1225,6 @@ edge_badness (struct cgraph_edge *edge, bool dump) badness = badness.shift (badness > 0 ? 4 : -4); if ((hints & (INLINE_HINT_indirect_call | INLINE_HINT_loop_iterations - | INLINE_HINT_array_index | INLINE_HINT_loop_stride)) || callee_info->growth <= 0) badness = badness.shift (badness > 0 ? -2 : 2); diff --git a/gcc/params.def b/gcc/params.def index c56055d..7d0dcae 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -1109,12 +1109,6 @@ DEFPARAM (PARAM_IPA_CP_LOOP_HINT_BONUS, "bounds or strides known.", 64, 0, 0) -DEFPARAM (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS, - "ipa-cp-array-index-hint-bonus", - "Compile-time bonus IPA-CP assigns to candidates which make an array " - "index known.", - 48, 0, 0) - DEFPARAM (PARAM_IPA_MAX_AA_STEPS, "ipa-max-aa-steps", "Maximum number of statements that will be visited by IPA formal " -- cgit v1.1 From cbfde6ee68dab649e3cf86b0ae569f2fc6ef3900 Mon Sep 17 00:00:00 2001 From: Vladislav Ivanishin Date: Sun, 14 Jul 2019 13:19:29 +0000 Subject: gdbhooks.py: dump-fn, dot-fn: cast ret values of fopen/fclose Work around the following (gdb) Python Exception 'fclose@@GLIBC_2.2.5' has unknown return type; cast the call to its declared return type: (gdb) Error occurred in Python: 'fclose@@GLIBC_2.2.5' has unknown return type; cast the call to its declared return type This is due to GDB not being able to pick up and use the return types from debug info for external declarations. 2019-07-14 Vladislav Ivanishin * gdbhooks.py (DumpFn.invoke): Add explicit casts of return values of fopen and fclose to their respective types. (DotFn.invoke): Ditto. From-SVN: r273480 --- gcc/ChangeLog | 6 ++++++ gcc/gdbhooks.py | 10 ++++------ 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b5cc7a..a9887b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-14 Vladislav Ivanishin + + * gdbhooks.py (DumpFn.invoke): Add explicit casts of return values of + fopen and fclose to their respective types. + (DotFn.invoke): Ditto. + 2019-07-14 Jan Hubicka * ipa-fnsummary.c (ipa_dump_hints): Do not dump array_index. diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py index 191a5e2..09802c9 100644 --- a/gcc/gdbhooks.py +++ b/gcc/gdbhooks.py @@ -740,18 +740,17 @@ class DumpFn(gdb.Command): f.close() # Open file - fp = gdb.parse_and_eval("fopen (\"%s\", \"w\")" % filename) + fp = gdb.parse_and_eval("(FILE *) fopen (\"%s\", \"w\")" % filename) if fp == 0: print ("Could not open file: %s" % filename) return - fp = "(FILE *)%u" % fp # Dump function to file _ = gdb.parse_and_eval("dump_function_to_file (%s, %s, %u)" % (func, fp, flags)) # Close file - ret = gdb.parse_and_eval("fclose (%s)" % fp) + ret = gdb.parse_and_eval("(int) fclose (%s)" % fp) if ret != 0: print ("Could not close file: %s" % filename) return @@ -810,11 +809,10 @@ class DotFn(gdb.Command): # Close and reopen temp file to get C FILE* f.close() - fp = gdb.parse_and_eval("fopen (\"%s\", \"w\")" % filename) + fp = gdb.parse_and_eval("(FILE *) fopen (\"%s\", \"w\")" % filename) if fp == 0: print("Cannot open temp file") return - fp = "(FILE *)%u" % fp # Write graph to temp file _ = gdb.parse_and_eval("start_graph_dump (%s, \"\")" % fp) @@ -823,7 +821,7 @@ class DotFn(gdb.Command): _ = gdb.parse_and_eval("end_graph_dump (%s)" % fp) # Close temp file - ret = gdb.parse_and_eval("fclose (%s)" % fp) + ret = gdb.parse_and_eval("(int) fclose (%s)" % fp) if ret != 0: print("Could not close temp file: %s" % filename) return -- cgit v1.1 From 3e4ceed077aa7e94755fbf6bf213fd4305540bd9 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Sun, 14 Jul 2019 20:52:16 +0200 Subject: i386.md (nonmemory_szext_operand): New mode attribute. * config/i386/i386.md (nonmemory_szext_operand): New mode attribute. (test_ccno_1): Macroize insn pattern from testsi_ccno_1 and testdi_ccno_1 using SWI48 mode attribute. (*testdi_1): Use x86_64_szext_nonmemory_operand instead of x86_64_szext_general_operand. (*testqi_1_maybe_si): Use nonmemory_operand instead of general_operand. (*test_1): Use nonmemory_szext_operand mode attribute instead of genera_operand mode attribute. From-SVN: r273482 --- gcc/ChangeLog | 11 +++++++++++ gcc/config/i386/i386.md | 41 +++++++++++++++++++---------------------- 2 files changed, 30 insertions(+), 22 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a9887b7..81bf833 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2019-07-14 Uroš Bizjak + + * config/i386/i386.md (nonmemory_szext_operand): New mode attribute. + (test_ccno_1): Macroize insn pattern from testsi_ccno_1 + and testdi_ccno_1 using SWI48 mode attribute. + (*testdi_1): Use x86_64_szext_nonmemory_operand instead of + x86_64_szext_general_operand. + (*testqi_1_maybe_si): Use nonmemory_operand instead of general_operand. + (*test_1): Use nonmemory_szext_operand mode attribute + instead of genera_operand mode attribute. + 2019-07-14 Vladislav Ivanishin * gdbhooks.py (DumpFn.invoke): Add explicit casts of return values of diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index db5fa9a..58797ba 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1122,6 +1122,12 @@ (SI "x86_64_szext_general_operand") (DI "x86_64_szext_general_operand")]) +(define_mode_attr nonmemory_szext_operand + [(QI "nonmemory_operand") + (HI "nonmemory_operand") + (SI "x86_64_szext_nonmemory_operand") + (DI "x86_64_szext_nonmemory_operand")]) + ;; Immediate operand predicate for integer modes. (define_mode_attr immediate_operand [(QI "immediate_operand") @@ -8118,11 +8124,12 @@ ;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al. ;; Note that this excludes ah. -(define_expand "testsi_ccno_1" +(define_expand "test_ccno_1" [(set (reg:CCNO FLAGS_REG) (compare:CCNO - (and:SI (match_operand:SI 0 "nonimmediate_operand") - (match_operand:SI 1 "x86_64_nonmemory_operand")) + (and:SWI48 + (match_operand:SWI48 0 "nonimmediate_operand") + (match_operand:SWI48 1 "")) (const_int 0)))]) (define_expand "testqi_ccz_1" @@ -8131,23 +8138,14 @@ (match_operand:QI 1 "nonmemory_operand")) (const_int 0)))]) -(define_expand "testdi_ccno_1" - [(set (reg:CCNO FLAGS_REG) - (compare:CCNO - (and:DI (match_operand:DI 0 "nonimmediate_operand") - (match_operand:DI 1 "x86_64_szext_general_operand")) - (const_int 0)))] - "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))") - (define_insn "*testdi_1" [(set (reg FLAGS_REG) (compare (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm") - (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re")) + (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,Z,e,e,re")) (const_int 0)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" "@ test{l}\t{%k1, %k0|%k0, %k1} test{l}\t{%k1, %k0|%k0, %k1} @@ -8163,12 +8161,12 @@ (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r") - (match_operand:QI 1 "general_operand" "n,n,qn,n")) + (match_operand:QI 1 "nonmemory_operand" "n,n,qn,n")) (const_int 0)))] - "!(MEM_P (operands[0]) && MEM_P (operands[1])) - && ix86_match_ccmode (insn, - CONST_INT_P (operands[1]) - && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)" + + "ix86_match_ccmode (insn, + CONST_INT_P (operands[1]) + && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)" { if (which_alternative == 3) { @@ -8188,10 +8186,9 @@ (compare (and:SWI124 (match_operand:SWI124 0 "nonimmediate_operand" "%!*a,,m") - (match_operand:SWI124 1 "" ",,")) + (match_operand:SWI124 1 "" ",,")) (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "ix86_match_ccmode (insn, CCNOmode)" "test{}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "modrm" "0,1,1") -- cgit v1.1 From c5e02838afa5a79091dc22b480951fc5effb42e6 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Sun, 14 Jul 2019 22:27:25 +0200 Subject: pr84512.c (dg-final): Remove XFAIL on alpha*-*-*. * gcc.dg/tree-ssa/pr84512.c (dg-final): Remove XFAIL on alpha*-*-*. From-SVN: r273483 --- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr84512.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8993a818..b22a8c7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-14 Uroš Bizjak + + * gcc.dg/tree-ssa/pr84512.c (dg-final): Remove XFAIL on alpha*-*-*. + 2019-07-14 Segher Boessenkool PR target/91148 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c b/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c index 3975757..5065dfe 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c @@ -13,4 +13,4 @@ int foo() } /* Listed targets xfailed due to PR84958. */ -/* { dg-final { scan-tree-dump "return 285;" "optimized" { xfail { { alpha*-*-* amdgcn*-*-* nvptx*-*-* } || { sparc*-*-* && lp64 } } } } } */ +/* { dg-final { scan-tree-dump "return 285;" "optimized" { xfail { { amdgcn*-*-* nvptx*-*-* } || { sparc*-*-* && lp64 } } } } } */ -- cgit v1.1 From 1b034a958d4255f1cf57463655b9c74ec1e329bb Mon Sep 17 00:00:00 2001 From: Jerry DeLisle Date: Sun, 14 Jul 2019 22:52:58 +0000 Subject: re PR fortran/87233 (Constraint C1279 still followed after f2008 standard revision (?)) 2019-07-14 Jerry DeLisle PR fortran/87233 * expr.c (check_restricted): Relax constraint C1279 which was removed from F2008 and above. * gfortran.dg/initialization_14.f90: Modify to now pass by removing two dg-error commands. Added comments. * gfortran.dg/initialization_30.f90: New test that includes the two tests removed above with the 'dg-options -std=f95'. From-SVN: r273484 --- gcc/fortran/ChangeLog | 6 ++++++ gcc/fortran/expr.c | 10 ++++++---- gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/gfortran.dg/initialization_14.f90 | 6 +++--- gcc/testsuite/gfortran.dg/initialization_30.f90 | 21 +++++++++++++++++++++ 5 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/initialization_30.f90 (limited to 'gcc') diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 0376f00..c92c85a 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2019-07-14 Jerry DeLisle + + PR fortran/87233 + * expr.c (check_restricted): Relax constraint C1279 which was + removed from F2008 and above. + 2019-07-07 Paul Thomas PR fortran/91077 diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index ec9e328..a164370 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -3305,12 +3305,14 @@ check_restricted (gfc_expr *e) restricted expression in an elemental procedure, it will have already been simplified away once we get here. Therefore we don't need to jump through hoops to distinguish valid from - invalid cases. */ - if (sym->attr.dummy && sym->ns == gfc_current_ns + invalid cases. Allowed in F2008 and F2018. */ + if (gfc_notification_std (GFC_STD_F2008) + && sym->attr.dummy && sym->ns == gfc_current_ns && sym->ns->proc_name && sym->ns->proc_name->attr.elemental) { - gfc_error ("Dummy argument %qs not allowed in expression at %L", - sym->name, &e->where); + gfc_error_now ("Dummy argument %qs not " + "allowed in expression at %L", + sym->name, &e->where); break; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b22a8c7..ae16c7d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-07-14 Jerry DeLisle + + PR fortran/87233 + * gfortran.dg/initialization_14.f90: Modify to now pass by + removing two dg-error commands. Added comments. + * gfortran.dg/initialization_30.f90: New test that includes the + two tests removed above with the 'dg-options -std=f95'. + 2019-07-14 Uroš Bizjak * gcc.dg/tree-ssa/pr84512.c (dg-final): Remove XFAIL on alpha*-*-*. diff --git a/gcc/testsuite/gfortran.dg/initialization_14.f90 b/gcc/testsuite/gfortran.dg/initialization_14.f90 index 4d5b685..aa14377 100644 --- a/gcc/testsuite/gfortran.dg/initialization_14.f90 +++ b/gcc/testsuite/gfortran.dg/initialization_14.f90 @@ -3,18 +3,18 @@ ! Dummy arguments are disallowed in initialization expressions in ! elemental functions except as arguments to the intrinsic functions ! BIT_SIZE, KIND, LEN, or to the numeric inquiry functions listed -! in 13.11.8 +! in 13.11.8 F95, likewise not allowed in F2003, now allowed in F2008. MODULE TT INTEGER M CONTAINS ELEMENTAL REAL FUNCTION two(N) INTEGER, INTENT(IN) :: N - INTEGER, DIMENSION(N) :: scr ! { dg-error "Dummy argument 'n' not allowed in expression" } + INTEGER, DIMENSION(N) :: scr ! Now valid under F2008 END FUNCTION ELEMENTAL REAL FUNCTION twopointfive(N) INTEGER, INTENT(IN) :: N - INTEGER, DIMENSION(MAX(N,2)) :: scr ! { dg-error "Dummy argument 'n' not allowed in expression" } + INTEGER, DIMENSION(MAX(N,2)) :: scr ! Now valid under F2008 end FUNCTION twopointfive REAL FUNCTION three(N) diff --git a/gcc/testsuite/gfortran.dg/initialization_30.f90 b/gcc/testsuite/gfortran.dg/initialization_30.f90 new file mode 100644 index 0000000..ff8436b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/initialization_30.f90 @@ -0,0 +1,21 @@ +! { dg-do compile } +! { dg-options "-std=f95" } +! PR 20851 +! Dummy arguments are disallowed in initialization expressions in +! elemental functions except as arguments to the intrinsic functions +! BIT_SIZE, KIND, LEN, or to the numeric inquiry functions listed +! in 13.11.8 +MODULE TT +INTEGER M +CONTAINS + ELEMENTAL REAL FUNCTION two(N) + INTEGER, INTENT(IN) :: N + INTEGER, DIMENSION(N) :: scr ! { dg-error "Dummy argument 'n' not allowed in expression" } + END FUNCTION + + ELEMENTAL REAL FUNCTION twopointfive(N) + INTEGER, INTENT(IN) :: N + INTEGER, DIMENSION(MAX(N,2)) :: scr ! { dg-error "Dummy argument 'n' not allowed in expression" } + end FUNCTION twopointfive +END MODULE +END -- cgit v1.1 From 3126c241afaa38bc9002b3c15e244070b80af09d Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 15 Jul 2019 00:16:18 +0000 Subject: Daily bump. From-SVN: r273488 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7c107ea..58603ab 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190714 +20190715 -- cgit v1.1 From 6c2833e74e4e64a71bafaf6e20e65506bbce5a5c Mon Sep 17 00:00:00 2001 From: Kewen Lin Date: Mon, 15 Jul 2019 05:12:05 +0000 Subject: re PR tree-optimization/88497 (Improve Accumulation in Auto-Vectorized Code) gcc/ChangeLog 2019-07-15 Kewen Lin PR tree-optimization/88497 * tree-ssa-reassoc.c (reassociate_bb): Swap the positions of GIMPLE_BINARY_RHS check and gimple_visited_p check, call new function undistribute_bitref_for_vector. (undistribute_bitref_for_vector): New function. (cleanup_vinfo_map): Likewise. (sort_by_mach_mode): Likewise. gcc/testsuite/ChangeLog 2019-07-15 Kewen Lin PR tree-optimization/88497 * gcc.dg/tree-ssa/pr88497-1.c: New test. * gcc.dg/tree-ssa/pr88497-2.c: Likewise. * gcc.dg/tree-ssa/pr88497-3.c: Likewise. * gcc.dg/tree-ssa/pr88497-4.c: Likewise. * gcc.dg/tree-ssa/pr88497-5.c: Likewise. * gcc.dg/tree-ssa/pr88497-6.c: Likewise. * gcc.dg/tree-ssa/pr88497-7.c: Likewise. From-SVN: r273490 --- gcc/ChangeLog | 10 ++ gcc/testsuite/ChangeLog | 11 ++ gcc/testsuite/gcc.dg/tree-ssa/pr88497-1.c | 60 +++++++ gcc/testsuite/gcc.dg/tree-ssa/pr88497-2.c | 37 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr88497-3.c | 37 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr88497-4.c | 37 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr88497-5.c | 37 ++++ gcc/testsuite/gcc.dg/tree-ssa/pr88497-6.c | 65 +++++++ gcc/testsuite/gcc.dg/tree-ssa/pr88497-7.c | 77 ++++++++ gcc/tree-ssa-reassoc.c | 285 +++++++++++++++++++++++++++++- 10 files changed, 650 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88497-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88497-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88497-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88497-4.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88497-5.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88497-6.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr88497-7.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81bf833..1ff1c4c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-07-15 Kewen Lin + + PR tree-optimization/88497 + * tree-ssa-reassoc.c (reassociate_bb): Swap the positions of + GIMPLE_BINARY_RHS check and gimple_visited_p check, call new + function undistribute_bitref_for_vector. + (undistribute_bitref_for_vector): New function. + (cleanup_vinfo_map): Likewise. + (sort_by_mach_mode): Likewise. + 2019-07-14 Uroš Bizjak * config/i386/i386.md (nonmemory_szext_operand): New mode attribute. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ae16c7d..57d1141 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2019-07-15 Kewen Lin + + PR tree-optimization/88497 + * gcc.dg/tree-ssa/pr88497-1.c: New test. + * gcc.dg/tree-ssa/pr88497-2.c: Likewise. + * gcc.dg/tree-ssa/pr88497-3.c: Likewise. + * gcc.dg/tree-ssa/pr88497-4.c: Likewise. + * gcc.dg/tree-ssa/pr88497-5.c: Likewise. + * gcc.dg/tree-ssa/pr88497-6.c: Likewise. + * gcc.dg/tree-ssa/pr88497-7.c: Likewise. + 2019-07-14 Jerry DeLisle PR fortran/87233 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88497-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-1.c new file mode 100644 index 0000000..b6dd7ba --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-1.c @@ -0,0 +1,60 @@ +/* { dg-do run } */ +/* { dg-require-effective-target vect_double } */ +/* { dg-require-effective-target vsx_hw { target { powerpc*-*-* } } } */ +/* { dg-require-effective-target sse2_runtime { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1" } */ +/* { dg-additional-options "-mvsx" { target { powerpc*-*-* } } } */ +/* { dg-additional-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ + +/* To test reassoc can undistribute vector bit_field_ref summation. + + arg1 and arg2 are two arrays whose elements of type vector double. + Assuming: + A0 = arg1[0], A1 = arg1[1], A2 = arg1[2], A3 = arg1[3], + B0 = arg2[0], B1 = arg2[1], B2 = arg2[2], B3 = arg2[3], + + Then: + V0 = A0 * B0, V1 = A1 * B1, V2 = A2 * B2, V3 = A3 * B3, + + reassoc transforms + + accumulator += V0[0] + V0[1] + V1[0] + V1[1] + V2[0] + V2[1] + + V3[0] + V3[1]; + + into: + + T = V0 + V1 + V2 + V3 + accumulator += T[0] + T[1]; + + Fewer bit_field_refs, only two for 128 or more bits vector. */ + +typedef double v2df __attribute__ ((vector_size (16))); +__attribute__ ((noinline)) double +test (double accumulator, v2df arg1[], v2df arg2[]) +{ + v2df temp; + temp = arg1[0] * arg2[0]; + accumulator += temp[0] + temp[1]; + temp = arg1[1] * arg2[1]; + accumulator += temp[0] + temp[1]; + temp = arg1[2] * arg2[2]; + accumulator += temp[0] + temp[1]; + temp = arg1[3] * arg2[3]; + accumulator += temp[0] + temp[1]; + return accumulator; +} + +extern void abort (void); + +int +main () +{ + v2df v2[4] = {{1.0, 2.0}, {4.0, 8.0}, {1.0, 3.0}, {9.0, 27.0}}; + v2df v3[4] = {{1.0, 4.0}, {16.0, 64.0}, {1.0, 2.0}, {3.0, 4.0}}; + double acc = 100.0; + double res = test (acc, v2, v3); + if (res != 827.0) + abort (); + return 0; +} +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 2 "reassoc1" { target { powerpc*-*-* i?86-*-* x86_64-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88497-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-2.c new file mode 100644 index 0000000..8da5920 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-2.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-require-effective-target powerpc_altivec_ok { target { powerpc*-*-* } } } */ +/* { dg-require-effective-target sse2 { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1" } */ +/* { dg-additional-options "-maltivec" { target { powerpc*-*-* } } } */ +/* { dg-additional-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ + +/* To test reassoc can undistribute vector bit_field_ref on multiplication. + + v1, v2, v3, v4 of type vector float. + + reassoc transforms + + accumulator *= v1[0] * v1[1] * v1[2] * v1[3] * + v2[0] * v2[1] * v2[2] * v2[3] * + v3[0] * v3[1] * v3[2] * v3[3] * + v4[0] * v4[1] * v4[2] * v4[3] ; + + into: + + T = v1 * v2 * v3 * v4; + accumulator *= T[0] * T[1] * T[2] * T[3]; + + Fewer bit_field_refs, only four for 128 or more bits vector. */ + +typedef float v4sf __attribute__ ((vector_size (16))); +float +test (float accumulator, v4sf v1, v4sf v2, v4sf v3, v4sf v4) +{ + accumulator *= v1[0] * v1[1] * v1[2] * v1[3]; + accumulator *= v2[0] * v2[1] * v2[2] * v2[3]; + accumulator *= v3[0] * v3[1] * v3[2] * v3[3]; + accumulator *= v4[0] * v4[1] * v4[2] * v4[3]; + return accumulator; +} +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 4 "reassoc1" { target { powerpc*-*-* i?86-*-* x86_64-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88497-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-3.c new file mode 100644 index 0000000..449f282 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-3.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target powerpc_altivec_ok { target { powerpc*-*-* } } } */ +/* { dg-require-effective-target sse2 { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1" } */ +/* { dg-additional-options "-maltivec" { target { powerpc*-*-* } } } */ +/* { dg-additional-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ + +/* To test reassoc can undistribute vector bit_field_ref on bitwise AND. + + v1, v2, v3, v4 of type vector int. + + reassoc transforms + + accumulator &= v1[0] & v1[1] & v1[2] & v1[3] & + v2[0] & v2[1] & v2[2] & v2[3] & + v3[0] & v3[1] & v3[2] & v3[3] & + v4[0] & v4[1] & v4[2] & v4[3] ; + + into: + + T = v1 & v2 & v3 & v4; + accumulator &= T[0] & T[1] & T[2] & T[3]; + + Fewer bit_field_refs, only four for 128 or more bits vector. */ + +typedef int v4si __attribute__ ((vector_size (16))); +int +test (int accumulator, v4si v1, v4si v2, v4si v3, v4si v4) +{ + accumulator &= v1[0] & v1[1] & v1[2] & v1[3]; + accumulator &= v2[0] & v2[1] & v2[2] & v2[3]; + accumulator &= v3[0] & v3[1] & v3[2] & v3[3]; + accumulator &= v4[0] & v4[1] & v4[2] & v4[3]; + return accumulator; +} +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 4 "reassoc1" { target { powerpc*-*-* i?86-*-* x86_64-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88497-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-4.c new file mode 100644 index 0000000..f7b6c91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-4.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target powerpc_altivec_ok { target { powerpc*-*-* } } } */ +/* { dg-require-effective-target sse2 { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1" } */ +/* { dg-additional-options "-maltivec" { target { powerpc*-*-* } } } */ +/* { dg-additional-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ + +/* To test reassoc can undistribute vector bit_field_ref on bitwise IOR. + + v1, v2, v3, v4 of type vector int. + + reassoc transforms + + accumulator |= v1[0] | v1[1] | v1[2] | v1[3] | + v2[0] | v2[1] | v2[2] | v2[3] | + v3[0] | v3[1] | v3[2] | v3[3] | + v4[0] | v4[1] | v4[2] | v4[3] ; + + into: + + T = v1 | v2 | v3 | v4; + accumulator |= T[0] | T[1] | T[2] | T[3]; + + Fewer bit_field_refs, only four for 128 or more bits vector. */ + +typedef int v4si __attribute__ ((vector_size (16))); +int +test (int accumulator, v4si v1, v4si v2, v4si v3, v4si v4) +{ + accumulator |= v1[0] | v1[1] | v1[2] | v1[3]; + accumulator |= v2[0] | v2[1] | v2[2] | v2[3]; + accumulator |= v3[0] | v3[1] | v3[2] | v3[3]; + accumulator |= v4[0] | v4[1] | v4[2] | v4[3]; + return accumulator; +} +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 4 "reassoc1" { target { powerpc*-*-* i?86-*-* x86_64-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88497-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-5.c new file mode 100644 index 0000000..cbd1224 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-5.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target powerpc_altivec_ok { target { powerpc*-*-* } } } */ +/* { dg-require-effective-target sse2 { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1" } */ +/* { dg-additional-options "-maltivec" { target { powerpc*-*-* } } } */ +/* { dg-additional-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */ + +/* To test reassoc can undistribute vector bit_field_ref on bitwise XOR. + + v1, v2, v3, v4 of type vector int. + + reassoc transforms + + accumulator ^= v1[0] ^ v1[1] ^ v1[2] ^ v1[3] ^ + v2[0] ^ v2[1] ^ v2[2] ^ v2[3] ^ + v3[0] ^ v3[1] ^ v3[2] ^ v3[3] ^ + v4[0] ^ v4[1] ^ v4[2] ^ v4[3] ; + + into: + + T = v1 ^ v2 ^ v3 ^ v4; + accumulator ^= T[0] ^ T[1] ^ T[2] ^ T[3]; + + Fewer bit_field_refs, only four for 128 or more bits vector. */ + +typedef int v4si __attribute__ ((vector_size (16))); +int +test (int accumulator, v4si v1, v4si v2, v4si v3, v4si v4) +{ + accumulator ^= v1[0] ^ v1[1] ^ v1[2] ^ v1[3]; + accumulator ^= v2[0] ^ v2[1] ^ v2[2] ^ v2[3]; + accumulator ^= v3[0] ^ v3[1] ^ v3[2] ^ v3[3]; + accumulator ^= v4[0] ^ v4[1] ^ v4[2] ^ v4[3]; + return accumulator; +} +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 4 "reassoc1" { target { powerpc*-*-* i?86-*-* x86_64-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88497-6.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-6.c new file mode 100644 index 0000000..0146518 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-6.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target avx512f } */ +/* { dg-options "-O2 -mavx512f -ffast-math -fdump-tree-reassoc1" } */ + +/* To test reassoc can undistribute vector bit_field_ref on multiple + vector machine modes. + + v1, v2 of type vector 4 x float + v3, v4 of type vector 8 x float + v5, v6 of type vector 16 x float + + reassoc transforms + + accumulator += v1[0] + v1[1] + v1[2] + v1[3] + + v2[0] + v2[1] + v2[2] + v2[3] + + v3[0] + v3[1] + v3[2] + v3[3] + + v3[4] + v3[5] + v3[6] + v3[7] + + v4[0] + v4[1] + v4[2] + v4[3] + + v4[4] + v4[5] + v4[6] + v4[7] + + v5[0] + v5[1] + v5[2] + v5[3] + + v5[4] + v5[5] + v5[6] + v5[7] + + v5[8] + v5[9] + v5[10] + v5[11] + + v5[12] + v5[13] + v5[14] + v5[15] + + v6[0] + v6[1] + v6[2] + v6[3] + + v6[4] + v6[5] + v6[6] + v6[7] + + v6[8] + v6[9] + v6[10] + v6[11] + + v6[12] + v6[13] + v6[14] + v6[15] ; + + into: + + T12 = v1 + v2; + T34 = v3 + v4; + T56 = v5 + v6; + accumulator += T12[0] + T12[1] + T12[2] + T12[3] + + accumulator += T34[0] + T34[1] + T34[2] + T34[3] + + accumulator += T34[4] + T34[5] + T34[6] + T34[7] + + accumulator += T56[0] + T56[1] + T56[2] + T56[3] + + accumulator += T56[4] + T56[5] + T56[6] + T56[7] + + accumulator += T56[8] + T56[9] + T56[10] + T56[11] + + accumulator += T56[12] + T56[13] + T56[14] + T56[15] ; */ + +typedef float v4sf __attribute__((vector_size(16))); +typedef float v8sf __attribute__((vector_size(32))); +typedef float v16sf __attribute__((vector_size(64))); + +float +test (float accumulator, v4sf v1, v4sf v2, v8sf v3, v8sf v4, v16sf v5, v16sf v6) +{ + accumulator += v1[0] + v1[1] + v1[2] + v1[3]; + accumulator += v2[0] + v2[1] + v2[2] + v2[3]; + accumulator += v3[0] + v3[1] + v3[2] + v3[3]; + accumulator += v3[4] + v3[5] + v3[6] + v3[7]; + accumulator += v4[0] + v4[1] + v4[2] + v4[3]; + accumulator += v4[4] + v4[5] + v4[6] + v4[7]; + accumulator += v5[0] + v5[1] + v5[2] + v5[3]; + accumulator += v5[4] + v5[5] + v5[6] + v5[7]; + accumulator += v5[8] + v5[9] + v5[10] + v5[11]; + accumulator += v5[12] + v5[13] + v5[14] + v5[15]; + accumulator += v6[0] + v6[1] + v6[2] + v6[3]; + accumulator += v6[4] + v6[5] + v6[6] + v6[7]; + accumulator += v6[8] + v6[9] + v6[10] + v6[11]; + accumulator += v6[12] + v6[13] + v6[14] + v6[15]; + return accumulator; +} +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 28 "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88497-7.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-7.c new file mode 100644 index 0000000..0445878 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88497-7.c @@ -0,0 +1,77 @@ +/* { dg-do run } */ +/* { dg-require-effective-target avx512f_runtime } */ +/* { dg-options "-O2 -mavx512f -ffast-math -fdump-tree-reassoc1" } */ + +/* To test reassoc can undistribute vector bit_field_ref on multiple + vector machine modes, bypass those modes with only one candidate. + + v1, v2 of type vector 4 x float + v3 of type vector 8 x float + v5, v6 of type vector 16 x float + + reassoc transforms + + accumulator += v1[0] + v1[1] + v1[2] + v1[3] + + v2[0] + v2[1] + v2[2] + v2[3] + + v3[0] + v3[1] + v3[2] + v3[3] + + v3[4] + v3[5] + v3[6] + v3[7] + + v5[0] + v5[1] + v5[2] + v5[3] + + v5[4] + v5[5] + v5[6] + v5[7] + + v5[8] + v5[9] + v5[10] + v5[11] + + v5[12] + v5[13] + v5[14] + v5[15] + + v6[0] + v6[1] + v6[2] + v6[3] + + v6[4] + v6[5] + v6[6] + v6[7] + + v6[8] + v6[9] + v6[10] + v6[11] + + v6[12] + v6[13] + v6[14] + v6[15] ; + + into: + + T12 = v1 + v2; + T56 = v5 + v6; + accumulator += T12[0] + T12[1] + T12[2] + T12[3] + + accumulator += v3[0] + v3[1] + v3[2] + v3[3] + + accumulator += v3[4] + v3[5] + v3[6] + v3[7] + + accumulator += T56[0] + T56[1] + T56[2] + T56[3] + + accumulator += T56[4] + T56[5] + T56[6] + T56[7] + + accumulator += T56[8] + T56[9] + T56[10] + T56[11] + + accumulator += T56[12] + T56[13] + T56[14] + T56[15] ; */ + +typedef float v4sf __attribute__((vector_size(16))); +typedef float v8sf __attribute__((vector_size(32))); +typedef float v16sf __attribute__((vector_size(64))); + +__attribute__ ((noinline)) +float test(float accumulator, v4sf v1, v4sf v2, v8sf v3, v16sf v5, v16sf v6) { + accumulator += v1[0] + v1[1] + v1[2] + v1[3]; + accumulator += v2[0] + v2[1] + v2[2] + v2[3]; + accumulator += v3[0] + v3[1] + v3[2] + v3[3]; + accumulator += v3[4] + v3[5] + v3[6] + v3[7]; + accumulator += v5[0] + v5[1] + v5[2] + v5[3]; + accumulator += v5[4] + v5[5] + v5[6] + v5[7]; + accumulator += v5[8] + v5[9] + v5[10] + v5[11]; + accumulator += v5[12] + v5[13] + v5[14] + v5[15]; + accumulator += v6[0] + v6[1] + v6[2] + v6[3]; + accumulator += v6[4] + v6[5] + v6[6] + v6[7]; + accumulator += v6[8] + v6[9] + v6[10] + v6[11]; + accumulator += v6[12] + v6[13] + v6[14] + v6[15]; + return accumulator; +} + +extern void abort (void); + +int +main () +{ + v4sf v1 = {1.0, 2.0, 3.0, 4.0 }; + v4sf v2 = {5.0, 6.0, 7.0, 8.0 }; + v8sf v3 = {9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 }; + v16sf v5 = {17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0}; + v16sf v6 = {33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0}; + float acc = 24.0; + double res = test (acc, v1, v2, v3, v5, v6); + if (res != 1200.0) + abort(); + return 0; +} + +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 28 "reassoc1" } } */ diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 635fc93..df76e66 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -1772,6 +1772,274 @@ undistribute_ops_list (enum tree_code opcode, return changed; } +/* Pair to hold the information of one specific VECTOR_TYPE SSA_NAME: + first: element index for each relevant BIT_FIELD_REF. + second: the index of vec ops* for each relevant BIT_FIELD_REF. */ +typedef std::pair v_info_elem; +typedef auto_vec v_info; +typedef v_info *v_info_ptr; + +/* Comparison function for qsort on VECTOR SSA_NAME trees by machine mode. */ +static int +sort_by_mach_mode (const void *p_i, const void *p_j) +{ + const tree tr1 = *((const tree *) p_i); + const tree tr2 = *((const tree *) p_j); + unsigned int mode1 = TYPE_MODE (TREE_TYPE (tr1)); + unsigned int mode2 = TYPE_MODE (TREE_TYPE (tr2)); + if (mode1 > mode2) + return 1; + else if (mode1 < mode2) + return -1; + else + return 0; +} + +/* Cleanup hash map for VECTOR information. */ +static void +cleanup_vinfo_map (hash_map &info_map) +{ + for (hash_map::iterator it = info_map.begin (); + it != info_map.end (); ++it) + { + v_info_ptr info = (*it).second; + delete info; + (*it).second = NULL; + } +} + +/* Perform un-distribution of BIT_FIELD_REF on VECTOR_TYPE. + V1[0] + V1[1] + ... + V1[k] + V2[0] + V2[1] + ... + V2[k] + ... Vn[k] + is transformed to + Vs = (V1 + V2 + ... + Vn) + Vs[0] + Vs[1] + ... + Vs[k] + + The basic steps are listed below: + + 1) Check the addition chain *OPS by looking those summands coming from + VECTOR bit_field_ref on VECTOR type. Put the information into + v_info_map for each satisfied summand, using VECTOR SSA_NAME as key. + + 2) For each key (VECTOR SSA_NAME), validate all its BIT_FIELD_REFs are + continuous, they can cover the whole VECTOR perfectly without any holes. + Obtain one VECTOR list which contain candidates to be transformed. + + 3) Sort the VECTOR list by machine mode of VECTOR type, for each group of + candidates with same mode, build the addition statements for them and + generate BIT_FIELD_REFs accordingly. + + TODO: + The current implementation requires the whole VECTORs should be fully + covered, but it can be extended to support partial, checking adjacent + but not fill the whole, it may need some cost model to define the + boundary to do or not. +*/ +static bool +undistribute_bitref_for_vector (enum tree_code opcode, + vec *ops, struct loop *loop) +{ + if (ops->length () <= 1) + return false; + + if (opcode != PLUS_EXPR && opcode != MULT_EXPR && opcode != BIT_XOR_EXPR + && opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR) + return false; + + hash_map v_info_map; + operand_entry *oe1; + unsigned i; + + /* Find those summands from VECTOR BIT_FIELD_REF in addition chain, put the + information into map. */ + FOR_EACH_VEC_ELT (*ops, i, oe1) + { + enum tree_code dcode; + gimple *oe1def; + + if (TREE_CODE (oe1->op) != SSA_NAME) + continue; + oe1def = SSA_NAME_DEF_STMT (oe1->op); + if (!is_gimple_assign (oe1def)) + continue; + dcode = gimple_assign_rhs_code (oe1def); + if (dcode != BIT_FIELD_REF || !is_reassociable_op (oe1def, dcode, loop)) + continue; + + tree rhs = gimple_assign_rhs1 (oe1def); + tree vec = TREE_OPERAND (rhs, 0); + tree vec_type = TREE_TYPE (vec); + + if (TREE_CODE (vec) != SSA_NAME || !VECTOR_TYPE_P (vec_type)) + continue; + + /* Ignore it if target machine can't support this VECTOR type. */ + if (!VECTOR_MODE_P (TYPE_MODE (vec_type))) + continue; + + /* Check const vector type, constrain BIT_FIELD_REF offset and size. */ + if (!TYPE_VECTOR_SUBPARTS (vec_type).is_constant ()) + continue; + + tree elem_type = TREE_TYPE (vec_type); + unsigned HOST_WIDE_INT elem_size + = TREE_INT_CST_LOW (TYPE_SIZE (elem_type)); + if (maybe_ne (bit_field_size (rhs), elem_size)) + continue; + + unsigned idx; + if (!constant_multiple_p (bit_field_offset (rhs), elem_size, &idx)) + continue; + + /* Ignore it if target machine can't support this type of VECTOR + operation. */ + optab op_tab = optab_for_tree_code (opcode, vec_type, optab_vector); + if (optab_handler (op_tab, TYPE_MODE (vec_type)) == CODE_FOR_nothing) + continue; + + bool existed; + v_info_ptr &info = v_info_map.get_or_insert (vec, &existed); + if (!existed) + info = new v_info; + info->safe_push (std::make_pair (idx, i)); + } + + /* At least two VECTOR to combine. */ + if (v_info_map.elements () <= 1) + { + cleanup_vinfo_map (v_info_map); + return false; + } + + /* Verify all VECTOR candidates by checking two conditions: + 1) sorted offsets are adjacent, no holes. + 2) can fill the whole VECTOR perfectly. + And add the valid candidates to a vector for further handling. */ + auto_vec valid_vecs (v_info_map.elements ()); + for (hash_map::iterator it = v_info_map.begin (); + it != v_info_map.end (); ++it) + { + tree cand_vec = (*it).first; + v_info_ptr cand_info = (*it).second; + unsigned int num_elems = VECTOR_CST_NELTS (cand_vec).to_constant (); + if (cand_info->length () != num_elems) + continue; + sbitmap holes = sbitmap_alloc (num_elems); + bitmap_ones (holes); + bool valid = true; + v_info_elem *curr; + FOR_EACH_VEC_ELT (*cand_info, i, curr) + { + if (!bitmap_bit_p (holes, curr->first)) + { + valid = false; + break; + } + else + bitmap_clear_bit (holes, curr->first); + } + if (valid && bitmap_empty_p (holes)) + valid_vecs.quick_push (cand_vec); + sbitmap_free (holes); + } + + /* At least two VECTOR to combine. */ + if (valid_vecs.length () <= 1) + { + cleanup_vinfo_map (v_info_map); + return false; + } + + valid_vecs.qsort (sort_by_mach_mode); + /* Go through all candidates by machine mode order, query the mode_to_total + to get the total number for each mode and skip the single one. */ + for (unsigned i = 0; i < valid_vecs.length () - 1; ++i) + { + tree tvec = valid_vecs[i]; + enum machine_mode mode = TYPE_MODE (TREE_TYPE (tvec)); + + /* Skip modes with only a single candidate. */ + if (TYPE_MODE (TREE_TYPE (valid_vecs[i + 1])) != mode) + continue; + + unsigned int idx, j; + gimple *sum = NULL; + v_info_ptr info_ptr; + tree sum_vec = tvec; + v_info_elem *elem; + + /* Build the sum for all candidates with same mode. */ + do + { + sum = build_and_add_sum (TREE_TYPE (sum_vec), sum_vec, + valid_vecs[i + 1], opcode); + sum_vec = gimple_get_lhs (sum); + info_ptr = *(v_info_map.get (valid_vecs[i + 1])); + /* Update those related ops of current candidate VECTOR. */ + FOR_EACH_VEC_ELT (*info_ptr, j, elem) + { + idx = elem->second; + gimple *def = SSA_NAME_DEF_STMT ((*ops)[idx]->op); + /* Set this then op definition will get DCEd later. */ + gimple_set_visited (def, true); + if (opcode == PLUS_EXPR || opcode == BIT_XOR_EXPR + || opcode == BIT_IOR_EXPR) + (*ops)[idx]->op = build_zero_cst (TREE_TYPE ((*ops)[idx]->op)); + else if (opcode == MULT_EXPR) + (*ops)[idx]->op = build_one_cst (TREE_TYPE ((*ops)[idx]->op)); + else + { + gcc_assert (opcode == BIT_AND_EXPR); + (*ops)[idx]->op + = build_all_ones_cst (TREE_TYPE ((*ops)[idx]->op)); + } + (*ops)[idx]->rank = 0; + } + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Generating addition -> "); + print_gimple_stmt (dump_file, sum, 0); + } + i++; + } + while ((i < valid_vecs.length () - 1) + && TYPE_MODE (TREE_TYPE (valid_vecs[i + 1])) == mode); + + /* Referring to first valid VECTOR with this mode, generate the + BIT_FIELD_REF statements accordingly. */ + info_ptr = *(v_info_map.get (tvec)); + gcc_assert (sum); + tree elem_type = TREE_TYPE (TREE_TYPE (tvec)); + FOR_EACH_VEC_ELT (*info_ptr, j, elem) + { + idx = elem->second; + tree dst = make_ssa_name (elem_type); + gimple *gs = gimple_build_assign ( + dst, BIT_FIELD_REF, + build3 (BIT_FIELD_REF, elem_type, sum_vec, TYPE_SIZE (elem_type), + bitsize_int (elem->first + * tree_to_uhwi (TYPE_SIZE (elem_type))))); + insert_stmt_after (gs, sum); + gimple *def = SSA_NAME_DEF_STMT ((*ops)[idx]->op); + /* Set this then op definition will get DCEd later. */ + gimple_set_visited (def, true); + (*ops)[idx]->op = gimple_assign_lhs (gs); + (*ops)[idx]->rank = get_rank ((*ops)[idx]->op); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Generating bit_field_ref -> "); + print_gimple_stmt (dump_file, gs, 0); + } + } + } + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "undistributiong bit_field_ref for vector done.\n"); + + cleanup_vinfo_map (v_info_map); + + return true; +} + /* If OPCODE is BIT_IOR_EXPR or BIT_AND_EXPR and CURR is a comparison expression, examine the other OPS to see if any of them are comparisons of the same values, which we may be able to combine or eliminate. @@ -5879,11 +6147,6 @@ reassociate_bb (basic_block bb) tree lhs, rhs1, rhs2; enum tree_code rhs_code = gimple_assign_rhs_code (stmt); - /* If this is not a gimple binary expression, there is - nothing for us to do with it. */ - if (get_gimple_rhs_class (rhs_code) != GIMPLE_BINARY_RHS) - continue; - /* If this was part of an already processed statement, we don't need to touch it again. */ if (gimple_visited_p (stmt)) @@ -5910,6 +6173,11 @@ reassociate_bb (basic_block bb) continue; } + /* If this is not a gimple binary expression, there is + nothing for us to do with it. */ + if (get_gimple_rhs_class (rhs_code) != GIMPLE_BINARY_RHS) + continue; + lhs = gimple_assign_lhs (stmt); rhs1 = gimple_assign_rhs1 (stmt); rhs2 = gimple_assign_rhs2 (stmt); @@ -5948,7 +6216,12 @@ reassociate_bb (basic_block bb) ops.qsort (sort_by_operand_rank); optimize_ops_list (rhs_code, &ops); } - + if (undistribute_bitref_for_vector (rhs_code, &ops, + loop_containing_stmt (stmt))) + { + ops.qsort (sort_by_operand_rank); + optimize_ops_list (rhs_code, &ops); + } if (rhs_code == PLUS_EXPR && transform_add_to_multiply (&ops)) ops.qsort (sort_by_operand_rank); -- cgit v1.1 From 5e79b147663c2f24079f3292e25cd66693da8cf5 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 15 Jul 2019 12:48:47 +0000 Subject: re PR tree-optimization/91162 (ICE: tree check: expected class 'type', have 'exceptional' (error_mark) in useless_type_conversion_p, at gimple-expr.c:86 (error: invalid 'PHI' argument)) 2019-07-15 Richard Biener PR middle-end/91162 * tree-cfg.c (move_block_to_fn): When releasing a virtual PHI node make sure to replace all uses with something valid. * gcc.dg/autopar/pr91162.c: New testcase. From-SVN: r273492 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/autopar/pr91162.c | 25 +++++++++++++++++++++++++ gcc/tree-cfg.c | 9 ++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/autopar/pr91162.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1ff1c4c..af0b4b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-15 Richard Biener + + PR middle-end/91162 + * tree-cfg.c (move_block_to_fn): When releasing a virtual PHI + node make sure to replace all uses with something valid. + 2019-07-15 Kewen Lin PR tree-optimization/88497 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 57d1141..d36652f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-15 Richard Biener + + PR middle-end/91162 + * gcc.dg/autopar/pr91162.c: New testcase. + 2019-07-15 Kewen Lin PR tree-optimization/88497 diff --git a/gcc/testsuite/gcc.dg/autopar/pr91162.c b/gcc/testsuite/gcc.dg/autopar/pr91162.c new file mode 100644 index 0000000..4bfedb9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/autopar/pr91162.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ftree-parallelize-loops=2 -fno-tree-dominator-opts --param parloops-min-per-thread=30" } */ + +void +zf (__int128 ct) +{ + __int128 *rk = &ct; + + if (0) + { + int jj; + +t9: + for (jj = 0; jj < 60; ++jj) + { + } + + __builtin_unreachable (); + } + + while (*rk < 1) + ++*rk; + + goto t9; +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 5c67d02..4521fe3 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -7088,7 +7088,14 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, if (virtual_operand_p (op)) { /* Remove the phi nodes for virtual operands (alias analysis will be - run for the new function, anyway). */ + run for the new function, anyway). But replace all uses that + might be outside of the region we move. */ + use_operand_p use_p; + imm_use_iterator iter; + gimple *use_stmt; + FOR_EACH_IMM_USE_STMT (use_stmt, iter, op) + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, SSA_NAME_VAR (op)); remove_phi_node (&psi, true); continue; } -- cgit v1.1 From c559f3ef4eec68c43c8937c3aa08a383e9cf6251 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Mon, 15 Jul 2019 21:21:36 +0200 Subject: tree-ssa-alias.c (aliasing_component_refs_walk): Initialize same_p to 0. * tree-ssa-alias.c (aliasing_component_refs_walk): Initialize same_p to 0. From-SVN: r273495 --- gcc/ChangeLog | 5 +++++ gcc/tree-ssa-alias.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af0b4b5..e56ae5f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-15 Jan Hubicka + + * tree-ssa-alias.c (aliasing_component_refs_walk): Initialize same_p + to 0. + 2019-07-15 Richard Biener PR middle-end/91162 diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index d6e3976..dd2a43e 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -931,7 +931,7 @@ aliasing_component_refs_walk (tree ref1, tree type1, tree base1, bool *maybe_match) { tree ref = ref2; - int same_p; + int same_p = 0; while (true) { -- cgit v1.1 From ea298f7ad0170458e740b03eb9af9b90b697f92f Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Mon, 15 Jul 2019 22:26:43 +0200 Subject: i386.md (@test_ccno_1): Rename from test_ccno_1. * config/i386/i386.md (@test_ccno_1): Rename from test_ccno_1. (*testdi_1): Remove redundant alternatives. Remove modrm attribute. (*testqi_1_maybe_si): Remove modrm attribute. (*test_1): Ditto. * config/i386/i386-expand.c (ix86_split_idivmod): Use gen_test_ccno_1 and gen_extend_insn. From-SVN: r273496 --- gcc/ChangeLog | 10 ++++++++++ gcc/config/i386/i386-expand.c | 21 ++++++++------------- gcc/config/i386/i386.md | 14 ++++---------- 3 files changed, 22 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e56ae5f..92aed39 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2019-07-15 UroÅ¡ Bizjak + + * config/i386/i386.md (@test_ccno_1): + Rename from test_ccno_1. + (*testdi_1): Remove redundant alternatives. Remove modrm attribute. + (*testqi_1_maybe_si): Remove modrm attribute. + (*test_1): Ditto. + * config/i386/i386-expand.c (ix86_split_idivmod): Use + gen_test_ccno_1 and gen_extend_insn. + 2019-07-15 Jan Hubicka * tree-ssa-alias.c (aliasing_component_refs_walk): Initialize same_p diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 0519da8..d50e21e 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -1122,8 +1122,6 @@ ix86_split_idivmod (machine_mode mode, rtx operands[], rtx_insn *insn; rtx scratch, tmp0, tmp1, tmp2; rtx (*gen_divmod4_1) (rtx, rtx, rtx, rtx); - rtx (*gen_zero_extend) (rtx, rtx); - rtx (*gen_test_ccno_1) (rtx, rtx); switch (mode) { @@ -1135,21 +1133,16 @@ ix86_split_idivmod (machine_mode mode, rtx operands[], else gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2; - gen_zero_extend = gen_zero_extendqisi2; } else - { - gen_divmod4_1 - = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1; - gen_zero_extend = gen_zero_extendqidi2; - } - gen_test_ccno_1 = gen_testsi_ccno_1; + gen_divmod4_1 + = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1; break; + case E_DImode: gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1; - gen_test_ccno_1 = gen_testdi_ccno_1; - gen_zero_extend = gen_zero_extendqidi2; break; + default: gcc_unreachable (); } @@ -1164,7 +1157,7 @@ ix86_split_idivmod (machine_mode mode, rtx operands[], emit_move_insn (scratch, operands[2]); scratch = expand_simple_binop (mode, IOR, scratch, operands[3], scratch, 1, OPTAB_DIRECT); - emit_insn (gen_test_ccno_1 (scratch, GEN_INT (-0x100))); + emit_insn (gen_test_ccno_1 (mode, scratch, GEN_INT (-0x100))); tmp0 = gen_rtx_REG (CCNOmode, FLAGS_REG); tmp0 = gen_rtx_EQ (VOIDmode, tmp0, const0_rtx); tmp0 = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp0, @@ -1227,7 +1220,9 @@ ix86_split_idivmod (machine_mode mode, rtx operands[], /* Zero extend quotient from AL. */ tmp1 = gen_lowpart (QImode, tmp0); - insn = emit_insn (gen_zero_extend (operands[0], tmp1)); + insn = emit_insn (gen_extend_insn + (operands[0], tmp1, + GET_MODE (operands[0]), QImode, 1)); set_unique_reg_note (insn, REG_EQUAL, div); emit_label (end_label); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 58797ba..19d1682 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8124,7 +8124,7 @@ ;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al. ;; Note that this excludes ah. -(define_expand "test_ccno_1" +(define_expand "@test_ccno_1" [(set (reg:CCNO FLAGS_REG) (compare:CCNO (and:SWI48 @@ -8142,19 +8142,15 @@ [(set (reg FLAGS_REG) (compare (and:DI - (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm") - (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,Z,e,e,re")) + (match_operand:DI 0 "nonimmediate_operand" "r,rm") + (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,re")) (const_int 0)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" "@ test{l}\t{%k1, %k0|%k0, %k1} - test{l}\t{%k1, %k0|%k0, %k1} - test{q}\t{%1, %0|%0, %1} - test{q}\t{%1, %0|%0, %1} test{q}\t{%1, %0|%0, %1}" [(set_attr "type" "test") - (set_attr "modrm" "0,1,0,1,1") - (set_attr "mode" "SI,SI,DI,DI,DI")]) + (set_attr "mode" "SI,DI")]) (define_insn "*testqi_1_maybe_si" [(set (reg FLAGS_REG) @@ -8177,7 +8173,6 @@ return "test{b}\t{%1, %0|%0, %1}"; } [(set_attr "type" "test") - (set_attr "modrm" "0,1,1,1") (set_attr "mode" "QI,QI,QI,SI") (set_attr "pent_pair" "uv,np,uv,np")]) @@ -8191,7 +8186,6 @@ "ix86_match_ccmode (insn, CCNOmode)" "test{}\t{%1, %0|%0, %1}" [(set_attr "type" "test") - (set_attr "modrm" "0,1,1") (set_attr "mode" "") (set_attr "pent_pair" "uv,np,uv")]) -- cgit v1.1 From 2d94f7dea9c73ef3c116a0ddc722724578a860fe Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Mon, 15 Jul 2019 22:57:53 +0200 Subject: rs6000: Always output .machine We now can always output .machine (if we output it at all for the current target). PR target/91050 * config/rs6000/rs6000.c (rs6000_file_start): Never skip emitting a .machine directive. From-SVN: r273498 --- gcc/ChangeLog | 6 ++++++ gcc/config/rs6000/rs6000.c | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92aed39..7ab87da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-15 Segher Boessenkool + + PR target/91050 + * config/rs6000/rs6000.c (rs6000_file_start): Never skip emitting a + .machine directive. + 2019-07-15 UroÅ¡ Bizjak * config/i386/i386.md (@test_ccno_1): diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 827894c..63f3075 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -5644,9 +5644,7 @@ rs6000_file_start (void) #ifdef USING_ELFOS_H rs6000_machine = rs6000_machine_from_flags (); - if (!(rs6000_default_cpu && rs6000_default_cpu[0]) - && !global_options_set.x_rs6000_cpu_index) - emit_asm_machine (); + emit_asm_machine (); #endif if (DEFAULT_ABI == ABI_ELFv2) -- cgit v1.1 From 4e62f891cdeabc14cf6195a69dc6528aab11e753 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 15 Jul 2019 21:17:16 +0000 Subject: runtime: expose the g variable Currently, getg is implemented in C, which loads the thread-local g variable. The g variable is declared static in C. This CL exposes the g variable, so it can be accessed from the Go side. This allows the Go compiler to inline getg calls to direct access of g. Currently, the actual inlining is only implemented in the gollvm compiler. The g variable is thread-local and the compiler backend may choose to cache the TLS address in a register or on stack. If a thread switch happens the cache may become invalid. I don't know how to disable the TLS address cache in gccgo, therefore the inlining of getg is not implemented. In the future gccgo may gain this if we know how to do it safely. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/186238 From-SVN: r273499 --- gcc/go/gofrontend/MERGE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 28fc223..4e19c52 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -70ceba5e95716653b9f829a457a44a829175d4da +0e51b7e9c03c6f6bc3d06343f2050f17349ccdc3 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. -- cgit v1.1 From c4a193bcba544c24246308f83e947f425219fb84 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Tue, 16 Jul 2019 00:23:11 +0200 Subject: * config/i386/i386.md (*testdi_1): Put back "%" constraint modifier. From-SVN: r273501 --- gcc/config/i386/i386.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 19d1682..410731f 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8142,7 +8142,7 @@ [(set (reg FLAGS_REG) (compare (and:DI - (match_operand:DI 0 "nonimmediate_operand" "r,rm") + (match_operand:DI 0 "nonimmediate_operand" "%r,rm") (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,re")) (const_int 0)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" -- cgit v1.1 From b4ad799f45b60a06ee92ea9ba01000f09d33c909 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 16 Jul 2019 00:16:48 +0000 Subject: Daily bump. From-SVN: r273505 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 58603ab..51bd565 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190715 +20190716 -- cgit v1.1 From 42b593d5e0e424e42eb22290acee7160fd2d690a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 16 Jul 2019 03:34:58 -0400 Subject: Remove trailing space. From-SVN: r273506 --- gcc/cp/parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c46740a..f91c50e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -9679,7 +9679,7 @@ cp_parser_question_colon_clause (cp_parser* parser, cp_expr logical_or_expr) if (cp_parser_allow_gnu_extensions_p (parser) && token->type == CPP_COLON) { - pedwarn (token->location, OPT_Wpedantic, + pedwarn (token->location, OPT_Wpedantic, "ISO C++ does not allow % with omitted middle operand"); /* Implicit true clause. */ expr = NULL_TREE; -- cgit v1.1 From d3ed5b56646511a52db9992f4024969bfc9a13f9 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 16 Jul 2019 10:12:05 +0200 Subject: PR91176: Skip debug insns when computing inline costs Apply Honza's fix for an aarch64-linux-gnu bootstrap failure. 2019-07-16 Jan Hubicka gcc/ PR bootstrap/91176 * ipa-fnsummary.c (analyze_function_body): Skip debug stmts From-SVN: r273507 --- gcc/ChangeLog | 5 +++++ gcc/ipa-fnsummary.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7ab87da..82a8f0b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-16 Jan Hubicka + + PR bootstrap/91176 + * ipa-fnsummary.c (analyze_function_body): Skip debug stmts + 2019-07-15 Segher Boessenkool PR target/91050 diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 78eb8cb..fe125ac 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -2078,8 +2078,8 @@ analyze_function_body (struct cgraph_node *node, bool early) fix_builtin_expect_stmt = find_foldable_builtin_expect (bb); - for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); - gsi_next (&bsi)) + for (gimple_stmt_iterator bsi = gsi_start_nondebug_bb (bb); + !gsi_end_p (bsi); gsi_next_nondebug (&bsi)) { gimple *stmt = gsi_stmt (bsi); int this_size = estimate_num_insns (stmt, &eni_size_weights); -- cgit v1.1 From 8f5b616591371edc9ec4f31f9b8c1d611b3b7577 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 16 Jul 2019 08:40:55 +0000 Subject: [mips] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. No behavioural change -- produces the same code as before. 2019-07-16 Richard Sandiford gcc/ * config/mips/micromips.md (*movep): Explicitly use for the mode attribute. From-SVN: r273508 --- gcc/ChangeLog | 5 +++++ gcc/config/mips/micromips.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 82a8f0b..69a7f8e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-16 Richard Sandiford + + * config/mips/micromips.md (*movep): + Explicitly use for the mode attribute. + 2019-07-16 Jan Hubicka PR bootstrap/91176 diff --git a/gcc/config/mips/micromips.md b/gcc/config/mips/micromips.md index 9f8158e..782d9d1 100644 --- a/gcc/config/mips/micromips.md +++ b/gcc/config/mips/micromips.md @@ -133,5 +133,5 @@ return "movep\t%2,%0,%z3,%z1"; } [(set_attr "type" "move") - (set_attr "mode" "") + (set_attr "mode" "") (set_attr "can_delay" "no")]) -- cgit v1.1 From f6e5e4b83b153d056b93048fd23b4afebcd49bcf Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 16 Jul 2019 08:41:03 +0000 Subject: [rs6000] Fix ambiguous .md attribute uses This patch is part of a series that fixes ambiguous attribute uses in .md files, i.e. cases in which attributes didn't use to specify an iterator, and in which could have different values depending on the iterator chosen. No behavioural change -- produces the same code as before except for formatting and line numbers. 2019-07-16 Richard Sandiford gcc/ * config/rs6000/rs6000.md (*mov_update1): Explicitly use , , and rather than leaving the choice between SFDF and P implicit. (*mov_update2): Likewise. (*cmp_internal2): Explicitly use rather than leaving the choice betweem IBM128 and GPR implicit. (*fix_trunc2_mem): Explicitly use rather than leaving the choice between IEEE128 and QHSI implicit. (AltiVec define_peephole2s): Explicitly use rather than leaving the choice between ALTIVEC_DFORM and P implicit. * config/rs6000/vsx.md (*vsx_ext__fl_) (*vsx_ext__ufl_): Explicitly use rather than leaving the choice between FL_CONV and VSX_EXTRACT_I implicit. From-SVN: r273509 --- gcc/ChangeLog | 19 +++++++++++++++++++ gcc/config/rs6000/rs6000.md | 38 +++++++++++++++++++++----------------- gcc/config/rs6000/vsx.md | 4 ++-- 3 files changed, 42 insertions(+), 19 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69a7f8e..d8998f6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,24 @@ 2019-07-16 Richard Sandiford + * config/rs6000/rs6000.md (*mov_update1): Explicitly + use , , and rather than + leaving the choice between SFDF and P implicit. + (*mov_update2): Likewise. + (*cmp_internal2): Explicitly use + rather than leaving the choice betweem IBM128 and GPR implicit. + (*fix_trunc2_mem): Explicitly use + rather than leaving the choice between IEEE128 and + QHSI implicit. + (AltiVec define_peephole2s): Explicitly use + rather than leaving the choice between ALTIVEC_DFORM and P implicit. + * config/rs6000/vsx.md + (*vsx_ext__fl_) + (*vsx_ext__ufl_): Explicitly + use rather than leaving the choice between FL_CONV + and VSX_EXTRACT_I implicit. + +2019-07-16 Richard Sandiford + * config/mips/micromips.md (*movep): Explicitly use for the mode attribute. diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index e1f0b0a..4ef1993 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -9311,14 +9311,14 @@ (set_attr "update" "yes") (set_attr "indexed" "yes,no")]) -(define_insn "*mov_update1" - [(set (match_operand:SFDF 3 "gpc_reg_operand" "=,") +(define_insn "*mov_update1" + [(set (match_operand:SFDF 3 "gpc_reg_operand" "=,") (mem:SFDF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0") (match_operand:P 2 "reg_or_short_operand" "r,I")))) (set (match_operand:P 0 "gpc_reg_operand" "=b,b") (plus:P (match_dup 1) (match_dup 2)))] "TARGET_HARD_FLOAT && TARGET_UPDATE - && (!avoiding_indexed_address_p (mode) + && (!avoiding_indexed_address_p (mode) || !gpc_reg_operand (operands[2], Pmode))" "@ lfux %3,%0,%2 @@ -9326,16 +9326,16 @@ [(set_attr "type" "fpload") (set_attr "update" "yes") (set_attr "indexed" "yes,no") - (set_attr "size" "")]) + (set_attr "size" "")]) -(define_insn "*mov_update2" +(define_insn "*mov_update2" [(set (mem:SFDF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0") (match_operand:P 2 "reg_or_short_operand" "r,I"))) - (match_operand:SFDF 3 "gpc_reg_operand" ",")) + (match_operand:SFDF 3 "gpc_reg_operand" ",")) (set (match_operand:P 0 "gpc_reg_operand" "=b,b") (plus:P (match_dup 1) (match_dup 2)))] "TARGET_HARD_FLOAT && TARGET_UPDATE - && (!avoiding_indexed_address_p (mode) + && (!avoiding_indexed_address_p (mode) || !gpc_reg_operand (operands[2], Pmode))" "@ stfux %3,%0,%2 @@ -9343,7 +9343,7 @@ [(set_attr "type" "fpstore") (set_attr "update" "yes") (set_attr "indexed" "yes,no") - (set_attr "size" "")]) + (set_attr "size" "")]) (define_insn "*movsf_update3" [(set (match_operand:SF 3 "gpc_reg_operand" "=r,r") @@ -11557,7 +11557,7 @@ [(set_attr "type" "fpcompare") (set_attr "length" "12")]) -(define_insn_and_split "*cmp_internal2" +(define_insn_and_split "*cmp_internal2" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") (compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d") (match_operand:IBM128 2 "gpc_reg_operand" "d"))) @@ -11570,7 +11570,7 @@ (clobber (match_scratch:DF 9 "=d")) (clobber (match_scratch:DF 10 "=d")) (clobber (match_scratch:GPR 11 "=b"))] - "TARGET_XL_COMPAT && FLOAT128_IBM_P (mode) + "TARGET_XL_COMPAT && FLOAT128_IBM_P (mode) && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128" "#" "&& reload_completed" @@ -11594,10 +11594,14 @@ const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0; const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode); - operands[5] = simplify_gen_subreg (DFmode, operands[1], mode, hi_word); - operands[6] = simplify_gen_subreg (DFmode, operands[1], mode, lo_word); - operands[7] = simplify_gen_subreg (DFmode, operands[2], mode, hi_word); - operands[8] = simplify_gen_subreg (DFmode, operands[2], mode, lo_word); + operands[5] = simplify_gen_subreg (DFmode, operands[1], + mode, hi_word); + operands[6] = simplify_gen_subreg (DFmode, operands[1], + mode, lo_word); + operands[7] = simplify_gen_subreg (DFmode, operands[2], + mode, hi_word); + operands[8] = simplify_gen_subreg (DFmode, operands[2], + mode, lo_word); operands[12] = gen_label_rtx (); operands[13] = gen_label_rtx (); real_inf (&rv); @@ -13596,7 +13600,7 @@ new_addr = gen_rtx_PLUS (Pmode, add_op0, tmp_reg); operands[4] = add_op1; - operands[5] = change_address (mem, mode, new_addr); + operands[5] = change_address (mem, mode, new_addr); }) ;; Optimize cases were want to do a D-form store on ISA 2.06/2.07 from an @@ -13632,7 +13636,7 @@ new_addr = gen_rtx_PLUS (Pmode, add_op0, tmp_reg); operands[4] = add_op1; - operands[5] = change_address (mem, mode, new_addr); + operands[5] = change_address (mem, mode, new_addr); }) @@ -14072,7 +14076,7 @@ (any_fix:QHSI (match_operand:IEEE128 1 "altivec_register_operand" "v"))) (clobber (match_scratch:QHSI 2 "=v"))] - "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" "#" "&& reload_completed" [(set (match_dup 2) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index c33b45a..7633171 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -3828,7 +3828,7 @@ { operands[4] = gen_rtx_REG (DImode, REGNO (operands[3])); } - [(set_attr "isa" "")]) + [(set_attr "isa" "")]) (define_insn_and_split "*vsx_ext__ufl_" [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=wa") @@ -3851,7 +3851,7 @@ { operands[4] = gen_rtx_REG (DImode, REGNO (operands[3])); } - [(set_attr "isa" "")]) + [(set_attr "isa" "")]) ;; V4SI/V8HI/V16QI set operation on ISA 3.0 (define_insn "vsx_set__p9" -- cgit v1.1 From 737eb76789cd454918a85983255a1f62efcbfdc9 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 16 Jul 2019 08:41:13 +0000 Subject: Use file_location for md_reader's ptr_loc Also make it public, so that clients can use the location for error reporting. 2019-07-16 Richard Sandiford gcc/ * read-md.h (md_reader::ptr_loc): Moved from read-md.c. Use file_location instead of separate fields. (md_reader::set_md_ptr_loc): Take a file_location instead of a separate filename and line number. * read-md.c (ptr_loc): As above. (md_reader::copy_md_ptr_loc): Update for new ptr_loc layout. (md_reader::fprint_md_ptr_loc): Likewise. (md_reader::set_md_ptr_loc): Likewise. Take a file_location instead of a separate filename and line number. (md_reader::read_string): Update call accordingly. From-SVN: r273510 --- gcc/ChangeLog | 13 +++++++++++++ gcc/read-md.c | 27 +++++++++------------------ gcc/read-md.h | 9 ++++++++- 3 files changed, 30 insertions(+), 19 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d8998f6..ec6567d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,18 @@ 2019-07-16 Richard Sandiford + * read-md.h (md_reader::ptr_loc): Moved from read-md.c. + Use file_location instead of separate fields. + (md_reader::set_md_ptr_loc): Take a file_location instead of a + separate filename and line number. + * read-md.c (ptr_loc): As above. + (md_reader::copy_md_ptr_loc): Update for new ptr_loc layout. + (md_reader::fprint_md_ptr_loc): Likewise. + (md_reader::set_md_ptr_loc): Likewise. Take a file_location + instead of a separate filename and line number. + (md_reader::read_string): Update call accordingly. + +2019-07-16 Richard Sandiford + * config/rs6000/rs6000.md (*mov_update1): Explicitly use , , and rather than leaving the choice between SFDF and P implicit. diff --git a/gcc/read-md.c b/gcc/read-md.c index 8247640..d9a27ac 100644 --- a/gcc/read-md.c +++ b/gcc/read-md.c @@ -43,14 +43,6 @@ int have_error = 0; #endif /* #ifndef GENERATOR_FILE */ -/* Associates PTR (which can be a string, etc.) with the file location - specified by FILENAME and LINENO. */ -struct ptr_loc { - const void *ptr; - const char *filename; - int lineno; -}; - /* This callback will be invoked whenever an md include directive is processed. To be used for creation of the dependency file. */ void (*include_callback) (const char *); @@ -94,25 +86,24 @@ leading_ptr_eq_p (const void *def1, const void *def2) return *(const void *const *) def1 == *(const void *const *) def2; } -/* Associate PTR with the file position given by FILENAME and LINENO. */ +/* Associate PTR with the file position given by FILE_LOC. */ void -md_reader::set_md_ptr_loc (const void *ptr, const char *filename, int lineno) +md_reader::set_md_ptr_loc (const void *ptr, file_location file_loc) { struct ptr_loc *loc; loc = (struct ptr_loc *) obstack_alloc (&m_ptr_loc_obstack, sizeof (struct ptr_loc)); loc->ptr = ptr; - loc->filename = filename; - loc->lineno = lineno; + loc->loc = file_loc; *htab_find_slot (m_ptr_locs, loc, INSERT) = loc; } /* Return the position associated with pointer PTR. Return null if no position was set. */ -const struct ptr_loc * +const md_reader::ptr_loc * md_reader::get_md_ptr_loc (const void *ptr) { return (const struct ptr_loc *) htab_find (m_ptr_locs, &ptr); @@ -125,7 +116,7 @@ md_reader::copy_md_ptr_loc (const void *new_ptr, const void *old_ptr) { const struct ptr_loc *loc = get_md_ptr_loc (old_ptr); if (loc != 0) - set_md_ptr_loc (new_ptr, loc->filename, loc->lineno); + set_md_ptr_loc (new_ptr, loc->loc); } /* If PTR is associated with a known file position, print a #line @@ -136,7 +127,7 @@ md_reader::fprint_md_ptr_loc (FILE *outf, const void *ptr) { const struct ptr_loc *loc = get_md_ptr_loc (ptr); if (loc != 0) - fprintf (outf, "#line %d \"%s\"\n", loc->lineno, loc->filename); + fprintf (outf, "#line %d \"%s\"\n", loc->loc.lineno, loc->loc.filename); } /* Special fprint_md_ptr_loc for writing to STDOUT. */ @@ -672,7 +663,7 @@ md_reader::read_string (int star_if_braced) { char *stringbuf; int saw_paren = 0; - int c, old_lineno; + int c; c = read_skip_spaces (); if (c == '(') @@ -681,7 +672,7 @@ md_reader::read_string (int star_if_braced) c = read_skip_spaces (); } - old_lineno = get_lineno (); + file_location loc = get_current_location (); if (c == '"') stringbuf = read_quoted_string (); else if (c == '{') @@ -704,7 +695,7 @@ md_reader::read_string (int star_if_braced) if (saw_paren) require_char_ws (')'); - set_md_ptr_loc (stringbuf, get_filename (), old_lineno); + set_md_ptr_loc (stringbuf, loc); return stringbuf; } diff --git a/gcc/read-md.h b/gcc/read-md.h index 9cb7569..eff4012 100644 --- a/gcc/read-md.h +++ b/gcc/read-md.h @@ -149,6 +149,13 @@ struct mapping; class md_reader { public: + /* Associates PTR (which can be a string, etc.) with the file location + specified by LOC. */ + struct ptr_loc { + const void *ptr; + file_location loc; + }; + md_reader (bool compact); virtual ~md_reader (); @@ -183,7 +190,7 @@ class md_reader void require_word_ws (const char *expected); int peek_char (void); - void set_md_ptr_loc (const void *ptr, const char *filename, int lineno); + void set_md_ptr_loc (const void *ptr, file_location); const struct ptr_loc *get_md_ptr_loc (const void *ptr); void copy_md_ptr_loc (const void *new_ptr, const void *old_ptr); void fprint_md_ptr_loc (FILE *outf, const void *ptr); -- cgit v1.1 From 10b04d1e0b3f4435a8f2e806fddf12ff8b864623 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 16 Jul 2019 08:41:21 +0000 Subject: Report ambiguous uses of .md attributes This patch reports an error if the .md file has an unscoped attribute that maps to more than one possible value. 2019-07-16 Richard Sandiford gcc/ * read-md.h (md_reader::record_potential_iterator_use): Add a file_location parameter. * read-rtl.c (attribute_use::loc): New field. (map_attr_string): Take a file_location parameter. Report cases in which attributes map to multiple distinct values. (apply_attribute_uses): Update call accordingly. (md_reader::handle_overloaded_name): Likewise. (md_reader::apply_iterator_to_string): Likewise. Skip empty nonnull strings. (record_attribute_use): Take a file_location parameter. Initialize attribute_use::loc. (md_reader::record_potential_iterator_use): Take a file_location parameter. Update call to record_attribute_use. (rtx_reader::rtx_alloc_for_name): Update call accordingly. (rtx_reader::read_rtx_code): Likewise. (rtx_reader::read_rtx_operand): Likewise. Record a location for implicitly-expanded empty strings. From-SVN: r273511 --- gcc/ChangeLog | 20 ++++++++++++++++++ gcc/read-md.h | 4 ++-- gcc/read-rtl.c | 67 +++++++++++++++++++++++++++++++++++++++------------------- 3 files changed, 67 insertions(+), 24 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec6567d..30e6e7e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,25 @@ 2019-07-16 Richard Sandiford + * read-md.h (md_reader::record_potential_iterator_use): Add a + file_location parameter. + * read-rtl.c (attribute_use::loc): New field. + (map_attr_string): Take a file_location parameter. Report cases + in which attributes map to multiple distinct values. + (apply_attribute_uses): Update call accordingly. + (md_reader::handle_overloaded_name): Likewise. + (md_reader::apply_iterator_to_string): Likewise. Skip empty + nonnull strings. + (record_attribute_use): Take a file_location parameter. + Initialize attribute_use::loc. + (md_reader::record_potential_iterator_use): Take a file_location + parameter. Update call to record_attribute_use. + (rtx_reader::rtx_alloc_for_name): Update call accordingly. + (rtx_reader::read_rtx_code): Likewise. + (rtx_reader::read_rtx_operand): Likewise. Record a location + for implicitly-expanded empty strings. + +2019-07-16 Richard Sandiford + * read-md.h (md_reader::ptr_loc): Moved from read-md.c. Use file_location instead of separate fields. (md_reader::set_md_ptr_loc): Take a file_location instead of a diff --git a/gcc/read-md.h b/gcc/read-md.h index eff4012..377b9f1 100644 --- a/gcc/read-md.h +++ b/gcc/read-md.h @@ -212,8 +212,8 @@ class md_reader rtx copy_rtx_for_iterators (rtx original); void read_conditions (); void record_potential_iterator_use (struct iterator_group *group, - rtx x, unsigned int index, - const char *name); + file_location loc, rtx x, + unsigned int index, const char *name); struct mapping *read_mapping (struct iterator_group *group, htab_t table); overloaded_name *handle_overloaded_name (rtx, vec *); diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c index 6b1b811..3b5d999 100644 --- a/gcc/read-rtl.c +++ b/gcc/read-rtl.c @@ -106,6 +106,9 @@ struct attribute_use { /* The group that describes the use site. */ struct iterator_group *group; + /* The location at which the use occurs. */ + file_location loc; + /* The name of the attribute, possibly with an "iterator:" prefix. */ const char *value; @@ -361,10 +364,10 @@ find_subst_iter_by_attr (const char *attr) /* Map attribute string P to its current value. Return null if the attribute isn't known. If ITERATOR_OUT is nonnull, store the associated iterator - there. */ + there. Report any errors against location LOC. */ static struct map_value * -map_attr_string (const char *p, mapping **iterator_out = 0) +map_attr_string (file_location loc, const char *p, mapping **iterator_out = 0) { const char *attr; struct mapping *iterator; @@ -372,6 +375,8 @@ map_attr_string (const char *p, mapping **iterator_out = 0) struct mapping *m; struct map_value *v; int iterator_name_len; + struct map_value *res = NULL; + struct mapping *prev = NULL; /* Peel off any "iterator:" prefix. Set ATTR to the start of the attribute name. */ @@ -414,13 +419,22 @@ map_attr_string (const char *p, mapping **iterator_out = 0) for (v = m->values; v; v = v->next) if (v->number == iterator->current_value->number) { + if (res && strcmp (v->string, res->string) != 0) + { + error_at (loc, "ambiguous attribute '%s'; could be" + " '%s' (via '%s:%s') or '%s' (via '%s:%s')", + attr, res->string, prev->name, attr, + v->string, iterator->name, attr); + return v; + } if (iterator_out) *iterator_out = iterator; - return v; + prev = iterator; + res = v; } } } - return NULL; + return res; } /* Apply the current iterator values to STRING. Return the new string @@ -432,16 +446,17 @@ md_reader::apply_iterator_to_string (const char *string) char *base, *copy, *p, *start, *end; struct map_value *v; - if (string == 0) + if (string == 0 || string[0] == 0) return string; + file_location loc = get_md_ptr_loc (string)->loc; base = p = copy = ASTRDUP (string); while ((start = strchr (p, '<')) && (end = strchr (start, '>'))) { p = start + 1; *end = 0; - v = map_attr_string (p); + v = map_attr_string (loc, p); *end = '>'; if (v == 0) continue; @@ -572,7 +587,7 @@ apply_attribute_uses (void) FOR_EACH_VEC_ELT (attribute_uses, i, ause) { - v = map_attr_string (ause->value); + v = map_attr_string (ause->loc, ause->value); if (!v) fatal_with_file_and_line ("unknown iterator value `%s'", ause->value); ause->group->apply_iterator (ause->x, ause->index, @@ -656,6 +671,7 @@ md_reader::handle_overloaded_name (rtx original, vec *iterators) /* Remove the '@', so that no other code needs to worry about it. */ const char *name = XSTR (original, 0); + file_location loc = get_md_ptr_loc (name)->loc; copy_md_ptr_loc (name + 1, name); name += 1; XSTR (original, 0) = name; @@ -672,7 +688,7 @@ md_reader::handle_overloaded_name (rtx original, vec *iterators) { *end = 0; mapping *iterator; - if (!map_attr_string (start + 1, &iterator)) + if (!map_attr_string (loc, start + 1, &iterator)) fatal_with_file_and_line ("unknown iterator `%s'", start + 1); *end = '>'; @@ -1126,24 +1142,25 @@ record_iterator_use (struct mapping *iterator, rtx x, unsigned int index) iterator_uses.safe_push (iuse); } -/* Record that X uses attribute VALUE, which must match a built-in - value from group GROUP. If the use is in an operand of X, INDEX - is the index of that operand, otherwise it is ignored. */ +/* Record that X uses attribute VALUE at location LOC, where VALUE must + match a built-in value from group GROUP. If the use is in an operand + of X, INDEX is the index of that operand, otherwise it is ignored. */ static void -record_attribute_use (struct iterator_group *group, rtx x, +record_attribute_use (struct iterator_group *group, file_location loc, rtx x, unsigned int index, const char *value) { - struct attribute_use ause = {group, value, x, index}; + struct attribute_use ause = {group, loc, value, x, index}; attribute_uses.safe_push (ause); } /* Interpret NAME as either a built-in value, iterator or attribute for group GROUP. X and INDEX are the values to pass to GROUP's - apply_iterator callback. */ + apply_iterator callback. LOC is the location of the use. */ void md_reader::record_potential_iterator_use (struct iterator_group *group, + file_location loc, rtx x, unsigned int index, const char *name) { @@ -1156,7 +1173,7 @@ md_reader::record_potential_iterator_use (struct iterator_group *group, /* Copy the attribute string into permanent storage, without the angle brackets around it. */ obstack_grow0 (&m_string_obstack, name + 1, len - 2); - record_attribute_use (group, x, index, + record_attribute_use (group, loc, x, index, XOBFINISH (&m_string_obstack, char *)); } else @@ -1540,7 +1557,8 @@ rtx_reader::rtx_alloc_for_name (const char *name) /* Pick the first possible code for now, and record the attribute use for later. */ rtx x = rtx_alloc (check_code_attribute (m)); - record_attribute_use (&codes, x, 0, deferred_name); + record_attribute_use (&codes, get_current_location (), + x, 0, deferred_name); return x; } @@ -1639,8 +1657,8 @@ rtx_reader::read_rtx_code (const char *code_name) c = read_skip_spaces (); if (c == ':') { - read_name (&name); - record_potential_iterator_use (&modes, return_rtx, 0, name.string); + file_location loc = read_name (&name); + record_potential_iterator_use (&modes, loc, return_rtx, 0, name.string); } else unread_char (c); @@ -1862,6 +1880,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT || GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE)) { + const char *old_stringbuf = stringbuf; struct obstack *string_obstack = get_string_obstack (); char line_name[20]; const char *read_md_filename = get_filename (); @@ -1875,6 +1894,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) sprintf (line_name, ":%d", get_lineno ()); obstack_grow (string_obstack, line_name, strlen (line_name)+1); stringbuf = XOBFINISH (string_obstack, char *); + copy_md_ptr_loc (stringbuf, old_stringbuf); } /* Find attr-names in the string. */ @@ -1946,10 +1966,13 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) case 'i': case 'n': case 'p': - /* Can be an iterator or an integer constant. */ - read_name (&name); - record_potential_iterator_use (&ints, return_rtx, idx, name.string); - break; + { + /* Can be an iterator or an integer constant. */ + file_location loc = read_name (&name); + record_potential_iterator_use (&ints, loc, return_rtx, idx, + name.string); + break; + } case 'r': read_name (&name); -- cgit v1.1 From 19bd90282641da569f3da6c26eac3fd248296cb2 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 16 Jul 2019 04:49:04 -0400 Subject: Fix g++.dg/template/pr84789.C on new concepts branch. On the concepts branch I ran into trouble where a pre-parsed dependent nested-name-specifier got replaced on a subsequent parse with is_declaration by one with typenames resolved, which was then used wrongly on a further parse with !is_declaration. * parser.c (cp_parser_nested_name_specifier_opt): If the token is already CPP_NESTED_NAME_SPECIFIER, leave it alone. From-SVN: r273513 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/parser.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a18959d..bd85c70 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2019-07-16 Jason Merrill + + * parser.c (cp_parser_nested_name_specifier_opt): If the token is + already CPP_NESTED_NAME_SPECIFIER, leave it alone. + 2019-07-12 Jakub Jelinek * parser.c (cp_parser_omp_clause_name): Handle order clause. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f91c50e..14a2168 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6275,7 +6275,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, cp_token *token; /* Remember where the nested-name-specifier starts. */ - if (cp_parser_uncommitted_to_tentative_parse_p (parser)) + if (cp_parser_uncommitted_to_tentative_parse_p (parser) + && cp_lexer_next_token_is_not (parser->lexer, CPP_NESTED_NAME_SPECIFIER)) { start = cp_lexer_token_position (parser->lexer, false); push_deferring_access_checks (dk_deferred); -- cgit v1.1 From fd860f7d441d1f414bb13f2b6e1be6c4addac11f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 16 Jul 2019 04:50:16 -0400 Subject: Simplify type-specifier parsing. Previously, the tentative parses for optional type-specifier and to support class template argument deduction were combined awkwardly. This reorganization was motivated by the new concepts branch. * parser.c (cp_parser_simple_type_specifier): Separate tentative parses for optional type-spec and CTAD. From-SVN: r273514 --- gcc/cp/ChangeLog | 3 +++ gcc/cp/parser.c | 57 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 31 insertions(+), 29 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bd85c70..ad7f4a3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2019-07-16 Jason Merrill + * parser.c (cp_parser_simple_type_specifier): Separate tentative + parses for optional type-spec and CTAD. + * parser.c (cp_parser_nested_name_specifier_opt): If the token is already CPP_NESTED_NAME_SPECIFIER, leave it alone. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 14a2168..5e4b453 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -17833,7 +17833,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, /* Don't gobble tokens or issue error messages if this is an optional type-specifier. */ - if ((flags & CP_PARSER_FLAGS_OPTIONAL) || cxx_dialect >= cxx17) + if (flags & CP_PARSER_FLAGS_OPTIONAL) cp_parser_parse_tentatively (parser); token = cp_lexer_peek_token (parser->lexer); @@ -17873,37 +17873,26 @@ cp_parser_simple_type_specifier (cp_parser* parser, else { cp_parser_error (parser, "expected template-id for type"); - type = NULL_TREE; + type = error_mark_node; } } } - /* Otherwise, look for a type-name. */ - else - type = cp_parser_type_name (parser, (qualified_p && typename_p)); - /* Keep track of all name-lookups performed in class scopes. */ - if (type - && !global_p - && !qualified_p - && TREE_CODE (type) == TYPE_DECL - && identifier_p (DECL_NAME (type))) - maybe_note_name_used_in_class (DECL_NAME (type), type); - /* If it didn't work out, we don't have a TYPE. */ - if (((flags & CP_PARSER_FLAGS_OPTIONAL) || cxx_dialect >= cxx17) - && !cp_parser_parse_definitely (parser)) - type = NULL_TREE; - if (!type && cxx_dialect >= cxx17) + /* Otherwise, look for a type-name. */ + if (!type) { - if (flags & CP_PARSER_FLAGS_OPTIONAL) + if (cxx_dialect >= cxx17) cp_parser_parse_tentatively (parser); - cp_parser_global_scope_opt (parser, - /*current_scope_valid_p=*/false); - cp_parser_nested_name_specifier_opt (parser, - /*typename_keyword_p=*/false, - /*check_dependency_p=*/true, - /*type_p=*/false, - /*is_declaration=*/false); + type = cp_parser_type_name (parser, (qualified_p && typename_p)); + + if (cxx_dialect >= cxx17 && !cp_parser_parse_definitely (parser)) + type = NULL_TREE; + } + + if (!type && cxx_dialect >= cxx17) + { + /* Try class template argument deduction. */ tree name = cp_parser_identifier (parser); if (name && TREE_CODE (name) == IDENTIFIER_NODE && parser->scope != error_mark_node) @@ -17929,11 +17918,21 @@ cp_parser_simple_type_specifier (cp_parser* parser, } else type = error_mark_node; - - if ((flags & CP_PARSER_FLAGS_OPTIONAL) - && !cp_parser_parse_definitely (parser)) - type = NULL_TREE; } + + /* If it didn't work out, we don't have a TYPE. */ + if ((flags & CP_PARSER_FLAGS_OPTIONAL) + && !cp_parser_parse_definitely (parser)) + type = NULL_TREE; + + /* Keep track of all name-lookups performed in class scopes. */ + if (type + && !global_p + && !qualified_p + && TREE_CODE (type) == TYPE_DECL + && identifier_p (DECL_NAME (type))) + maybe_note_name_used_in_class (DECL_NAME (type), type); + if (type && decl_specs) cp_parser_set_decl_spec_type (decl_specs, type, token, -- cgit v1.1 From 6eaf3f9eeb7aa8edeb4a55987ef7e6ab22918f97 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 16 Jul 2019 04:57:03 -0400 Subject: Simplify range location creation in C++ parser. Many places in the parser follow the same pattern of capturing the location of the last lexed token, either before or after lexing it, and then using that as the end of a location range; this can be simplified by passing the lexer to make_location and grabbing the token location there. * parser.c (make_location): Add overload taking cp_lexer* as last parameter. From-SVN: r273516 --- gcc/cp/ChangeLog | 3 +++ gcc/cp/parser.c | 72 ++++++++++++++++++++------------------------------------ 2 files changed, 29 insertions(+), 46 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ad7f4a3..c9091f5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2019-07-16 Jason Merrill + * parser.c (make_location): Add overload taking cp_lexer* as last + parameter. + * parser.c (cp_parser_simple_type_specifier): Separate tentative parses for optional type-spec and CTAD. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 5e4b453..1a5da1d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -773,6 +773,16 @@ cp_lexer_previous_token (cp_lexer *lexer) return cp_lexer_token_at (lexer, tp); } +/* Overload for make_location, taking the lexer to mean the location of the + previous token. */ + +static inline location_t +make_location (location_t caret, location_t start, cp_lexer *lexer) +{ + cp_token *t = cp_lexer_previous_token (lexer); + return make_location (caret, start, t->location); +} + /* nonzero if we are presently saving tokens. */ static inline int @@ -7774,10 +7784,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, ~~~^~~~~~~~~~~~~ where the caret is at the deref token, ranging from the start of postfix_expression to the end of the access expr. */ - location_t end_loc - = get_finish (cp_lexer_previous_token (parser->lexer)->location); location_t combined_loc - = make_location (input_location, start_loc, end_loc); + = make_location (input_location, start_loc, parser->lexer); protected_set_expr_location (postfix_expression, combined_loc); } } @@ -8187,10 +8195,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, ^~~~~~~~~~~~~~ with start == caret at the start of the "alignof"/"sizeof" token, with the endpoint at the final closing paren. */ - location_t finish_loc - = cp_lexer_previous_token (parser->lexer)->location; location_t compound_loc - = make_location (start_loc, start_loc, finish_loc); + = make_location (start_loc, start_loc, parser->lexer); cp_expr ret_expr (ret); ret_expr.set_location (compound_loc); @@ -8291,8 +8297,6 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, parser->type_definition_forbidden_message = saved_message; - location_t finish_loc - = cp_lexer_peek_token (parser->lexer)->location; parens.require_close (parser); /* Construct a location of the form: @@ -8300,7 +8304,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, ^~~~~~~~~~~~~~~ with start == caret, finishing at the close-paren. */ location_t noexcept_loc - = make_location (start_loc, start_loc, finish_loc); + = make_location (start_loc, start_loc, parser->lexer); return cp_expr (finish_noexcept_expr (expr, tf_warning_or_error), noexcept_loc); @@ -8351,15 +8355,13 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, /* Consume the '&&' token. */ cp_lexer_consume_token (parser->lexer); /* Look for the identifier. */ - location_t finish_loc - = get_finish (cp_lexer_peek_token (parser->lexer)->location); identifier = cp_parser_identifier (parser); /* Construct a location of the form: &&label ^~~~~~~ with caret==start at the "&&", finish at the end of the label. */ location_t combined_loc - = make_location (start_loc, start_loc, finish_loc); + = make_location (start_loc, start_loc, parser->lexer); /* Create an expression representing the address. */ expression = finish_label_address_expr (identifier, combined_loc); if (cp_parser_non_integral_constant_expression (parser, @@ -8607,10 +8609,8 @@ cp_parser_has_attribute_expression (cp_parser *parser) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ with start == caret at the start of the built-in token, and with the endpoint at the final closing paren. */ - location_t finish_loc - = cp_lexer_previous_token (parser->lexer)->location; location_t compound_loc - = make_location (start_loc, start_loc, finish_loc); + = make_location (start_loc, start_loc, parser->lexer); cp_expr ret_expr (ret ? boolean_true_node : boolean_false_node); ret_expr.set_location (compound_loc); @@ -8732,9 +8732,8 @@ cp_parser_new_expression (cp_parser* parser) ^~~~~~~~~~~~ with caret == start at the start of the "new" token, and the end at the end of the final token we consumed. */ - cp_token *end_tok = cp_lexer_previous_token (parser->lexer); - location_t end_loc = get_finish (end_tok->location); - location_t combined_loc = make_location (start_loc, start_loc, end_loc); + location_t combined_loc = make_location (start_loc, start_loc, + parser->lexer); /* Create a representation of the new-expression. */ ret = build_new (&placement, type, nelts, &initializer, global_scope_p, @@ -10501,10 +10500,9 @@ cp_parser_lambda_expression (cp_parser* parser) insert_pending_capture_proxies (); /* Update the lambda expression to a range. */ - cp_token *end_tok = cp_lexer_previous_token (parser->lexer); LAMBDA_EXPR_LOCATION (lambda_expr) = make_location (token->location, token->location, - end_tok->location); + parser->lexer); if (ok) lambda_expr = build_lambda_object (lambda_expr); @@ -11147,11 +11145,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, cp_parser_parse_tentatively (parser); std_attrs = cp_parser_std_attribute_spec_seq (parser); if (std_attrs) - { - location_t end_loc - = cp_lexer_previous_token (parser->lexer)->location; - attrs_loc = make_location (attrs_loc, attrs_loc, end_loc); - } + attrs_loc = make_location (attrs_loc, attrs_loc, parser->lexer); if (c_dialect_objc ()) { if (!cp_parser_parse_definitely (parser)) @@ -15529,10 +15523,8 @@ cp_parser_operator (cp_parser* parser, location_t start_loc) ^~~~~~~~~~~~~~~~~~~~~ with caret == start at the start token, finish at the end of the suffix identifier. */ - location_t finish_loc - = get_finish (cp_lexer_previous_token (parser->lexer)->location); location_t combined_loc - = make_location (start_loc, start_loc, finish_loc); + = make_location (start_loc, start_loc, parser->lexer); return cp_expr (id, combined_loc); } @@ -16454,10 +16446,8 @@ cp_parser_template_id (cp_parser *parser, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ with caret == start at the start of the template-name, ranging until the closing '>'. */ - location_t finish_loc - = get_finish (cp_lexer_previous_token (parser->lexer)->location); location_t combined_loc - = make_location (token->location, token->location, finish_loc); + = make_location (token->location, token->location, parser->lexer); /* Check for concepts autos where they don't belong. We could identify types in some cases of idnetifier TEMPL, looking ahead @@ -28567,10 +28557,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type) ^~~~~~~~~~~~~~~ with caret == start at the start of the type name, finishing at the closing brace. */ - location_t finish_loc - = get_finish (cp_lexer_previous_token (parser->lexer)->location); location_t combined_loc = make_location (start_loc, start_loc, - finish_loc); + parser->lexer); cast.set_location (combined_loc); return cast; } @@ -28605,9 +28593,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type) ^~~~~~~~ with caret == start at the start of the type name, finishing at the closing paren. */ - location_t finish_loc - = get_finish (cp_lexer_previous_token (parser->lexer)->location); - location_t combined_loc = make_location (start_loc, start_loc, finish_loc); + location_t combined_loc = make_location (start_loc, start_loc, parser->lexer); cast.set_location (combined_loc); return cast; } @@ -30652,9 +30638,7 @@ cp_parser_objc_encode_expression (cp_parser* parser) @encode(int) ^~~~~~~~~~~~ with caret==start at the @ token, finishing at the close paren. */ - location_t combined_loc - = make_location (start_loc, start_loc, - cp_lexer_previous_token (parser->lexer)->location); + location_t combined_loc = make_location (start_loc, start_loc, parser->lexer); return cp_expr (objc_build_encode_expr (type), combined_loc); } @@ -30698,9 +30682,7 @@ cp_parser_objc_protocol_expression (cp_parser* parser) @protocol(prot) ^~~~~~~~~~~~~~~ with caret==start at the @ token, finishing at the close paren. */ - location_t combined_loc - = make_location (start_loc, start_loc, - cp_lexer_previous_token (parser->lexer)->location); + location_t combined_loc = make_location (start_loc, start_loc, parser->lexer); tree result = objc_build_protocol_expr (proto); protected_set_expr_location (result, combined_loc); return result; @@ -30785,9 +30767,7 @@ cp_parser_objc_selector_expression (cp_parser* parser) @selector(func) ^~~~~~~~~~~~~~~ with caret==start at the @ token, finishing at the close paren. */ - location_t combined_loc - = make_location (loc, loc, - cp_lexer_previous_token (parser->lexer)->location); + location_t combined_loc = make_location (loc, loc, parser->lexer); tree result = objc_build_selector_expr (combined_loc, sel_seq); /* TODO: objc_build_selector_expr doesn't always honor the location. */ protected_set_expr_location (result, combined_loc); -- cgit v1.1 From 656867bc6657191a2175c863f00abce9cd8c6fdf Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Tue, 16 Jul 2019 09:13:16 +0000 Subject: Require int128 support in gcc.dg/autopar/pr91162.c * gcc.dg/autopar/pr91162.c: Require int128 support. From-SVN: r273518 --- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/autopar/pr91162.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d36652f..bd94f71 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-16 Rainer Orth + + * gcc.dg/autopar/pr91162.c: Require int128 support. + 2019-07-15 Richard Biener PR middle-end/91162 diff --git a/gcc/testsuite/gcc.dg/autopar/pr91162.c b/gcc/testsuite/gcc.dg/autopar/pr91162.c index 4bfedb9..ff243e4 100644 --- a/gcc/testsuite/gcc.dg/autopar/pr91162.c +++ b/gcc/testsuite/gcc.dg/autopar/pr91162.c @@ -1,4 +1,4 @@ -/* { dg-do compile } */ +/* { dg-do compile { target int128 } } */ /* { dg-options "-O -ftree-parallelize-loops=2 -fno-tree-dominator-opts --param parloops-min-per-thread=30" } */ void -- cgit v1.1 From ee8c45492a5001b062ff449b18a1f4f13eaa631d Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Tue, 16 Jul 2019 09:27:57 +0000 Subject: Don't xfail gcc.dg/tree-ssa/pr84512.c on 64-bit SPARC * gcc.dg/tree-ssa/pr84512.c: Don't xfail scan-tree-dump on sparcv9. From-SVN: r273519 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/tree-ssa/pr84512.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bd94f71..e6ca043 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2019-07-16 Rainer Orth + * gcc.dg/tree-ssa/pr84512.c: Don't xfail scan-tree-dump on + sparcv9. + +2019-07-16 Rainer Orth + * gcc.dg/autopar/pr91162.c: Require int128 support. 2019-07-15 Richard Biener diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c b/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c index 5065dfe..48d829a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr84512.c @@ -13,4 +13,4 @@ int foo() } /* Listed targets xfailed due to PR84958. */ -/* { dg-final { scan-tree-dump "return 285;" "optimized" { xfail { { amdgcn*-*-* nvptx*-*-* } || { sparc*-*-* && lp64 } } } } } */ +/* { dg-final { scan-tree-dump "return 285;" "optimized" { xfail { amdgcn*-*-* nvptx*-*-* } } } } */ -- cgit v1.1 From f6bbf1ca1d4f8f81b5fd439a36318079f7fa73a8 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 16 Jul 2019 11:29:17 +0200 Subject: alias-1_0.C: Use -O3. * g++.dg/lto/alias-1_0.C: Use -O3. * g++.dg/lto/alias-2_0.C: Use -O3. * g++.dg/lto/alias-3_0.C: Add loop to enable inlining with -fno-use-linker-plugin. * g++.dg/lto/alias-3_1.C: Remove dg-lto-do and dg-lto-options. From-SVN: r273520 --- gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/g++.dg/lto/alias-1_0.C | 2 +- gcc/testsuite/g++.dg/lto/alias-2_0.C | 2 +- gcc/testsuite/g++.dg/lto/alias-3_0.C | 4 +++- gcc/testsuite/g++.dg/lto/alias-3_1.c | 2 -- 5 files changed, 13 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e6ca043..633ded6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-07-16 Jan Hubicka + + * g++.dg/lto/alias-1_0.C: Use -O3. + * g++.dg/lto/alias-2_0.C: Use -O3. + * g++.dg/lto/alias-3_0.C: Add loop to enable inlining with + -fno-use-linker-plugin. + * g++.dg/lto/alias-3_1.C: Remove dg-lto-do and dg-lto-options. + 2019-07-16 Rainer Orth * gcc.dg/tree-ssa/pr84512.c: Don't xfail scan-tree-dump on diff --git a/gcc/testsuite/g++.dg/lto/alias-1_0.C b/gcc/testsuite/g++.dg/lto/alias-1_0.C index 333bcf0..9a79bda 100644 --- a/gcc/testsuite/g++.dg/lto/alias-1_0.C +++ b/gcc/testsuite/g++.dg/lto/alias-1_0.C @@ -1,5 +1,5 @@ /* { dg-lto-do run } */ -/* { dg-lto-options { { -O2 -flto } } } */ +/* { dg-lto-options { { -O3 -flto } } } */ /* With LTO we consider all pointers to incomplete types to be possibly aliasing. This makes *bptr to alias with aptr. diff --git a/gcc/testsuite/g++.dg/lto/alias-2_0.C b/gcc/testsuite/g++.dg/lto/alias-2_0.C index adad3ec..07b432c 100644 --- a/gcc/testsuite/g++.dg/lto/alias-2_0.C +++ b/gcc/testsuite/g++.dg/lto/alias-2_0.C @@ -1,5 +1,5 @@ /* { dg-lto-do run } */ -/* { dg-lto-options { { -O2 -flto } } } */ +/* { dg-lto-options { { -O3 -flto } } } */ /* With LTO we consider all pointers to incomplete types to be possibly aliasing. This makes *bptr to alias with aptr. diff --git a/gcc/testsuite/g++.dg/lto/alias-3_0.C b/gcc/testsuite/g++.dg/lto/alias-3_0.C index facba59..9ed95304 100644 --- a/gcc/testsuite/g++.dg/lto/alias-3_0.C +++ b/gcc/testsuite/g++.dg/lto/alias-3_0.C @@ -14,13 +14,15 @@ __attribute__ ((used)) struct b b, *bptr=&b, *bptr2=&b; __attribute__ ((used)) int i,j; extern "C" void inline_me_late (void); +int n=1; int main (void) { int jj=j; bptr2->a[jj].bar = 0; - inline_me_late (); + for (int i=0; ia[jj].bar == 0)) __builtin_abort (); return 0; diff --git a/gcc/testsuite/g++.dg/lto/alias-3_1.c b/gcc/testsuite/g++.dg/lto/alias-3_1.c index 11b0268..f633271 100644 --- a/gcc/testsuite/g++.dg/lto/alias-3_1.c +++ b/gcc/testsuite/g++.dg/lto/alias-3_1.c @@ -1,5 +1,3 @@ -/* { dg-lto-do run } */ -/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */ struct a { int foo,bar; -- cgit v1.1 From 7f5ddfcb3cb9e5d89d08e08d2a3aaed948aaf1af Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 16 Jul 2019 13:37:05 +0200 Subject: re PR rtl-optimization/91164 (ICE in verify_dominators, at dominance.c:1184 (error: dominator of 114 should be 112, not 16)) PR rtl-optimization/91164 * dse.c (rest_of_handle_dse): If dead edges have been purged, invalidate dominance info. * g++.dg/opt/pr91164.C: New test. From-SVN: r273522 --- gcc/ChangeLog | 6 +++ gcc/dse.c | 5 ++- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/opt/pr91164.C | 89 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr91164.C (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 30e6e7e..1eb2797 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-16 Jakub Jelinek + + PR rtl-optimization/91164 + * dse.c (rest_of_handle_dse): If dead edges have been purged, + invalidate dominance info. + 2019-07-16 Richard Sandiford * read-md.h (md_reader::record_potential_iterator_use): Add a diff --git a/gcc/dse.c b/gcc/dse.c index a1c7e3b..8d7358d 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -3621,7 +3621,10 @@ rest_of_handle_dse (void) if ((locally_deleted || globally_deleted) && cfun->can_throw_non_call_exceptions && purge_all_dead_edges ()) - cleanup_cfg (0); + { + free_dominance_info (CDI_DOMINATORS); + cleanup_cfg (0); + } return 0; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 633ded6..1f04ebb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-16 Jakub Jelinek + + PR rtl-optimization/91164 + * g++.dg/opt/pr91164.C: New test. + 2019-07-16 Jan Hubicka * g++.dg/lto/alias-1_0.C: Use -O3. diff --git a/gcc/testsuite/g++.dg/opt/pr91164.C b/gcc/testsuite/g++.dg/opt/pr91164.C new file mode 100644 index 0000000..8cf4fd0 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr91164.C @@ -0,0 +1,89 @@ +// PR rtl-optimization/91164 +// { dg-do compile { target c++11 } } +// { dg-options "-O2 -fdelete-dead-exceptions -fnon-call-exceptions -fno-rerun-cse-after-loop -fno-tree-forwprop" } + +template class b; +template struct d { static constexpr int e = v; }; +template using g = f; +struct h { template using j = i; }; +template using k = h::j; +void *operator new(__SIZE_TYPE__, void *); +struct l { l(); }; +struct m; +template n aa(m); +struct o { template using ab = l; }; +template struct b { + struct q : o::ab { q(int, l = l()) : p() {} int p; } ac; + void ad(); + b() : ac(0) {} + ~b() { bool r = ac.p == 0; if (r) ad(); } + const wchar_t *ae(); +}; +struct m {}; +struct t { virtual void f(); }; +struct u { l a; }; +struct af : t { + struct ag { ag(l); }; + af(l ah) : ai(ah) {} + ag ai; +}; +struct w { + template w(f, x y) { new (0) af(y.a); } +}; +struct z { + using aj = int; + template z(x ah) : ak(al, ah) {} + aj al; + w ak; +}; +struct am : z { template am(x ah) : z(ah) {} }; +template am an(x) { return u{}; } +template am ao() { return an(l()); } +struct ap { + k aq; + k ar; + k as; +}; +struct at { ap a; long au; ap av; ap aw; }; +struct ax { at c; ax() : c() {} }; +enum ay : int; +ay az, ba; +struct bb { bb(wchar_t *, wchar_t *, ay, m); }; +template struct bd { + typedef typename bc::be *bf; + bd(bf, bf, const typename bc::bg &, ay); + ay bh; + bb bi; + am bj; + typename bc::bk e; + ax bl; + int bm; +}; +template using bn = g::e, am>; +template +bd::bd(bf ah, bf y, const typename bc::bg &bu, ay) + : bi(ah, y, bh, bu), bj(ao()), bm(aa(bu)) {} +struct bt { typedef wchar_t be; typedef b bk; typedef m bg; }; +template bn bar(); +template bn bq(bo) { + typename bc::bg bp; + auto bs = nullptr; + using br = bd; + br(bs, bs, bp, ba); + return bar(); +} +struct bw { + bw(); + template void assign(b ah) { + const wchar_t by = *ah.ae(); + bw(&by, ah.ae(), bp, az); + } + template bw(bo, bo y, m, ay) : automaton(bq(y)) {} + m bp; + am automaton; +}; +void bx() { + b s; + bw ca; + ca.assign(s); +} -- cgit v1.1 From de2ad117f603491e404acb90510981aa27e087cc Mon Sep 17 00:00:00 2001 From: Wilco Dijkstra Date: Tue, 16 Jul 2019 12:06:55 +0000 Subject: Add missing testcase for PR89190 testsuite/ PR target/89190 * gcc.target/arm/pr89190.c: New test. From-SVN: r273524 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/arm/pr89190.c | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 gcc/testsuite/gcc.target/arm/pr89190.c (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1f04ebb..fc0b129 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-16 Wilco Dijkstra + + PR target/89190 + * gcc.target/arm/pr89190.c: New test. + 2019-07-16 Jakub Jelinek PR rtl-optimization/91164 diff --git a/gcc/testsuite/gcc.target/arm/pr89190.c b/gcc/testsuite/gcc.target/arm/pr89190.c new file mode 100644 index 0000000..e622d70 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr89190.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arch_v8m_base_ok } */ +/* { dg-options "-O2" } */ +/* { dg-add-options arm_arch_v8m_base } */ + +long long a; +int b, c; +int d(int e, int f) { return e << f; } +void g() { + long long h; + char i = d(b >= 7, 2); + c = i == 0 ?: 1 / i; + h = c && a ?: c + a; + b = h; +} -- cgit v1.1 From f0593c53f3684f82b29f96b43393f5f39e890fed Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 16 Jul 2019 08:44:44 -0600 Subject: re PR rtl-optimization/91173 (ICE: in int_mode_for_mode, at stor-layout.c:403) PR rtl-optimization/91173 * tree-ssa-address.c (addr_for_mem_ref): If the base is an SSA_NAME with a constant value, fold its value into the offset and clear the base before calling gen_addr_rtx. From-SVN: r273529 --- gcc/ChangeLog | 7 +++++++ gcc/tree-ssa-address.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1eb2797..2bce569 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-16 Jeff Law + + PR rtl-optimization/91173 + * tree-ssa-address.c (addr_for_mem_ref): If the base is an + SSA_NAME with a constant value, fold its value into the offset + and clear the base before calling gen_addr_rtx. + 2019-07-16 Jakub Jelinek PR rtl-optimization/91164 diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c index e83e1b9..8004951 100644 --- a/gcc/tree-ssa-address.c +++ b/gcc/tree-ssa-address.c @@ -259,6 +259,20 @@ addr_for_mem_ref (struct mem_address *addr, addr_space_t as, ? expand_expr (addr->index, NULL_RTX, pointer_mode, EXPAND_NORMAL) : NULL_RTX); + /* addr->base could be an SSA_NAME that was set to a constant value. The + call to expand_expr may expose that constant. If so, fold the value + into OFF and clear BSE. Otherwise we may later try to pull a mode from + BSE to generate a REG, which won't work with constants because they + are modeless. */ + if (bse && GET_CODE (bse) == CONST_INT) + { + if (off) + off = simplify_gen_binary (PLUS, pointer_mode, bse, off); + else + off = bse; + gcc_assert (GET_CODE (off) == CONST_INT); + bse = NULL_RTX; + } gen_addr_rtx (pointer_mode, sym, bse, idx, st, off, &address, NULL, NULL); if (pointer_mode != address_mode) address = convert_memory_address (address_mode, address); -- cgit v1.1 From f615b74e95263a697cfe4c8e5f6909db7243d589 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 16 Jul 2019 08:57:51 -0600 Subject: re PR rtl-optimization/91173 (ICE: in int_mode_for_mode, at stor-layout.c:403) PR rtl-optimization/91173 * g++.dg/pr91173.C: New test. From-SVN: r273531 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/pr91173.C | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 gcc/testsuite/g++.dg/pr91173.C (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fc0b129..23d8c77 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-16 Jeff Law + + PR rtl-optimization/91173 + * g++.dg/pr91173.C: New test. + 2019-07-16 Wilco Dijkstra PR target/89190 diff --git a/gcc/testsuite/g++.dg/pr91173.C b/gcc/testsuite/g++.dg/pr91173.C new file mode 100644 index 0000000..b8fb41b --- /dev/null +++ b/gcc/testsuite/g++.dg/pr91173.C @@ -0,0 +1,45 @@ +class a { + int b; + void *c; + +public: + bool aa(); + int &ab() { + if (aa()) { + void *d(c); + return static_cast(d)[b]; + } + return *(int *)0; + } +}; +typedef enum {E} e; +class f : public a { + int g; + +public: + int ac() { + if (g) + return 1; + return ac(); + } +}; +int *ad; +struct h { + static int ae(e, int *m) { + f ag; + int *ah; + while (!0) { + ad = &ag.ab(); + ah = ad + ag.ac(); + while (ad < ah) + *m = *ad++; + } + } +}; +template +void i(int *, int *, int, int *, e n, int *o) { + h::ae(n, o); +} +int aq, ar, as, at, au; +void aw() { i(&aq, &ar, as, &at, (e)0, &au); } + -- cgit v1.1 From 460bf043c8266dd080308f4783137aee0d0f862c Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Tue, 16 Jul 2019 19:18:32 +0200 Subject: i386.md (*testdi_1): Match CCZmode for constants that might have the SImode sign bit set. * config/i386/i386.md (*testdi_1): Match CCZmode for constants that might have the SImode sign bit set. (*testqi_1_maybe_si): Remove "!" constraint modifier. Use correct constraints for pentium pairing. (*test_1): Ditto. From-SVN: r273534 --- gcc/ChangeLog | 9 ++++++++- gcc/config/i386/i386.md | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2bce569..851f04a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-16 UroÅ¡ Bizjak + + * config/i386/i386.md (*testdi_1): Match CCZmode for + constants that might have the SImode sign bit set. + (*testqi_1_maybe_si): Remove "!" constraint modifier. + Use correct constraints for pentium pairing. + (*test_1): Ditto. + 2019-07-16 Jeff Law PR rtl-optimization/91173 @@ -6180,7 +6188,6 @@ (*call_indirect_pcrel): New insn. (*call_value_indirect_pcrel): Likewise. - 2019-05-29 UroÅ¡ Bizjak * config/i386/sse.md (*save_multiple): Rename from diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 410731f..eb32d7c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8134,18 +8134,31 @@ (define_expand "testqi_ccz_1" [(set (reg:CCZ FLAGS_REG) - (compare:CCZ (and:QI (match_operand:QI 0 "nonimmediate_operand") - (match_operand:QI 1 "nonmemory_operand")) - (const_int 0)))]) + (compare:CCZ + (and:QI + (match_operand:QI 0 "nonimmediate_operand") + (match_operand:QI 1 "nonmemory_operand")) + (const_int 0)))]) (define_insn "*testdi_1" [(set (reg FLAGS_REG) (compare - (and:DI - (match_operand:DI 0 "nonimmediate_operand" "%r,rm") - (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,re")) + (and:DI + (match_operand:DI 0 "nonimmediate_operand" "%r,rm") + (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,re")) (const_int 0)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" + "TARGET_64BIT + && ix86_match_ccmode + (insn, + /* If we are going to emit testl instead of testq, and the operands[1] + constant might have the SImode sign bit set, make sure the sign + flag isn't tested, because the instruction will set the sign flag + based on bit 31 rather than bit 63. If it isn't CONST_INT, + conservatively assume it might have bit 31 set. */ + (satisfies_constraint_Z (operands[1]) + && (!CONST_INT_P (operands[1]) + || val_signbit_known_set_p (SImode, INTVAL (operands[1])))) + ? CCZmode : CCNOmode)" "@ test{l}\t{%k1, %k0|%k0, %k1} test{q}\t{%1, %0|%0, %1}" @@ -8154,12 +8167,11 @@ (define_insn "*testqi_1_maybe_si" [(set (reg FLAGS_REG) - (compare + (compare (and:QI - (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r") - (match_operand:QI 1 "nonmemory_operand" "n,n,qn,n")) + (match_operand:QI 0 "nonimmediate_operand" "%qm,*a,qm,r") + (match_operand:QI 1 "nonmemory_operand" "q,n,n,n")) (const_int 0)))] - "ix86_match_ccmode (insn, CONST_INT_P (operands[1]) && INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)" @@ -8174,20 +8186,20 @@ } [(set_attr "type" "test") (set_attr "mode" "QI,QI,QI,SI") - (set_attr "pent_pair" "uv,np,uv,np")]) + (set_attr "pent_pair" "uv,uv,np,np")]) (define_insn "*test_1" [(set (reg FLAGS_REG) (compare - (and:SWI124 - (match_operand:SWI124 0 "nonimmediate_operand" "%!*a,,m") - (match_operand:SWI124 1 "" ",,")) + (and:SWI124 + (match_operand:SWI124 0 "nonimmediate_operand" "%m,*a,m") + (match_operand:SWI124 1 "" ",,")) (const_int 0)))] "ix86_match_ccmode (insn, CCNOmode)" "test{}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "mode" "") - (set_attr "pent_pair" "uv,np,uv")]) + (set_attr "pent_pair" "uv,uv,np")]) (define_expand "testqi_ext_1_ccno" [(set (reg:CCNO FLAGS_REG) -- cgit v1.1 From df1afcca584270fcb6b8902492758b5ec261a4d5 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Tue, 16 Jul 2019 19:58:15 +0000 Subject: re PR fortran/90903 (Implement runtime checks for bit manipulation intrinsics) 2019-07-16 Harald Anlauf PR fortran/90903 * libgfortran.h: Add mask for -fcheck=bits option. * options.c (gfc_handle_runtime_check_option): Add option "bits" to run-time checks selectable via -fcheck. * trans-intrinsic.c (gfc_conv_intrinsic_btest) (gfc_conv_intrinsic_singlebitop, gfc_conv_intrinsic_ibits) (gfc_conv_intrinsic_shift, gfc_conv_intrinsic_ishft) (gfc_conv_intrinsic_ishftc): Implement run-time checks for the POS, LEN, SHIFT, and SIZE arguments. * gfortran.texi: Document run-time checks for bit manipulation intrinsics. * invoke.texi: Document new -fcheck=bits option. PR fortran/90903 * gfortran.dg/check_bits_1.f90: New testcase. From-SVN: r273535 --- gcc/fortran/ChangeLog | 15 +++ gcc/fortran/gfortran.texi | 3 +- gcc/fortran/invoke.texi | 7 +- gcc/fortran/libgfortran.h | 4 +- gcc/fortran/options.c | 4 +- gcc/fortran/trans-intrinsic.c | 167 ++++++++++++++++++++++++++++- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gfortran.dg/check_bits_1.f90 | 49 +++++++++ 8 files changed, 247 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/check_bits_1.f90 (limited to 'gcc') diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index c92c85a..342aaa5 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,18 @@ +2019-07-16 Harald Anlauf + + PR fortran/90903 + * libgfortran.h: Add mask for -fcheck=bits option. + * options.c (gfc_handle_runtime_check_option): Add option "bits" + to run-time checks selectable via -fcheck. + * trans-intrinsic.c (gfc_conv_intrinsic_btest) + (gfc_conv_intrinsic_singlebitop, gfc_conv_intrinsic_ibits) + (gfc_conv_intrinsic_shift, gfc_conv_intrinsic_ishft) + (gfc_conv_intrinsic_ishftc): Implement run-time checks for the + POS, LEN, SHIFT, and SIZE arguments. + * gfortran.texi: Document run-time checks for bit manipulation + intrinsics. + * invoke.texi: Document new -fcheck=bits option. + 2019-07-14 Jerry DeLisle PR fortran/87233 diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index c887e7d..4f65450 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -3790,7 +3790,8 @@ initialization using @code{_gfortran_set_args}. Default: enabled. @item @var{option}[6] @tab Enables run-time checking. Possible values are (bitwise or-ed): GFC_RTCHECK_BOUNDS (1), GFC_RTCHECK_ARRAY_TEMPS (2), -GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32). +GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32), +GFC_RTCHECK_BITS (64). Default: disabled. @item @var{option}[7] @tab Unused. @item @var{option}[8] @tab Show a warning when invoking @code{STOP} and diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 2b08ac4..f8efcd8 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -183,7 +183,7 @@ and warnings}. @gccoptlist{-faggressive-function-elimination -fblas-matmul-limit=@var{n} @gol -fbounds-check -ftail-call-workaround -ftail-call-workaround=@var{n} @gol -fcheck-array-temporaries @gol --fcheck=@var{} @gol +-fcheck=@var{} @gol -fcoarray=@var{} -fexternal-blas -ff2c -ffrontend-loop-interchange @gol -ffrontend-optimize @gol @@ -1558,6 +1558,7 @@ library needs to be linked. @item -fcheck=@var{} @opindex @code{fcheck} @cindex array, bounds checking +@cindex bit intrinsics checking @cindex bounds checking @cindex pointer checking @cindex memory checking @@ -1582,6 +1583,10 @@ sometimes useful in optimization, in order to avoid such temporaries. Note: The warning is only printed once per location. +@item @samp{bits} +Enable generation of run-time checks for invalid arguments to the bit +manipulation intrinsics. + @item @samp{bounds} Enable generation of run-time checks for array subscripts and against the declared minimum and maximum values. It also diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h index 581b2f5..f82fc6a 100644 --- a/gcc/fortran/libgfortran.h +++ b/gcc/fortran/libgfortran.h @@ -73,9 +73,11 @@ along with GCC; see the file COPYING3. If not see #define GFC_RTCHECK_DO (1<<3) #define GFC_RTCHECK_POINTER (1<<4) #define GFC_RTCHECK_MEM (1<<5) +#define GFC_RTCHECK_BITS (1<<6) #define GFC_RTCHECK_ALL (GFC_RTCHECK_BOUNDS | GFC_RTCHECK_ARRAY_TEMPS \ | GFC_RTCHECK_RECURSION | GFC_RTCHECK_DO \ - | GFC_RTCHECK_POINTER | GFC_RTCHECK_MEM) + | GFC_RTCHECK_POINTER | GFC_RTCHECK_MEM \ + | GFC_RTCHECK_BITS) /* Special unit numbers used to convey certain conditions. Numbers -4 thru -9 available. NEWUNIT values start at -10. */ diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c index 3bc79ef..ef37ccc 100644 --- a/gcc/fortran/options.c +++ b/gcc/fortran/options.c @@ -580,12 +580,12 @@ gfc_handle_runtime_check_option (const char *arg) int result, pos = 0, n; static const char * const optname[] = { "all", "bounds", "array-temps", "recursion", "do", "pointer", - "mem", NULL }; + "mem", "bits", NULL }; static const int optmask[] = { GFC_RTCHECK_ALL, GFC_RTCHECK_BOUNDS, GFC_RTCHECK_ARRAY_TEMPS, GFC_RTCHECK_RECURSION, GFC_RTCHECK_DO, GFC_RTCHECK_POINTER, GFC_RTCHECK_MEM, - 0 }; + GFC_RTCHECK_BITS, 0 }; while (*arg) { diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index a7ebc41..a6e3383 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -6166,6 +6166,24 @@ gfc_conv_intrinsic_btest (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_function_args (se, expr, args, 2); type = TREE_TYPE (args[0]); + /* Optionally generate code for runtime argument check. */ + if (gfc_option.rtcheck & GFC_RTCHECK_BITS) + { + tree below = fold_build2_loc (input_location, LT_EXPR, + logical_type_node, args[1], + build_int_cst (TREE_TYPE (args[1]), 0)); + tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type)); + tree above = fold_build2_loc (input_location, GE_EXPR, + logical_type_node, args[1], nbits); + tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, + logical_type_node, below, above); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "POS argument (%ld) out of range 0:%ld " + "in intrinsic BTEST", + fold_convert (long_integer_type_node, args[1]), + fold_convert (long_integer_type_node, nbits)); + } + tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type, build_int_cst (type, 1), args[1]); tmp = fold_build2_loc (input_location, BIT_AND_EXPR, type, args[0], tmp); @@ -6236,6 +6254,32 @@ gfc_conv_intrinsic_singlebitop (gfc_se * se, gfc_expr * expr, int set) gfc_conv_intrinsic_function_args (se, expr, args, 2); type = TREE_TYPE (args[0]); + /* Optionally generate code for runtime argument check. */ + if (gfc_option.rtcheck & GFC_RTCHECK_BITS) + { + tree below = fold_build2_loc (input_location, LT_EXPR, + logical_type_node, args[1], + build_int_cst (TREE_TYPE (args[1]), 0)); + tree nbits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type)); + tree above = fold_build2_loc (input_location, GE_EXPR, + logical_type_node, args[1], nbits); + tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, + logical_type_node, below, above); + size_t len_name = strlen (expr->value.function.isym->name); + char *name = XALLOCAVEC (char, len_name + 1); + for (size_t i = 0; i < len_name; i++) + name[i] = TOUPPER (expr->value.function.isym->name[i]); + name[len_name] = '\0'; + tree iname = gfc_build_addr_expr (pchar_type_node, + gfc_build_cstring_const (name)); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "POS argument (%ld) out of range 0:%ld " + "in intrinsic %s", + fold_convert (long_integer_type_node, args[1]), + fold_convert (long_integer_type_node, nbits), + iname); + } + tmp = fold_build2_loc (input_location, LSHIFT_EXPR, type, build_int_cst (type, 1), args[1]); if (set) @@ -6261,6 +6305,42 @@ gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_function_args (se, expr, args, 3); type = TREE_TYPE (args[0]); + /* Optionally generate code for runtime argument check. */ + if (gfc_option.rtcheck & GFC_RTCHECK_BITS) + { + tree tmp1 = fold_convert (long_integer_type_node, args[1]); + tree tmp2 = fold_convert (long_integer_type_node, args[2]); + tree nbits = build_int_cst (long_integer_type_node, + TYPE_PRECISION (type)); + tree below = fold_build2_loc (input_location, LT_EXPR, + logical_type_node, args[1], + build_int_cst (TREE_TYPE (args[1]), 0)); + tree above = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, tmp1, nbits); + tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, + logical_type_node, below, above); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "POS argument (%ld) out of range 0:%ld " + "in intrinsic IBITS", tmp1, nbits); + below = fold_build2_loc (input_location, LT_EXPR, + logical_type_node, args[2], + build_int_cst (TREE_TYPE (args[2]), 0)); + above = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, tmp2, nbits); + scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, + logical_type_node, below, above); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "LEN argument (%ld) out of range 0:%ld " + "in intrinsic IBITS", tmp2, nbits); + above = fold_build2_loc (input_location, PLUS_EXPR, + long_integer_type_node, tmp1, tmp2); + scond = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, above, nbits); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "POS(%ld)+LEN(%ld)>BIT_SIZE(%ld) " + "in intrinsic IBITS", tmp1, tmp2, nbits); + } + mask = build_int_cst (type, -1); mask = fold_build2_loc (input_location, LSHIFT_EXPR, type, mask, args[2]); mask = fold_build1_loc (input_location, BIT_NOT_EXPR, type, mask); @@ -6382,6 +6462,32 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift, gcc requires a shift width < BIT_SIZE(I), so we have to catch this special case. */ num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type)); + + /* Optionally generate code for runtime argument check. */ + if (gfc_option.rtcheck & GFC_RTCHECK_BITS) + { + tree below = fold_build2_loc (input_location, LT_EXPR, + logical_type_node, args[1], + build_int_cst (TREE_TYPE (args[1]), 0)); + tree above = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, args[1], num_bits); + tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, + logical_type_node, below, above); + size_t len_name = strlen (expr->value.function.isym->name); + char *name = XALLOCAVEC (char, len_name + 1); + for (size_t i = 0; i < len_name; i++) + name[i] = TOUPPER (expr->value.function.isym->name[i]); + name[len_name] = '\0'; + tree iname = gfc_build_addr_expr (pchar_type_node, + gfc_build_cstring_const (name)); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "SHIFT argument (%ld) out of range 0:%ld " + "in intrinsic %s", + fold_convert (long_integer_type_node, args[1]), + fold_convert (long_integer_type_node, num_bits), + iname); + } + cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, args[1], num_bits); @@ -6436,6 +6542,20 @@ gfc_conv_intrinsic_ishft (gfc_se * se, gfc_expr * expr) gcc requires a shift width < BIT_SIZE(I), so we have to catch this special case. */ num_bits = build_int_cst (TREE_TYPE (args[1]), TYPE_PRECISION (type)); + + /* Optionally generate code for runtime argument check. */ + if (gfc_option.rtcheck & GFC_RTCHECK_BITS) + { + tree outside = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, width, num_bits); + gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where, + "SHIFT argument (%ld) out of range -%ld:%ld " + "in intrinsic ISHFT", + fold_convert (long_integer_type_node, args[1]), + fold_convert (long_integer_type_node, num_bits), + fold_convert (long_integer_type_node, num_bits)); + } + cond = fold_build2_loc (input_location, GE_EXPR, logical_type_node, width, num_bits); se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond, @@ -6454,6 +6574,7 @@ gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr) tree lrot; tree rrot; tree zero; + tree nbits; unsigned int num_args; num_args = gfc_intrinsic_argument_list_length (expr); @@ -6461,12 +6582,14 @@ gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_function_args (se, expr, args, num_args); + type = TREE_TYPE (args[0]); + nbits = build_int_cst (long_integer_type_node, TYPE_PRECISION (type)); + if (num_args == 3) { /* Use a library function for the 3 parameter version. */ tree int4type = gfc_get_int_type (4); - type = TREE_TYPE (args[0]); /* We convert the first argument to at least 4 bytes, and convert back afterwards. This removes the need for library functions for all argument sizes, and function will be @@ -6480,6 +6603,32 @@ gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr) args[1] = convert (int4type, args[1]); args[2] = convert (int4type, args[2]); + /* Optionally generate code for runtime argument check. */ + if (gfc_option.rtcheck & GFC_RTCHECK_BITS) + { + tree size = fold_convert (long_integer_type_node, args[2]); + tree below = fold_build2_loc (input_location, LE_EXPR, + logical_type_node, size, + build_int_cst (TREE_TYPE (args[1]), 0)); + tree above = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, size, nbits); + tree scond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, + logical_type_node, below, above); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "SIZE argument (%ld) out of range 1:%ld " + "in intrinsic ISHFTC", size, nbits); + tree width = fold_convert (long_integer_type_node, args[1]); + width = fold_build1_loc (input_location, ABS_EXPR, + long_integer_type_node, width); + scond = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, width, size); + gfc_trans_runtime_check (true, false, scond, &se->pre, &expr->where, + "SHIFT argument (%ld) out of range -%ld:%ld " + "in intrinsic ISHFTC", + fold_convert (long_integer_type_node, args[1]), + size, size); + } + switch (expr->ts.kind) { case 1: @@ -6505,12 +6654,26 @@ gfc_conv_intrinsic_ishftc (gfc_se * se, gfc_expr * expr) return; } - type = TREE_TYPE (args[0]); /* Evaluate arguments only once. */ args[0] = gfc_evaluate_now (args[0], &se->pre); args[1] = gfc_evaluate_now (args[1], &se->pre); + /* Optionally generate code for runtime argument check. */ + if (gfc_option.rtcheck & GFC_RTCHECK_BITS) + { + tree width = fold_convert (long_integer_type_node, args[1]); + width = fold_build1_loc (input_location, ABS_EXPR, + long_integer_type_node, width); + tree outside = fold_build2_loc (input_location, GT_EXPR, + logical_type_node, width, nbits); + gfc_trans_runtime_check (true, false, outside, &se->pre, &expr->where, + "SHIFT argument (%ld) out of range -%ld:%ld " + "in intrinsic ISHFTC", + fold_convert (long_integer_type_node, args[1]), + nbits, nbits); + } + /* Rotate left if positive. */ lrot = fold_build2_loc (input_location, LROTATE_EXPR, type, args[0], args[1]); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 23d8c77..689299b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-16 Harald Anlauf + + PR fortran/90903 + * gfortran.dg/check_bits_1.f90: New testcase. + 2019-07-16 Jeff Law PR rtl-optimization/91173 diff --git a/gcc/testsuite/gfortran.dg/check_bits_1.f90 b/gcc/testsuite/gfortran.dg/check_bits_1.f90 new file mode 100644 index 0000000..1ed3e81 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/check_bits_1.f90 @@ -0,0 +1,49 @@ +! { dg-do run } +! { dg-options "-fcheck=bits -fdump-tree-original" } +! { dg-shouldfail "Fortran runtime error: SIZE argument (0) out of range 1:32 in intrinsic ISHFTC" } +! { dg-output "At line 44 .*" } +! +! Verify that the runtime checks for the bit manipulation intrinsic functions +! do not generate false-positives +program check + implicit none + integer :: i, k, pos, len, shift, size, nb + nb = bit_size (i) + i = 0 + do pos = 0, nb-1 + k = ibset (i, pos) + i = ibclr (k, pos) + if (btest (i, pos)) stop 1 + end do + do pos = 0, nb + do len = 0, nb-pos + i = ibits (i, pos, len) + end do + end do + do shift = 0, nb + k = ishft (i, shift) + i = ishft (k, -shift) + end do + do shift = 0, nb + k = shiftl (i, shift) ! Fortran 2008 + i = shiftr (k, shift) + i = shifta (i, shift) + k = lshift (i, shift) ! GNU extensions + i = rshift (k, shift) + end do + do shift = 0, nb + k = ishftc (i, shift) + i = ishftc (k, -shift) + do size = max (1,shift), nb + k = ishftc (i, shift, size) + i = ishftc (k, -shift, size) + end do + end do + size = 0 + ! The following line should fail with a runtime error: + k = ishftc (i, 0, size) + ! Should never get here with -fcheck=bits + stop 2 +end program check + +! { dg-final { scan-tree-dump-times "_gfortran_runtime_error_at" 21 "original" } } -- cgit v1.1 From 361c0470f5d27a3b39d7d789ebca5550437359c8 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 17 Jul 2019 00:16:21 +0000 Subject: Daily bump. From-SVN: r273541 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 51bd565..72cde0b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190716 +20190717 -- cgit v1.1 From d6350f82315a6d811c6dd0910ea37f64524ef07b Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 17 Jul 2019 07:07:21 +0000 Subject: re PR tree-optimization/91181 (Failing as_as type conversion in vect_build_slp_tree_1) 2019-07-17 Richard Biener PR tree-optimization/91181 * tree-vect-slp.c (vect_build_slp_tree_1): Do not compare IFN_LOADs as calls. * gcc.dg/pr91181.c: New testcase. From-SVN: r273542 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/pr91181.c | 21 +++++++++++++++++++++ gcc/tree-vect-slp.c | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr91181.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 851f04a..36ebe6e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-17 Richard Biener + + PR tree-optimization/91181 + * tree-vect-slp.c (vect_build_slp_tree_1): Do not compare + IFN_LOADs as calls. + 2019-07-16 UroÅ¡ Bizjak * config/i386/i386.md (*testdi_1): Match CCZmode for diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 689299b..9cf270f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-17 Richard Biener + + PR tree-optimization/91181 + * gcc.dg/pr91181.c: New testcase. + 2019-07-16 Harald Anlauf PR fortran/90903 diff --git a/gcc/testsuite/gcc.dg/pr91181.c b/gcc/testsuite/gcc.dg/pr91181.c new file mode 100644 index 0000000..63e3362 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr91181.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast" } */ +/* { dg-additional-options "-mavx" { target x86_64-*-* i?86-*-* } } */ + +enum { a, b, c }; +float *d, *e; +int f, g, h, i; +int j() +{ + float a; + for (; h; h++) + { + i = h * 4; + a = d[i + b]; + if (a) { + e[i + b] = g < d[i + b] * f * a ? g : d[i + b] * f * a; + e[i + c] = g < d[i + c] * f * a ? g : d[i + c] * f * a; + } + e[i + b] = e[i + c]; + } +} diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 31f4519..0220b18 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -857,7 +857,7 @@ vect_build_slp_tree_1 (unsigned char *swap, continue; } - if (rhs_code == CALL_EXPR) + if (!load_p && rhs_code == CALL_EXPR) { if (!compatible_calls_p (as_a (stmts[0]->stmt), as_a (stmt))) -- cgit v1.1 From 7eb5baff994b249c0fb5d913e6f7afa7b9fbbc63 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 17 Jul 2019 09:13:17 +0200 Subject: re PR tree-optimization/91157 (ICE: verify_gimple failed (error: position plus size exceeds size of referenced object in 'bit_field_ref')) PR tree-optimization/91157 * tree-vect-generic.c (expand_vector_comparison): Handle lhs being a vector boolean with scalar mode. (expand_vector_condition): Handle first operand being a vector boolean with scalar mode. (expand_vector_operations_1): For comparisons, don't bail out early if the return type is vector boolean with scalar mode, but comparison operand type is not. * gcc.target/i386/avx512f-pr91157.c: New test. * gcc.target/i386/avx512bw-pr91157.c: New test. From-SVN: r273543 --- gcc/ChangeLog | 11 ++++ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.target/i386/avx512bw-pr91157.c | 6 ++ gcc/testsuite/gcc.target/i386/avx512f-pr91157.c | 29 ++++++++++ gcc/tree-vect-generic.c | 73 +++++++++++++++++++++++- 5 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/avx512bw-pr91157.c create mode 100644 gcc/testsuite/gcc.target/i386/avx512f-pr91157.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 36ebe6e..df99777 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2019-07-17 Jakub Jelinek + + PR tree-optimization/91157 + * tree-vect-generic.c (expand_vector_comparison): Handle lhs being + a vector boolean with scalar mode. + (expand_vector_condition): Handle first operand being a vector boolean + with scalar mode. + (expand_vector_operations_1): For comparisons, don't bail out early + if the return type is vector boolean with scalar mode, but comparison + operand type is not. + 2019-07-17 Richard Biener PR tree-optimization/91181 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9cf270f..5c156c7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-17 Jakub Jelinek + + PR tree-optimization/91157 + * gcc.target/i386/avx512f-pr91157.c: New test. + * gcc.target/i386/avx512bw-pr91157.c: New test. + 2019-07-17 Richard Biener PR tree-optimization/91181 diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr91157.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr91157.c new file mode 100644 index 0000000..602d922 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr91157.c @@ -0,0 +1,6 @@ +/* PR tree-optimization/91157 */ +/* { dg-do run { target { avx512bw && lp64 } } } */ +/* { dg-options "-O2 -mavx512bw -fexceptions -fnon-call-exceptions -fsignaling-nans" } */ + +#define AVX512BW +#include "avx512f-pr91157.c" diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr91157.c b/gcc/testsuite/gcc.target/i386/avx512f-pr91157.c new file mode 100644 index 0000000..c7d0d8b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-pr91157.c @@ -0,0 +1,29 @@ +/* PR tree-optimization/91157 */ +/* { dg-do run { target { avx512f && lp64 } } } */ +/* { dg-options "-O2 -mavx512f -fexceptions -fnon-call-exceptions -fsignaling-nans" } */ + +#include "avx512f-helper.h" + +typedef long double V __attribute__ ((vector_size (4 * sizeof (long double)))); +typedef __int128 W __attribute__ ((vector_size (4 * sizeof (__int128)))); + +__attribute__((noipa)) W +foo (V x) +{ + return x == 0; +} + +static void +test_512 (void) +{ + V a = { 5.0L, 0.0L, -0.0L, -17.0L }; + V b = { -0.0L, 16.0L, 0.0L, 18.0L }; + V c = { 6.0L, 7.0L, 8.0L, 0.0L }; + W ar = foo (a); + W br = foo (b); + W cr = foo (c); + if (ar[0] != 0 || ar[1] != -1 || ar[2] != -1 || ar[3] != 0 + || br[0] != -1 || br[1] != 0 || br[2] != -1 || br[3] != 0 + || cr[0] != 0 || cr[1] != 0 || cr[2] != 0 || cr[3] != -1) + __builtin_abort (); +} diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 8389f55..6fcd37c 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -382,8 +382,48 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0, tree t; if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code) && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code)) - t = expand_vector_piecewise (gsi, do_compare, type, - TREE_TYPE (TREE_TYPE (op0)), op0, op1, code); + { + if (VECTOR_BOOLEAN_TYPE_P (type) + && VECTOR_BOOLEAN_TYPE_P (type) + && SCALAR_INT_MODE_P (TYPE_MODE (type)) + && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)), + TYPE_VECTOR_SUBPARTS (type) + * GET_MODE_BITSIZE (SCALAR_TYPE_MODE + (TREE_TYPE (type))))) + { + tree inner_type = TREE_TYPE (TREE_TYPE (op0)); + tree part_width = TYPE_SIZE (inner_type); + tree index = bitsize_int (0); + int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0)); + int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type)); + tree ret_type = build_nonstandard_integer_type (prec, 1); + tree ret_inner_type = boolean_type_node; + int i; + location_t loc = gimple_location (gsi_stmt (*gsi)); + t = build_zero_cst (ret_type); + + if (TYPE_PRECISION (ret_inner_type) != 1) + ret_inner_type = build_nonstandard_integer_type (1, 1); + warning_at (loc, OPT_Wvector_operation_performance, + "vector operation will be expanded piecewise"); + for (i = 0; i < nunits; + i++, index = int_const_binop (PLUS_EXPR, index, part_width)) + { + tree a = tree_vec_extract (gsi, inner_type, op0, part_width, + index); + tree b = tree_vec_extract (gsi, inner_type, op1, part_width, + index); + tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b); + t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result, + bitsize_int (i)); + } + t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t); + } + else + t = expand_vector_piecewise (gsi, do_compare, type, + TREE_TYPE (TREE_TYPE (op0)), op0, op1, + code); + } else t = NULL_TREE; @@ -879,6 +919,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi) tree a1 = a; tree a2 = NULL_TREE; bool a_is_comparison = false; + bool a_is_scalar_bitmask = false; tree b = gimple_assign_rhs2 (stmt); tree c = gimple_assign_rhs3 (stmt); vec *v; @@ -942,6 +983,20 @@ expand_vector_condition (gimple_stmt_iterator *gsi) warning_at (loc, OPT_Wvector_operation_performance, "vector condition will be expanded piecewise"); + if (!a_is_comparison + && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)) + && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a))) + && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))), + TYPE_VECTOR_SUBPARTS (TREE_TYPE (a)) + * GET_MODE_BITSIZE (SCALAR_TYPE_MODE + (TREE_TYPE (TREE_TYPE (a)))))) + { + a_is_scalar_bitmask = true; + int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a))); + tree atype = build_nonstandard_integer_type (prec, 1); + a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a); + } + int nunits = nunits_for_known_piecewise_op (type); vec_alloc (v, nunits); for (i = 0; i < nunits; i++) @@ -957,6 +1012,14 @@ expand_vector_condition (gimple_stmt_iterator *gsi) comp_width, comp_index); aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2); } + else if (a_is_scalar_bitmask) + { + wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a))); + result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a), + a, wide_int_to_tree (TREE_TYPE (a), w)); + aa = fold_build2 (NE_EXPR, boolean_type_node, result, + build_zero_cst (TREE_TYPE (a))); + } else aa = tree_vec_extract (gsi, cond_type, a, width, index); result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc); @@ -1941,7 +2004,11 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) /* A scalar operation pretending to be a vector one. */ if (VECTOR_BOOLEAN_TYPE_P (type) && !VECTOR_MODE_P (TYPE_MODE (type)) - && TYPE_MODE (type) != BLKmode) + && TYPE_MODE (type) != BLKmode + && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison + || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)) + && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1))) + && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode))) return; /* If the vector operation is operating on all same vector elements -- cgit v1.1 From dfa6e5b43b9a801973f5c8be21e158586beb8056 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 17 Jul 2019 09:13:52 +0200 Subject: gimple.h (enum gf_mask): Remove GF_OMP_FOR_SIMD... * gimple.h (enum gf_mask): Remove GF_OMP_FOR_SIMD, change GF_OMP_FOR_KIND_SIMD to a value serially after other kinds, divide GF_OMP_FOR_KIND_MASK, GF_OMP_FOR_COMBINED, GF_OMP_FOR_COMBINED_INTO, GF_OMP_FOR_GRID_PHONY, GF_OMP_FOR_GRID_INTRA_GROUP and GF_OMP_FOR_GRID_GROUP_ITER by two. * omp-grid.c (grid_process_grid_body, grid_eliminate_combined_simd_part): Use GF_OMP_FOR_KIND_SIMD instead of GF_OMP_FOR_SIMD, don't test & GF_OMP_FOR_SIMD but == GF_OMP_FOR_KIND_SIMD. * omp-low.c (build_outer_var_ref, scan_sharing_clauses, check_omp_nesting_restrictions, scan_omp_1_stmt, lower_rec_input_clauses, lower_lastprivate_conditional_clauses, lower_lastprivate_clauses, lower_reduction_clauses, lower_omp_scan, omp_find_scan): Likewise. * omp-expand.c (expand_omp_for): Likewise. * omp-general.c (omp_extract_for_data): Likewise. From-SVN: r273544 --- gcc/ChangeLog | 17 +++++++++++++++++ gcc/gimple.h | 18 ++++++++---------- gcc/omp-expand.c | 2 +- gcc/omp-general.c | 2 +- gcc/omp-grid.c | 6 +++--- gcc/omp-low.c | 20 ++++++++++---------- 6 files changed, 40 insertions(+), 25 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index df99777..0c1c133 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2019-07-17 Jakub Jelinek + * gimple.h (enum gf_mask): Remove GF_OMP_FOR_SIMD, change + GF_OMP_FOR_KIND_SIMD to a value serially after other kinds, + divide GF_OMP_FOR_KIND_MASK, GF_OMP_FOR_COMBINED, + GF_OMP_FOR_COMBINED_INTO, GF_OMP_FOR_GRID_PHONY, + GF_OMP_FOR_GRID_INTRA_GROUP and GF_OMP_FOR_GRID_GROUP_ITER by two. + * omp-grid.c (grid_process_grid_body, + grid_eliminate_combined_simd_part): Use GF_OMP_FOR_KIND_SIMD instead + of GF_OMP_FOR_SIMD, don't test & GF_OMP_FOR_SIMD but + == GF_OMP_FOR_KIND_SIMD. + * omp-low.c (build_outer_var_ref, scan_sharing_clauses, + check_omp_nesting_restrictions, scan_omp_1_stmt, + lower_rec_input_clauses, lower_lastprivate_conditional_clauses, + lower_lastprivate_clauses, lower_reduction_clauses, lower_omp_scan, + omp_find_scan): Likewise. + * omp-expand.c (expand_omp_for): Likewise. + * omp-general.c (omp_extract_for_data): Likewise. + PR tree-optimization/91157 * tree-vect-generic.c (expand_vector_comparison): Handle lhs being a vector boolean with scalar mode. diff --git a/gcc/gimple.h b/gcc/gimple.h index 47070e7..442a121 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -153,24 +153,22 @@ enum gf_mask { GF_OMP_PARALLEL_GRID_PHONY = 1 << 1, GF_OMP_TASK_TASKLOOP = 1 << 0, GF_OMP_TASK_TASKWAIT = 1 << 1, - GF_OMP_FOR_KIND_MASK = (1 << 4) - 1, + GF_OMP_FOR_KIND_MASK = (1 << 3) - 1, GF_OMP_FOR_KIND_FOR = 0, GF_OMP_FOR_KIND_DISTRIBUTE = 1, GF_OMP_FOR_KIND_TASKLOOP = 2, GF_OMP_FOR_KIND_OACC_LOOP = 4, - GF_OMP_FOR_KIND_GRID_LOOP = 5, - /* Flag for SIMD variants of OMP_FOR kinds. */ - GF_OMP_FOR_SIMD = 1 << 3, - GF_OMP_FOR_KIND_SIMD = GF_OMP_FOR_SIMD | 0, - GF_OMP_FOR_COMBINED = 1 << 4, - GF_OMP_FOR_COMBINED_INTO = 1 << 5, + GF_OMP_FOR_KIND_GRID_LOOP = 5, + GF_OMP_FOR_KIND_SIMD = 6, + GF_OMP_FOR_COMBINED = 1 << 3, + GF_OMP_FOR_COMBINED_INTO = 1 << 4, /* The following flag must not be used on GF_OMP_FOR_KIND_GRID_LOOP loop statements. */ - GF_OMP_FOR_GRID_PHONY = 1 << 6, + GF_OMP_FOR_GRID_PHONY = 1 << 5, /* The following two flags should only be set on GF_OMP_FOR_KIND_GRID_LOOP loop statements. */ - GF_OMP_FOR_GRID_INTRA_GROUP = 1 << 6, - GF_OMP_FOR_GRID_GROUP_ITER = 1 << 7, + GF_OMP_FOR_GRID_INTRA_GROUP = 1 << 5, + GF_OMP_FOR_GRID_GROUP_ITER = 1 << 6, GF_OMP_TARGET_KIND_MASK = (1 << 4) - 1, GF_OMP_TARGET_KIND_REGION = 0, GF_OMP_TARGET_KIND_DATA = 1, diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c index c007ec1..94543de 100644 --- a/gcc/omp-expand.c +++ b/gcc/omp-expand.c @@ -6532,7 +6532,7 @@ expand_omp_for (struct omp_region *region, gimple *inner_stmt) original loops from being detected. Fix that up. */ loops_state_set (LOOPS_NEED_FIXUP); - if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD) + if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD) expand_omp_simd (region, &fd); else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP) { diff --git a/gcc/omp-general.c b/gcc/omp-general.c index 8086f9a..66be94f 100644 --- a/gcc/omp-general.c +++ b/gcc/omp-general.c @@ -156,7 +156,7 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd, int i; struct omp_for_data_loop dummy_loop; location_t loc = gimple_location (for_stmt); - bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD; + bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD; bool distribute = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE; bool taskloop = gimple_omp_for_kind (for_stmt) diff --git a/gcc/omp-grid.c b/gcc/omp-grid.c index 898d73f..e7e18aa 100644 --- a/gcc/omp-grid.c +++ b/gcc/omp-grid.c @@ -1002,7 +1002,7 @@ grid_process_grid_body (gimple_stmt_iterator *gsi, bool *handled_ops_p, *handled_ops_p = false; gimple *stmt = gsi_stmt (*gsi); if (gimple_code (stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)) + && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD) { gomp_for *loop = as_a (stmt); tree clauses = gimple_omp_for_clauses (loop); @@ -1030,14 +1030,14 @@ grid_eliminate_combined_simd_part (gomp_for *parloop) memset (&wi, 0, sizeof (wi)); wi.val_only = true; - enum gf_mask msk = GF_OMP_FOR_SIMD; + enum gf_mask msk = GF_OMP_FOR_KIND_SIMD; wi.info = (void *) &msk; walk_gimple_seq (gimple_omp_body (parloop), omp_find_combined_for, NULL, &wi); gimple *stmt = (gimple *) wi.info; /* We expect that the SIMD id the only statement in the parallel loop. */ gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (stmt) == GF_OMP_FOR_SIMD) + && (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD) && gimple_omp_for_combined_into_p (stmt) && !gimple_omp_for_combined_p (stmt)); gomp_for *simd = as_a (stmt); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 01cf728..a18f24c 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -580,7 +580,7 @@ build_outer_var_ref (tree var, omp_context *ctx, x = build_receiver_ref (var, by_ref, ctx); } else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) || (code == OMP_CLAUSE_PRIVATE && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS @@ -1441,7 +1441,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) install_var_local (decl, ctx); } else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD && !OMP_CLAUSE__CONDTEMP__ITER (c)) install_var_local (decl, ctx); break; @@ -2750,7 +2750,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) switch (gimple_code (stmt)) { case GIMPLE_OMP_FOR: - if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD) + if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD) return true; if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE) { @@ -3496,7 +3496,7 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, { if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_SIMD + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD && setjmp_or_longjmp_p (fndecl)) { remove = true; @@ -4118,7 +4118,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, bool reduction_omp_orig_ref = false; int pass; bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD); + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD); omplow_simd_context sctx = omplow_simd_context (); tree simt_lane = NULL_TREE, simtrec = NULL_TREE; tree ivar = NULL_TREE, lvar = NULL_TREE, uid = NULL_TREE; @@ -6093,7 +6093,7 @@ lower_lastprivate_conditional_clauses (tree *clauses, omp_context *ctx) tree cond_ptr = NULL_TREE; tree iter_var = NULL_TREE; bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD); + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD); tree next = *clauses; for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE @@ -6225,7 +6225,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p, bool maybe_simt = false; if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) { maybe_simt = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMT_); simduid = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMDUID_); @@ -6707,7 +6707,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, /* SIMD reductions are handled in lower_rec_input_clauses. */ if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) return; /* inscan reductions are handled elsewhere. */ @@ -8923,7 +8923,7 @@ lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx) bool input_phase = has_clauses ^ octx->scan_inclusive; bool is_simd = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (octx->stmt) & GF_OMP_FOR_SIMD)); + && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_SIMD); bool is_for = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_FOR && !gimple_omp_for_combined_p (octx->stmt)); @@ -9409,7 +9409,7 @@ omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, WALK_SUBSTMTS; case GIMPLE_OMP_FOR: - if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD) + if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD && gimple_omp_for_combined_into_p (stmt)) *handled_ops_p = false; break; -- cgit v1.1 From b9333ec437f272951ced9a390737116ef3f56909 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 17 Jul 2019 09:15:30 +0200 Subject: re PR tree-optimization/91157 (ICE: verify_gimple failed (error: position plus size exceeds size of referenced object in 'bit_field_ref')) PR tree-optimization/91157 * tree-vect-generic.c (expand_vector_comparison): Handle lhs being a vector boolean with scalar mode. (expand_vector_condition): Handle first operand being a vector boolean with scalar mode. (expand_vector_operations_1): For comparisons, don't bail out early if the return type is vector boolean with scalar mode, but comparison operand type is not. * gcc.target/i386/avx512f-pr91157.c: New test. * gcc.target/i386/avx512bw-pr91157.c: New test. From-SVN: r273545 --- gcc/tree-vect-generic.c | 1 - 1 file changed, 1 deletion(-) (limited to 'gcc') diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 6fcd37c..5855653 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -384,7 +384,6 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0, && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code)) { if (VECTOR_BOOLEAN_TYPE_P (type) - && VECTOR_BOOLEAN_TYPE_P (type) && SCALAR_INT_MODE_P (TYPE_MODE (type)) && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)), TYPE_VECTOR_SUBPARTS (type) -- cgit v1.1 From 9505acd8501e6c79bc4fa9ed9f1ee174462601d1 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 17 Jul 2019 09:35:04 +0000 Subject: re PR tree-optimization/91180 (wrong code at -O and above with __builtin_memset()) 2019-07-17 Richard Biener PR tree-optimization/91180 * tree-ssa-sccvn.c (vn_reference_lookup_3): Fix offset computation for memset partial defs. * gcc.dg/torture/pr91180.c: New testcase. From-SVN: r273548 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr91180.c | 13 +++++++++++++ gcc/tree-ssa-sccvn.c | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr91180.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0c1c133..877de19 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-17 Richard Biener + + PR tree-optimization/91180 + * tree-ssa-sccvn.c (vn_reference_lookup_3): Fix offset + computation for memset partial defs. + 2019-07-17 Jakub Jelinek * gimple.h (enum gf_mask): Remove GF_OMP_FOR_SIMD, change diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5c156c7..f9ee482 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-17 Richard Biener + + PR tree-optimization/91180 + * gcc.dg/torture/pr91180.c: New testcase. + 2019-07-17 Jakub Jelinek PR tree-optimization/91157 diff --git a/gcc/testsuite/gcc.dg/torture/pr91180.c b/gcc/testsuite/gcc.dg/torture/pr91180.c new file mode 100644 index 0000000..02b2425 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr91180.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ + +int +main () +{ +#if __SIZEOF_INT__ == 4 + unsigned x = 0xffffffff; + __builtin_memset (1 + (char *) &x, 0, 2); + if (x != 0xff0000ff) + __builtin_abort (); +#endif + return 0; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 73c77d1..830d37b 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2486,7 +2486,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, { pd_data pd; pd.rhs = build_constructor (NULL_TREE, NULL); - pd.offset = offset2i - offseti; + pd.offset = (offset2i - offseti) / BITS_PER_UNIT; pd.size = leni; return data->push_partial_def (pd, vuse, maxsizei); } -- cgit v1.1 From 7921a90e334117206c6bb78bad57e07fb242214c Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 17 Jul 2019 10:26:25 +0000 Subject: re PR tree-optimization/91178 (Infinite recursion in split_constant_offset in slp after r260289) 2019-07-17 Richard Biener PR tree-optimization/91178 * tree-vect-stmts.c (get_group_load_store_type): For SLP loads with a gap larger than the vector size always use VMAT_STRIDED_SLP. (vectorizable_load): For VMAT_STRIDED_SLP with a permutation avoid loading vectors that are only contained in the gap and thus are not needed. * gcc.dg/torture/pr91178.c: New testcase. From-SVN: r273549 --- gcc/ChangeLog | 10 ++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr91178.c | 11 +++++++++++ gcc/tree-vect-stmts.c | 22 ++++++++++++++++++++-- 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr91178.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 877de19..b15db2d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2019-07-17 Richard Biener + PR tree-optimization/91178 + * tree-vect-stmts.c (get_group_load_store_type): For SLP + loads with a gap larger than the vector size always use + VMAT_STRIDED_SLP. + (vectorizable_load): For VMAT_STRIDED_SLP with a permutation + avoid loading vectors that are only contained in the gap + and thus are not needed. + +2019-07-17 Richard Biener + PR tree-optimization/91180 * tree-ssa-sccvn.c (vn_reference_lookup_3): Fix offset computation for memset partial defs. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f9ee482..2d7a6bf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2019-07-17 Richard Biener + PR tree-optimization/91178 + * gcc.dg/torture/pr91178.c: New testcase. + +2019-07-17 Richard Biener + PR tree-optimization/91180 * gcc.dg/torture/pr91180.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/torture/pr91178.c b/gcc/testsuite/gcc.dg/torture/pr91178.c new file mode 100644 index 0000000..b7a2dbe --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr91178.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ + +int a; +extern int f[10][91125]; +int b[50]; +void c() +{ + for (int d = 6; d <= a; d++) + for (int e = 16; e <= 24; e++) + b[e] -= f[d][d]; +} diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 601a6f5..5d05e10 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -2267,6 +2267,14 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp, / vect_get_scalar_dr_size (first_dr_info))) overrun_p = false; + /* If the gap at the end of the group exceeds a whole vector + in size use the strided SLP code which can skip code-generation + for the gap. */ + if (vls_type == VLS_LOAD && known_gt (gap, nunits)) + *memory_access_type = VMAT_STRIDED_SLP; + else + *memory_access_type = VMAT_CONTIGUOUS; + /* If the gap splits the vector in half and the target can do half-vector operations avoid the epilogue peeling by simply loading half of the vector only. Usually @@ -2274,7 +2282,8 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp, dr_alignment_support alignment_support_scheme; scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vectype)); machine_mode vmode; - if (overrun_p + if (*memory_access_type == VMAT_CONTIGUOUS + && overrun_p && !masked_p && (((alignment_support_scheme = vect_supportable_dr_alignment (first_dr_info, false))) @@ -2297,7 +2306,6 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp, "Peeling for outer loop is not supported\n"); return false; } - *memory_access_type = VMAT_CONTIGUOUS; } } else @@ -8732,6 +8740,7 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, /* Checked by get_load_store_type. */ unsigned int const_nunits = nunits.to_constant (); unsigned HOST_WIDE_INT cst_offset = 0; + unsigned int group_gap = 0; gcc_assert (!LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)); gcc_assert (!nested_in_vect_loop); @@ -8749,6 +8758,7 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, if (slp && grouped_load) { group_size = DR_GROUP_SIZE (first_stmt_info); + group_gap = DR_GROUP_GAP (first_stmt_info); ref_type = get_group_alias_ptr_type (first_stmt_info); } else @@ -8892,6 +8902,14 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, if (nloads > 1) vec_alloc (v, nloads); stmt_vec_info new_stmt_info = NULL; + if (slp && slp_perm + && (group_el % group_size) > group_size - group_gap + && (group_el % group_size) + nloads * lnel < group_size) + { + dr_chain.quick_push (NULL_TREE); + group_el += nloads * lnel; + continue; + } for (i = 0; i < nloads; i++) { tree this_off = build_int_cst (TREE_TYPE (alias_off), -- cgit v1.1 From 4efd8968f8bf48265f18022b4eda5e7a99c24445 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 17 Jul 2019 11:21:49 +0000 Subject: re PR tree-optimization/91178 (Infinite recursion in split_constant_offset in slp after r260289) 2019-07-17 Richard Biener PR tree-optimization/91178 * tree-ssa.c (release_defs_bitset): Iterate from higher to lower SSA names to avoid quadratic behavior in the common case. * tree-data-ref.c (split_constant_offset): Add limit argument and pass it down. Initialize it from PARAM_SSA_NAME_DEF_CHAIN_LIMIT. (split_constant_offset_1): Add limit argument and use it to limit SSA def walking. Optimize the common plus/minus case. From-SVN: r273550 --- gcc/ChangeLog | 10 ++++++++++ gcc/tree-data-ref.c | 39 +++++++++++++++++++++++++++------------ gcc/tree-ssa.c | 36 +++++++++++++++++++++--------------- 3 files changed, 58 insertions(+), 27 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b15db2d..f13d8a6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,16 @@ 2019-07-17 Richard Biener PR tree-optimization/91178 + * tree-ssa.c (release_defs_bitset): Iterate from higher to + lower SSA names to avoid quadratic behavior in the common case. + * tree-data-ref.c (split_constant_offset): Add limit argument + and pass it down. Initialize it from PARAM_SSA_NAME_DEF_CHAIN_LIMIT. + (split_constant_offset_1): Add limit argument and use it to + limit SSA def walking. Optimize the common plus/minus case. + +2019-07-17 Richard Biener + + PR tree-optimization/91178 * tree-vect-stmts.c (get_group_load_store_type): For SLP loads with a gap larger than the vector size always use VMAT_STRIDED_SLP. diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index df1a7b8..7f75b7e 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -583,7 +583,8 @@ debug_ddrs (vec ddrs) static void split_constant_offset (tree exp, tree *var, tree *off, - hash_map > &cache); + hash_map > &cache, + unsigned *limit); /* Helper function for split_constant_offset. Expresses OP0 CODE OP1 (the type of the result is TYPE) as VAR + OFF, where OFF is a nonzero @@ -594,7 +595,8 @@ split_constant_offset (tree exp, tree *var, tree *off, static bool split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, tree *var, tree *off, - hash_map > &cache) + hash_map > &cache, + unsigned *limit) { tree var0, var1; tree off0, off1; @@ -615,8 +617,15 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, /* FALLTHROUGH */ case PLUS_EXPR: case MINUS_EXPR: - split_constant_offset (op0, &var0, &off0, cache); - split_constant_offset (op1, &var1, &off1, cache); + if (TREE_CODE (op1) == INTEGER_CST) + { + split_constant_offset (op0, &var0, &off0, cache, limit); + *var = var0; + *off = size_binop (ocode, off0, fold_convert (ssizetype, op1)); + return true; + } + split_constant_offset (op0, &var0, &off0, cache, limit); + split_constant_offset (op1, &var1, &off1, cache, limit); *var = fold_build2 (code, type, var0, var1); *off = size_binop (ocode, off0, off1); return true; @@ -625,7 +634,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, if (TREE_CODE (op1) != INTEGER_CST) return false; - split_constant_offset (op0, &var0, &off0, cache); + split_constant_offset (op0, &var0, &off0, cache, limit); *var = fold_build2 (MULT_EXPR, type, var0, op1); *off = size_binop (MULT_EXPR, off0, fold_convert (ssizetype, op1)); return true; @@ -649,7 +658,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, if (poffset) { - split_constant_offset (poffset, &poffset, &off1, cache); + split_constant_offset (poffset, &poffset, &off1, cache, limit); off0 = size_binop (PLUS_EXPR, off0, off1); if (POINTER_TYPE_P (TREE_TYPE (base))) base = fold_build_pointer_plus (base, poffset); @@ -719,11 +728,15 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, e = std::make_pair (op0, ssize_int (0)); } + if (*limit == 0) + return false; + --*limit; + var0 = gimple_assign_rhs1 (def_stmt); var1 = gimple_assign_rhs2 (def_stmt); bool res = split_constant_offset_1 (type, var0, subcode, var1, - var, off, cache); + var, off, cache, limit); if (res && use_cache) *cache.get (op0) = std::make_pair (*var, *off); return res; @@ -746,7 +759,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, /* Split the unconverted operand and try to prove that wrapping isn't a problem. */ tree tmp_var, tmp_off; - split_constant_offset (op0, &tmp_var, &tmp_off, cache); + split_constant_offset (op0, &tmp_var, &tmp_off, cache, limit); /* See whether we have an SSA_NAME whose range is known to be [A, B]. */ @@ -781,7 +794,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, *off = wide_int_to_tree (ssizetype, diff); } else - split_constant_offset (op0, &var0, off, cache); + split_constant_offset (op0, &var0, off, cache, limit); *var = fold_convert (type, var0); return true; } @@ -798,7 +811,8 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, static void split_constant_offset (tree exp, tree *var, tree *off, - hash_map > &cache) + hash_map > &cache, + unsigned *limit) { tree type = TREE_TYPE (exp), op0, op1, e, o; enum tree_code code; @@ -812,7 +826,7 @@ split_constant_offset (tree exp, tree *var, tree *off, code = TREE_CODE (exp); extract_ops_from_tree (exp, &code, &op0, &op1); - if (split_constant_offset_1 (type, op0, code, op1, &e, &o, cache)) + if (split_constant_offset_1 (type, op0, code, op1, &e, &o, cache, limit)) { *var = e; *off = o; @@ -822,10 +836,11 @@ split_constant_offset (tree exp, tree *var, tree *off, void split_constant_offset (tree exp, tree *var, tree *off) { + unsigned limit = PARAM_VALUE (PARAM_SSA_NAME_DEF_CHAIN_LIMIT); static hash_map > *cache; if (!cache) cache = new hash_map > (37); - split_constant_offset (exp, var, off, *cache); + split_constant_offset (exp, var, off, *cache, &limit); cache->empty (); } diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 16eaa8e..b4b5c90 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -559,20 +559,25 @@ release_defs_bitset (bitmap toremove) /* Performing a topological sort is probably overkill, this will most likely run in slightly superlinear time, rather than the - pathological quadratic worst case. */ + pathological quadratic worst case. + But iterate from max SSA name version to min one because + that mimics allocation order during code generation behavior best. + Use an array for this which we compact on-the-fly with a NULL + marker moving towards the end of the vector. */ + auto_vec names; + names.reserve (bitmap_count_bits (toremove) + 1); + names.quick_push (NULL_TREE); + EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi) + names.quick_push (ssa_name (j)); + + bitmap_tree_view (toremove); while (!bitmap_empty_p (toremove)) { - unsigned to_remove_bit = -1U; - EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi) + j = names.length () - 1; + for (unsigned i = names.length () - 1; names[i];) { - if (to_remove_bit != -1U) - { - bitmap_clear_bit (toremove, to_remove_bit); - to_remove_bit = -1U; - } - bool remove_now = true; - tree var = ssa_name (j); + tree var = names[i]; gimple *stmt; imm_use_iterator uit; @@ -617,14 +622,15 @@ release_defs_bitset (bitmap toremove) gsi_remove (&gsi, true); release_defs (def); } - - to_remove_bit = j; + bitmap_clear_bit (toremove, SSA_NAME_VERSION (var)); } + else + --i; + if (--j != i) + names[i] = names[j]; } - if (to_remove_bit != -1U) - bitmap_clear_bit (toremove, to_remove_bit); } - + bitmap_list_view (toremove); } /* Disable warnings about missing quoting in GCC diagnostics for -- cgit v1.1 From a7dbb77712c20e1e04186d68377875a428b635f5 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 17 Jul 2019 16:33:53 +0200 Subject: i386.md (*andqi_2_maybe_si): Handle potential partial reg stall on alternative 2. * config/i386/i386.md (*andqi_2_maybe_si): Handle potential partial reg stall on alternative 2. From-SVN: r273551 --- gcc/ChangeLog | 5 +++++ gcc/config/i386/i386.md | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f13d8a6..5c69a63 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-17 UroÅ¡ Bizjak + + * config/i386/i386.md (*andqi_2_maybe_si): Handle potential + partial reg stall on alternative 2. + 2019-07-17 Richard Biener PR tree-optimization/91178 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index eb32d7c..47e36d4 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8689,7 +8689,7 @@ (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") (match_operand:QI 2 "general_operand" "qmn,qn,n")) (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,*r") + (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,r") (and:QI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (AND, QImode, operands) && ix86_match_ccmode (insn, @@ -8705,7 +8705,12 @@ return "and{b}\t{%2, %0|%0, %2}"; } [(set_attr "type" "alu") - (set_attr "mode" "QI,QI,SI")]) + (set_attr "mode" "QI,QI,SI") + ;; Potential partial reg stall on alternative 2. + (set (attr "preferred_for_speed") + (cond [(eq_attr "alternative" "2") + (symbol_ref "!TARGET_PARTIAL_REG_STALL")] + (symbol_ref "true")))]) (define_insn "*and_2" [(set (reg FLAGS_REG) -- cgit v1.1 From 17b99c984b69b0b4927af6f81380c855c60475b7 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 17 Jul 2019 19:19:21 +0200 Subject: alias.c (record_component_aliases): Do not simplify pointed-to types of ODR types * alias.c (record_component_aliases): Do not simplify pointed-to types of ODR types * testsuite/g++.dg/lto/alias-4_0.C From-SVN: r273552 --- gcc/ChangeLog | 5 +++ gcc/alias.c | 87 +++++++++++++++++++----------------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/lto/alias-4_0.C | 31 +++++++++++++ 4 files changed, 86 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lto/alias-4_0.C (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5c69a63..26c647f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-17 Jan Hubicka + + * alias.c (record_component_aliases): Do not simplify pointed-to + types of ODR types + 2019-07-17 UroÅ¡ Bizjak * config/i386/i386.md (*andqi_2_maybe_si): Handle potential diff --git a/gcc/alias.c b/gcc/alias.c index eece84a..2755df7 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -1202,47 +1202,52 @@ record_component_aliases (tree type) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field)) - if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field)) - { - /* LTO type merging does not make any difference between - component pointer types. We may have - - struct foo {int *a;}; - - as TYPE_CANONICAL of - - struct bar {float *a;}; - - Because accesses to int * and float * do not alias, we would get - false negative when accessing the same memory location by - float ** and bar *. We thus record the canonical type as: - - struct {void *a;}; - - void * is special cased and works as a universal pointer type. - Accesses to it conflicts with accesses to any other pointer - type. */ - tree t = TREE_TYPE (field); - if (in_lto_p) - { - /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their - element type and that type has to be normalized to void *, - too, in the case it is a pointer. */ - while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t)) - { - gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t)); - t = TREE_TYPE (t); - } - if (POINTER_TYPE_P (t)) - t = ptr_type_node; - else if (flag_checking) - gcc_checking_assert (get_alias_set (t) - == get_alias_set (TREE_TYPE (field))); - } - - record_alias_subset (superset, get_alias_set (t)); - } + { + /* LTO non-ODR type merging does not make any difference between + component pointer types. We may have + + struct foo {int *a;}; + + as TYPE_CANONICAL of + + struct bar {float *a;}; + + Because accesses to int * and float * do not alias, we would get + false negative when accessing the same memory location by + float ** and bar *. We thus record the canonical type as: + + struct {void *a;}; + + void * is special cased and works as a universal pointer type. + Accesses to it conflicts with accesses to any other pointer + type. */ + bool void_pointers = in_lto_p + && (!odr_type_p (type) + || !odr_based_tbaa_p (type)); + for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field)) + { + tree t = TREE_TYPE (field); + if (void_pointers) + { + /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their + element type and that type has to be normalized to void *, + too, in the case it is a pointer. */ + while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t)) + { + gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t)); + t = TREE_TYPE (t); + } + if (POINTER_TYPE_P (t)) + t = ptr_type_node; + else if (flag_checking) + gcc_checking_assert (get_alias_set (t) + == get_alias_set (TREE_TYPE (field))); + } + + record_alias_subset (superset, get_alias_set (t)); + } + } break; case COMPLEX_TYPE: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2d7a6bf..d3d7107 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-17 Jan Hubicka + + * g++.dg/lto/alias-4_0.C + 2019-07-17 Richard Biener PR tree-optimization/91178 diff --git a/gcc/testsuite/g++.dg/lto/alias-4_0.C b/gcc/testsuite/g++.dg/lto/alias-4_0.C new file mode 100644 index 0000000..410c314 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/alias-4_0.C @@ -0,0 +1,31 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */ +__attribute__ ((used)) +short *ptr_init, **ptr=&ptr_init; + +__attribute__ ((used)) +struct a { + int *aptr; +} a, *aptr=&a; + +void +write_ptr () +{ + *aptr = a; +} + +__attribute__ ((used)) +void +test () +{ + *ptr = (short int *)0; + write_ptr (); + if (!__builtin_constant_p (*ptr == (void *)0)) + __builtin_abort (); +} +int +main() +{ + test (); + return 0; +} -- cgit v1.1 From d767a594c6818c1de586dba4f9c6b0a5cc6cae19 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 17 Jul 2019 18:10:14 +0000 Subject: re PR c++/90455 (braced-init and incomplete type instantiation) PR c++/90455 * g++.dg/cpp0x/nsdmi-list6.C: New test. From-SVN: r273553 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/cpp0x/nsdmi-list6.C | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-list6.C (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d3d7107..61baf9c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-17 Marek Polacek + + PR c++/90455 + * g++.dg/cpp0x/nsdmi-list6.C: New test. + 2019-07-17 Jan Hubicka * g++.dg/lto/alias-4_0.C diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list6.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list6.C new file mode 100644 index 0000000..83ab2e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list6.C @@ -0,0 +1,28 @@ +// PR c++/90455 +// { dg-do compile { target c++11 } } + +struct B; +template struct b { + void operator()(a *) { sizeof(a); } +}; +struct c { + struct D { + using d = B *; + }; + + using e = D::d; + e f(); +}; +template class g { + c h; + using i = b; +public: + ~g() { + auto j = h.f(); + k()(j); + } + i k(); +}; +struct l { + g m{}; +}; -- cgit v1.1 From 3697a5b8db822f91fad4516b3c625ff2f48993ce Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 17 Jul 2019 20:32:36 +0200 Subject: i386.md (*add3_doubleword): Remove redundant constraints. * config/i386/i386.md (*add3_doubleword): Remove redundant constraints. (*add_1): Ditto. (*addhi_1): Ditto. (*addqi_1): Ditto. (*addqi_1_slp): Ditto. (*add_2): Ditto. (*addv4): Ditto. (*sub3_doubleword): Ditto. (*sub_1): Ditto. (*subqi_1_slp): Ditto. (*sub_2): Ditto. (*subv4): Ditto. (*sub_3): Ditto. (@add3_carry): Ditto. (@sub3_carry): Ditto. (*add3_cc_overflow_1): Ditto. (*add3_zext_cc_overflow_2): Ditto. (*anddi_1): Ditto. (*and_1): Ditto. (*andqi_1): Ditto. (*andqi_1_slp): Ditto. (*anddi_2): Ditto. (*andqi_2_maybe_si): Ditto. (*and_2): Ditto. (*andqi_2_slp): Ditto. (*_1): Ditto. (*qi_1): Ditto. (*qi_1_slp): Ditto. (*_2): Ditto. (*qi_2_slp): Ditto. From-SVN: r273554 --- gcc/ChangeLog | 36 ++++++++++++++++- gcc/config/i386/i386.md | 105 +++++++++++++++++++++++------------------------- 2 files changed, 85 insertions(+), 56 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 26c647f..c43cf95 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,7 +1,41 @@ +2019-07-17 UroÅ¡ Bizjak + + * config/i386/i386.md (*add3_doubleword): + Remove redundant constraints. + (*add_1): Ditto. + (*addhi_1): Ditto. + (*addqi_1): Ditto. + (*addqi_1_slp): Ditto. + (*add_2): Ditto. + (*addv4): Ditto. + (*sub3_doubleword): Ditto. + (*sub_1): Ditto. + (*subqi_1_slp): Ditto. + (*sub_2): Ditto. + (*subv4): Ditto. + (*sub_3): Ditto. + (@add3_carry): Ditto. + (@sub3_carry): Ditto. + (*add3_cc_overflow_1): Ditto. + (*add3_zext_cc_overflow_2): Ditto. + (*anddi_1): Ditto. + (*and_1): Ditto. + (*andqi_1): Ditto. + (*andqi_1_slp): Ditto. + (*anddi_2): Ditto. + (*andqi_2_maybe_si): Ditto. + (*and_2): Ditto. + (*andqi_2_slp): Ditto. + (*_1): Ditto. + (*qi_1): Ditto. + (*qi_1_slp): Ditto. + (*_2): Ditto. + (*qi_2_slp): Ditto. + 2019-07-17 Jan Hubicka * alias.c (record_component_aliases): Do not simplify pointed-to - types of ODR types + types of ODR types. 2019-07-17 UroÅ¡ Bizjak diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 47e36d4..62485c3 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -5337,11 +5337,10 @@ "ix86_expand_binary_operator (PLUS, mode, operands); DONE;") (define_insn_and_split "*add3_doubleword" - [(set (match_operand: 0 "nonimmediate_operand" "=r,o") + [(set (match_operand: 0 "nonimmediate_operand" "=ro,r") (plus: (match_operand: 1 "nonimmediate_operand" "%0,0") - (match_operand: 2 "x86_64_hilo_general_operand" - "ro,r"))) + (match_operand: 2 "x86_64_hilo_general_operand" "r,o"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, mode, operands)" "#" @@ -5369,10 +5368,10 @@ }) (define_insn "*add_1" - [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r") + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r") (plus:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r") - (match_operand:SWI48 2 "x86_64_general_operand" "rme,re,0,le"))) + (match_operand:SWI48 2 "x86_64_general_operand" "re,m,0,le"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, mode, operands)" { @@ -5475,7 +5474,7 @@ (define_insn "*addhi_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r,Yp") (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r,Yp") - (match_operand:HI 2 "general_operand" "rn,rm,0,ln"))) + (match_operand:HI 2 "general_operand" "rn,m,0,ln"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, HImode, operands)" { @@ -5524,7 +5523,7 @@ (define_insn "*addqi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,q,r,r,Yp") (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,q,0,r,Yp") - (match_operand:QI 2 "general_operand" "qn,qm,0,rn,0,ln"))) + (match_operand:QI 2 "general_operand" "qn,m,0,rn,0,ln"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, QImode, operands)" { @@ -5587,7 +5586,7 @@ (define_insn "*addqi_1_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (plus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qm"))) + (match_operand:QI 1 "general_operand" "qn,m"))) (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" @@ -5680,9 +5679,9 @@ (compare (plus:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0,0,") - (match_operand:SWI 2 "" ",,0")) + (match_operand:SWI 2 "" ",m,0")) (const_int 0))) - (set (match_operand:SWI 0 "nonimmediate_operand" "=,m,") + (set (match_operand:SWI 0 "nonimmediate_operand" "=m,,") (plus:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) && ix86_binary_operator_ok (PLUS, mode, operands)" @@ -6073,11 +6072,10 @@ (sign_extend: (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) (sign_extend: - (match_operand:SWI 2 "" - "mWe,We"))) + (match_operand:SWI 2 "" "We,m"))) (sign_extend: (plus:SWI (match_dup 1) (match_dup 2))))) - (set (match_operand:SWI 0 "nonimmediate_operand" "=,m") + (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (plus:SWI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, mode, operands)" "add{}\t{%2, %0|%0, %2}" @@ -6091,9 +6089,9 @@ (match_operand:SWI 1 "nonimmediate_operand" "0")) (match_operand: 3 "const_int_operand" "i")) (sign_extend: - (plus:SWI (match_dup 1) - (match_operand:SWI 2 "x86_64_immediate_operand" - ""))))) + (plus:SWI + (match_dup 1) + (match_operand:SWI 2 "x86_64_immediate_operand" ""))))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m") (plus:SWI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (PLUS, mode, operands) @@ -6297,11 +6295,10 @@ "ix86_expand_binary_operator (MINUS, mode, operands); DONE;") (define_insn_and_split "*sub3_doubleword" - [(set (match_operand: 0 "nonimmediate_operand" "=r,o") + [(set (match_operand: 0 "nonimmediate_operand" "=ro,r") (minus: (match_operand: 1 "nonimmediate_operand" "0,0") - (match_operand: 2 "x86_64_hilo_general_operand" - "ro,r"))) + (match_operand: 2 "x86_64_hilo_general_operand" "r,o"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, mode, operands)" "#" @@ -6330,7 +6327,7 @@ [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (minus:SWI (match_operand:SWI 1 "nonimmediate_operand" "0,0") - (match_operand:SWI 2 "" ",m"))) + (match_operand:SWI 2 "" ",m"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, mode, operands)" "sub{}\t{%2, %0|%0, %2}" @@ -6351,7 +6348,7 @@ (define_insn "*subqi_1_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (minus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qm"))) + (match_operand:QI 1 "general_operand" "qn,m"))) (clobber (reg:CC FLAGS_REG))] "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" @@ -6364,7 +6361,7 @@ (compare (minus:SWI (match_operand:SWI 1 "nonimmediate_operand" "0,0") - (match_operand:SWI 2 "" ",m")) + (match_operand:SWI 2 "" ",m")) (const_int 0))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (minus:SWI (match_dup 1) (match_dup 2)))] @@ -6422,8 +6419,7 @@ (sign_extend: (match_operand:SWI 1 "nonimmediate_operand" "0,0")) (sign_extend: - (match_operand:SWI 2 "" - "We,m"))) + (match_operand:SWI 2 "" "We,m"))) (sign_extend: (minus:SWI (match_dup 1) (match_dup 2))))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") @@ -6440,9 +6436,9 @@ (match_operand:SWI 1 "nonimmediate_operand" "0")) (match_operand: 3 "const_int_operand" "i")) (sign_extend: - (minus:SWI (match_dup 1) - (match_operand:SWI 2 "x86_64_immediate_operand" - ""))))) + (minus:SWI + (match_dup 1) + (match_operand:SWI 2 "x86_64_immediate_operand" ""))))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m") (minus:SWI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (MINUS, mode, operands) @@ -6475,7 +6471,7 @@ (define_insn "*sub_3" [(set (reg FLAGS_REG) (compare (match_operand:SWI 1 "nonimmediate_operand" "0,0") - (match_operand:SWI 2 "" ",m"))) + (match_operand:SWI 2 "" ",m"))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (minus:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCmode) @@ -6518,7 +6514,7 @@ (match_operator:SWI 4 "ix86_carry_flag_operator" [(match_operand 3 "flags_reg_operand") (const_int 0)]) (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) - (match_operand:SWI 2 "" ",m"))) + (match_operand:SWI 2 "" ",m"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, mode, operands)" "adc{}\t{%2, %0|%0, %2}" @@ -6618,7 +6614,7 @@ (match_operand:SWI 1 "nonimmediate_operand" "0,0") (match_operator:SWI 4 "ix86_carry_flag_operator" [(match_operand 3 "flags_reg_operand") (const_int 0)])) - (match_operand:SWI 2 "" ",m"))) + (match_operand:SWI 2 "" ",m"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (MINUS, mode, operands)" "sbb{}\t{%2, %0|%0, %2}" @@ -6783,7 +6779,7 @@ (compare:CCC (plus:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0,0") - (match_operand:SWI 2 "" ",m")) + (match_operand:SWI 2 "" ",m")) (match_dup 1))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (plus:SWI (match_dup 1) (match_dup 2)))] @@ -6824,7 +6820,7 @@ (compare:CCC (plus:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0,0") - (match_operand:SWI 2 "" ",m")) + (match_operand:SWI 2 "" ",m")) (match_dup 2))) (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (plus:SWI (match_dup 1) (match_dup 2)))] @@ -8431,7 +8427,7 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r") (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm") - (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L"))) + (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,m,L"))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)" "@ @@ -8516,7 +8512,7 @@ (define_insn "*and_1" [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,Ya") (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,qm") - (match_operand:SWI24 2 "" "r,rm,L"))) + (match_operand:SWI24 2 "" "r,m,L"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, mode, operands)" "@ @@ -8537,7 +8533,7 @@ (define_insn "*andqi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qn,qmn,rn"))) + (match_operand:QI 2 "general_operand" "qn,m,rn"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (AND, QImode, operands)" "@ @@ -8555,7 +8551,7 @@ (define_insn "*andqi_1_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (and:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,qmn"))) + (match_operand:QI 1 "general_operand" "qn,m"))) (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" @@ -8644,9 +8640,9 @@ (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re")) + (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,m")) (const_int 0))) - (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm") + (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r") (and:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode @@ -8687,9 +8683,9 @@ [(set (reg FLAGS_REG) (compare (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qmn,qn,n")) + (match_operand:QI 2 "general_operand" "qn,m,n")) (const_int 0))) - (set (match_operand:QI 0 "nonimmediate_operand" "=q,qm,r") + (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") (and:QI (match_dup 1) (match_dup 2)))] "ix86_binary_operator_ok (AND, QImode, operands) && ix86_match_ccmode (insn, @@ -8716,9 +8712,9 @@ [(set (reg FLAGS_REG) (compare (and:SWI124 (match_operand:SWI124 1 "nonimmediate_operand" "%0,0") - (match_operand:SWI124 2 "" ",")) + (match_operand:SWI124 2 "" ",m")) (const_int 0))) - (set (match_operand:SWI124 0 "nonimmediate_operand" "=,m") + (set (match_operand:SWI124 0 "nonimmediate_operand" "=m,") (and:SWI124 (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCNOmode) && ix86_binary_operator_ok (AND, mode, operands)" @@ -8728,9 +8724,8 @@ (define_insn "*andqi_2_slp" [(set (reg FLAGS_REG) - (compare (and:QI - (match_operand:QI 0 "nonimmediate_operand" "+q,qm") - (match_operand:QI 1 "nonimmediate_operand" "qmn,qn")) + (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "+qm,q") + (match_operand:QI 1 "nonimmediate_operand" "qn,m")) (const_int 0))) (set (strict_low_part (match_dup 0)) (and:QI (match_dup 0) (match_dup 1)))] @@ -9006,10 +9001,10 @@ }) (define_insn "*_1" - [(set (match_operand:SWI248 0 "nonimmediate_operand" "=r,rm") + [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r") (any_or:SWI248 (match_operand:SWI248 1 "nonimmediate_operand" "%0,0") - (match_operand:SWI248 2 "" ",r"))) + (match_operand:SWI248 2 "" "r,m"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (, mode, operands)" "{}\t{%2, %0|%0, %2}" @@ -9086,9 +9081,9 @@ (set_attr "mode" "SI")]) (define_insn "*qi_1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m,r") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r") (any_or:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "qmn,qn,rn"))) + (match_operand:QI 2 "general_operand" "qn,m,rn"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (, QImode, operands)" "@ @@ -9104,9 +9099,9 @@ (symbol_ref "true")))]) (define_insn "*qi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m")) + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (any_or:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qmn,qn"))) + (match_operand:QI 1 "general_operand" "qn,m"))) (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" @@ -9118,9 +9113,9 @@ [(set (reg FLAGS_REG) (compare (any_or:SWI (match_operand:SWI 1 "nonimmediate_operand" "%0,0") - (match_operand:SWI 2 "" ",")) + (match_operand:SWI 2 "" ",m")) (const_int 0))) - (set (match_operand:SWI 0 "nonimmediate_operand" "=,m") + (set (match_operand:SWI 0 "nonimmediate_operand" "=m,") (any_or:SWI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCNOmode) && ix86_binary_operator_ok (, mode, operands)" @@ -9159,8 +9154,8 @@ (define_insn "*qi_2_slp" [(set (reg FLAGS_REG) - (compare (any_or:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm") - (match_operand:QI 1 "general_operand" "qmn,qn")) + (compare (any_or:QI (match_operand:QI 0 "nonimmediate_operand" "+qm,q") + (match_operand:QI 1 "general_operand" "qn,m")) (const_int 0))) (set (strict_low_part (match_dup 0)) (any_or:QI (match_dup 0) (match_dup 1)))] -- cgit v1.1 From caffb6e56c2914e64e65f3c336b770c178f265a3 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Wed, 17 Jul 2019 14:58:23 -0600 Subject: tree-ssa-dse.c (initialize_ao_ref_for_dse): Fix formatting. * tree-ssa-dse.c (initialize_ao_ref_for_dse): Fix formatting. (dse_walker::dse_optimize_stmt): Likewise. Add missing return to avoid unexpected switch statement fallthru. From-SVN: r273556 --- gcc/ChangeLog | 6 ++ gcc/tree-ssa-dse.c | 161 +++++++++++++++++++++++++++-------------------------- 2 files changed, 87 insertions(+), 80 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c43cf95..6d8b082 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-17 Jeff Law + + * tree-ssa-dse.c (initialize_ao_ref_for_dse): Fix formatting. + (dse_walker::dse_optimize_stmt): Likewise. Add missing return to + avoid unexpected switch statement fallthru. + 2019-07-17 UroÅ¡ Bizjak * config/i386/i386.md (*add3_doubleword): diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index df05a55..9bdcf9a 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -107,42 +107,42 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write) { switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))) { - case BUILT_IN_MEMCPY: - case BUILT_IN_MEMMOVE: - case BUILT_IN_MEMSET: - case BUILT_IN_MEMCPY_CHK: - case BUILT_IN_MEMMOVE_CHK: - case BUILT_IN_MEMSET_CHK: - { - tree size = NULL_TREE; - if (gimple_call_num_args (stmt) == 3) - size = gimple_call_arg (stmt, 2); - tree ptr = gimple_call_arg (stmt, 0); - ao_ref_init_from_ptr_and_size (write, ptr, size); - return true; - } + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMSET: + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_MEMSET_CHK: + { + tree size = NULL_TREE; + if (gimple_call_num_args (stmt) == 3) + size = gimple_call_arg (stmt, 2); + tree ptr = gimple_call_arg (stmt, 0); + ao_ref_init_from_ptr_and_size (write, ptr, size); + return true; + } - /* A calloc call can never be dead, but it can make - subsequent stores redundant if they store 0 into - the same memory locations. */ - case BUILT_IN_CALLOC: - { - tree nelem = gimple_call_arg (stmt, 0); - tree selem = gimple_call_arg (stmt, 1); - tree lhs; - if (TREE_CODE (nelem) == INTEGER_CST - && TREE_CODE (selem) == INTEGER_CST - && (lhs = gimple_call_lhs (stmt)) != NULL_TREE) - { - tree size = fold_build2 (MULT_EXPR, TREE_TYPE (nelem), - nelem, selem); - ao_ref_init_from_ptr_and_size (write, lhs, size); - return true; - } - } + /* A calloc call can never be dead, but it can make + subsequent stores redundant if they store 0 into + the same memory locations. */ + case BUILT_IN_CALLOC: + { + tree nelem = gimple_call_arg (stmt, 0); + tree selem = gimple_call_arg (stmt, 1); + tree lhs; + if (TREE_CODE (nelem) == INTEGER_CST + && TREE_CODE (selem) == INTEGER_CST + && (lhs = gimple_call_lhs (stmt)) != NULL_TREE) + { + tree size = fold_build2 (MULT_EXPR, TREE_TYPE (nelem), + nelem, selem); + ao_ref_init_from_ptr_and_size (write, lhs, size); + return true; + } + } - default: - break; + default: + break; } } else if (is_gimple_assign (stmt)) @@ -964,57 +964,58 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi) tree fndecl = gimple_call_fndecl (stmt); switch (DECL_FUNCTION_CODE (fndecl)) { - case BUILT_IN_MEMCPY: - case BUILT_IN_MEMMOVE: - case BUILT_IN_MEMSET: - case BUILT_IN_MEMCPY_CHK: - case BUILT_IN_MEMMOVE_CHK: - case BUILT_IN_MEMSET_CHK: - { - /* Occasionally calls with an explicit length of zero - show up in the IL. It's pointless to do analysis - on them, they're trivially dead. */ - tree size = gimple_call_arg (stmt, 2); - if (integer_zerop (size)) - { - delete_dead_or_redundant_call (gsi, "dead"); - return; - } - - /* If this is a memset call that initializes an object - to zero, it may be redundant with an earlier memset - or empty CONSTRUCTOR of a larger object. */ - if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET - || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHK) - && integer_zerop (gimple_call_arg (stmt, 1))) - dse_optimize_redundant_stores (stmt); - - enum dse_store_status store_status; - m_byte_tracking_enabled - = setup_live_bytes_from_ref (&ref, m_live_bytes); - store_status = dse_classify_store (&ref, stmt, - m_byte_tracking_enabled, - m_live_bytes); - if (store_status == DSE_STORE_LIVE) - return; - - if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD) - { - maybe_trim_memstar_call (&ref, m_live_bytes, stmt); - return; - } - - if (store_status == DSE_STORE_DEAD) + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMSET: + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_MEMSET_CHK: + { + /* Occasionally calls with an explicit length of zero + show up in the IL. It's pointless to do analysis + on them, they're trivially dead. */ + tree size = gimple_call_arg (stmt, 2); + if (integer_zerop (size)) + { delete_dead_or_redundant_call (gsi, "dead"); + return; + } + + /* If this is a memset call that initializes an object + to zero, it may be redundant with an earlier memset + or empty CONSTRUCTOR of a larger object. */ + if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET + || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHK) + && integer_zerop (gimple_call_arg (stmt, 1))) + dse_optimize_redundant_stores (stmt); + + enum dse_store_status store_status; + m_byte_tracking_enabled + = setup_live_bytes_from_ref (&ref, m_live_bytes); + store_status = dse_classify_store (&ref, stmt, + m_byte_tracking_enabled, + m_live_bytes); + if (store_status == DSE_STORE_LIVE) return; - } - case BUILT_IN_CALLOC: - /* We already know the arguments are integer constants. */ - dse_optimize_redundant_stores (stmt); + if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD) + { + maybe_trim_memstar_call (&ref, m_live_bytes, stmt); + return; + } - default: + if (store_status == DSE_STORE_DEAD) + delete_dead_or_redundant_call (gsi, "dead"); return; + } + + case BUILT_IN_CALLOC: + /* We already know the arguments are integer constants. */ + dse_optimize_redundant_stores (stmt); + return; + + default: + return; } } -- cgit v1.1 From 9cc7debee91270a91ce6e9ad65740b8e35743c61 Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Thu, 18 Jul 2019 00:06:41 +0000 Subject: pa.c (pa_som_asm_init_sections): Don't force all constant data into data section when generating PIC code. * config/pa/pa.c (pa_som_asm_init_sections): Don't force all constant data into data section when generating PIC code. (pa_select_section): Use pa_reloc_rw_mask() to qualify relocs. (pa_reloc_rw_mask): Return 3 when generating PIC code and when generating code for SOM targets earlier than HP-UX 11. Otherwise, return 2 for SOM and 0 for other targets. From-SVN: r273557 --- gcc/ChangeLog | 9 +++++++++ gcc/config/pa/pa.c | 35 +++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 16 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6d8b082..7f55623 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-17 John David Anglin + + * config/pa/pa.c (pa_som_asm_init_sections): Don't force all constant + data into data section when generating PIC code. + (pa_select_section): Use pa_reloc_rw_mask() to qualify relocs. + (pa_reloc_rw_mask): Return 3 when generating PIC code and when + generating code for SOM targets earlier than HP-UX 11. Otherwise, + return 2 for SOM and 0 for other targets. + 2019-07-17 Jeff Law * tree-ssa-dse.c (initialize_ao_ref_for_dse): Fix formatting. diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 0d00bf6..f54ca6e 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -9805,19 +9805,22 @@ pa_som_asm_init_sections (void) = get_unnamed_section (0, output_section_asm_op, "\t.SPACE $PRIVATE$\n\t.SUBSPA $TM_CLONE_TABLE$"); - /* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups - which reference data within the $TEXT$ space (for example constant + /* HPUX ld generates incorrect GOT entries for "T" fixups which + reference data within the $TEXT$ space (for example constant strings in the $LIT$ subspace). The assemblers (GAS and HP as) both have problems with handling - the difference of two symbols which is the other correct way to + the difference of two symbols. This is the other correct way to reference constant data during PIC code generation. - So, there's no way to reference constant data which is in the - $TEXT$ space during PIC generation. Instead place all constant - data into the $PRIVATE$ subspace (this reduces sharing, but it - works correctly). */ - readonly_data_section = flag_pic ? data_section : som_readonly_data_section; + Thus, we can't put constant data needing relocation in the $TEXT$ + space during PIC generation. + + Previously, we placed all constant data into the $DATA$ subspace + when generating PIC code. This reduces sharing, but it works + correctly. Now we rely on pa_reloc_rw_mask() for section selection. + This puts constant data not needing relocation into the $TEXT$ space. */ + readonly_data_section = som_readonly_data_section; /* We must not have a reference to an external symbol defined in a shared library in a readonly section, else the SOM linker will @@ -9850,7 +9853,7 @@ pa_select_section (tree exp, int reloc, && DECL_INITIAL (exp) && (DECL_INITIAL (exp) == error_mark_node || TREE_CONSTANT (DECL_INITIAL (exp))) - && !reloc) + && !(reloc & pa_reloc_rw_mask ())) { if (TARGET_SOM && DECL_ONE_ONLY (exp) @@ -9859,7 +9862,8 @@ pa_select_section (tree exp, int reloc, else return readonly_data_section; } - else if (CONSTANT_CLASS_P (exp) && !reloc) + else if (CONSTANT_CLASS_P (exp) + && !(reloc & pa_reloc_rw_mask ())) return readonly_data_section; else if (TARGET_SOM && TREE_CODE (exp) == VAR_DECL @@ -9875,12 +9879,11 @@ pa_select_section (tree exp, int reloc, static int pa_reloc_rw_mask (void) { - /* We force (const (plus (symbol) (const_int))) to memory when the - const_int doesn't fit in a 14-bit integer. The SOM linker can't - handle this construct in read-only memory and we want to avoid - this for ELF. So, we always force an RTX needing relocation to - the data section. */ - return 3; + if (flag_pic || (TARGET_SOM && !TARGET_HPUX_11)) + return 3; + + /* HP linker does not support global relocs in readonly memory. */ + return TARGET_SOM ? 2 : 0; } static void -- cgit v1.1 From 8ea3c020a234e25d4a976e69902208f744c0819c Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 18 Jul 2019 00:16:38 +0000 Subject: Daily bump. From-SVN: r273562 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 72cde0b..861a822 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190717 +20190718 -- cgit v1.1 From dea78431676f0104f5467788e8e78fc05c3ab981 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 18 Jul 2019 00:38:45 +0000 Subject: -Wmissing-attributes: check that we avoid duplicates and false positives The initial patch for PR 81824 fixed various possibilities of -Wmissing-attributes reporting duplicates and false positives. The test that avoided them was a little obscure, though, so this patch rewrites it into a more self-evident form. The patch also adds a testcase that already passed, but that explicitly covers some of the possibilities of reporting duplicates and false positives that preexisting tests did not cover. for gcc/ChangeLog PR middle-end/81824 * attribs.c (decls_mismatched_attributes): Simplify the logic that avoids duplicates and false positives. for gcc/testsuite/ChangeLog PR middle-end/81824 * g++.dg/Wmissing-attributes-1.C: New. Some of its fragments are from Martin Sebor. From-SVN: r273563 --- gcc/ChangeLog | 6 +++ gcc/attribs.c | 14 ++++-- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/Wmissing-attributes-1.C | 66 ++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/Wmissing-attributes-1.C (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f55623..e2da4ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-17 Alexandre Oliva + + PR middle-end/81824 + * attribs.c (decls_mismatched_attributes): Simplify the logic + that avoids duplicates and false positives. + 2019-07-17 John David Anglin * config/pa/pa.c (pa_som_asm_init_sections): Don't force all constant diff --git a/gcc/attribs.c b/gcc/attribs.c index 8e54016..f4777c6 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -1931,15 +1931,19 @@ decls_mismatched_attributes (tree tmpl, tree decl, tree attrlist, if (!has_attribute (tmpls[j], tmpl_attrs[j], blacklist[i])) continue; + bool found = false; unsigned kmax = 1 + !!decl_attrs[1]; for (unsigned k = 0; k != kmax; ++k) { if (has_attribute (decls[k], decl_attrs[k], blacklist[i])) - break; - - if (!k && kmax > 1) - continue; + { + found = true; + break; + } + } + if (!found) + { if (nattrs) pp_string (attrstr, ", "); pp_begin_quote (attrstr, pp_show_color (global_dc->printer)); @@ -1947,6 +1951,8 @@ decls_mismatched_attributes (tree tmpl, tree decl, tree attrlist, pp_end_quote (attrstr, pp_show_color (global_dc->printer)); ++nattrs; } + + break; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 61baf9c..69e82b5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-17 Alexandre Oliva + + PR middle-end/81824 + * g++.dg/Wmissing-attributes-1.C: New. Some of its fragments + are from Martin Sebor. + 2019-07-17 Marek Polacek PR c++/90455 diff --git a/gcc/testsuite/g++.dg/Wmissing-attributes-1.C b/gcc/testsuite/g++.dg/Wmissing-attributes-1.C new file mode 100644 index 0000000..972e683 --- /dev/null +++ b/gcc/testsuite/g++.dg/Wmissing-attributes-1.C @@ -0,0 +1,66 @@ +// { dg-do compile } +// { dg-options "-Wmissing-attributes" } + +#define ATTR(list) __attribute__ (list) + +/* Type attributes are normally absent in template functions, and the + mere presence of any such attribute used to cause the + -Wmissing-attributes checks, that checked for attributes typically + associated with functions rather than types, to report any missing + attributes twice: once for the specialization attribute list, once + for its type attribute list. + + This test uses both decl and type attributes to exercise the code + that avoids reporting duplicates, in ways that failed in the past + but that were not covered in other tests. */ +typedef void* ATTR ((alloc_size (1))) f_type (int); + +template +f_type +ATTR ((malloc)) +missing_malloc; // { dg-message "missing primary template attribute .malloc." } + +template <> +f_type +missing_malloc; // { dg-warning "explicit specialization .\[^\n\r\]+. may be missing attributes" } + + +/* Check that even an attribute that appears in both lists (decl and + type) in a template declaration is reported as missing only + once. */ + +template +f_type +ATTR ((alloc_size (1))) // In both attr lists, decl's and type's. +missing_alloc_size; // { dg-message "missing primary template attribute .alloc_size." } + +template <> +void * +missing_alloc_size(int); // { dg-warning "explicit specialization .\[^\n\r\]+. may be missing attributes" } + + +/* Check that even an attribute that appears in both lists (decl and + type) is not reported as missing if it's present only in the type + list. */ + +template +f_type +ATTR ((alloc_size (1))) // In both attr lists, decl's and type's. +missing_nothing; + +template <> +f_type +missing_nothing; + + +/* For completeness, check that a type attribute is matched by a decl + attribute in the specialization. */ + +template +f_type +missing_nothing2; + +template <> +void * +ATTR ((alloc_size (1))) +missing_nothing2(int); -- cgit v1.1 From b94b6cc0251d4775ac15f43885ed63279edb9581 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 18 Jul 2019 05:05:20 +0000 Subject: compiler: fix bug in handling of unordered set during exporting In CL 183850 a change was made to combine tracking/discovery of exported types and imported packages during export data generation. As a result of this refactoring a bug was introduced: the new code can potentially insert items into the exports set (an unordered_set) while iterating through the same set, which is illegal according to the spec for std::unordered_set. This patch fixes the problem by changing the type discovery phase to iterate through a separate list of sorted exports, as opposed to iterating through the main unordered set. Also included is a change to fix the code that looks for variables that are referenced from inlined routine bodies (this code wasn't scanning all of the function that it needed to scan). New test case for this problem in CL 186697. Updates golang/go#33020. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/185977 From-SVN: r273564 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/export.cc | 77 ++++++++++++++++++++++++--------------------- gcc/go/gofrontend/export.h | 3 +- gcc/go/gofrontend/gogo.cc | 24 ++++++++++---- 4 files changed, 63 insertions(+), 43 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 4e19c52..c5ace5a 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -0e51b7e9c03c6f6bc3d06343f2050f17349ccdc3 +19ed722fb3ae5e618c746da20efb79fc837337cd The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc index cb778a0..32ab498 100644 --- a/gcc/go/gofrontend/export.cc +++ b/gcc/go/gofrontend/export.cc @@ -111,7 +111,7 @@ class Collect_export_references : public Traverse : Traverse(traverse_expressions | traverse_types), exp_(exp), exports_(exports), imports_(imports), - inline_fcn_worklist_(NULL) + inline_fcn_worklist_(NULL), exports_finalized_(false) { } // Initial entry point; performs a walk to expand the exports set. @@ -121,7 +121,7 @@ class Collect_export_references : public Traverse // Second entry point (called after the method above), to find // all types referenced by exports. void - prepare_types(); + prepare_types(const std::vector& sorted_exports); protected: // Override of parent class method. @@ -141,6 +141,13 @@ class Collect_export_references : public Traverse traverse_named_type(Named_type*); private: + + // Add a named object to the exports set (during expand_exports()). + // Returns TRUE if a new object was added to the exports set, + // FALSE otherwise. + bool + add_to_exports(Named_object*); + // The exporter. Export* exp_; // The set of named objects to export. @@ -152,6 +159,8 @@ class Collect_export_references : public Traverse // Worklist of functions we are exporting with inline bodies that need // to be checked. std::vector* inline_fcn_worklist_; + // Set to true if expand_exports() has been called and is complete. + bool exports_finalized_; }; void @@ -172,6 +181,18 @@ Collect_export_references::expand_exports(std::vector* fcns) } } this->inline_fcn_worklist_ = NULL; + this->exports_finalized_ = true; +} + +bool +Collect_export_references::add_to_exports(Named_object* no) +{ + std::pair ins = + this->exports_->insert(no); + // If the export list has been finalized, then we should not be + // adding anything new to the exports set. + go_assert(!this->exports_finalized_ || !ins.second); + return ins.second; } int @@ -189,7 +210,7 @@ Collect_export_references::expression(Expression** pexpr) if (var_package != NULL) this->imports_->insert(var_package); - this->exports_->insert(no); + this->add_to_exports(no); no->var_value()->set_is_referenced_by_inline(); } return TRAVERSE_CONTINUE; @@ -210,17 +231,16 @@ Collect_export_references::expression(Expression** pexpr) if (this->inline_fcn_worklist_ != NULL) { - std::pair ins = - this->exports_->insert(no); + bool added = this->add_to_exports(no); if (no->is_function()) no->func_value()->set_is_referenced_by_inline(); - // If ins.second is false then this object was already in + // If 'added' is false then this object was already in // exports_, in which case it was already added to // check_inline_refs_ the first time we added it to exports_, so // we don't need to add it again. - if (ins.second + if (added && no->is_function() && no->func_value()->export_for_inlining()) this->inline_fcn_worklist_->push_back(no); @@ -238,11 +258,11 @@ Collect_export_references::expression(Expression** pexpr) // exported inline function from another package). void -Collect_export_references::prepare_types() +Collect_export_references::prepare_types(const std::vector& sorted_exports) { // Iterate through the exported objects and traverse any types encountered. - for (Unordered_set(Named_object*)::iterator p = this->exports_->begin(); - p != this->exports_->end(); + for (std::vector::const_iterator p = sorted_exports.begin(); + p != sorted_exports.end(); ++p) { Named_object* no = *p; @@ -506,7 +526,8 @@ Export::export_globals(const std::string& package_name, const std::map& imports, const std::string& import_init_fn, const Import_init_set& imported_init_fns, - const Bindings* bindings) + const Bindings* bindings, + Unordered_set(Named_object*)* functions_marked_inline) { // If there have been any errors so far, don't try to export // anything. That way the export code doesn't have to worry about @@ -520,35 +541,21 @@ Export::export_globals(const std::string& package_name, // CHECK_INLINE_REFS is also on EXPORTS. Unordered_set(Named_object*) exports; std::vector check_inline_refs; + check_inline_refs.reserve(functions_marked_inline->size()); + + // Add all functions/methods from the "marked inlined" set to the + // CHECK_INLINE_REFS worklist. + for (Unordered_set(Named_object*)::const_iterator p = functions_marked_inline->begin(); + p != functions_marked_inline->end(); + ++p) + check_inline_refs.push_back(*p); for (Bindings::const_definitions_iterator p = bindings->begin_definitions(); p != bindings->end_definitions(); ++p) { if (should_export(*p)) - { - exports.insert(*p); - - if ((*p)->is_function() - && (*p)->func_value()->export_for_inlining()) - check_inline_refs.push_back(*p); - else if ((*p)->is_type()) - { - const Bindings* methods = (*p)->type_value()->local_methods(); - if (methods != NULL) - { - for (Bindings::const_definitions_iterator pm = - methods->begin_definitions(); - pm != methods->end_definitions(); - ++pm) - { - Function* fn = (*pm)->func_value(); - if (fn->export_for_inlining()) - check_inline_refs.push_back(*pm); - } - } - } - } + exports.insert(*p); } for (Bindings::const_declarations_iterator p = @@ -593,7 +600,7 @@ Export::export_globals(const std::string& package_name, // Collect up the set of types mentioned in things we're exporting, // and any packages that may be referred to indirectly. - collect.prepare_types(); + collect.prepare_types(sorted_exports); // Assign indexes to all exported types and types referenced by // things we're exporting. Return value is index of first non-exported diff --git a/gcc/go/gofrontend/export.h b/gcc/go/gofrontend/export.h index 1af386c1..c93bced 100644 --- a/gcc/go/gofrontend/export.h +++ b/gcc/go/gofrontend/export.h @@ -158,7 +158,8 @@ class Export : public String_dump const std::map& imports, const std::string& import_init_fn, const Import_init_set& imported_init_fns, - const Bindings* bindings); + const Bindings* bindings, + Unordered_set(Named_object*)* marked_inline_functions); // Record a type that is mentioned in export data. Return value is // TRUE for newly visited types, FALSE for types that have been seen diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index f9a18bc..abd8686 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -5078,9 +5078,10 @@ Inline_within_budget::expression(Expression** pexpr) class Mark_inline_candidates : public Traverse { public: - Mark_inline_candidates() + Mark_inline_candidates(Unordered_set(Named_object*)* marked) : Traverse(traverse_functions - | traverse_types) + | traverse_types), + marked_functions_(marked) { } int @@ -5097,6 +5098,9 @@ class Mark_inline_candidates : public Traverse // budget is a heuristic. In the usual GCC spirit, we could // consider setting this via a command line option. const int budget_heuristic = 80; + + // Set of named objects that are marked as inline candidates. + Unordered_set(Named_object*)* marked_functions_; }; // Mark a function if it is an inline candidate. @@ -5109,7 +5113,10 @@ Mark_inline_candidates::function(Named_object* no) Inline_within_budget iwb(&budget); func->block()->traverse(&iwb); if (budget >= 0) - func->set_export_for_inlining(); + { + func->set_export_for_inlining(); + this->marked_functions_->insert(no); + } return TRAVERSE_CONTINUE; } @@ -5135,7 +5142,10 @@ Mark_inline_candidates::type(Type* t) Inline_within_budget iwb(&budget); func->block()->traverse(&iwb); if (budget >= 0) - func->set_export_for_inlining(); + { + func->set_export_for_inlining(); + this->marked_functions_->insert(no); + } } return TRAVERSE_CONTINUE; } @@ -5150,7 +5160,8 @@ Gogo::do_exports() // Mark any functions whose body should be exported for inlining by // other packages. - Mark_inline_candidates mic; + Unordered_set(Named_object*) marked_functions; + Mark_inline_candidates mic(&marked_functions); this->traverse(&mic); // For now we always stream to a section. Later we may want to @@ -5187,7 +5198,8 @@ Gogo::do_exports() this->imports_, init_fn_name, this->imported_init_fns_, - this->package_->bindings()); + this->package_->bindings(), + &marked_functions); if (!this->c_header_.empty() && !saw_errors()) this->write_c_header(); -- cgit v1.1 From d1f2e4c1027b826cf3ba353e86c37589f63f8efe Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 18 Jul 2019 08:09:16 +0000 Subject: tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Refactor branches to make code less indented. 2019-07-18 Richard Biener * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Refactor branches to make code less indented. From-SVN: r273567 --- gcc/ChangeLog | 5 + gcc/tree-ssa-sccvn.c | 262 +++++++++++++++++++++++---------------------------- 2 files changed, 124 insertions(+), 143 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e2da4ba..76baf87 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-18 Richard Biener + + * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Refactor + branches to make code less indented. + 2019-07-17 Alexandre Oliva PR middle-end/81824 diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 830d37b..f12c9dd 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1746,160 +1746,136 @@ vn_walk_cb_data::push_partial_def (const pd_data &pd, tree vuse, first_range.size = pd.size; first_vuse = vuse; last_vuse_ptr = NULL; + /* Continue looking for partial defs. */ + return NULL; + } + + if (!known_ranges) + { + /* ??? Optimize the case where the 2nd partial def completes things. */ + gcc_obstack_init (&ranges_obstack); + known_ranges = splay_tree_new_with_allocator (pd_range_compare, 0, 0, + pd_tree_alloc, + pd_tree_dealloc, this); + splay_tree_insert (known_ranges, + (splay_tree_key)&first_range.offset, + (splay_tree_value)&first_range); + } + + pd_range newr = { pd.offset, pd.size }; + splay_tree_node n; + pd_range *r; + /* Lookup the predecessor of offset + 1 and see if we need to merge. */ + HOST_WIDE_INT loffset = newr.offset + 1; + if ((n = splay_tree_predecessor (known_ranges, (splay_tree_key)&loffset)) + && ((r = (pd_range *)n->value), true) + && ranges_known_overlap_p (r->offset, r->size + 1, + newr.offset, newr.size)) + { + /* Ignore partial defs already covered. */ + if (known_subrange_p (newr.offset, newr.size, r->offset, r->size)) + return NULL; + r->size = MAX (r->offset + r->size, newr.offset + newr.size) - r->offset; } else { - if (!known_ranges) - { - /* ??? Optimize the case where the second partial def - completes things. */ - gcc_obstack_init (&ranges_obstack); - known_ranges - = splay_tree_new_with_allocator (pd_range_compare, 0, 0, - pd_tree_alloc, - pd_tree_dealloc, this); - splay_tree_insert (known_ranges, - (splay_tree_key)&first_range.offset, - (splay_tree_value)&first_range); - } - if (known_ranges) + /* newr.offset wasn't covered yet, insert the range. */ + r = XOBNEW (&ranges_obstack, pd_range); + *r = newr; + splay_tree_insert (known_ranges, (splay_tree_key)&r->offset, + (splay_tree_value)r); + } + /* Merge r which now contains newr and is a member of the splay tree with + adjacent overlapping ranges. */ + pd_range *rafter; + while ((n = splay_tree_successor (known_ranges, (splay_tree_key)&r->offset)) + && ((rafter = (pd_range *)n->value), true) + && ranges_known_overlap_p (r->offset, r->size + 1, + rafter->offset, rafter->size)) + { + r->size = MAX (r->offset + r->size, + rafter->offset + rafter->size) - r->offset; + splay_tree_remove (known_ranges, (splay_tree_key)&rafter->offset); + } + partial_defs.safe_push (pd); + + /* Now we have merged newr into the range tree. When we have covered + [offseti, sizei] then the tree will contain exactly one node which has + the desired properties and it will be 'r'. */ + if (!known_subrange_p (0, maxsizei / BITS_PER_UNIT, r->offset, r->size)) + /* Continue looking for partial defs. */ + return NULL; + + /* Now simply native encode all partial defs in reverse order. */ + unsigned ndefs = partial_defs.length (); + /* We support up to 512-bit values (for V8DFmode). */ + unsigned char buffer[64]; + int len; + + while (!partial_defs.is_empty ()) + { + pd_data pd = partial_defs.pop (); + if (TREE_CODE (pd.rhs) == CONSTRUCTOR) + /* Empty CONSTRUCTOR. */ + memset (buffer + MAX (0, pd.offset), + 0, MIN ((HOST_WIDE_INT)sizeof (buffer), pd.size)); + else { - pd_range newr = { pd.offset, pd.size }; - splay_tree_node n; - pd_range *r; - /* Lookup the predecessor of offset + 1 and see if - we need to merge with it. */ - HOST_WIDE_INT loffset = newr.offset + 1; - if ((n = splay_tree_predecessor (known_ranges, - (splay_tree_key)&loffset)) - && ((r = (pd_range *)n->value), true) - && ranges_known_overlap_p (r->offset, r->size + 1, - newr.offset, newr.size)) + unsigned pad = 0; + if (BYTES_BIG_ENDIAN + && is_a (TYPE_MODE (TREE_TYPE (pd.rhs)))) { - /* Ignore partial defs already covered. */ - if (known_subrange_p (newr.offset, newr.size, - r->offset, r->size)) - return NULL; - r->size = MAX (r->offset + r->size, - newr.offset + newr.size) - r->offset; + /* On big-endian the padding is at the 'front' so just skip + the initial bytes. */ + fixed_size_mode mode + = as_a (TYPE_MODE (TREE_TYPE (pd.rhs))); + pad = GET_MODE_SIZE (mode) - pd.size; } - else - { - /* newr.offset wasn't covered yet, insert the - range. */ - r = XOBNEW (&ranges_obstack, pd_range); - *r = newr; - splay_tree_insert (known_ranges, - (splay_tree_key)&r->offset, - (splay_tree_value)r); - } - /* Merge r which now contains newr and is a member - of the splay tree with adjacent overlapping ranges. */ - pd_range *rafter; - while ((n = splay_tree_successor (known_ranges, - (splay_tree_key)&r->offset)) - && ((rafter = (pd_range *)n->value), true) - && ranges_known_overlap_p (r->offset, r->size + 1, - rafter->offset, rafter->size)) + len = native_encode_expr (pd.rhs, buffer + MAX (0, pd.offset), + sizeof (buffer - MAX (0, pd.offset)), + MAX (0, -pd.offset) + pad); + if (len <= 0 || len < (pd.size - MAX (0, -pd.offset))) { - r->size = MAX (r->offset + r->size, - rafter->offset + rafter->size) - r->offset; - splay_tree_remove (known_ranges, - (splay_tree_key)&rafter->offset); + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Failed to encode %u " + "partial definitions\n", ndefs); + return (void *)-1; } - partial_defs.safe_push (pd); - - /* Now we have merged newr into the range tree. - When we have covered [offseti, sizei] then the - tree will contain exactly one node which has - the desired properties and it will be 'r'. */ - if (known_subrange_p (0, maxsizei / BITS_PER_UNIT, - r->offset, r->size)) - { - /* Now simply native encode all partial defs - in reverse order. */ - unsigned ndefs = partial_defs.length (); - /* We support up to 512-bit values (for V8DFmode). */ - unsigned char buffer[64]; - int len; - - while (!partial_defs.is_empty ()) - { - pd_data pd = partial_defs.pop (); - if (TREE_CODE (pd.rhs) == CONSTRUCTOR) - /* Empty CONSTRUCTOR. */ - memset (buffer + MAX (0, pd.offset), - 0, MIN ((HOST_WIDE_INT)sizeof (buffer), pd.size)); - else - { - unsigned pad = 0; - if (BYTES_BIG_ENDIAN - && is_a (TYPE_MODE (TREE_TYPE (pd.rhs)))) - { - /* On big-endian the padding is at the 'front' so - just skip the initial bytes. */ - fixed_size_mode mode = as_a - (TYPE_MODE (TREE_TYPE (pd.rhs))); - pad = GET_MODE_SIZE (mode) - pd.size; - } - len = native_encode_expr (pd.rhs, - buffer + MAX (0, pd.offset), - sizeof (buffer - MAX (0, pd.offset)), - MAX (0, -pd.offset) + pad); - if (len <= 0 - || len < (pd.size - MAX (0, -pd.offset))) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Failed to encode %u " - "partial definitions\n", ndefs); - return (void *)-1; - } - } - } + } + } - tree type = vr->type; - /* Make sure to interpret in a type that has a range - covering the whole access size. */ - if (INTEGRAL_TYPE_P (vr->type) - && maxsizei != TYPE_PRECISION (vr->type)) - type = build_nonstandard_integer_type (maxsizei, - TYPE_UNSIGNED (type)); - tree val = native_interpret_expr (type, buffer, - maxsizei / BITS_PER_UNIT); - /* If we chop off bits because the types precision doesn't - match the memory access size this is ok when optimizing - reads but not when called from the DSE code during - elimination. */ - if (val - && type != vr->type) - { - if (! int_fits_type_p (val, vr->type)) - val = NULL_TREE; - else - val = fold_convert (vr->type, val); - } + tree type = vr->type; + /* Make sure to interpret in a type that has a range covering the whole + access size. */ + if (INTEGRAL_TYPE_P (vr->type) && maxsizei != TYPE_PRECISION (vr->type)) + type = build_nonstandard_integer_type (maxsizei, TYPE_UNSIGNED (type)); + tree val = native_interpret_expr (type, buffer, maxsizei / BITS_PER_UNIT); + /* If we chop off bits because the types precision doesn't match the memory + access size this is ok when optimizing reads but not when called from + the DSE code during elimination. */ + if (val && type != vr->type) + { + if (! int_fits_type_p (val, vr->type)) + val = NULL_TREE; + else + val = fold_convert (vr->type, val); + } - if (val) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Successfully combined %u " - "partial definitions\n", ndefs); - return vn_reference_lookup_or_insert_for_pieces - (first_vuse, - vr->set, vr->type, vr->operands, val); - } - else - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Failed to interpret %u " - "encoded partial definitions\n", ndefs); - return (void *)-1; - } - } - } + if (val) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, + "Successfully combined %u partial definitions\n", ndefs); + return vn_reference_lookup_or_insert_for_pieces + (first_vuse, vr->set, vr->type, vr->operands, val); + } + else + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, + "Failed to interpret %u encoded partial definitions\n", ndefs); + return (void *)-1; } - /* Continue looking for partial defs. */ - return NULL; } /* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_ -- cgit v1.1 From d119bf79862015d4ba3c7f8774835c216c9a26ed Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 18 Jul 2019 08:22:50 +0000 Subject: Fix -Wreturn-type for static naked functions in C This patch extends the fix for PR53633 to include static functions, which were giving a bogus -Wreturn-type warning for C but not for C++. 2019-07-18 Richard Sandiford gcc/c/ PR c/53633 * c-decl.c (finish_function): Check targetm.warn_func_return before issuing a -Wreturn-type warning. gcc/testsuite/ * c-c++-common/pr53633-2.c: New test. From-SVN: r273568 --- gcc/c/ChangeLog | 6 ++++++ gcc/c/c-decl.c | 1 + gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/c-c++-common/pr53633-2.c | 19 +++++++++++++++++++ 4 files changed, 30 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/pr53633-2.c (limited to 'gcc') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 927fa91..ee0c559 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2019-07-18 Richard Sandiford + + PR c/53633 + * c-decl.c (finish_function): Check targetm.warn_func_return + before issuing a -Wreturn-type warning. + 2019-07-12 Alexandre Oliva * gimple-parser.c (c_parser_gimple_try_stmt): New. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index d75648a..0d107ad 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -9687,6 +9687,7 @@ finish_function (void) /* Normally, with -Wreturn-type, flow will complain, but we might optimize out static functions. */ && !TREE_PUBLIC (fndecl) + && targetm.warn_func_return (fndecl) && warning (OPT_Wreturn_type, "no return statement in function returning non-void")) TREE_NO_WARNING (fndecl) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 69e82b5..f9f1789 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-18 Richard Sandiford + + * c-c++-common/pr53633-2.c: New test. + 2019-07-17 Alexandre Oliva PR middle-end/81824 diff --git a/gcc/testsuite/c-c++-common/pr53633-2.c b/gcc/testsuite/c-c++-common/pr53633-2.c new file mode 100644 index 0000000..c26cb10 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr53633-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target naked_functions } */ +/* { dg-options "-O2 -Wall" } */ +/* Check that we do not get warnings about missing return statements + or bogus looking noreturn functions. */ +static int __attribute__((naked)) +foo (void) +{ + __asm__ (""); +} + +static int __attribute__((naked,noreturn)) +bar (void) +{ + __asm__ (""); +} + +int foo_caller (void) { return foo (); } +int bar_caller (void) { return bar (); } -- cgit v1.1 From f1f10541903b082d27114db38947fb31f5364bcc Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 18 Jul 2019 08:24:16 +0000 Subject: Make ifcvt clean up dead comparisons This change is needed to avoid a regression in gcc.dg/ifcvt-3.c for a later patch. Without it, we enter CSE with a dead comparison left by if-conversion and then eliminate the second (live) comparison in favour of the dead one. That's functionally correct in itself, but it meant that we'd combine the subtraction and comparison into a SUBS before we have a chance to fold away the subtraction. 2019-07-18 Richard Sandiford gcc/ * basic-block.h (CLEANUP_FORCE_FAST_DCE): New macro. * cfgcleanup.c (cleanup_cfg): Call run_fast_dce if CLEANUP_FORCE_FAST_DCE is set. * ifcvt.c (rest_of_handle_if_conversion): Pass CLEANUP_FORCE_FAST_DCE to the final cleanup_cfg call if if-conversion succeeded. From-SVN: r273569 --- gcc/ChangeLog | 9 +++++++++ gcc/basic-block.h | 2 ++ gcc/cfgcleanup.c | 8 +++++++- gcc/ifcvt.c | 7 ++++++- 4 files changed, 24 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 76baf87..b545a03 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-18 Richard Sandiford + + * basic-block.h (CLEANUP_FORCE_FAST_DCE): New macro. + * cfgcleanup.c (cleanup_cfg): Call run_fast_dce if + CLEANUP_FORCE_FAST_DCE is set. + * ifcvt.c (rest_of_handle_if_conversion): Pass + CLEANUP_FORCE_FAST_DCE to the final cleanup_cfg call if + if-conversion succeeded. + 2019-07-18 Richard Biener * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Refactor diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 5e0fbc0..2a0e826 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -508,6 +508,8 @@ ei_cond (edge_iterator ei, edge *p) #define CLEANUP_CFGLAYOUT 32 /* Do cleanup in cfglayout mode. */ #define CLEANUP_CFG_CHANGED 64 /* The caller changed the CFG. */ #define CLEANUP_NO_PARTITIONING 128 /* Do not try to fix partitions. */ +#define CLEANUP_FORCE_FAST_DCE 0x100 /* Force run_fast_dce to be called + at least once. */ /* Return true if BB is in a transaction. */ diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index fca3a08..b930763 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -3193,7 +3193,10 @@ cleanup_cfg (int mode) && !delete_trivially_dead_insns (get_insns (), max_reg_num ())) break; if ((mode & CLEANUP_CROSSJUMP) && crossjumps_occurred) - run_fast_dce (); + { + run_fast_dce (); + mode &= ~CLEANUP_FORCE_FAST_DCE; + } } else break; @@ -3202,6 +3205,9 @@ cleanup_cfg (int mode) if (mode & CLEANUP_CROSSJUMP) remove_fake_exit_edges (); + if (mode & CLEANUP_FORCE_FAST_DCE) + run_fast_dce (); + /* Don't call delete_dead_jumptables in cfglayout mode, because that function assumes that jump tables are in the insns stream. But we also don't _have_ to delete dead jumptables in cfglayout diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 7b2f6e6..e0c9522 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -5457,6 +5457,8 @@ if_convert (bool after_combine) static unsigned int rest_of_handle_if_conversion (void) { + int flags = 0; + if (flag_if_conversion) { if (dump_file) @@ -5466,9 +5468,12 @@ rest_of_handle_if_conversion (void) } cleanup_cfg (CLEANUP_EXPENSIVE); if_convert (false); + if (num_updated_if_blocks) + /* Get rid of any dead CC-related instructions. */ + flags |= CLEANUP_FORCE_FAST_DCE; } - cleanup_cfg (0); + cleanup_cfg (flags); return 0; } -- cgit v1.1 From 3796e3b399875dac8e6d100c7fe662a91a39ba42 Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Thu, 18 Jul 2019 08:38:09 +0000 Subject: re PR tree-optimization/91137 (Wrong code with -O3) PR tree-optimization/91137 * tree-ssa-loop-ivopts.c (struct ivopts_data): New field. (tree_ssa_iv_optimize_init, alloc_iv, tree_ssa_iv_optimize_finalize): Init, use and fini the above new field. (determine_base_object_1): New function. (determine_base_object): Reimplement using walk_tree. gcc/testsuite PR tree-optimization/91137 * gcc.c-torture/execute/pr91137.c: New test. From-SVN: r273570 --- gcc/ChangeLog | 9 +++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.c-torture/execute/pr91137.c | 34 ++++++++++ gcc/tree-ssa-loop-ivopts.c | 92 +++++++++++++++------------ 4 files changed, 100 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr91137.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b545a03..e7ba87a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-18 Bin Cheng + + PR tree-optimization/91137 + * tree-ssa-loop-ivopts.c (struct ivopts_data): New field. + (tree_ssa_iv_optimize_init, alloc_iv, tree_ssa_iv_optimize_finalize): + Init, use and fini the above new field. + (determine_base_object_1): New function. + (determine_base_object): Reimplement using walk_tree. + 2019-07-18 Richard Sandiford * basic-block.h (CLEANUP_FORCE_FAST_DCE): New macro. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f9f1789..0bbbd8a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-18 Bin Cheng + + PR tree-optimization/91137 + * gcc.c-torture/execute/pr91137.c: New test. + 2019-07-18 Richard Sandiford * c-c++-common/pr53633-2.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr91137.c b/gcc/testsuite/gcc.c-torture/execute/pr91137.c new file mode 100644 index 0000000..aa6bb6c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr91137.c @@ -0,0 +1,34 @@ +long long a; +unsigned b; +int c[70]; +int d[70][70]; +int e; + +__attribute__ ((noinline)) void f(long long *g, int p2) { + *g = p2; +} + +__attribute__ ((noinline)) void fn2() { + for (int j = 0; j < 70; j++) { + for (int i = 0; i < 70; i++) { + if (b) + c[i] = 0; + for (int l = 0; l < 70; l++) + d[i][1] = d[l][i]; + } + for (int k = 0; k < 70; k++) + e = c[0]; + } +} + +int main() { + b = 5; + for (int j = 0; j < 70; ++j) + c[j] = 2075593088; + fn2(); + f(&a, e); + if (a) + __builtin_abort(); + return 0; +} + diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index fd5e99b..43ba429 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -591,6 +591,9 @@ struct ivopts_data /* The common candidates. */ vec iv_common_cands; + /* Hash map recording base object information of tree exp. */ + hash_map *base_object_map; + /* The maximum invariant variable id. */ unsigned max_inv_var_id; @@ -1043,61 +1046,68 @@ tree_ssa_iv_optimize_init (struct ivopts_data *data) data->vcands.create (20); data->inv_expr_tab = new hash_table (10); data->name_expansion_cache = NULL; + data->base_object_map = NULL; data->iv_common_cand_tab = new hash_table (10); data->iv_common_cands.create (20); decl_rtl_to_reset.create (20); gcc_obstack_init (&data->iv_obstack); } -/* Returns a memory object to that EXPR points. In case we are able to - determine that it does not point to any such object, NULL is returned. */ +/* walk_tree callback for determine_base_object. */ static tree -determine_base_object (tree expr) +determine_base_object_1 (tree *tp, int *walk_subtrees, void *wdata) { - enum tree_code code = TREE_CODE (expr); - tree base, obj; - - /* If this is a pointer casted to any type, we need to determine - the base object for the pointer; so handle conversions before - throwing away non-pointer expressions. */ - if (CONVERT_EXPR_P (expr)) - return determine_base_object (TREE_OPERAND (expr, 0)); - - if (!POINTER_TYPE_P (TREE_TYPE (expr))) - return NULL_TREE; - - switch (code) + tree_code code = TREE_CODE (*tp); + tree obj = NULL_TREE; + if (code == ADDR_EXPR) { - case INTEGER_CST: - return NULL_TREE; - - case ADDR_EXPR: - obj = TREE_OPERAND (expr, 0); - base = get_base_address (obj); - + tree base = get_base_address (TREE_OPERAND (*tp, 0)); if (!base) - return expr; - - if (TREE_CODE (base) == MEM_REF) - return determine_base_object (TREE_OPERAND (base, 0)); + obj = *tp; + else if (TREE_CODE (base) != MEM_REF) + obj = fold_convert (ptr_type_node, build_fold_addr_expr (base)); + } + else if (code == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (*tp))) + obj = fold_convert (ptr_type_node, *tp); - return fold_convert (ptr_type_node, - build_fold_addr_expr (base)); + if (!obj) + { + if (!EXPR_P (*tp)) + *walk_subtrees = 0; - case POINTER_PLUS_EXPR: - return determine_base_object (TREE_OPERAND (expr, 0)); + return NULL_TREE; + } + /* Record special node for multiple base objects and stop. */ + if (*static_cast (wdata)) + { + *static_cast (wdata) = integer_zero_node; + return integer_zero_node; + } + /* Record the base object and continue looking. */ + *static_cast (wdata) = obj; + return NULL_TREE; +} - case PLUS_EXPR: - case MINUS_EXPR: - /* Pointer addition is done solely using POINTER_PLUS_EXPR. */ - gcc_unreachable (); +/* Returns a memory object to that EXPR points with caching. Return NULL if we + are able to determine that it does not point to any such object; specially + return integer_zero_node if EXPR contains multiple base objects. */ - default: - if (POLY_INT_CST_P (expr)) - return NULL_TREE; - return fold_convert (ptr_type_node, expr); +static tree +determine_base_object (struct ivopts_data *data, tree expr) +{ + tree *slot, obj = NULL_TREE; + if (data->base_object_map) + { + if ((slot = data->base_object_map->get(expr)) != NULL) + return *slot; } + else + data->base_object_map = new hash_map; + + (void) walk_tree_without_duplicates (&expr, determine_base_object_1, &obj); + data->base_object_map->put (expr, obj); + return obj; } /* Return true if address expression with non-DECL_P operand appears @@ -1155,7 +1165,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step, } iv->base = base; - iv->base_object = determine_base_object (base); + iv->base_object = determine_base_object (data, base); iv->step = step; iv->biv_p = false; iv->nonlin_use = NULL; @@ -7527,6 +7537,8 @@ tree_ssa_iv_optimize_finalize (struct ivopts_data *data) delete data->inv_expr_tab; data->inv_expr_tab = NULL; free_affine_expand_cache (&data->name_expansion_cache); + if (data->base_object_map) + delete data->base_object_map; delete data->iv_common_cand_tab; data->iv_common_cand_tab = NULL; data->iv_common_cands.release (); -- cgit v1.1 From b01659aa867a8fee932ef389f5066495f531da77 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 18 Jul 2019 15:08:34 +0200 Subject: lto-common.c (gimple_register_canonical_type_1): Do not look for non-ODR conflicts of types in anonymous namespaces. * lto-common.c (gimple_register_canonical_type_1): Do not look for non-ODR conflicts of types in anonymous namespaces. (unify_scc): Do not merge anonymous namespace types. * g++.dg/lto/alias-5_0.C: New testcase. * g++.dg/lto/alias-5_1.C: New. * g++.dg/lto/alias-5_2.c: New. From-SVN: r273571 --- gcc/lto/ChangeLog | 6 ++++++ gcc/lto/lto-common.c | 27 ++++++++++++++++++--------- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/lto/alias-5_0.C | 35 +++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/lto/alias-5_1.C | 9 +++++++++ gcc/testsuite/g++.dg/lto/alias-5_2.c | 7 +++++++ 6 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lto/alias-5_0.C create mode 100644 gcc/testsuite/g++.dg/lto/alias-5_1.C create mode 100644 gcc/testsuite/g++.dg/lto/alias-5_2.c (limited to 'gcc') diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 83d166d..22e7739 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2019-07-18 Jan Hubicka + + * lto-common.c (gimple_register_canonical_type_1): Do not look for + non-ODR conflicts of types in anonymous namespaces. + (unify_scc): Do not merge anonymous namespace types. + 2019-07-09 Martin Sebor PR c++/61339 diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c index c9d9781..ef2d02a 100644 --- a/gcc/lto/lto-common.c +++ b/gcc/lto/lto-common.c @@ -418,13 +418,19 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash) if (RECORD_OR_UNION_TYPE_P (t) && odr_type_p (t) && !odr_type_violation_reported_p (t)) { - /* Here we rely on fact that all non-ODR types was inserted into - canonical type hash and thus we can safely detect conflicts between - ODR types and interoperable non-ODR types. */ - gcc_checking_assert (type_streaming_finished - && TYPE_MAIN_VARIANT (t) == t); - slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash, - NO_INSERT); + /* Anonymous namespace types never conflict with non-C++ types. */ + if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t)) + slot = NULL; + else + { + /* Here we rely on fact that all non-ODR types was inserted into + canonical type hash and thus we can safely detect conflicts between + ODR types and interoperable non-ODR types. */ + gcc_checking_assert (type_streaming_finished + && TYPE_MAIN_VARIANT (t) == t); + slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash, + NO_INSERT); + } if (slot && !TYPE_CXX_ODR_P (*(tree *)slot)) { tree nonodr = *(tree *)slot; @@ -1640,11 +1646,14 @@ unify_scc (class data_in *data_in, unsigned from, tree t = streamer_tree_cache_get_tree (cache, from + i); scc->entries[i] = t; /* Do not merge SCCs with local entities inside them. Also do - not merge TRANSLATION_UNIT_DECLs. */ + not merge TRANSLATION_UNIT_DECLs and anonymous namespace types. */ if (TREE_CODE (t) == TRANSLATION_UNIT_DECL || (VAR_OR_FUNCTION_DECL_P (t) && !(TREE_PUBLIC (t) || DECL_EXTERNAL (t))) - || TREE_CODE (t) == LABEL_DECL) + || TREE_CODE (t) == LABEL_DECL + || (TYPE_P (t) + && type_with_linkage_p (TYPE_MAIN_VARIANT (t)) + && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t)))) { /* Avoid doing any work for these cases and do not worry to record the SCCs for further merging. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0bbbd8a..0f47604 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-18 Jan Hubicka + + * g++.dg/lto/alias-5_0.C: New testcase. + * g++.dg/lto/alias-5_1.C: New. + * g++.dg/lto/alias-5_2.c: New. + 2019-07-18 Bin Cheng PR tree-optimization/91137 diff --git a/gcc/testsuite/g++.dg/lto/alias-5_0.C b/gcc/testsuite/g++.dg/lto/alias-5_0.C new file mode 100644 index 0000000..779cc39 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/alias-5_0.C @@ -0,0 +1,35 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { { -O3 -flto } } } */ +/* This testcase tests that anonymous namespaces in different TUs are treated + as different types by LTO TBAA and that they never alias with structurally + same C types. */ +namespace { + __attribute__((used)) + struct a {int a;} *p,**ptr=&p; +}; +void +set1() +{ + *ptr=0; +} +void +get1() +{ + if (!__builtin_constant_p (*ptr==0)) + __builtin_abort (); +} +extern void set2(); +extern "C" void set3(); +int n = 1; +int +main() +{ + for (int i = 0; i < n; i++) + { + set1(); + set2(); + set3(); + get1(); + } + return 0; +} diff --git a/gcc/testsuite/g++.dg/lto/alias-5_1.C b/gcc/testsuite/g++.dg/lto/alias-5_1.C new file mode 100644 index 0000000..f12bd56 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/alias-5_1.C @@ -0,0 +1,9 @@ +namespace { + __attribute__((used)) + struct a {int a;} *p,**ptr=&p,q; +}; +void +set2() +{ + *ptr=&q; +} diff --git a/gcc/testsuite/g++.dg/lto/alias-5_2.c b/gcc/testsuite/g++.dg/lto/alias-5_2.c new file mode 100644 index 0000000..d126833 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/alias-5_2.c @@ -0,0 +1,7 @@ + __attribute__((used)) + struct a {int a;} *p,**ptr=&p,q; +void +set3() +{ + *ptr=&q; +} -- cgit v1.1 From 24990170d318194b265c2fc76d93965275da462c Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Thu, 18 Jul 2019 13:56:52 +0000 Subject: [arm] Fix incorrect modes with 'borrow' operations Looking through the arm backend I noticed that the modes used to pass comparison types into subtract-with-carry operations were being incorrectly set. The result is that the compiler is not truly self-consistent. To clean this up I've introduced a new predicate, arm_borrow_operation (borrowed from the AArch64 backend) which can match the comparison type with the required mode and then fixed all the patterns to use this. The split patterns that were generating incorrect modes have all obviously been fixed as well. The basic rule for the use of a borrow is: - if the condition code was set by a 'subtract-like' operation (subs, cmp), then use CCmode and LTU. - if the condition code was by unsigned overflow of addition (adds), then use CC_Cmode and GEU. * config/arm/predicates.md (arm_borrow_operation): New predicate. * config/arm/arm.c (subdi3_compare1): Use CCmode for the split. (arm_subdi3, subdi_di_zesidi, subdi_di_sesidi): Likewise. (subdi_zesidi_zesidi): Likewise. (negdi2_compare, negdi2_insn): Likewise. (negdi_extensidi): Likewise. (negdi_zero_extendsidi): Likewise. (arm_cmpdi_insn): Likewise. (subsi3_carryin): Use arm_borrow_operation. (subsi3_carryin_const): Likewise. (subsi3_carryin_const0): Likewise. (subsi3_carryin_compare): Likewise. (subsi3_carryin_compare_const): Likewise. (subsi3_carryin_compare_const0): Likewise. (subsi3_carryin_shift): Likewise. (rsbsi3_carryin_shift): Likewise. (negsi2_carryin_compare): Likewise. From-SVN: r273572 --- gcc/ChangeLog | 20 +++++++++ gcc/config/arm/arm.md | 99 ++++++++++++++++++++++---------------------- gcc/config/arm/predicates.md | 21 ++++++++++ 3 files changed, 91 insertions(+), 49 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e7ba87a..a4a625e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2019-07-18 Richard Earnshaw + + * config/arm/predicates.md (arm_borrow_operation): New predicate. + * config/arm/arm.c (subdi3_compare1): Use CCmode for the split. + (arm_subdi3, subdi_di_zesidi, subdi_di_sesidi): Likewise. + (subdi_zesidi_zesidi): Likewise. + (negdi2_compare, negdi2_insn): Likewise. + (negdi_extensidi): Likewise. + (negdi_zero_extendsidi): Likewise. + (arm_cmpdi_insn): Likewise. + (subsi3_carryin): Use arm_borrow_operation. + (subsi3_carryin_const): Likewise. + (subsi3_carryin_const0): Likewise. + (subsi3_carryin_compare): Likewise. + (subsi3_carryin_compare_const): Likewise. + (subsi3_carryin_compare_const0): Likewise. + (subsi3_carryin_shift): Likewise. + (rsbsi3_carryin_shift): Likewise. + (negsi2_carryin_compare): Likewise. + 2019-07-18 Bin Cheng PR tree-optimization/91137 diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 8f4a4c2..dcb5737 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1110,7 +1110,7 @@ (parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 4) (match_dup 5))) (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1141,7 +1141,7 @@ [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz") (match_operand:SI 2 "s_register_operand" "r,r,r")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (match_operand:SI 3 "arm_borrow_operation" "")))] "TARGET_32BIT" "@ sbc%?\\t%0, %1, %2 @@ -1155,9 +1155,10 @@ (define_insn "*subsi3_carryin_const" [(set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_neg_immediate_operand" "L")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (plus:SI + (match_operand:SI 1 "s_register_operand" "r") + (match_operand:SI 2 "arm_neg_immediate_operand" "L")) + (match_operand:SI 3 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbc\\t%0, %1, #%n2" [(set_attr "conds" "use") @@ -1166,8 +1167,8 @@ (define_insn "*subsi3_carryin_const0" [(set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (match_operand:SI 1 "s_register_operand" "r") + (match_operand:SI 2 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbc\\t%0, %1, #0" [(set_attr "conds" "use") @@ -1176,12 +1177,11 @@ (define_insn "*subsi3_carryin_compare" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "r"))) + (compare:CC (match_operand:SI 1 "s_register_operand" "r") + (match_operand:SI 2 "s_register_operand" "r"))) (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (minus:SI (match_dup 1) - (match_dup 2)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (minus:SI (match_dup 1) (match_dup 2)) + (match_operand:SI 3 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbcs\\t%0, %1, %2" [(set_attr "conds" "set") @@ -1190,12 +1190,13 @@ (define_insn "*subsi3_carryin_compare_const" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") - (match_operand:SI 2 "const_int_I_operand" "I"))) + (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") + (match_operand:SI 2 "const_int_I_operand" "I"))) (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (plus:SI (match_dup 1) - (match_operand:SI 3 "arm_neg_immediate_operand" "L")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (plus:SI + (match_dup 1) + (match_operand:SI 3 "arm_neg_immediate_operand" "L")) + (match_operand:SI 4 "arm_borrow_operation" "")))] "TARGET_32BIT && (INTVAL (operands[2]) == trunc_int_for_mode (-INTVAL (operands[3]), SImode))" @@ -1206,11 +1207,11 @@ (define_insn "*subsi3_carryin_compare_const0" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") + (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") (const_int 0))) (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (match_dup 1) + (match_operand:SI 2 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbcs\\t%0, %1, #0" [(set_attr "conds" "set") @@ -1220,28 +1221,28 @@ (define_insn "*subsi3_carryin_shift" [(set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (minus:SI - (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (match_operand:SI 1 "s_register_operand" "r") + (match_operator:SI 2 "shift_operator" + [(match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 4 "reg_or_int_operand" "rM")])) + (match_operand:SI 5 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbc%?\\t%0, %1, %3%S2" [(set_attr "conds" "use") (set_attr "predicable" "yes") (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift_imm") - (const_string "alu_shift_reg")))] + (const_string "alu_shift_imm") + (const_string "alu_shift_reg")))] ) (define_insn "*rsbsi3_carryin_shift" [(set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (minus:SI - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")]) + (match_operator:SI 2 "shift_operator" + [(match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 4 "reg_or_int_operand" "rM")]) (match_operand:SI 1 "s_register_operand" "r")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (match_operand:SI 5 "arm_borrow_operation" "")))] "TARGET_ARM" "rsc%?\\t%0, %1, %3%S2" [(set_attr "conds" "use") @@ -1311,7 +1312,7 @@ (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1338,7 +1339,7 @@ (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (minus:SI (match_dup 4) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1365,7 +1366,7 @@ (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (ashiftrt:SI (match_dup 2) (const_int 31))) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1392,7 +1393,7 @@ (compare:CC (match_dup 2) (match_dup 1))) (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))]) (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1422,7 +1423,7 @@ (ashiftrt:SI (match_dup 2) (const_int 31)) (match_dup 4)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1448,7 +1449,7 @@ (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -4661,7 +4662,7 @@ (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3)) - (ltu:SI (reg:CC_C CC_REGNUM) + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])] { operands[2] = gen_highpart (SImode, operands[0]); @@ -4703,7 +4704,7 @@ (compare:CC (const_int 0) (match_dup 1))) (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))]) (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[2] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -4722,7 +4723,7 @@ (set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (minus:SI (const_int 0) (match_dup 1)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (match_operand:SI 2 "arm_borrow_operation" "")))] "TARGET_ARM" "rscs\\t%0, %1, #0" [(set_attr "conds" "set") @@ -4799,7 +4800,7 @@ asr Rhi, Rin, #31 rsbs Rlo, Rin, #0 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */ - rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM); + rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); emit_insn (gen_rtx_SET (high, gen_rtx_ASHIFTRT (SImode, operands[1], @@ -4861,10 +4862,10 @@ ;; since we just need to propagate the carry. "&& reload_completed" [(parallel [(set (reg:CC CC_REGNUM) - (compare:CC (const_int 0) (match_dup 1))) - (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))]) + (compare:CC (const_int 0) (match_dup 1))) + (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))]) (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[2] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -7448,12 +7449,12 @@ "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1" "&& reload_completed" [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 0) (match_dup 1))) + (compare:CC (match_dup 0) (match_dup 1))) (parallel [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 3) (match_dup 4))) - (set (match_dup 2) - (minus:SI (match_dup 5) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])] + (compare:CC (match_dup 3) (match_dup 4))) + (set (match_dup 2) + (minus:SI (match_dup 5) + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index f53378a..25f8647 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -358,6 +358,27 @@ (define_special_predicate "lt_ge_comparison_operator" (match_code "lt,ge")) +;; Match a "borrow" operation for use with SBC. The precise code will +;; depend on the form of the comparison. This is generally the inverse of +;; a carry operation, since the logic of SBC uses "not borrow" in it's +;; calculation. +(define_special_predicate "arm_borrow_operation" + (match_code "geu,ltu") + { + if (XEXP (op, 1) != const0_rtx) + return false; + rtx op0 = XEXP (op, 0); + if (!REG_P (op0) || REGNO (op0) != CC_REGNUM) + return false; + machine_mode ccmode = GET_MODE (op0); + if (ccmode == CC_Cmode) + return GET_CODE (op) == GEU; + else if (ccmode == CCmode) + return GET_CODE (op) == LTU; + return false; + } +) + ;; The vsel instruction only accepts the ARM condition codes listed below. (define_special_predicate "arm_vsel_comparison_operator" (and (match_operand 0 "expandable_comparison_operator") -- cgit v1.1 From e38341a8e0c7f89eb2146feddea8c2f3bf25a331 Mon Sep 17 00:00:00 2001 From: Sylvia Taylor Date: Thu, 18 Jul 2019 15:42:13 +0000 Subject: [patch1/2][arm][PR90317]: fix sha1 patterns This patch fixes: 1) Ice message thrown when using the crypto_sha1h intrinsic due to incompatible mode used for zero_extend. Removed zero extend as it is not a good choice for vector modes and using an equivalent single mode like TI (128bits) instead of V4SI produces extra instructions making it inefficient. This affects gcc version 8 and above. 2) Incorrect combine optimizations made due to vec_select usage in the sha1 patterns on arm. The patterns should only combine a vec select within a sha1h instruction when the lane is 0. This affects gcc version 5 and above. - Fixed by explicitly declaring the valid const int for such optimizations. For cases when the lane is not 0, the vector lane selection now occurs in a e.g. vmov instruction prior to sha1h. - Updated the sha1h testcases on arm to check for additional cases with custom vector lane selection. The intrinsic functions for the sha1 patterns have also been simplified which seems to eliminate extra vmovs like: - vmov.i32 q8, #0. 2019-07-18 Sylvia Taylor PR target/90317 * config/arm/arm_neon.h (vsha1h_u32): Refactor. (vsha1cq_u32): Likewise. (vsha1pq_u32): Likewise. (vsha1mq_u32): Likewise. * config/arm/crypto.md: (crypto_sha1h): Remove zero extend, correct vec select. (crypto_sha1c): Correct vec select. (crypto_sha1m): Likewise. (crypto_sha1p): Likewise. * gcc.target/arm/crypto-vsha1cq_u32.c (foo): Change return type to uint32_t. (GET_LANE, TEST_SHA1C_VEC_SELECT): New. * gcc.target/arm/crypto-vsha1h_u32.c (foo): Change return type to uint32_t. (GET_LANE, TEST_SHA1H_VEC_SELECT): New. * gcc.target/arm/crypto-vsha1mq_u32.c (foo): Change return type to uint32_t. (GET_LANE, TEST_SHA1M_VEC_SELECT): New. * gcc.target/arm/crypto-vsha1pq_u32.c (foo): Change return type to uint32_t. (GET_LANE, TEST_SHA1P_VEC_SELECT): New. From-SVN: r273574 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/config/arm/arm_neon.h | 21 ++++++++------------- gcc/config/arm/crypto.md | 22 +++++++++++++++------- gcc/testsuite/ChangeLog | 16 ++++++++++++++++ gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c | 23 ++++++++++++++++++++--- gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c | 23 ++++++++++++++++++++--- gcc/testsuite/gcc.target/arm/crypto-vsha1mq_u32.c | 23 ++++++++++++++++++++--- gcc/testsuite/gcc.target/arm/crypto-vsha1pq_u32.c | 23 ++++++++++++++++++++--- 8 files changed, 133 insertions(+), 32 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a4a625e..668dc40 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-07-18 Sylvia Taylor + + PR target/90317 + * config/arm/arm_neon.h + (vsha1h_u32): Refactor. + (vsha1cq_u32): Likewise. + (vsha1pq_u32): Likewise. + (vsha1mq_u32): Likewise. + * config/arm/crypto.md: + (crypto_sha1h): Remove zero extend, correct vec select. + (crypto_sha1c): Correct vec select. + (crypto_sha1m): Likewise. + (crypto_sha1p): Likewise. + 2019-07-18 Richard Earnshaw * config/arm/predicates.md (arm_borrow_operation): New predicate. diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h index 6b98239..1f200d4 100644 --- a/gcc/config/arm/arm_neon.h +++ b/gcc/config/arm/arm_neon.h @@ -16938,37 +16938,32 @@ __extension__ extern __inline uint32_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vsha1h_u32 (uint32_t __hash_e) { - uint32x4_t __t = vdupq_n_u32 (0); - __t = vsetq_lane_u32 (__hash_e, __t, 0); - __t = __builtin_arm_crypto_sha1h (__t); - return vgetq_lane_u32 (__t, 0); + return vgetq_lane_u32 (__builtin_arm_crypto_sha1h (vdupq_n_u32 (__hash_e)), + 0); } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vsha1cq_u32 (uint32x4_t __hash_abcd, uint32_t __hash_e, uint32x4_t __wk) { - uint32x4_t __t = vdupq_n_u32 (0); - __t = vsetq_lane_u32 (__hash_e, __t, 0); - return __builtin_arm_crypto_sha1c (__hash_abcd, __t, __wk); + return __builtin_arm_crypto_sha1c (__hash_abcd, vdupq_n_u32 (__hash_e), + __wk); } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vsha1pq_u32 (uint32x4_t __hash_abcd, uint32_t __hash_e, uint32x4_t __wk) { - uint32x4_t __t = vdupq_n_u32 (0); - __t = vsetq_lane_u32 (__hash_e, __t, 0); - return __builtin_arm_crypto_sha1p (__hash_abcd, __t, __wk); + return __builtin_arm_crypto_sha1p (__hash_abcd, vdupq_n_u32 (__hash_e), + __wk); } __extension__ extern __inline uint32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vsha1mq_u32 (uint32x4_t __hash_abcd, uint32_t __hash_e, uint32x4_t __wk) { - uint32x4_t __t = vdupq_n_u32 (0); - __t = vsetq_lane_u32 (__hash_e, __t, 0); - return __builtin_arm_crypto_sha1m (__hash_abcd, __t, __wk); + return __builtin_arm_crypto_sha1m (__hash_abcd, vdupq_n_u32 (__hash_e), + __wk); } __extension__ extern __inline uint32x4_t diff --git a/gcc/config/arm/crypto.md b/gcc/config/arm/crypto.md index bf34f69..115c515 100644 --- a/gcc/config/arm/crypto.md +++ b/gcc/config/arm/crypto.md @@ -105,14 +105,18 @@ [(set_attr "type" "")] ) +/* The vec_select operation always selects index 0 from the lower V2SI subreg + of the V4SI, adjusted for endianness. Required due to neon_vget_lane and + neon_set_lane that change the element ordering in memory for big-endian. */ + (define_insn "crypto_sha1h" [(set (match_operand:V4SI 0 "register_operand" "=w") - (zero_extend:V4SI - (unspec:SI [(vec_select:SI - (match_operand:V4SI 1 "register_operand" "w") - (parallel [(match_operand:SI 2 "immediate_operand" "i")]))] - UNSPEC_SHA1H)))] - "TARGET_CRYPTO" + (unspec:V4SI + [(vec_select:SI + (match_operand:V4SI 1 "register_operand" "w") + (parallel [(match_operand:SI 2 "immediate_operand" "i")]))] + UNSPEC_SHA1H))] + "TARGET_CRYPTO && INTVAL (operands[2]) == NEON_ENDIAN_LANE_N (V2SImode, 0)" "sha1h.32\\t%q0, %q1" [(set_attr "type" "crypto_sha1_fast")] ) @@ -127,6 +131,10 @@ [(set_attr "type" "crypto_pmull")] ) +/* The vec_select operation always selects index 0 from the lower V2SI subreg + of the V4SI, adjusted for endianness. Required due to neon_vget_lane and + neon_set_lane that change the element ordering in memory for big-endian. */ + (define_insn "crypto_" [(set (match_operand:V4SI 0 "register_operand" "=w") (unspec: @@ -136,7 +144,7 @@ (parallel [(match_operand:SI 4 "immediate_operand" "i")])) (match_operand: 3 "register_operand" "w")] CRYPTO_SELECTING))] - "TARGET_CRYPTO" + "TARGET_CRYPTO && INTVAL (operands[4]) == NEON_ENDIAN_LANE_N (V2SImode, 0)" ".\\t%q0, %q2, %q3" [(set_attr "type" "")] ) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f47604..7bf322f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2019-07-18 Sylvia Taylor + + PR target/90317 + * gcc.target/arm/crypto-vsha1cq_u32.c (foo): Change return type to + uint32_t. + (GET_LANE, TEST_SHA1C_VEC_SELECT): New. + * gcc.target/arm/crypto-vsha1h_u32.c (foo): Change return type to + uint32_t. + (GET_LANE, TEST_SHA1H_VEC_SELECT): New. + * gcc.target/arm/crypto-vsha1mq_u32.c (foo): Change return type to + uint32_t. + (GET_LANE, TEST_SHA1M_VEC_SELECT): New. + * gcc.target/arm/crypto-vsha1pq_u32.c (foo): Change return type to + uint32_t. + (GET_LANE, TEST_SHA1P_VEC_SELECT): New. + 2019-07-18 Jan Hubicka * g++.dg/lto/alias-5_0.C: New testcase. diff --git a/gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c b/gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c index 4dc9dee..41f97a7 100644 --- a/gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c +++ b/gcc/testsuite/gcc.target/arm/crypto-vsha1cq_u32.c @@ -1,11 +1,12 @@ /* { dg-do compile } */ /* { dg-require-effective-target arm_crypto_ok } */ /* { dg-add-options arm_crypto } */ +/* { dg-additional-options "-O3" } */ #include "arm_neon.h" -int -foo (void) +uint32_t foo (void) + { uint32_t hash = 0xdeadbeef; uint32x4_t a = {0, 1, 2, 3}; @@ -15,4 +16,20 @@ foo (void) return res[0]; } -/* { dg-final { scan-assembler "sha1c.32\tq\[0-9\]+, q\[0-9\]+" } } */ +#define GET_LANE(lane) \ + uint32x4_t foo_lane##lane (uint32x4_t val,uint32x4_t a, uint32x4_t b)\ + { \ + return vsha1cq_u32 (a, vgetq_lane_u32 (val, lane), b); \ + } + +#define TEST_SHA1C_VEC_SELECT(FUNC) \ + FUNC (0) \ + FUNC (1) \ + FUNC (2) \ + FUNC (3) \ + +TEST_SHA1C_VEC_SELECT (GET_LANE) + +/* { dg-final { scan-assembler-times {sha1c.32\tq[0-9]+, q[0-9]+} 5 } } */ +/* { dg-final { scan-assembler-times {vdup.32\tq[0-9]+, r[0-9]+} 3 } } */ +/* { dg-final { scan-assembler-times {vmov.32\tr[0-9]+, d[0-9]+\[[0-9]+\]+} 4 } } */ diff --git a/gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c b/gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c index dee2774..b284667 100644 --- a/gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c +++ b/gcc/testsuite/gcc.target/arm/crypto-vsha1h_u32.c @@ -1,14 +1,31 @@ /* { dg-do compile } */ /* { dg-require-effective-target arm_crypto_ok } */ /* { dg-add-options arm_crypto } */ +/* { dg-additional-options "-O3" } */ #include "arm_neon.h" -int -foo (void) +uint32_t foo (void) + { uint32_t val = 0xdeadbeef; return vsha1h_u32 (val); } -/* { dg-final { scan-assembler "sha1h.32\tq\[0-9\]+, q\[0-9\]+" } } */ +#define GET_LANE(lane) \ + uint32_t foo_lane##lane (uint32x4_t val) \ + { \ + return vsha1h_u32 (vgetq_lane_u32 (val, lane)); \ + } + +#define TEST_SHA1H_VEC_SELECT(FUNC) \ + FUNC (0) \ + FUNC (1) \ + FUNC (2) \ + FUNC (3) \ + +TEST_SHA1H_VEC_SELECT (GET_LANE) + +/* { dg-final { scan-assembler-times {sha1h.32\tq[0-9]+, q[0-9]+} 5 } } */ +/* { dg-final { scan-assembler-times {vdup.32\tq[0-9]+, r[0-9]+} 3 } } */ +/* { dg-final { scan-assembler-times {vmov.32\tr[0-9]+, d[0-9]+\[[0-9]+\]+} 8 } } */ diff --git a/gcc/testsuite/gcc.target/arm/crypto-vsha1mq_u32.c b/gcc/testsuite/gcc.target/arm/crypto-vsha1mq_u32.c index 672b93a..676e64c 100644 --- a/gcc/testsuite/gcc.target/arm/crypto-vsha1mq_u32.c +++ b/gcc/testsuite/gcc.target/arm/crypto-vsha1mq_u32.c @@ -1,11 +1,12 @@ /* { dg-do compile } */ /* { dg-require-effective-target arm_crypto_ok } */ /* { dg-add-options arm_crypto } */ +/* { dg-additional-options "-O3" } */ #include "arm_neon.h" -int -foo (void) +uint32_t foo (void) + { uint32_t hash = 0xdeadbeef; uint32x4_t a = {0, 1, 2, 3}; @@ -15,4 +16,20 @@ foo (void) return res[0]; } -/* { dg-final { scan-assembler "sha1m.32\tq\[0-9\]+, q\[0-9\]+" } } */ +#define GET_LANE(lane) \ + uint32x4_t foo_lane##lane (uint32x4_t val,uint32x4_t a, uint32x4_t b)\ + { \ + return vsha1mq_u32 (a, vgetq_lane_u32 (val, lane), b); \ + } + +#define TEST_SHA1M_VEC_SELECT(FUNC) \ + FUNC (0) \ + FUNC (1) \ + FUNC (2) \ + FUNC (3) \ + +TEST_SHA1M_VEC_SELECT (GET_LANE) + +/* { dg-final { scan-assembler-times {sha1m.32\tq[0-9]+, q[0-9]+} 5 } } */ +/* { dg-final { scan-assembler-times {vdup.32\tq[0-9]+, r[0-9]+} 3 } } */ +/* { dg-final { scan-assembler-times {vmov.32\tr[0-9]+, d[0-9]+\[[0-9]+\]+} 4 } } */ diff --git a/gcc/testsuite/gcc.target/arm/crypto-vsha1pq_u32.c b/gcc/testsuite/gcc.target/arm/crypto-vsha1pq_u32.c index ff508e0..ed10fe2 100644 --- a/gcc/testsuite/gcc.target/arm/crypto-vsha1pq_u32.c +++ b/gcc/testsuite/gcc.target/arm/crypto-vsha1pq_u32.c @@ -1,11 +1,12 @@ /* { dg-do compile } */ /* { dg-require-effective-target arm_crypto_ok } */ /* { dg-add-options arm_crypto } */ +/* { dg-additional-options "-O3" } */ #include "arm_neon.h" -int -foo (void) +uint32_t foo (void) + { uint32_t hash = 0xdeadbeef; uint32x4_t a = {0, 1, 2, 3}; @@ -15,4 +16,20 @@ foo (void) return res[0]; } -/* { dg-final { scan-assembler "sha1p.32\tq\[0-9\]+, q\[0-9\]+" } } */ +#define GET_LANE(lane) \ + uint32x4_t foo_lane##lane (uint32x4_t val,uint32x4_t a, uint32x4_t b)\ + { \ + return vsha1pq_u32 (a, vgetq_lane_u32 (val, lane), b); \ + } + +#define TEST_SHA1P_VEC_SELECT(FUNC) \ + FUNC (0) \ + FUNC (1) \ + FUNC (2) \ + FUNC (3) \ + +TEST_SHA1P_VEC_SELECT (GET_LANE) + +/* { dg-final { scan-assembler-times {sha1p.32\tq[0-9]+, q[0-9]+} 5 } } */ +/* { dg-final { scan-assembler-times {vdup.32\tq[0-9]+, r[0-9]+} 3 } } */ +/* { dg-final { scan-assembler-times {vmov.32\tr[0-9]+, d[0-9]+\[[0-9]+\]+} 4 } } */ -- cgit v1.1 From b9a0100963b357e7e84084e45bbc51d6576410a4 Mon Sep 17 00:00:00 2001 From: Sylvia Taylor Date: Thu, 18 Jul 2019 16:02:05 +0000 Subject: [patch2/2][arm]: remove builtin expand for sha1 This patch removes the builtin expand handling for sha1h/c/m/p and replaces it with expand patterns. This should make it more consistent with how we handle intrinsic implementations and cleans up the custom sha1 code in the arm_expand builtins for unop and ternop. 2019-07-18 Sylvia Taylor * config/arm/arm-builtins.c (arm_expand_ternop_builtin): Remove explicit sha1 builtin handling. (arm_expand_unop_builtin): Likewise. * config/arm/crypto.md (crypto_sha1h): Convert from define_insn to define_expand. (crypto_): Likewise. (crypto_sha1h_lb): New define_insn. (crypto__lb): Likewise. From-SVN: r273575 --- gcc/ChangeLog | 11 +++++++++++ gcc/config/arm/arm-builtins.c | 36 +++--------------------------------- gcc/config/arm/crypto.md | 39 ++++++++++++++++++++++++++++++++------- 3 files changed, 46 insertions(+), 40 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 668dc40..7055ca4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2019-07-18 Sylvia Taylor + * config/arm/arm-builtins.c + (arm_expand_ternop_builtin): Remove explicit sha1 builtin handling. + (arm_expand_unop_builtin): Likewise. + * config/arm/crypto.md + (crypto_sha1h): Convert from define_insn to define_expand. + (crypto_): Likewise. + (crypto_sha1h_lb): New define_insn. + (crypto__lb): Likewise. + +2019-07-18 Sylvia Taylor + PR target/90317 * config/arm/arm_neon.h (vsha1h_u32): Refactor. diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index 55bbb48..8f2c937 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -1993,25 +1993,12 @@ arm_expand_ternop_builtin (enum insn_code icode, rtx op0 = expand_normal (arg0); rtx op1 = expand_normal (arg1); rtx op2 = expand_normal (arg2); - rtx op3 = NULL_RTX; - /* The sha1c, sha1p, sha1m crypto builtins require a different vec_select - lane operand depending on endianness. */ - bool builtin_sha1cpm_p = false; - - if (insn_data[icode].n_operands == 5) - { - gcc_assert (icode == CODE_FOR_crypto_sha1c - || icode == CODE_FOR_crypto_sha1p - || icode == CODE_FOR_crypto_sha1m); - builtin_sha1cpm_p = true; - } machine_mode tmode = insn_data[icode].operand[0].mode; machine_mode mode0 = insn_data[icode].operand[1].mode; machine_mode mode1 = insn_data[icode].operand[2].mode; machine_mode mode2 = insn_data[icode].operand[3].mode; - if (VECTOR_MODE_P (mode0)) op0 = safe_vector_operand (op0, mode0); if (VECTOR_MODE_P (mode1)) @@ -2034,13 +2021,8 @@ arm_expand_ternop_builtin (enum insn_code icode, op1 = copy_to_mode_reg (mode1, op1); if (! (*insn_data[icode].operand[3].predicate) (op2, mode2)) op2 = copy_to_mode_reg (mode2, op2); - if (builtin_sha1cpm_p) - op3 = GEN_INT (TARGET_BIG_END ? 1 : 0); - if (builtin_sha1cpm_p) - pat = GEN_FCN (icode) (target, op0, op1, op2, op3); - else - pat = GEN_FCN (icode) (target, op0, op1, op2); + pat = GEN_FCN (icode) (target, op0, op1, op2); if (! pat) return 0; emit_insn (pat); @@ -2096,16 +2078,8 @@ arm_expand_unop_builtin (enum insn_code icode, rtx pat; tree arg0 = CALL_EXPR_ARG (exp, 0); rtx op0 = expand_normal (arg0); - rtx op1 = NULL_RTX; machine_mode tmode = insn_data[icode].operand[0].mode; machine_mode mode0 = insn_data[icode].operand[1].mode; - bool builtin_sha1h_p = false; - - if (insn_data[icode].n_operands == 3) - { - gcc_assert (icode == CODE_FOR_crypto_sha1h); - builtin_sha1h_p = true; - } if (! target || GET_MODE (target) != tmode @@ -2121,13 +2095,9 @@ arm_expand_unop_builtin (enum insn_code icode, if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) op0 = copy_to_mode_reg (mode0, op0); } - if (builtin_sha1h_p) - op1 = GEN_INT (TARGET_BIG_END ? 1 : 0); - if (builtin_sha1h_p) - pat = GEN_FCN (icode) (target, op0, op1); - else - pat = GEN_FCN (icode) (target, op0); + pat = GEN_FCN (icode) (target, op0); + if (! pat) return 0; emit_insn (pat); diff --git a/gcc/config/arm/crypto.md b/gcc/config/arm/crypto.md index 115c515..03596fe 100644 --- a/gcc/config/arm/crypto.md +++ b/gcc/config/arm/crypto.md @@ -109,13 +109,23 @@ of the V4SI, adjusted for endianness. Required due to neon_vget_lane and neon_set_lane that change the element ordering in memory for big-endian. */ -(define_insn "crypto_sha1h" +(define_expand "crypto_sha1h" + [(set (match_operand:V4SI 0 "register_operand") + (match_operand:V4SI 1 "register_operand"))] + "TARGET_CRYPTO" +{ + rtx op2 = GEN_INT (NEON_ENDIAN_LANE_N (V2SImode, 0)); + emit_insn (gen_crypto_sha1h_lb (operands[0], operands[1], op2)); + DONE; +}) + +(define_insn "crypto_sha1h_lb" [(set (match_operand:V4SI 0 "register_operand" "=w") - (unspec:V4SI - [(vec_select:SI - (match_operand:V4SI 1 "register_operand" "w") - (parallel [(match_operand:SI 2 "immediate_operand" "i")]))] - UNSPEC_SHA1H))] + (unspec:V4SI + [(vec_select:SI + (match_operand:V4SI 1 "register_operand" "w") + (parallel [(match_operand:SI 2 "immediate_operand" "i")]))] + UNSPEC_SHA1H))] "TARGET_CRYPTO && INTVAL (operands[2]) == NEON_ENDIAN_LANE_N (V2SImode, 0)" "sha1h.32\\t%q0, %q1" [(set_attr "type" "crypto_sha1_fast")] @@ -135,7 +145,22 @@ of the V4SI, adjusted for endianness. Required due to neon_vget_lane and neon_set_lane that change the element ordering in memory for big-endian. */ -(define_insn "crypto_" +(define_expand "crypto_" + [(set (match_operand:V4SI 0 "register_operand") + (unspec: + [(match_operand: 1 "register_operand") + (match_operand: 2 "register_operand") + (match_operand: 3 "register_operand")] + CRYPTO_SELECTING))] + "TARGET_CRYPTO" +{ + rtx op4 = GEN_INT (NEON_ENDIAN_LANE_N (V2SImode, 0)); + emit_insn (gen_crypto__lb + (operands[0], operands[1], operands[2], operands[3], op4)); + DONE; +}) + +(define_insn "crypto__lb" [(set (match_operand:V4SI 0 "register_operand" "=w") (unspec: [(match_operand: 1 "register_operand" "0") -- cgit v1.1 From a6fc663e311b2b862373e4a4f3ee7d6836acb1a2 Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 18 Jul 2019 16:37:40 +0000 Subject: Makefile.rtl, [...]: Introduce a "STANDALONE" mode where C runtime files do not have any dependency... * Makefile.rtl, expect.c, env.c, aux-io.c, mkdir.c, initialize.c, cstreams.c, raise.c, tracebak.c, adadecode.c, init.c, raise-gcc.c, argv.c, adaint.c, adaint.h, ctrl_c.c, sysdep.c, rtinit.c, cio.c, seh_init.c, exit.c, targext.c: Introduce a "STANDALONE" mode where C runtime files do not have any dependency on GCC include files. Remove unnecessary includes. Remove remaining references to VMS in runtime C file. * runtime.h: new File. From-SVN: r273576 --- gcc/ada/ChangeLog | 11 ++++++ gcc/ada/Makefile.rtl | 2 +- gcc/ada/adadecode.c | 10 +---- gcc/ada/adaint.c | 18 +++++++++ gcc/ada/adaint.h | 2 +- gcc/ada/argv.c | 5 +-- gcc/ada/aux-io.c | 5 +-- gcc/ada/cio.c | 3 +- gcc/ada/cstreams.c | 4 +- gcc/ada/ctrl_c.c | 6 +-- gcc/ada/env.c | 108 ++++----------------------------------------------- gcc/ada/exit.c | 15 ------- gcc/ada/expect.c | 9 ++--- gcc/ada/init.c | 8 ++++ gcc/ada/initialize.c | 3 +- gcc/ada/mkdir.c | 3 +- gcc/ada/raise-gcc.c | 8 +++- gcc/ada/raise.c | 13 +------ gcc/ada/rtinit.c | 2 - gcc/ada/runtime.h | 44 +++++++++++++++++++++ gcc/ada/seh_init.c | 4 +- gcc/ada/sysdep.c | 6 ++- gcc/ada/targext.c | 7 ++++ gcc/ada/tracebak.c | 8 +--- 24 files changed, 125 insertions(+), 179 deletions(-) create mode 100644 gcc/ada/runtime.h (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index efd9d2f..ff3582f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2019-07-18 Arnaud Charlet + + * Makefile.rtl, expect.c, env.c, aux-io.c, mkdir.c, initialize.c, + cstreams.c, raise.c, tracebak.c, adadecode.c, init.c, raise-gcc.c, + argv.c, adaint.c, adaint.h, ctrl_c.c, sysdep.c, rtinit.c, cio.c, + seh_init.c, exit.c, targext.c: Introduce a "STANDALONE" mode where C + runtime files do not have any dependency on GCC include files. + Remove unnecessary includes. + Remove remaining references to VMS in runtime C file. + * runtime.h: new File. + 2019-07-13 Andreas Schwab * Makefile.rtl: Use g-sercom__linux.adb for all linuxes. diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index daee19a..6528df8 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -2610,7 +2610,7 @@ LIBGNAT_OBJS = adadecode.o adaint.o argv.o aux-io.o \ LIBGNAT_SRCS = $(patsubst %.o,%.c,$(LIBGNAT_OBJS)) \ adadecode.h adaint.h env.h gsocket.h raise.h standard.ads.h \ - tb-gcc.c libgnarl/thread.c $(EXTRA_LIBGNAT_SRCS) + tb-gcc.c runtime.h libgnarl/thread.c $(EXTRA_LIBGNAT_SRCS) # memtrack.o is special as not put into libgnat. GNATRTL_OBJS = $(GNATRTL_NONTASKING_OBJS) $(GNATRTL_TASKING_OBJS) \ diff --git a/gcc/ada/adadecode.c b/gcc/ada/adadecode.c index a574f3c..f87d421 100644 --- a/gcc/ada/adadecode.c +++ b/gcc/ada/adadecode.c @@ -29,15 +29,7 @@ * * ****************************************************************************/ - -#if defined(IN_RTS) -#include "tconfig.h" -#include "tsystem.h" -#elif defined(IN_GCC) -#include "config.h" -#include "system.h" -#endif - +#include "runtime.h" #include #include #include diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c index 4a75b59..fe8d955 100644 --- a/gcc/ada/adaint.c +++ b/gcc/ada/adaint.c @@ -88,8 +88,26 @@ #endif #ifdef IN_RTS + +#ifdef STANDALONE +#include +#include +#include +#include +#include +#include + +/* for CPU_SET/CPU_ZERO */ +#define _GNU_SOURCE +#define __USE_GNU + +#include "runtime.h" + +#else #include "tconfig.h" #include "tsystem.h" +#endif + #include #include #include diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h index 2ae8766..311e240 100644 --- a/gcc/ada/adaint.h +++ b/gcc/ada/adaint.h @@ -51,7 +51,7 @@ extern "C" { determine at compile time what support the system offers for large files. For now we just list the platforms we have manually tested. */ -#if defined (__GLIBC__) || defined (__sun__) || defined (__QNX__) +#if (defined (__GLIBC__) && !defined(STANDALONE)) || defined (__sun__) || defined (__QNX__) #define GNAT_FOPEN fopen64 #define GNAT_OPEN open64 #define GNAT_STAT stat64 diff --git a/gcc/ada/argv.c b/gcc/ada/argv.c index 3249c32..ca82ed5 100644 --- a/gcc/ada/argv.c +++ b/gcc/ada/argv.c @@ -43,9 +43,8 @@ Ada.Command_Line.Environment package. */ #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" -#include +#include "runtime.h" +#include #else #include "config.h" #include "system.h" diff --git a/gcc/ada/aux-io.c b/gcc/ada/aux-io.c index b55a6f9..e022b65 100644 --- a/gcc/ada/aux-io.c +++ b/gcc/ada/aux-io.c @@ -31,10 +31,7 @@ #include -#ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" -#else +#ifndef IN_RTS #include "config.h" #include "system.h" #endif diff --git a/gcc/ada/cio.c b/gcc/ada/cio.c index dd91a3e..7fca412 100644 --- a/gcc/ada/cio.c +++ b/gcc/ada/cio.c @@ -30,8 +30,7 @@ ****************************************************************************/ #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" +#include "runtime.h" #include #else #include "config.h" diff --git a/gcc/ada/cstreams.c b/gcc/ada/cstreams.c index e37070d..92392fc 100644 --- a/gcc/ada/cstreams.c +++ b/gcc/ada/cstreams.c @@ -53,9 +53,7 @@ #endif #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" -#include +#include #else #include "config.h" #include "system.h" diff --git a/gcc/ada/ctrl_c.c b/gcc/ada/ctrl_c.c index 546faa7..0e427ea 100644 --- a/gcc/ada/ctrl_c.c +++ b/gcc/ada/ctrl_c.c @@ -29,11 +29,7 @@ * * ****************************************************************************/ -#ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" -#include -#else +#ifndef IN_RTS #include "config.h" #include "system.h" #endif diff --git a/gcc/ada/env.c b/gcc/ada/env.c index 04e861e..698b177 100644 --- a/gcc/ada/env.c +++ b/gcc/ada/env.c @@ -30,15 +30,11 @@ ****************************************************************************/ #ifdef IN_RTS -# include "tconfig.h" -# include "tsystem.h" +# include "runtime.h" +# include +# include +# include -# include -# include -# include -# ifdef VMS -# include -# endif /* We don't have libiberty, so use malloc. */ # define xmalloc(S) malloc (S) #else /* IN_RTS */ @@ -109,89 +105,10 @@ __gnat_getenv (char *name, int *len, char **value) return; } -/* VMS specific declarations for set_env_value. */ - -#ifdef VMS - -typedef struct _ile3 -{ - unsigned short len, code; - __char_ptr32 adr; - __char_ptr32 retlen_adr; -} ile_s; - -#endif - void __gnat_setenv (char *name, char *value) { -#if defined (VMS) - struct dsc$descriptor_s name_desc; - $DESCRIPTOR (table_desc, "LNM$PROCESS"); - char *host_pathspec = value; - char *copy_pathspec; - int num_dirs_in_pathspec = 1; - char *ptr; - long status; - - name_desc.dsc$w_length = strlen (name); - name_desc.dsc$b_dtype = DSC$K_DTYPE_T; - name_desc.dsc$b_class = DSC$K_CLASS_S; - name_desc.dsc$a_pointer = name; /* ??? Danger, not 64bit safe. */ - - if (*host_pathspec == 0) - /* deassign */ - { - status = LIB$DELETE_LOGICAL (&name_desc, &table_desc); - /* no need to check status; if the logical name is not - defined, that's fine. */ - return; - } - - ptr = host_pathspec; - while (*ptr++) - if (*ptr == ',') - num_dirs_in_pathspec++; - - { - int i, status; - /* Alloca is guaranteed to be 32bit. */ - ile_s *ile_array = alloca (sizeof (ile_s) * (num_dirs_in_pathspec + 1)); - char *copy_pathspec = alloca (strlen (host_pathspec) + 1); - char *curr, *next; - - strcpy (copy_pathspec, host_pathspec); - curr = copy_pathspec; - for (i = 0; i < num_dirs_in_pathspec; i++) - { - next = strchr (curr, ','); - if (next == 0) - next = strchr (curr, 0); - - *next = 0; - ile_array[i].len = strlen (curr); - - /* Code 2 from lnmdef.h means it's a string. */ - ile_array[i].code = 2; - ile_array[i].adr = curr; - - /* retlen_adr is ignored. */ - ile_array[i].retlen_adr = 0; - curr = next + 1; - } - - /* Terminating item must be zero. */ - ile_array[i].len = 0; - ile_array[i].code = 0; - ile_array[i].adr = 0; - ile_array[i].retlen_adr = 0; - - status = LIB$SET_LOGICAL (&name_desc, 0, &table_desc, 0, ile_array); - if ((status & 1) != 1) - LIB$SIGNAL (status); - } - -#elif (defined (__vxworks) && defined (__RTP__)) || defined (__APPLE__) +#if (defined (__vxworks) && defined (__RTP__)) || defined (__APPLE__) setenv (name, value, 1); #else @@ -213,10 +130,7 @@ __gnat_setenv (char *name, char *value) char ** __gnat_environ (void) { -#if defined (VMS) || defined (RTX) - /* Not implemented */ - return NULL; -#elif defined (__MINGW32__) +#if defined (__MINGW32__) return _environ; #elif defined (__sun__) extern char **_environ; @@ -247,10 +161,7 @@ __gnat_environ (void) void __gnat_unsetenv (char *name) { -#if defined (VMS) - /* Not implemented */ - return; -#elif defined (__hpux__) || defined (__sun__) \ +#if defined (__hpux__) || defined (__sun__) \ || (defined (__vxworks) && ! defined (__RTP__)) \ || defined (_AIX) || defined (__Lynx__) @@ -306,10 +217,7 @@ void __gnat_unsetenv (char *name) void __gnat_clearenv (void) { -#if defined (VMS) - /* not implemented */ - return; -#elif defined (__sun__) \ +#if defined (__sun__) \ || (defined (__vxworks) && ! defined (__RTP__)) || defined (__Lynx__) \ || defined (__PikeOS__) /* On Solaris, VxWorks (not RTPs), and Lynx there is no system diff --git a/gcc/ada/exit.c b/gcc/ada/exit.c index 3ac3596..3f6ef21 100644 --- a/gcc/ada/exit.c +++ b/gcc/ada/exit.c @@ -29,21 +29,6 @@ * * ****************************************************************************/ -#ifdef __alpha_vxworks -#include "vxWorks.h" -#endif - -#ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" -#include -#else -#include "config.h" -#include "system.h" -#endif - -#include "adaint.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/gcc/ada/expect.c b/gcc/ada/expect.c index 76fce78..349af3f 100644 --- a/gcc/ada/expect.c +++ b/gcc/ada/expect.c @@ -29,14 +29,11 @@ * * ****************************************************************************/ -#ifdef __alpha_vxworks -#include "vxWorks.h" -#endif - #ifdef IN_RTS #define POSIX -#include "tconfig.h" -#include "tsystem.h" +#include "runtime.h" +#include + #else #include "config.h" #include "system.h" diff --git a/gcc/ada/init.c b/gcc/ada/init.c index 300a7e1..f7e830e 100644 --- a/gcc/ada/init.c +++ b/gcc/ada/init.c @@ -54,8 +54,14 @@ #endif #ifdef IN_RTS + +#ifdef STANDALONE +#include "runtime.h" +#else #include "tconfig.h" #include "tsystem.h" +#endif + #include /* We don't have libiberty, so use malloc. */ @@ -463,6 +469,7 @@ void fake_linux_sigemptyset (sigset_t *set) void __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext) { +#ifndef STANDALONE mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext; /* On the i386 and x86-64 architectures, stack checking is performed by @@ -513,6 +520,7 @@ __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext) mcontext->arm_pc+=1; #endif #endif +#endif } #endif diff --git a/gcc/ada/initialize.c b/gcc/ada/initialize.c index ab6d81d..0e52feb 100644 --- a/gcc/ada/initialize.c +++ b/gcc/ada/initialize.c @@ -41,8 +41,7 @@ #endif #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" +#include "runtime.h" /* We don't have libiberty, so use malloc. */ #define xmalloc(S) malloc (S) #define xrealloc(V,S) realloc (V,S) diff --git a/gcc/ada/mkdir.c b/gcc/ada/mkdir.c index d061476..e0efcce 100644 --- a/gcc/ada/mkdir.c +++ b/gcc/ada/mkdir.c @@ -35,8 +35,7 @@ #endif /* __vxworks */ #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" +#include "runtime.h" #include #else #include "config.h" diff --git a/gcc/ada/raise-gcc.c b/gcc/ada/raise-gcc.c index 6092a87..c15547d 100644 --- a/gcc/ada/raise-gcc.c +++ b/gcc/ada/raise-gcc.c @@ -39,11 +39,11 @@ /* Don't use fancy_abort. */ # undef abort #else -# ifndef CERT +# if !defined(CERT) && !defined(STANDALONE) # include "tconfig.h" # include "tsystem.h" # else -# define ATTRIBUTE_UNUSED __attribute__((unused)) +# include "runtime.h" # define HAVE_GETIPINFO 1 # endif #endif @@ -115,6 +115,10 @@ extern void __gnat_unhandled_except_handler (_Unwind_Exception *); /* Called in case of error during propagation. */ extern void __gnat_raise_abort (void) __attribute__ ((noreturn)); #define abort() __gnat_raise_abort() + +#elif defined(STANDALONE) +#include +#define inhibit_libc #endif #include "unwind-pe.h" diff --git a/gcc/ada/raise.c b/gcc/ada/raise.c index 480a0ea..bf8a879 100644 --- a/gcc/ada/raise.c +++ b/gcc/ada/raise.c @@ -33,8 +33,7 @@ is shared between all exception handling mechanisms. */ #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" +#include "runtime.h" #else #include "config.h" #include "system.h" @@ -56,16 +55,6 @@ extern "C" { void __gnat_unhandled_terminate (void) { -#ifdef VMS - /* Special termination handling for VMS */ - long prvhnd; - - /* Remove the exception vector so it won't intercept any errors - in the call to exit, and go into and endless loop */ - - SYS$SETEXV (1, 0, 3, &prvhnd); -#endif - /* Default termination handling */ __gnat_os_exit (1); } diff --git a/gcc/ada/rtinit.c b/gcc/ada/rtinit.c index 1df98f8..5c9c5ec 100644 --- a/gcc/ada/rtinit.c +++ b/gcc/ada/rtinit.c @@ -41,8 +41,6 @@ #endif #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" /* We don't have libiberty, so use malloc. */ #define xmalloc(S) malloc (S) #define xrealloc(V,S) realloc (V,S) diff --git a/gcc/ada/runtime.h b/gcc/ada/runtime.h new file mode 100644 index 0000000..df42730 --- /dev/null +++ b/gcc/ada/runtime.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * * + * GNAT COMPILER COMPONENTS * + * * + * RUNTIME * + * * + * C Header File * + * * + * Copyright (C) 2019, Free Software Foundation, Inc. * + * * + * GNAT is free software; you can redistribute it and/or modify it under * + * terms of the GNU General Public License as published by the Free Soft- * + * ware Foundation; either version 3, or (at your option) any later ver- * + * sion. GNAT is distributed in the hope that it will be useful, but WITH- * + * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * + * or FITNESS FOR A PARTICULAR PURPOSE. * + * * + * As a special exception under Section 7 of GPL version 3, you are granted * + * additional permissions described in the GCC Runtime Library Exception, * + * version 3.1, as published by the Free Software Foundation. * + * * + * You should have received a copy of the GNU General Public License and * + * a copy of the GCC Runtime Library Exception along with this program; * + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see * + * . * + * * + * GNAT was originally developed by the GNAT team at New York University. * + * Extensive contributions were provided by Ada Core Technologies Inc. * + * * + ****************************************************************************/ + +/* This file provides common definitions used by GNAT C runtime files. */ + +#ifdef __vxworks +#include "vxWorks.h" +#endif /* __vxworks */ + +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__((unused)) +#endif + +#ifndef ATTRIBUTE_NORETURN +#define ATTRIBUTE_NORETURN __attribute__((noreturn)) +#endif diff --git a/gcc/ada/seh_init.c b/gcc/ada/seh_init.c index fa9a693..2926605 100644 --- a/gcc/ada/seh_init.c +++ b/gcc/ada/seh_init.c @@ -39,8 +39,8 @@ #endif #ifdef IN_RTS -#include "tconfig.h" -#include "tsystem.h" + +#include "runtime.h" /* We don't have libiberty, so use malloc. */ #define xmalloc(S) malloc (S) diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c index 66c29d3..1e1f5ee 100644 --- a/gcc/ada/sysdep.c +++ b/gcc/ada/sysdep.c @@ -54,8 +54,10 @@ #ifdef IN_RTS #define POSIX -#include "tconfig.h" -#include "tsystem.h" +#include "runtime.h" +#include +#include + #include #include #else diff --git a/gcc/ada/targext.c b/gcc/ada/targext.c index 39d75d1..d761b2a 100644 --- a/gcc/ada/targext.c +++ b/gcc/ada/targext.c @@ -36,14 +36,21 @@ the file must be compiled with IN_GCC defined, even for the library. */ #ifdef IN_RTS + +#ifndef STANDALONE #include "tconfig.h" #include "tsystem.h" +#endif + #else #include "config.h" #include "system.h" #endif + +#ifndef STANDALONE #include "coretypes.h" #include "tm.h" +#endif #ifndef TARGET_OBJECT_SUFFIX #define TARGET_OBJECT_SUFFIX ".o" diff --git a/gcc/ada/tracebak.c b/gcc/ada/tracebak.c index a43dc4d..9e74282 100644 --- a/gcc/ada/tracebak.c +++ b/gcc/ada/tracebak.c @@ -50,14 +50,10 @@ extern "C" { #endif -#ifdef __alpha_vxworks -#include "vxWorks.h" -#endif - #ifdef IN_RTS #define POSIX -#include "tconfig.h" -#include "tsystem.h" +#include "runtime.h" +#include #else #include "config.h" #include "system.h" -- cgit v1.1 From 36729568fbf96ea0d481344cf3ef559c74f59f95 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 18 Jul 2019 16:51:00 +0000 Subject: compiler: fix bug in importing blocks from inline functions This patch fixes a buglet in the function body importer. Add hooks for keeping a stack of blocks corresponding to the block nesting in the imported function. This ensures that local variables and temps wind up correctly scoped and don't introduce collisions. New test case for this problem in CL 186717. Fixes golang/go#33158. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/186757 From-SVN: r273577 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/import.cc | 20 ++++++++++++++++++++ gcc/go/gofrontend/import.h | 23 +++++++++++++++-------- gcc/go/gofrontend/statements.cc | 2 ++ 4 files changed, 38 insertions(+), 9 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index c5ace5a..ccc1a24 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -19ed722fb3ae5e618c746da20efb79fc837337cd +4df7c8d7af894ee93f50c3a50debdcf4e369a2c6 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index ad7ba7f..be71f04 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -1535,6 +1535,26 @@ Stream_from_file::do_advance(size_t skip) // Class Import_function_body. +Import_function_body::Import_function_body(Gogo* gogo, + Import* imp, + Named_object* named_object, + const std::string& body, + size_t off, + Block* block, + int indent) + : gogo_(gogo), imp_(imp), named_object_(named_object), body_(body), + off_(off), indent_(indent), temporaries_(), labels_(), + saw_error_(false) +{ + this->blocks_.push_back(block); +} + +Import_function_body::~Import_function_body() +{ + // At this point we should be left with the original outer block only. + go_assert(saw_errors() || this->blocks_.size() == 1); +} + // The name of the function we are parsing. const std::string& diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h index ea01bbc..a78e48b 100644 --- a/gcc/go/gofrontend/import.h +++ b/gcc/go/gofrontend/import.h @@ -593,11 +593,8 @@ class Import_function_body : public Import_expression public: Import_function_body(Gogo* gogo, Import* imp, Named_object* named_object, const std::string& body, size_t off, Block* block, - int indent) - : gogo_(gogo), imp_(imp), named_object_(named_object), body_(body), - off_(off), block_(block), indent_(indent), temporaries_(), labels_(), - saw_error_(false) - { } + int indent); + ~Import_function_body(); // The IR. Gogo* @@ -637,7 +634,17 @@ class Import_function_body : public Import_expression // The current block. Block* block() - { return this->block_; } + { return this->blocks_.back(); } + + // Begin importing a new block BLOCK nested within the current block. + void + begin_block(Block *block) + { this->blocks_.push_back(block); } + + // Record the fact that we're done importing the current block. + void + finish_block() + { this->blocks_.pop_back(); } // The current indentation. int @@ -757,8 +764,8 @@ class Import_function_body : public Import_expression const std::string& body_; // The current offset into body_. size_t off_; - // Current block. - Block* block_; + // Stack to record nesting of blocks being imported. + std::vector blocks_; // Current expected indentation level. int indent_; // Temporary statements by index. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index b0b576f..27c4b95 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -2176,7 +2176,9 @@ Block_statement::do_import(Import_function_body* ifb, Location loc, ifb->set_off(nl + 1); ifb->increment_indent(); Block* block = new Block(ifb->block(), loc); + ifb->begin_block(block); bool ok = Block::import_block(block, ifb, loc); + ifb->finish_block(); ifb->decrement_indent(); if (!ok) return NULL; -- cgit v1.1 From 07d7662ff7ed987d98a61f333169b65620ec8202 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 18 Jul 2019 19:17:31 +0200 Subject: re PR target/91188 (strict_low_part operations do not work) PR target/91188 * config/i386/i386.md (*addqi_1_slp): Use register_operand predicate for operand 0. Do not use (match_dup) to match operand 1 with operand 0. Add check in insn constraint that either input operand matches operand 0. Use SWI12 mode iterator to also handle HImode operands. (*and_1_slp): Ditto. (*qi_1_slp): Ditto. (*sub_1_slp): Use register_operand predicate for operand 0. Do not use (match_dup) to match operand 1 with operand 0. Add check in insn constraint that operand 1 matches operand 0. Use SWI12 mode iterator to also handle HImode operands. (*ashl3_1_slp): Ditto. (*3_1_slp): Ditto. (*3_1_slp): Ditto. testsuite/ChangeLog: PR target/91188 * gcc.target/i386/pr91188-1a.c: New test. * gcc.target/i386/pr91188-1b.c: Ditto. * gcc.target/i386/pr91188-1c.c: Ditto. * gcc.target/i386/pr91188-2a.c: Ditto. * gcc.target/i386/pr91188-2b.c: Ditto. * gcc.target/i386/pr91188-2c.c: Ditto. From-SVN: r273578 --- gcc/ChangeLog | 18 +++ gcc/config/i386/i386.md | 194 ++++++++++++++--------------- gcc/testsuite/ChangeLog | 10 ++ gcc/testsuite/gcc.target/i386/pr91188-1a.c | 63 ++++++++++ gcc/testsuite/gcc.target/i386/pr91188-1b.c | 65 ++++++++++ gcc/testsuite/gcc.target/i386/pr91188-1c.c | 113 +++++++++++++++++ gcc/testsuite/gcc.target/i386/pr91188-2a.c | 62 +++++++++ gcc/testsuite/gcc.target/i386/pr91188-2b.c | 64 ++++++++++ gcc/testsuite/gcc.target/i386/pr91188-2c.c | 112 +++++++++++++++++ 9 files changed, 603 insertions(+), 98 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr91188-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr91188-1b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr91188-1c.c create mode 100644 gcc/testsuite/gcc.target/i386/pr91188-2a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr91188-2b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr91188-2c.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7055ca4..4a64253 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2019-07-18 UroÅ¡ Bizjak + + PR target/91188 + * config/i386/i386.md (*addqi_1_slp): Use register_operand predicate + for operand 0. Do not use (match_dup) to match operand 1 with + operand 0. Add check in insn constraint that either input operand + matches operand 0. Use SWI12 mode iterator to also handle + HImode operands. + (*and_1_slp): Ditto. + (*qi_1_slp): Ditto. + (*sub_1_slp): Use register_operand predicate for operand 0. + Do not use (match_dup) to match operand 1 with operand 0. Add + check in insn constraint that operand 1 matches operand 0. + Use SWI12 mode iterator to also handle HImode operands. + (*ashl3_1_slp): Ditto. + (*3_1_slp): Ditto. + (*3_1_slp): Ditto. + 2019-07-18 Sylvia Taylor * config/arm/arm-builtins.c diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 62485c3..4fc0300 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -5583,41 +5583,39 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*addqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (plus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*add_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (plus:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && (rtx_equal_p (operands[0], operands[1]) + || rtx_equal_p (operands[0], operands[2]))" { switch (get_attr_type (insn)) { case TYPE_INCDEC: - if (operands[1] == const1_rtx) - return "inc{b}\t%0"; + if (operands[2] == const1_rtx) + return "inc{}\t%0"; else { - gcc_assert (operands[1] == constm1_rtx); - return "dec{b}\t%0"; + gcc_assert (operands[2] == constm1_rtx); + return "dec{}\t%0"; } default: - if (x86_maybe_negate_const_int (&operands[1], QImode)) - return "sub{b}\t{%1, %0|%0, %1}"; + if (x86_maybe_negate_const_int (&operands[2], QImode)) + return "sub{}\t{%2, %0|%0, %2}"; - return "add{b}\t{%1, %0|%0, %1}"; + return "add{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (if_then_else (match_operand:QI 1 "incdec_operand") + (if_then_else (match_operand:QI 2 "incdec_operand") (const_string "incdec") - (const_string "alu1"))) - (set (attr "memory") - (if_then_else (match_operand 1 "memory_operand") - (const_string "load") - (const_string "none"))) - (set_attr "mode" "QI")]) + (const_string "alu"))) + (set_attr "mode" "")]) ;; Split non destructive adds if we cannot use lea. (define_split @@ -6345,16 +6343,17 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*subqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (minus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*sub_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (minus:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] - "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "sub{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" + "sub{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) (define_insn "*sub_2" [(set (reg FLAGS_REG) @@ -8548,16 +8547,18 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*andqi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (and:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*and_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (and:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "and{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && (rtx_equal_p (operands[0], operands[1]) + || rtx_equal_p (operands[0], operands[2]))" + "and{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) (define_split [(set (match_operand:SWI248 0 "register_operand") @@ -9098,16 +9099,18 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*qi_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (any_or:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "qn,m"))) +(define_insn "*_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (any_or:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "%0") + (match_operand:SWI12 2 "general_operand" "mn"))) (clobber (reg:CC FLAGS_REG))] "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && (rtx_equal_p (operands[0], operands[1]) + || rtx_equal_p (operands[0], operands[2]))" + "{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) (define_insn "*_2" [(set (reg FLAGS_REG) @@ -9162,7 +9165,7 @@ "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) && ix86_match_ccmode (insn, CCNOmode) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "{b}\t{%1, %0|%0, %1}" + "{}\t{%2, %0|%0, %2}" [(set_attr "type" "alu1") (set_attr "mode" "QI")]) @@ -10318,48 +10321,45 @@ (symbol_ref "!TARGET_PARTIAL_REG_STALL")] (symbol_ref "true")))]) -(define_insn "*ashlqi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (ashift:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "cI"))) +(define_insn "*ashl3_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (ashift:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_FLAG_REG_STALL - || (operands[1] == const1_rtx - && (TARGET_SHIFT1 - || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" { switch (get_attr_type (insn)) { - case TYPE_ALU1: - gcc_assert (operands[1] == const1_rtx); - return "add{b}\t%0, %0"; + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{}\t%0, %0"; default: - if (operands[1] == const1_rtx + if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "sal{b}\t%0"; + return "sal{}\t%0"; else - return "sal{b}\t{%1, %0|%0, %1}"; + return "sal{}\t{%2, %0|%0, %2}"; } } [(set (attr "type") - (cond [(and (and (match_test "TARGET_DOUBLE_WITH_ADD") - (match_operand 0 "register_operand")) - (match_operand 1 "const1_operand")) - (const_string "alu1") + (cond [(and (match_test "TARGET_DOUBLE_WITH_ADD") + (match_operand 2 "const1_operand")) + (const_string "alu") ] - (const_string "ishift1"))) + (const_string "ishift"))) (set (attr "length_immediate") (if_then_else - (ior (eq_attr "type" "alu1") - (and (eq_attr "type" "ishift1") - (and (match_operand 1 "const1_operand") + (ior (eq_attr "type" "alu") + (and (eq_attr "type" "ishift") + (and (match_operand 2 "const1_operand") (ior (match_test "TARGET_SHIFT1") (match_test "optimize_function_for_size_p (cfun)"))))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) ;; Convert ashift to the lea pattern to avoid flags dependency. (define_split @@ -10937,31 +10937,30 @@ (const_string "*"))) (set_attr "mode" "")]) -(define_insn "*qi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (any_shiftrt:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "cI"))) +(define_insn "*3_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (any_shiftrt:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_REG_STALL - || (operands[1] == const1_rtx - && TARGET_SHIFT1))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" { - if (operands[1] == const1_rtx + if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "{b}\t%0"; + return "{}\t%0"; else - return "{b}\t{%1, %0|%0, %1}"; + return "{}\t{%2, %0|%0, %2}"; } - [(set_attr "type" "ishift1") + [(set_attr "type" "ishift") (set (attr "length_immediate") (if_then_else - (and (match_operand 1 "const1_operand") + (and (match_operand 2 "const1_operand") (ior (match_test "TARGET_SHIFT1") (match_test "optimize_function_for_size_p (cfun)"))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant @@ -11366,31 +11365,30 @@ (const_string "*"))) (set_attr "mode" "")]) -(define_insn "*qi3_1_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) - (any_rotate:QI (match_dup 0) - (match_operand:QI 1 "nonmemory_operand" "cI"))) +(define_insn "*3_1_slp" + [(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+")) + (any_rotate:SWI12 (match_operand:SWI12 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "cI"))) (clobber (reg:CC FLAGS_REG))] - "(optimize_function_for_size_p (cfun) - || !TARGET_PARTIAL_REG_STALL - || (operands[1] == const1_rtx - && TARGET_SHIFT1))" + "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) + /* FIXME: without this LRA can't reload this pattern, see PR82524. */ + && rtx_equal_p (operands[0], operands[1])" { - if (operands[1] == const1_rtx + if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))) - return "{b}\t%0"; + return "{}\t%0"; else - return "{b}\t{%1, %0|%0, %1}"; + return "{}\t{%2, %0|%0, %2}"; } - [(set_attr "type" "rotate1") + [(set_attr "type" "rotate") (set (attr "length_immediate") (if_then_else - (and (match_operand 1 "const1_operand") + (and (match_operand 2 "const1_operand") (ior (match_test "TARGET_SHIFT1") (match_test "optimize_function_for_size_p (cfun)"))) (const_string "0") (const_string "*"))) - (set_attr "mode" "QI")]) + (set_attr "mode" "")]) (define_split [(set (match_operand:HI 0 "QIreg_operand") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7bf322f..7eb95f7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2019-07-18 UroÅ¡ Bizjak + + PR target/91188 + * gcc.target/i386/pr91188-1a.c: New test. + * gcc.target/i386/pr91188-1b.c: Ditto. + * gcc.target/i386/pr91188-1c.c: Ditto. + * gcc.target/i386/pr91188-2a.c: Ditto. + * gcc.target/i386/pr91188-2b.c: Ditto. + * gcc.target/i386/pr91188-2c.c: Ditto. + 2019-07-18 Sylvia Taylor PR target/90317 diff --git a/gcc/testsuite/gcc.target/i386/pr91188-1a.c b/gcc/testsuite/gcc.target/i386/pr91188-1a.c new file mode 100644 index 0000000..8673c2a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91188-1a.c @@ -0,0 +1,63 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzbl" } } */ +/* { dg-final { scan-assembler-not "movb" } } */ + +struct S +{ + unsigned char val; + unsigned char pad1; + unsigned short pad2; +}; + +struct S +test_and (struct S a, unsigned char b) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +struct S +test_or (struct S a, unsigned char b) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +struct S +test_xor (struct S a, unsigned char b) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +struct S +test_add (struct S a, unsigned char b) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +struct S +test_sub (struct S a, unsigned char b) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr91188-1b.c b/gcc/testsuite/gcc.target/i386/pr91188-1b.c new file mode 100644 index 0000000..9294911 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91188-1b.c @@ -0,0 +1,65 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzbl" } } */ +/* { dg-final { scan-assembler-not "movb" } } */ + +struct S +{ + unsigned char val; + unsigned char pad1; + unsigned short pad2; +}; + +unsigned char b; + +struct S +test_and (struct S a) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +struct S +test_or (struct S a) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +struct S +test_add (struct S a) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr91188-1c.c b/gcc/testsuite/gcc.target/i386/pr91188-1c.c new file mode 100644 index 0000000..0b32420 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91188-1c.c @@ -0,0 +1,113 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzbl" } } */ +/* { dg-final { scan-assembler-not "movb" } } */ + +struct S +{ + unsigned char val; + unsigned char pad1; + unsigned short pad2; +}; + +struct S +test_and (struct S a) +{ + a.val &= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andb" } } */ + +struct S +test_or (struct S a) +{ + a.val |= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orb" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorb" } } */ + +struct S +test_sal (struct S a) +{ + a.val <<= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]salb" } } */ + +struct S +test_shr (struct S a) +{ + a.val >>= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]shrb" } } */ + +struct S +test_sar (struct S a) +{ + a.val = (signed char) a.val >> 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]sarb" } } */ + +struct S +test_rol (struct S a) +{ + a.val = (a.val << 3 | a.val >> 5) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rolb" } } */ + +struct S +test_ror (struct S a) +{ + a.val = (a.val >> 3 | a.val << 5) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rorb" } } */ + +struct S +test_add (struct S a) +{ + a.val += 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addb" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subb" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr91188-2a.c b/gcc/testsuite/gcc.target/i386/pr91188-2a.c new file mode 100644 index 0000000..6529114 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91188-2a.c @@ -0,0 +1,62 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzwl" } } */ +/* { dg-final { scan-assembler-not "movw" } } */ + +struct S +{ + unsigned short val; + unsigned short pad; +}; + +struct S +test_and (struct S a, unsigned short b) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andw" } } */ + +struct S +test_or (struct S a, unsigned short b) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orw" } } */ + +struct S +test_xor (struct S a, unsigned short b) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorw" } } */ + +struct S +test_add (struct S a, unsigned short b) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addw" } } */ + +struct S +test_sub (struct S a, unsigned short b) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr91188-2b.c b/gcc/testsuite/gcc.target/i386/pr91188-2b.c new file mode 100644 index 0000000..cdaeae0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91188-2b.c @@ -0,0 +1,64 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzwl" } } */ +/* { dg-final { scan-assembler-not "movw" } } */ + +struct S +{ + unsigned short val; + unsigned short pad; +}; + +unsigned short b; + +struct S +test_and (struct S a) +{ + a.val &= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andw" } } */ + +struct S +test_or (struct S a) +{ + a.val |= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orw" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorw" } } */ + +struct S +test_add (struct S a) +{ + a.val += b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addw" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= b; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr91188-2c.c b/gcc/testsuite/gcc.target/i386/pr91188-2c.c new file mode 100644 index 0000000..c84e9c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr91188-2c.c @@ -0,0 +1,112 @@ +/* PR target/91188 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "movzwl" } } */ +/* { dg-final { scan-assembler-not "movw" } } */ + +struct S +{ + unsigned short val; + unsigned short pad; +}; + +struct S +test_and (struct S a) +{ + a.val &= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]andw" } } */ + +struct S +test_or (struct S a) +{ + a.val |= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]orw" } } */ + +struct S +test_xor (struct S a) +{ + a.val ^= 0x42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]xorw" } } */ + +struct S +test_sal (struct S a) +{ + a.val <<= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]salw" } } */ + +struct S +test_shr (struct S a) +{ + a.val >>= 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]shrw" } } */ + +struct S +test_sar (struct S a) +{ + a.val = (signed short) a.val >> 3; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]sarw" } } */ + +struct S +test_rol (struct S a) +{ + a.val = (a.val << 3 | a.val >> 13) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rolw" } } */ + +struct S +test_ror (struct S a) +{ + a.val = (a.val >> 3 | a.val << 13) ; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]rorw" } } */ + +struct S +test_add (struct S a) +{ + a.val += 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]addw" } } */ + +struct S +test_sub (struct S a) +{ + a.val -= 42; + + return a; +} + +/* { dg-final { scan-assembler "\[ \t\]subw" } } */ -- cgit v1.1 From 9ae813e89059b101d390e29912bc4348bfc538f2 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Thu, 18 Jul 2019 18:16:43 +0000 Subject: Update PowerPC compiler for pc-relative support. 2019-07-18 Michael Meissner * config/rs6000/aix.h (TARGET_HAS_TOC): Rename TARGET_TOC to TARGET_HAS_TOC. (TARGET_TOC): Likewise. (TARGET_NO_TOC): Delete here, define TARGET_NO_TOC_OR_PCREL in rs6000.h. * config/rs6000/darwin.h (TARGET_HAS_TOC): Rename TARGET_TOC to TARGET_HAS_TOC. (TARGET_TOC): Likewise. (TARGET_NO_TOC): Delete here, define TARGET_NO_TOC_OR_PCREL in rs6000.h. * config/rs6000/linux64.h (TARGET_HAS_TOC): Rename TARGET_TOC to TARGET_HAS_TOC. (TARGET_TOC): Likewise. * config/rs6000/rs6000.c (rs6000_option_override_internal): Add check to require -mcmodel=medium for pc-relative addressing. (create_TOC_reference): Add assertion for TARGET_TOC. (rs6000_legitimize_address): Use TARGET_NO_TOC_OR_PCREL instead of TARGET_NO_TOC. (rs6000_emit_move): Likewise. (TOC_alias_set): Rename TOC alias set static variable from 'set' to 'TOC_alias_set'. (get_TOC_alias_set): Likewise. (output_toc): Use TARGET_NO_TOC_OR_PCREL instead of TARGET_NO_TOC. (rs6000_can_eliminate): Likewise. * config/rs6000/rs6000.h (TARGET_TOC): Define in terms of TARGET_HAS_TOC and not pc-relative. (TARGET_NO_TOC_OR_PCREL): New macro to replace TARGET_NO_TOC. * config/rs6000/sysv4.h (TARGET_HAS_TOC): Rename TARGET_TOC to TARGET_HAS_TOC. (TARGET_TOC): Likewise. (TARGET_NO_TOC): Delete here, define TARGET_NO_TOC_OR_PCREL in rs6000.h. From-SVN: r273579 --- gcc/ChangeLog | 36 ++++++++++++++++++++++++++++++++++++ gcc/config/rs6000/aix.h | 3 +-- gcc/config/rs6000/darwin.h | 3 +-- gcc/config/rs6000/linux64.h | 4 ++-- gcc/config/rs6000/rs6000.c | 28 ++++++++++++++++++++-------- gcc/config/rs6000/rs6000.h | 7 +++++++ gcc/config/rs6000/sysv4.h | 3 +-- 7 files changed, 68 insertions(+), 16 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4a64253..151297a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2019-07-18 Michael Meissner + + * config/rs6000/aix.h (TARGET_HAS_TOC): Rename TARGET_TOC to + TARGET_HAS_TOC. + (TARGET_TOC): Likewise. + (TARGET_NO_TOC): Delete here, define TARGET_NO_TOC_OR_PCREL in + rs6000.h. + * config/rs6000/darwin.h (TARGET_HAS_TOC): Rename TARGET_TOC to + TARGET_HAS_TOC. + (TARGET_TOC): Likewise. + (TARGET_NO_TOC): Delete here, define TARGET_NO_TOC_OR_PCREL in + rs6000.h. + * config/rs6000/linux64.h (TARGET_HAS_TOC): Rename TARGET_TOC to + TARGET_HAS_TOC. + (TARGET_TOC): Likewise. + * config/rs6000/rs6000.c (rs6000_option_override_internal): Add + check to require -mcmodel=medium for pc-relative addressing. + (create_TOC_reference): Add assertion for TARGET_TOC. + (rs6000_legitimize_address): Use TARGET_NO_TOC_OR_PCREL instead of + TARGET_NO_TOC. + (rs6000_emit_move): Likewise. + (TOC_alias_set): Rename TOC alias set static variable from 'set' + to 'TOC_alias_set'. + (get_TOC_alias_set): Likewise. + (output_toc): Use TARGET_NO_TOC_OR_PCREL instead of + TARGET_NO_TOC. + (rs6000_can_eliminate): Likewise. + * config/rs6000/rs6000.h (TARGET_TOC): Define in terms of + TARGET_HAS_TOC and not pc-relative. + (TARGET_NO_TOC_OR_PCREL): New macro to replace TARGET_NO_TOC. + * config/rs6000/sysv4.h (TARGET_HAS_TOC): Rename TARGET_TOC to + TARGET_HAS_TOC. + (TARGET_TOC): Likewise. + (TARGET_NO_TOC): Delete here, define TARGET_NO_TOC_OR_PCREL in + rs6000.h. + 2019-07-18 UroÅ¡ Bizjak PR target/91188 diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index 01e1e74..75e080e 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -32,8 +32,7 @@ #define TARGET_AIX_OS 1 /* AIX always has a TOC. */ -#define TARGET_NO_TOC 0 -#define TARGET_TOC 1 +#define TARGET_HAS_TOC 1 #define FIXED_R2 1 /* AIX allows r13 to be used in 32-bit mode. */ diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index 272cd45..1bfb577 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -43,8 +43,7 @@ /* We're not ever going to do TOCs. */ -#define TARGET_TOC 0 -#define TARGET_NO_TOC 1 +#define TARGET_HAS_TOC 0 /* Override the default rs6000 definition. */ #undef PTRDIFF_TYPE diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 5380f6a..bd19749 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -277,8 +277,8 @@ extern int dot_symbols; #ifndef RS6000_BI_ARCH /* 64-bit PowerPC Linux always has a TOC. */ -#undef TARGET_TOC -#define TARGET_TOC 1 +#undef TARGET_HAS_TOC +#define TARGET_HAS_TOC 1 /* Some things from sysv4.h we don't do when 64 bit. */ #undef OPTION_RELOCATABLE diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 63f3075..3f64104 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -4333,6 +4333,16 @@ rs6000_option_override_internal (bool global_init_p) SUB3TARGET_OVERRIDE_OPTIONS; #endif + /* -mpcrel requires -mcmodel=medium, but we can't check TARGET_CMODEL until + after the subtarget override options are done. */ + if (TARGET_PCREL && TARGET_CMODEL != CMODEL_MEDIUM) + { + if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0) + error ("%qs requires %qs", "-mpcrel", "-mcmodel=medium"); + + rs6000_isa_flags &= ~OPTION_MASK_PCREL; + } + if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) rs6000_print_isa_options (stderr, 0, "after subtarget", rs6000_isa_flags); @@ -7742,6 +7752,8 @@ create_TOC_reference (rtx symbol, rtx largetoc_reg) { rtx tocrel, tocreg, hi; + gcc_assert (TARGET_TOC); + if (TARGET_DEBUG_ADDR) { if (SYMBOL_REF_P (symbol)) @@ -8121,7 +8133,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, #endif ) && TARGET_32BIT - && TARGET_NO_TOC + && TARGET_NO_TOC_OR_PCREL && !flag_pic && !CONST_INT_P (x) && !CONST_WIDE_INT_P (x) @@ -9811,7 +9823,7 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode) } if ((TARGET_ELF || DEFAULT_ABI == ABI_DARWIN) - && TARGET_NO_TOC + && TARGET_NO_TOC_OR_PCREL && ! flag_pic && mode == Pmode && CONSTANT_P (operands[1]) @@ -23725,14 +23737,14 @@ rs6000_split_multireg_move (rtx dst, rtx src) } } -static GTY(()) alias_set_type set = -1; +static GTY(()) alias_set_type TOC_alias_set = -1; alias_set_type get_TOC_alias_set (void) { - if (set == -1) - set = new_alias_set (); - return set; + if (TOC_alias_set == -1) + TOC_alias_set = new_alias_set (); + return TOC_alias_set; } /* Return the internal arg pointer used for function incoming @@ -24103,7 +24115,7 @@ output_toc (FILE *file, rtx x, int labelno, machine_mode mode) rtx base = x; HOST_WIDE_INT offset = 0; - gcc_assert (!TARGET_NO_TOC); + gcc_assert (!TARGET_NO_TOC_OR_PCREL); /* When the linker won't eliminate them, don't output duplicate TOC entries (this happens on AIX if there is any kind of TOC, @@ -30469,7 +30481,7 @@ rs6000_can_eliminate (const int from, const int to) return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : from == RS6000_PIC_OFFSET_TABLE_REGNUM - ? ! TARGET_MINIMAL_TOC || TARGET_NO_TOC + ? ! TARGET_MINIMAL_TOC || TARGET_NO_TOC_OR_PCREL || constant_pool_empty_p () : true); } diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 5f3b9ed..70e0616 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -54,6 +54,13 @@ #define TARGET_AIX_OS 0 #endif +/* Turn off TOC support if pc-relative addressing is used. */ +#define TARGET_TOC (TARGET_HAS_TOC && !TARGET_PCREL) + +/* On 32-bit systems without a TOC or pc-relative addressing, we need to use + ADDIS/ADDI to load up the address of a symbol. */ +#define TARGET_NO_TOC_OR_PCREL (!TARGET_HAS_TOC && !TARGET_PCREL) + /* Control whether function entry points use a "dot" symbol when ABI_AIX. */ #define DOT_SYMBOLS 1 diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 3861efd..17fea80 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -41,7 +41,7 @@ #undef ASM_DEFAULT_SPEC #define ASM_DEFAULT_SPEC "-mppc" -#define TARGET_TOC (TARGET_64BIT \ +#define TARGET_HAS_TOC (TARGET_64BIT \ || (TARGET_MINIMAL_TOC \ && flag_pic > 1) \ || DEFAULT_ABI != ABI_V4) @@ -50,7 +50,6 @@ #define TARGET_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) #define TARGET_PROTOTYPE target_prototype #define TARGET_NO_PROTOTYPE (! TARGET_PROTOTYPE) -#define TARGET_NO_TOC (! TARGET_TOC) #define TARGET_NO_EABI (! TARGET_EABI) #define TARGET_REGNAMES rs6000_regnames -- cgit v1.1 From 3f4ef678b4e701f9a702c6558993bc17460609b6 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Thu, 18 Jul 2019 19:07:13 +0000 Subject: Rename function. 2019-07-18 Michael Meissner * config/rs6000/predicates.md (prefixed_mem_operand): Call rs6000_prefixed_address_mode_p instead of rs6000_prefixed_address. * config/rs6000/rs6000-protos.h (rs6000_prefixed_address_mode_p): Rename function from rs6000_prefixed_address. * config/rs6000/rs6000.c (rs6000_prefixed_address_mode_p): Rename function from rs6000_prefixed_address. From-SVN: r273580 --- gcc/ChangeLog | 6 ++++++ gcc/config/rs6000/predicates.md | 2 +- gcc/config/rs6000/rs6000-protos.h | 2 +- gcc/config/rs6000/rs6000.c | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 151297a..55680d1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2019-07-18 Michael Meissner + * config/rs6000/predicates.md (prefixed_mem_operand): Call + rs6000_prefixed_address_mode_p instead of rs6000_prefixed_address. + * config/rs6000/rs6000-protos.h (rs6000_prefixed_address_mode_p): + Rename function from rs6000_prefixed_address. * config/rs6000/aix.h (TARGET_HAS_TOC): Rename TARGET_TOC to TARGET_HAS_TOC. (TARGET_TOC): Likewise. @@ -25,6 +29,8 @@ (output_toc): Use TARGET_NO_TOC_OR_PCREL instead of TARGET_NO_TOC. (rs6000_can_eliminate): Likewise. + (rs6000_prefixed_address_mode_p): Rename function from + rs6000_prefixed_address. * config/rs6000/rs6000.h (TARGET_TOC): Define in terms of TARGET_HAS_TOC and not pc-relative. (TARGET_NO_TOC_OR_PCREL): New macro to replace TARGET_NO_TOC. diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index e64f772..5f687ea 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -1686,7 +1686,7 @@ (define_predicate "prefixed_mem_operand" (match_code "mem") { - return rs6000_prefixed_address (XEXP (op, 0), GET_MODE (op)); + return rs6000_prefixed_address_mode_p (XEXP (op, 0), GET_MODE (op)); }) ;; Return 1 if op is a memory operand to an external variable when we diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index feb1250..06e40d9 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -154,7 +154,7 @@ extern align_flags rs6000_loop_align (rtx); extern void rs6000_split_logical (rtx [], enum rtx_code, bool, bool, bool); extern bool rs6000_pcrel_p (struct function *); extern bool rs6000_fndecl_pcrel_p (const_tree); -extern bool rs6000_prefixed_address (rtx, machine_mode); +extern bool rs6000_prefixed_address_mode_p (rtx, machine_mode); #endif /* RTX_CODE */ #ifdef TREE_CODE diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 3f64104..0013b39 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -21504,7 +21504,7 @@ mode_supports_prefixed_address_p (machine_mode mode) mode MODE. */ bool -rs6000_prefixed_address (rtx addr, machine_mode mode) +rs6000_prefixed_address_mode_p (rtx addr, machine_mode mode) { if (!TARGET_PREFIXED_ADDR || !mode_supports_prefixed_address_p (mode)) return false; -- cgit v1.1 From 2737c5909faa91ef1b8e0cbf42158632c4ab597e Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 18 Jul 2019 21:59:55 +0200 Subject: i386.md (*addqi_2_slp): Remove. * config/i386/i386.md (*addqi_2_slp): Remove. (*qi_2_slp): Ditto. From-SVN: r273583 --- gcc/ChangeLog | 5 +++++ gcc/config/i386/i386.md | 28 ---------------------------- 2 files changed, 5 insertions(+), 28 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 55680d1..35e4f37 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-18 UroÅ¡ Bizjak + + * config/i386/i386.md (*addqi_2_slp): Remove. + (*qi_2_slp): Ditto. + 2019-07-18 Michael Meissner * config/rs6000/predicates.md (prefixed_mem_operand): Call diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 4fc0300..63f18d7 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -8723,20 +8723,6 @@ [(set_attr "type" "alu") (set_attr "mode" "")]) -(define_insn "*andqi_2_slp" - [(set (reg FLAGS_REG) - (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "+qm,q") - (match_operand:QI 1 "nonimmediate_operand" "qn,m")) - (const_int 0))) - (set (strict_low_part (match_dup 0)) - (and:QI (match_dup 0) (match_dup 1)))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "and{b}\t{%1, %0|%0, %1}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) - (define_insn "andqi_ext_1" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q,Q") (const_int 8) @@ -9155,20 +9141,6 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) -(define_insn "*qi_2_slp" - [(set (reg FLAGS_REG) - (compare (any_or:QI (match_operand:QI 0 "nonimmediate_operand" "+qm,q") - (match_operand:QI 1 "general_operand" "qn,m")) - (const_int 0))) - (set (strict_low_part (match_dup 0)) - (any_or:QI (match_dup 0) (match_dup 1)))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && ix86_match_ccmode (insn, CCNOmode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "{}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu1") - (set_attr "mode" "QI")]) - (define_insn "*_3" [(set (reg FLAGS_REG) (compare (any_or:SWI -- cgit v1.1 From a349418ef5247fdc0063d0daee96f6e8b5fb4a28 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 19 Jul 2019 00:16:26 +0000 Subject: Daily bump. From-SVN: r273590 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 861a822..0d6cbf1 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190718 +20190719 -- cgit v1.1 From 59febe0ece37bedab7f42ae51b9f2b7a372d2950 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 19 Jul 2019 02:52:47 -0400 Subject: PR c++/90098 - partial specialization and class non-type parms. A non-type template parameter of class type used in an expression has const-qualified type; the pt.c hunks deal with this difference from the unqualified type of the parameter declaration. WAhen we use such a parameter as an argument to another template, we don't want to confuse things by copying it, we should pass it straight through. And we might as well skip copying other classes in constant evaluation context in a template, too; we'll get the copy semantics at instantiation time. PR c++/90099 PR c++/90101 * call.c (build_converted_constant_expr_internal): Don't copy. * pt.c (process_partial_specialization): Allow VIEW_CONVERT_EXPR around class non-type parameter. (unify) [TEMPLATE_PARM_INDEX]: Ignore cv-quals. From-SVN: r273591 --- gcc/cp/ChangeLog | 10 ++++++++++ gcc/cp/call.c | 5 +++++ gcc/cp/pt.c | 11 +++++++---- gcc/testsuite/g++.dg/cpp2a/nontype-class18.C | 17 +++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class19.C | 13 +++++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class20.C | 13 +++++++++++++ 6 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class18.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class19.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class20.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c9091f5..cef36b2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2019-07-18 Jason Merrill + + PR c++/90098 - partial specialization and class non-type parms. + PR c++/90099 + PR c++/90101 + * call.c (build_converted_constant_expr_internal): Don't copy. + * pt.c (process_partial_specialization): Allow VIEW_CONVERT_EXPR + around class non-type parameter. + (unify) [TEMPLATE_PARM_INDEX]: Ignore cv-quals. + 2019-07-16 Jason Merrill * parser.c (make_location): Add overload taking cp_lexer* as last diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e597d7a..38d229b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4278,6 +4278,11 @@ build_converted_constant_expr_internal (tree type, tree expr, if (conv) { + /* Don't copy a class in a template. */ + if (CLASS_TYPE_P (type) && conv->kind == ck_rvalue + && processing_template_decl) + conv = next_conversion (conv); + conv->check_narrowing = true; conv->check_narrowing_const_only = true; expr = convert_like (conv, expr, complain); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e23c0aa..53aaad1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4954,7 +4954,8 @@ process_partial_specialization (tree decl) simple identifier' condition and also the `specialized non-type argument' bit. */ && TREE_CODE (arg) != TEMPLATE_PARM_INDEX - && !(REFERENCE_REF_P (arg) + && !((REFERENCE_REF_P (arg) + || TREE_CODE (arg) == VIEW_CONVERT_EXPR) && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_PARM_INDEX)) { if ((!packed_args && tpd.arg_uses_template_parms[i]) @@ -22371,9 +22372,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* Template-parameter dependent expression. Just accept it for now. It will later be processed in convert_template_argument. */ ; - else if (same_type_p (non_reference (TREE_TYPE (arg)), - non_reference (tparm))) - /* OK */; + else if (same_type_ignoring_top_level_qualifiers_p + (non_reference (TREE_TYPE (arg)), + non_reference (tparm))) + /* OK. Ignore top-level quals here because a class-type template + parameter object is const. */; else if ((strict & UNIFY_ALLOW_INTEGER) && CP_INTEGRAL_TYPE_P (tparm)) /* Convert the ARG to the type of PARM; the deduced non-type diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C new file mode 100644 index 0000000..22f4788 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class18.C @@ -0,0 +1,17 @@ +// PR c++/90101 +// { dg-do compile { target c++2a } } + +template +struct A; + +template typename List> +struct A> {}; + +template typename List, auto V> +struct A> {}; + +template +struct B {}; + +struct X { int value; }; +A> a2; diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class19.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class19.C new file mode 100644 index 0000000..91267ac --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class19.C @@ -0,0 +1,13 @@ +// PR c++/90099 +// { dg-do compile { target c++2a } } + +struct Unit { + int value; + // auto operator<=>(const Unit&) = default; +}; + +template +struct X {}; + +template +struct X {}; diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class20.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class20.C new file mode 100644 index 0000000..5d3479c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class20.C @@ -0,0 +1,13 @@ +// PR c++/90098 +// { dg-do compile { target c++2a } } + +struct A { + int value; + // auto operator<=>(const A&) = default; +}; + +template +struct Z {}; + +template +struct Z {}; -- cgit v1.1 From daaa6fcc70ffe66bd56f5819ad4ee78fecd54bb6 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 19 Jul 2019 03:29:15 -0400 Subject: PR c++/90101 - dependent class non-type parameter. We shouldn't complain that a dependent type is incomplete. * pt.c (invalid_nontype_parm_type_p): Check for dependent class type. From-SVN: r273592 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/pt.c | 2 ++ gcc/testsuite/g++.dg/cpp2a/nontype-class21.C | 10 ++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class22.C | 21 +++++++++++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class21.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class22.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cef36b2..c1fc980 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2019-07-19 Jason Merrill + + PR c++/90101 - dependent class non-type parameter. + * pt.c (invalid_nontype_parm_type_p): Check for dependent class type. + 2019-07-18 Jason Merrill PR c++/90098 - partial specialization and class non-type parms. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 53aaad1..e433413 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -25228,6 +25228,8 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain) "with %<-std=c++2a%> or %<-std=gnu++2a%>"); return true; } + if (dependent_type_p (type)) + return false; if (!complete_type_or_else (type, NULL_TREE)) return true; if (!literal_type_p (type)) diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class21.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class21.C new file mode 100644 index 0000000..c58fe05 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class21.C @@ -0,0 +1,10 @@ +// PR c++/90101 +// { dg-do compile { target c++2a } } + +template +struct A{}; + +template> +struct B {}; + +B<2,A<2>{}> b; diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class22.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class22.C new file mode 100644 index 0000000..026855f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class22.C @@ -0,0 +1,21 @@ +// PR c++/90100 +// { dg-do compile { target c++2a } } + +template +inline constexpr bool is_nontype_list = false; + +template typename T, auto... NonTypes> +inline constexpr bool is_nontype_list> = true; + +// works +template +struct A {}; + +static_assert(is_nontype_list>); + +// fails +struct X { + int v; +}; + +static_assert(is_nontype_list>); -- cgit v1.1 From bc59a4cf1af79b77e3621b2103efc02c57ac7aec Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 19 Jul 2019 08:47:41 +0000 Subject: re PR tree-optimization/91207 (Wrong code with -O3) 2019-07-19 Richard Biener PR tree-optimization/91207 Revert 2019-07-17 Richard Biener PR tree-optimization/91178 * tree-vect-stmts.c (get_group_load_store_type): For SLP loads with a gap larger than the vector size always use VMAT_STRIDED_SLP. (vectorizable_load): For VMAT_STRIDED_SLP with a permutation avoid loading vectors that are only contained in the gap and thus are not needed. * gcc.dg/torture/pr91207.c: New testcase. From-SVN: r273593 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr91207.c | 25 +++++++++++++++++++++++++ gcc/tree-vect-stmts.c | 22 ++-------------------- 4 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr91207.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 35e4f37..95868ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2019-07-19 Richard Biener + + PR tree-optimization/91207 + Revert + 2019-07-17 Richard Biener + + PR tree-optimization/91178 + * tree-vect-stmts.c (get_group_load_store_type): For SLP + loads with a gap larger than the vector size always use + VMAT_STRIDED_SLP. + (vectorizable_load): For VMAT_STRIDED_SLP with a permutation + avoid loading vectors that are only contained in the gap + and thus are not needed. + 2019-07-18 UroÅ¡ Bizjak * config/i386/i386.md (*addqi_2_slp): Remove. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7eb95f7..b4fca28 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-19 Richard Biener + + PR tree-optimization/91207 + * gcc.dg/torture/pr91207.c: New testcase. + 2019-07-18 UroÅ¡ Bizjak PR target/91188 diff --git a/gcc/testsuite/gcc.dg/torture/pr91207.c b/gcc/testsuite/gcc.dg/torture/pr91207.c new file mode 100644 index 0000000..36d71d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr91207.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ + +long long a; +int b[92][32]; +unsigned int c, d; + +void e(long long *f, int p2) { *f = p2; } + +int main() +{ + for (int i = 6; i <= 20; d = i++) + for (int j = 6; j <= 91; j++) { + for (int k = 16; k <= 31;k++) + b[j][k] ^= 7; + c *= d; + } + + for (int i = 0; i < 21; ++i) + for (int j = 0; j < 32; ++j) + e(&a, b[i][j]); + + if (a != 7) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 5d05e10..601a6f5 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -2267,14 +2267,6 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp, / vect_get_scalar_dr_size (first_dr_info))) overrun_p = false; - /* If the gap at the end of the group exceeds a whole vector - in size use the strided SLP code which can skip code-generation - for the gap. */ - if (vls_type == VLS_LOAD && known_gt (gap, nunits)) - *memory_access_type = VMAT_STRIDED_SLP; - else - *memory_access_type = VMAT_CONTIGUOUS; - /* If the gap splits the vector in half and the target can do half-vector operations avoid the epilogue peeling by simply loading half of the vector only. Usually @@ -2282,8 +2274,7 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp, dr_alignment_support alignment_support_scheme; scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vectype)); machine_mode vmode; - if (*memory_access_type == VMAT_CONTIGUOUS - && overrun_p + if (overrun_p && !masked_p && (((alignment_support_scheme = vect_supportable_dr_alignment (first_dr_info, false))) @@ -2306,6 +2297,7 @@ get_group_load_store_type (stmt_vec_info stmt_info, tree vectype, bool slp, "Peeling for outer loop is not supported\n"); return false; } + *memory_access_type = VMAT_CONTIGUOUS; } } else @@ -8740,7 +8732,6 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, /* Checked by get_load_store_type. */ unsigned int const_nunits = nunits.to_constant (); unsigned HOST_WIDE_INT cst_offset = 0; - unsigned int group_gap = 0; gcc_assert (!LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)); gcc_assert (!nested_in_vect_loop); @@ -8758,7 +8749,6 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, if (slp && grouped_load) { group_size = DR_GROUP_SIZE (first_stmt_info); - group_gap = DR_GROUP_GAP (first_stmt_info); ref_type = get_group_alias_ptr_type (first_stmt_info); } else @@ -8902,14 +8892,6 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi, if (nloads > 1) vec_alloc (v, nloads); stmt_vec_info new_stmt_info = NULL; - if (slp && slp_perm - && (group_el % group_size) > group_size - group_gap - && (group_el % group_size) + nloads * lnel < group_size) - { - dr_chain.quick_push (NULL_TREE); - group_el += nloads * lnel; - continue; - } for (i = 0; i < nloads; i++) { tree this_off = build_int_cst (TREE_TYPE (alias_off), -- cgit v1.1 From 14298fa4891ee9b347d7f286cc8ef266976f9e18 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 19 Jul 2019 12:26:23 +0200 Subject: re PR middle-end/91190 (ICE on valid code: in hashtab_chk_error, at hash-table.c:137) PR middle-end/91190 * function.c (insert_temp_slot_address): Store into the hash table a copy of address to avoid RTL sharing issues. * gcc.c-torture/compile/pr91190.c: New test. From-SVN: r273599 --- gcc/ChangeLog | 6 ++++++ gcc/function.c | 2 +- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.c-torture/compile/pr91190.c | 31 +++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr91190.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 95868ab..3ac52e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-19 Jakub Jelinek + + PR middle-end/91190 + * function.c (insert_temp_slot_address): Store into the hash table + a copy of address to avoid RTL sharing issues. + 2019-07-19 Richard Biener PR tree-optimization/91207 diff --git a/gcc/function.c b/gcc/function.c index 373c1f2..2a0061c 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -704,7 +704,7 @@ static void insert_temp_slot_address (rtx address, class temp_slot *temp_slot) { struct temp_slot_address_entry *t = ggc_alloc (); - t->address = address; + t->address = copy_rtx (address); t->temp_slot = temp_slot; t->hash = temp_slot_address_compute_hash (t); *temp_slot_address_table->find_slot_with_hash (t, t->hash, INSERT) = t; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b4fca28..906ca0e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-19 Jakub Jelinek + + PR middle-end/91190 + * gcc.c-torture/compile/pr91190.c: New test. + 2019-07-19 Richard Biener PR tree-optimization/91207 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr91190.c b/gcc/testsuite/gcc.c-torture/compile/pr91190.c new file mode 100644 index 0000000..10b792f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr91190.c @@ -0,0 +1,31 @@ +/* PR middle-end/91190 */ + +unsigned a[1], c; +long d, h; +int e[2], f, g; +char i; + +int +main () +{ + char k = 0; + int l; + while (i || d) + { + if (g) + while (1) + ; + e[1] = 0; + long m[2], n = ~(3 & (5 | (h | 9) * 2237420170)); + g = 90 * n; + char b = m[300000000], j = 0; + c = 5 ^ a[c ^ (b & 5)]; + int o = d; + k = o ? : j; + if (k) + for (l = 0; l < 3; l++) + if (m[200000000000000000]) + __builtin_printf ("%d", f); + } + return 0; +} -- cgit v1.1 From c10abf530e52972ef708f6e72cf20dd920cd22a2 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 19 Jul 2019 11:24:31 +0000 Subject: [AArch64] Rename +bitperm to +sve2-bitperm After some discussion, we've decided to rename the +bitperm feature flag to +sve2-bitperm, so that it's consistent with the other SVE2 feature flags. The associated macro was already __ARM_FEATURE_SVE2_BITPERM, so only the feature flag itself needs to change. 2019-07-19 Richard Sandiford gcc/ * doc/invoke.texi: Rename the AArch64 +bitperm extension flag to +sve-bitperm. * config/aarch64/aarch64-option-extensions.def: Likewise. From-SVN: r273600 --- gcc/ChangeLog | 6 ++++++ gcc/config/aarch64/aarch64-option-extensions.def | 18 +++++++++--------- gcc/doc/invoke.texi | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3ac52e5..34c6d31 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-19 Richard Sandiford + + * doc/invoke.texi: Rename the AArch64 +bitperm extension flag + to +sve-bitperm. + * config/aarch64/aarch64-option-extensions.def: Likewise. + 2019-07-19 Jakub Jelinek PR middle-end/91190 diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def index 4b10c62..403a694 100644 --- a/gcc/config/aarch64/aarch64-option-extensions.def +++ b/gcc/config/aarch64/aarch64-option-extensions.def @@ -58,13 +58,13 @@ /* Enabling "fp" just enables "fp". Disabling "fp" also disables "simd", "crypto", "fp16", "aes", "sha2", "sha3", sm3/sm4, "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and - "bitperm". */ + "sve2-bitperm". */ AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "fp") /* Enabling "simd" also enables "fp". Disabling "simd" also disables "crypto", "dotprod", "aes", "sha2", "sha3", - "sm3/sm4", "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and "bitperm". - */ + "sm3/sm4", "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and + "sve2-bitperm". */ AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, AARCH64_FL_CRYPTO | AARCH64_FL_DOTPROD | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "asimd") /* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2". @@ -80,7 +80,7 @@ AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, false, "atomics") /* Enabling "fp16" also enables "fp". Disabling "fp16" disables "fp16", "fp16fml", "sve", "sve2", "sve2-aes", - "sve2-sha3", "sve2-sm4", and "bitperm". */ + "sve2-sha3", "sve2-sm4", and "sve2-bitperm". */ AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP, AARCH64_FL_F16FML | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "fphp asimdhp") /* Enabling or disabling "rcpc" only changes "rcpc". */ @@ -116,7 +116,7 @@ AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, AARCH64_FL_FP | AARCH64_FL_F /* Enabling "sve" also enables "fp16", "fp" and "simd". Disabling "sve" disables "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4" - and "bitperm". */ + and "sve2-bitperm". */ AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "sve") /* Enabling/Disabling "profile" does not enable/disable any other feature. */ @@ -139,7 +139,7 @@ AARCH64_OPT_EXTENSION("predres", AARCH64_FL_PREDRES, 0, 0, false, "") /* Enabling "sve2" also enables "sve", "fp16", "fp", and "simd". Disabling "sve2" disables "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and - "bitperm". */ + "sve2-bitperm". */ AARCH64_OPT_EXTENSION("sve2", AARCH64_FL_SVE2, AARCH64_FL_SVE | AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "") /* Enabling "sve2-sm4" also enables "sm4", "simd", "fp16", "fp", "sve", and @@ -154,8 +154,8 @@ AARCH64_OPT_EXTENSION("sve2-aes", AARCH64_FL_SVE2_AES, AARCH64_FL_AES | AARCH64_ "sve2". Disabling "sve2-sha3" just disables "sve2-sha3". */ AARCH64_OPT_EXTENSION("sve2-sha3", AARCH64_FL_SVE2_SHA3, AARCH64_FL_SHA3 | AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "") -/* Enabling "bitperm" also enables "simd", "fp16", "fp", "sve", and "sve2". - Disabling "bitperm" just disables "bitperm". */ -AARCH64_OPT_EXTENSION("bitperm", AARCH64_FL_SVE2_BITPERM, AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "") +/* Enabling "sve2-bitperm" also enables "simd", "fp16", "fp", "sve", and + "sve2". Disabling "sve2-bitperm" just disables "sve2-bitperm". */ +AARCH64_OPT_EXTENSION("sve2-bitperm", AARCH64_FL_SVE2_BITPERM, AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "") #undef AARCH64_OPT_EXTENSION diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 758aef3..b887f5f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -16083,7 +16083,7 @@ not affect code generation. This option is enabled by default for @item sve2 Enable the Armv8-a Scalable Vector Extension 2. This also enables SVE instructions. -@item bitperm +@item sve2-bitperm Enable SVE2 bitperm instructions. This also enables SVE2 instructions. @item sve2-sm4 Enable SVE2 sm4 instructions. This also enables SVE2 instructions. -- cgit v1.1 From a263e61a36e21451ff46318f0430e57aeaef6583 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 19 Jul 2019 12:24:53 +0000 Subject: re PR tree-optimization/91200 (ICE on valid code at -O1: verify_ssa failed) 2019-07-19 Richard Biener PR tree-optimization/91200 * tree-ssa-phiopt.c (cond_store_replacement): Check we have no PHI nodes in middle-bb. * gcc.dg/torture/pr91200.c: New testcase. From-SVN: r273602 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr91200.c | 32 ++++++++++++++++++++++++++++++++ gcc/tree-ssa-phiopt.c | 5 +++++ 4 files changed, 48 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/torture/pr91200.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34c6d31..96c0b96 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-19 Richard Biener + + PR tree-optimization/91200 + * tree-ssa-phiopt.c (cond_store_replacement): Check we have + no PHI nodes in middle-bb. + 2019-07-19 Richard Sandiford * doc/invoke.texi: Rename the AArch64 +bitperm extension flag diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 906ca0e..dfbf850 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-19 Richard Biener + + PR tree-optimization/91200 + * gcc.dg/torture/pr91200.c: New testcase. + 2019-07-19 Jakub Jelinek PR middle-end/91190 diff --git a/gcc/testsuite/gcc.dg/torture/pr91200.c b/gcc/testsuite/gcc.dg/torture/pr91200.c new file mode 100644 index 0000000..09db9e1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr91200.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ + +int printf (const char *, ...); + +char a; +int b, c, **d; + +int main () +{ + int f = -128, *g, *h[2] = {0, 0}, i; + printf("0"); + if (a) + { + while (f > a) { + int *j = &i; + *j |= 0; + } + h[i] = &c; + } + if (h[1]) + { + int **k = &g; + *k = &f; + while (i) + { + int **l[] = {&g}; + } + int **m = &g; + *d = *m = &b; + } + return 0; +} diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index a514ed8..b64bde6 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -2216,6 +2216,11 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb, || gimple_has_volatile_ops (assign)) return false; + /* And no PHI nodes so all uses in the single stmt are also + available where we insert to. */ + if (!gimple_seq_empty_p (phi_nodes (middle_bb))) + return false; + locus = gimple_location (assign); lhs = gimple_assign_lhs (assign); rhs = gimple_assign_rhs1 (assign); -- cgit v1.1 From 4eb503965ac70e747fa03a5298c1c9af04580c95 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 19 Jul 2019 16:31:09 +0200 Subject: re PR ipa/91194 (A suspicious condition in recursive_inlining) PR ipa/91194 * ipa-inline.c (recursive_inlining): Fix limits check. From-SVN: r273603 --- gcc/ChangeLog | 5 +++++ gcc/ipa-inline.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 96c0b96..2ccbcd1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-19 Jan Hubicka + + PR ipa/91194 + * ipa-inline.c (recursive_inlining): Fix limits check. + 2019-07-19 Richard Biener PR tree-optimization/91200 diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index e730066..5862d00 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -1504,7 +1504,7 @@ recursive_inlining (struct cgraph_edge *edge, struct cgraph_node *cnode, *dest = curr->callee; if (!can_inline_edge_p (curr, true) - || can_inline_edge_by_limits_p (curr, true)) + || !can_inline_edge_by_limits_p (curr, true)) continue; /* MASTER_CLONE is produced in the case we already started modified -- cgit v1.1 From d826ea32f6c98b59cbcb4140751374c583616239 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Fri, 19 Jul 2019 16:36:49 +0200 Subject: re PR target/91204 (ICE in expand_expr_real_2, at expr.c:9215 with -O3) PR target/91204 * config/i386/mmx.md (one_cmpl2): New expander. From-SVN: r273604 --- gcc/ChangeLog | 5 +++++ gcc/config/i386/mmx.md | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ccbcd1..8824ffd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-19 UroÅ¡ Bizjak + + PR target/91204 + * config/i386/mmx.md (one_cmpl2): New expander. + 2019-07-19 Jan Hubicka PR ipa/91194 diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 4c71e66..c78b33b 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -1158,6 +1158,14 @@ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define_expand "one_cmpl2" + [(set (match_operand:MMXMODEI 0 "register_operand") + (xor:MMXMODEI + (match_operand:MMXMODEI 1 "register_operand") + (match_dup 2)))] + "TARGET_MMX_WITH_SSE" + "operands[2] = force_reg (mode, CONSTM1_RTX (mode));") + (define_insn "mmx_andnot3" [(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,Yv") (and:MMXMODEI -- cgit v1.1 From 6b68f00d4c2b375dad66bd6e72c01c309b4085c5 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 19 Jul 2019 16:19:39 +0000 Subject: re PR tree-optimization/91211 (wrong code with __builtin_memset() and __builtin_memcpy() at -O1 and above) 2019-07-19 Richard Biener PR tree-optimization/91211 * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Fix memset encoding size. * gcc.dg/torture/pr91211.c: New testcase. From-SVN: r273605 --- gcc/ChangeLog | 6 ++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/torture/pr91211.c | 19 +++++++++++++++++++ gcc/tree-ssa-sccvn.c | 3 ++- 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr91211.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8824ffd..08f91ed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-19 Richard Biener + + PR tree-optimization/91211 + * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Fix + memset encoding size. + 2019-07-19 UroÅ¡ Bizjak PR target/91204 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dfbf850..98fb40d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2019-07-19 Richard Biener + PR tree-optimization/91211 + * gcc.dg/torture/pr91211.c: New testcase. + +2019-07-19 Richard Biener + PR tree-optimization/91200 * gcc.dg/torture/pr91200.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/torture/pr91211.c b/gcc/testsuite/gcc.dg/torture/pr91211.c new file mode 100644 index 0000000..84db92d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr91211.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ + +typedef __UINT32_TYPE__ u32; + +int +main (void) +{ + u32 b = 0x027C5902; + u32 a = 0; + __builtin_memset (1 + (char *) &b, 0, 2); + __builtin_memcpy (&a, 2 + (char *) &b, 2); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + if (a != 0x00000200) +#else + if (a != 0x00020000) +#endif + __builtin_abort(); + return 0; +} diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index f12c9dd..5b0460d 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1818,7 +1818,8 @@ vn_walk_cb_data::push_partial_def (const pd_data &pd, tree vuse, if (TREE_CODE (pd.rhs) == CONSTRUCTOR) /* Empty CONSTRUCTOR. */ memset (buffer + MAX (0, pd.offset), - 0, MIN ((HOST_WIDE_INT)sizeof (buffer), pd.size)); + 0, MIN ((HOST_WIDE_INT)sizeof (buffer), + pd.size + MIN (0, pd.offset))); else { unsigned pad = 0; -- cgit v1.1 From 192ece9e15d25fd9b6534b2a8bd271684bf76d38 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 19 Jul 2019 11:04:51 -0600 Subject: tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle strncpy. * tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle strncpy. Drop some trivial dead code. (maybe_trim_memstar_call): Handle strncpy. * gcc.dg/tree-ssa/ssa-dse-37.c: New test. * gcc.dg/tree-ssa/ssa-dse-38.c: New test. From-SVN: r273606 --- gcc/ChangeLog | 6 +++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-37.c | 60 ++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-38.c | 12 ++++++ gcc/tree-ssa-dse.c | 10 +++-- 5 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-37.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-38.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 08f91ed..d8f6004 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-19 Jeff Law + + * tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle + strncpy. Drop some trivial dead code. + (maybe_trim_memstar_call): Handle strncpy. + 2019-07-19 Richard Biener PR tree-optimization/91211 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 98fb40d..ce8e3c7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-19 Jeff Law + + * gcc.dg/tree-ssa/ssa-dse-37.c: New test. + * gcc.dg/tree-ssa/ssa-dse-38.c: New test. + 2019-07-19 Richard Biener PR tree-optimization/91211 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-37.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-37.c new file mode 100644 index 0000000..56251fc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-37.c @@ -0,0 +1,60 @@ +/* { dg-options "-O2 -fdump-tree-dse-details -fno-tree-fre" } */ + + +#ifndef SCOPE +#define SCOPE +#endif + +extern void frob (char *); + +void g (char *s) +{ + SCOPE char a[8]; + __builtin_strncpy (a, s, sizeof a); + __builtin_memset (a, 0, sizeof a); + frob (a); +} + +void h (char *s) +{ + SCOPE char a[8]; + __builtin_memset (a, 0, sizeof a); + __builtin_strncpy (a, s, sizeof a); + frob (a); +} + +void i (char *s) +{ + SCOPE char a[8]; + __builtin_strncpy (a, s, sizeof a); + __builtin_memset (a, 0, sizeof a - 5); + frob (a); +} + +void j (char *s) +{ + SCOPE char a[8]; + __builtin_memset (a, 0, sizeof a); + __builtin_strncpy (a, s, sizeof a - 5); + frob (a); +} + +void l (char *s) +{ + SCOPE char a[8]; + __builtin_strncpy (a, s, sizeof a); + __builtin_memset (a + 2, 0, sizeof a - 2); + frob (a); +} + +void m (char *s) +{ + SCOPE char a[8]; + __builtin_memset (a, 0, sizeof a); + __builtin_strncpy (a + 2, s, sizeof a - 2); + frob (a); +} + +/* { dg-final { scan-tree-dump-times "Deleted dead call" 2 "dse1" } } */ +/* { dg-final { scan-tree-dump-times "Trimming statement " 4 "dse1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-38.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-38.c new file mode 100644 index 0000000..7ae33bf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-38.c @@ -0,0 +1,12 @@ +/* { dg-options "-O2 -fdump-tree-dse-details -fno-tree-fre" } */ + + +/* This changes the scope of the destination object and exposes + missed optimizations in DSE. */ +#define SCOPE extern +#include "ssa-dse-37.c" + +/* { dg-final { scan-tree-dump-times "Deleted dead call" 2 "dse1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "Trimming statement " 4 "dse1" { xfail *-*-* } } } */ + + diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 9bdcf9a..5b7c4fc 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -113,10 +113,10 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write) case BUILT_IN_MEMCPY_CHK: case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMSET_CHK: + case BUILT_IN_STRNCPY: + case BUILT_IN_STRNCPY_CHK: { - tree size = NULL_TREE; - if (gimple_call_num_args (stmt) == 3) - size = gimple_call_arg (stmt, 2); + tree size = gimple_call_arg (stmt, 2); tree ptr = gimple_call_arg (stmt, 0); ao_ref_init_from_ptr_and_size (write, ptr, size); return true; @@ -469,8 +469,10 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt) { case BUILT_IN_MEMCPY: case BUILT_IN_MEMMOVE: + case BUILT_IN_STRNCPY: case BUILT_IN_MEMCPY_CHK: case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_STRNCPY_CHK: { int head_trim, tail_trim; compute_trims (ref, live, &head_trim, &tail_trim, stmt); @@ -966,9 +968,11 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi) { case BUILT_IN_MEMCPY: case BUILT_IN_MEMMOVE: + case BUILT_IN_STRNCPY: case BUILT_IN_MEMSET: case BUILT_IN_MEMCPY_CHK: case BUILT_IN_MEMMOVE_CHK: + case BUILT_IN_STRNCPY_CHK: case BUILT_IN_MEMSET_CHK: { /* Occasionally calls with an explicit length of zero -- cgit v1.1 From 1acf0246c8778feb2ad0056029991f90f9d48b57 Mon Sep 17 00:00:00 2001 From: Bill Seurer Date: Fri, 19 Jul 2019 18:33:59 +0000 Subject: [PATCH, rs6000] Split up rs6000.c. The source file rs6000.c has grown to unreasonable size and is being split up into several smaller source files. This should improve compilation speed for building gcc. This is the second of several patches to do this and moves most of the function call and builtin code to a new source file. Bootstrapped and tested on powerpc64le-unknown-linux-gnu and powerpc64-unknown-linux-gnu with no regressions. Is this ok for trunk? 2019-07-17 Bill Seurer * config/rs6000/rs6000.c (builtin_description, cpu_is_info, cpu_supports_info, builtin_hash_struct, builtin_hasher, builtin_hash_table, rs6000_builtin_info_type, rs6000_builtin_info, rs6000_aggregate_candidate, rs6000_discover_homogeneous_aggregate, rs6000_return_in_memory, rs6000_return_in_msb, call_ABI_of_interest, init_cumulative_args, rs6000_promote_function_mode, rs6000_must_pass_in_stack, is_complex_IBM_long_double, abi_v4_pass_in_fpr, rs6000_function_arg_padding, rs6000_function_arg_boundary, rs6000_parm_offset, rs6000_parm_start, rs6000_arg_size, rs6000_darwin64_record_arg_advance_flush, rs6000_darwin64_record_arg_advance_recurse, rs6000_darwin64_struct_check_p, rs6000_function_arg_advance_1, rs6000_function_arg_advance, rs6000_darwin64_record_arg_flush, rs6000_darwin64_record_arg_recurse, rs6000_darwin64_record_arg, rs6000_mixed_function_arg, rs6000_psave_function_arg, rs6000_finish_function_arg, rs6000_function_arg, rs6000_arg_partial_bytes, rs6000_pass_by_reference, rs6000_parm_needs_stack, rs6000_function_parms_need_stack, rs6000_reg_parm_stack_space, rs6000_move_block_from_reg, setup_incoming_varargs, rs6000_build_builtin_va_list, rs6000_va_start, rs6000_gimplify_va_arg, def_builtin, bdesc_3arg, bdesc_dst, bdesc_2arg, bdesc_altivec_preds, bdesc_abs, bdesc_1arg, bdesc_0arg, bdesc_htm, rs6000_overloaded_builtin_p, rs6000_overloaded_builtin_name, rs6000_expand_zeroop_builtin, rs6000_expand_mtfsf_builtin, rs6000_expand_mtfsb_builtin, rs6000_expand_set_fpscr_rn_builtin, rs6000_expand_set_fpscr_drn_builtin, rs6000_expand_unop_builtin, altivec_expand_abs_builtin, rs6000_expand_binop_builtin, altivec_expand_predicate_builtin, swap_endian_selector_for_mode, altivec_expand_lv_builtin, altivec_expand_stxvl_builtin, altivec_expand_stv_builtin, htm_spr_num, rs6000_htm_spr_icode, htm_expand_builtin, cpu_expand_builtin, rs6000_expand_ternop_builtin, altivec_expand_dst_builtin, altivec_expand_vec_init_builtin, get_element_number, altivec_expand_vec_set_builtin, altivec_expand_vec_ext_builtin, altivec_expand_builtin, rs6000_builtin_is_supported_p, rs6000_invalid_builtin, rs6000_fold_builtin, rs6000_builtin_valid_without_lhs, fold_build_vec_cmp, fold_compare_helper, fold_mergehl_helper, fold_mergeeo_helper, rs6000_gimple_fold_builtin, rs6000_expand_builtin, rs6000_vector_type, rs6000_init_builtins, rs6000_builtin_decl, altivec_init_builtins, htm_init_builtins, builtin_function_type, rs6000_common_init_builtins, rs6000_internal_arg_pointer, rs6000_output_mi_thunk): Move to rs6000-call.c. * config/rs6000/rs6000-call.c (builtin_description, cpu_is_info, cpu_supports_info, builtin_hash_struct, builtin_hasher, builtin_hash_table, rs6000_builtin_info_type, rs6000_builtin_info, rs6000_aggregate_candidate, rs6000_discover_homogeneous_aggregate, rs6000_return_in_memory, rs6000_return_in_msb, call_ABI_of_interest, init_cumulative_args, rs6000_promote_function_mode, rs6000_must_pass_in_stack, is_complex_IBM_long_double, abi_v4_pass_in_fpr, rs6000_function_arg_padding, rs6000_function_arg_boundary, rs6000_parm_offset, rs6000_parm_start, rs6000_arg_size, rs6000_darwin64_record_arg_advance_flush, rs6000_darwin64_record_arg_advance_recurse, rs6000_darwin64_struct_check_p, rs6000_function_arg_advance_1, rs6000_function_arg_advance, rs6000_darwin64_record_arg_flush, rs6000_darwin64_record_arg_recurse, rs6000_darwin64_record_arg, rs6000_mixed_function_arg, rs6000_psave_function_arg, rs6000_finish_function_arg, rs6000_function_arg, rs6000_arg_partial_bytes, rs6000_pass_by_reference, rs6000_parm_needs_stack, rs6000_function_parms_need_stack, rs6000_reg_parm_stack_space, rs6000_move_block_from_reg, setup_incoming_varargs, rs6000_build_builtin_va_list, rs6000_va_start, rs6000_gimplify_va_arg, def_builtin, bdesc_3arg, bdesc_dst, bdesc_2arg, bdesc_altivec_preds, bdesc_abs, bdesc_1arg, bdesc_0arg, bdesc_htm, rs6000_overloaded_builtin_p, rs6000_overloaded_builtin_name, rs6000_expand_zeroop_builtin, rs6000_expand_mtfsf_builtin, rs6000_expand_mtfsb_builtin, rs6000_expand_set_fpscr_rn_builtin, rs6000_expand_set_fpscr_drn_builtin, rs6000_expand_unop_builtin, altivec_expand_abs_builtin, rs6000_expand_binop_builtin, altivec_expand_predicate_builtin, swap_endian_selector_for_mode, altivec_expand_lv_builtin, altivec_expand_stxvl_builtin, altivec_expand_stv_builtin, htm_spr_num, rs6000_htm_spr_icode, htm_expand_builtin, cpu_expand_builtin, rs6000_expand_ternop_builtin, altivec_expand_dst_builtin, altivec_expand_vec_init_builtin, get_element_number, altivec_expand_vec_set_builtin, altivec_expand_vec_ext_builtin, altivec_expand_builtin, rs6000_builtin_is_supported_p, rs6000_invalid_builtin, rs6000_fold_builtin, rs6000_builtin_valid_without_lhs, fold_build_vec_cmp, fold_compare_helper, fold_mergehl_helper, fold_mergeeo_helper, rs6000_gimple_fold_builtin, rs6000_expand_builtin, rs6000_vector_type, rs6000_init_builtins, rs6000_builtin_decl, altivec_init_builtins, htm_init_builtins, builtin_function_type, rs6000_common_init_builtins, rs6000_internal_arg_pointer, rs6000_output_mi_thunk: Move to here from rs6000.c. * config/rs6000/rs6000-internal.h: (rs6000_darwin64_struct_check_p, rs6000_discover_homogeneous_aggregate, rs6000_output_mi_thunk, rs6000_output_addr_const_extra, rs6000_gimple_fold_builtin, rs6000_invalid_builtin, rs6000_build_builtin_va_list, rs6000_va_start, rs6000_gimplify_va_arg, rs6000_promote_function_mode, rs6000_return_in_memory, rs6000_return_in_msb, rs6000_pass_by_reference, setup_incoming_varargs, rs6000_function_arg_boundary, rs6000_must_pass_in_stack, rs6000_arg_partial_bytes, rs6000_function_arg_advance, rs6000_function_arg_padding, rs6000_function_arg, rs6000_darwin64_record_arg, rs6000_internal_arg_pointer, rs6000_init_builtins, rs6000_builtin_decl, rs6000_expand_builtin, rs6000_fold_builtin, rs6000_passes_ieee128, rs6000_passes_float, rs6000_passes_long_double, rs6000_passes_vector, rs6000_returns_struct, cpu_builtin_p, tree builtin_mode_to_type, altivec_builtin_mask_for_load) Add declarations. * config/rs6000/t-rs6000: Add new source file rs6000-call.c. * config/config.gcc: Add new source file rs6000-call.c to garbage collector and extra_objs. From-SVN: r273607 --- gcc/ChangeLog | 110 + gcc/config.gcc | 8 +- gcc/config/rs6000/rs6000-call.c | 8124 +++++++++++++++++++++++++++++++++ gcc/config/rs6000/rs6000-internal.h | 73 + gcc/config/rs6000/rs6000.c | 8436 +---------------------------------- gcc/config/rs6000/t-rs6000 | 4 + 6 files changed, 8508 insertions(+), 8247 deletions(-) create mode 100644 gcc/config/rs6000/rs6000-call.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d8f6004..a9c2450 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,113 @@ +2019-07-19 Bill Seurer + + * config/rs6000/rs6000.c (builtin_description, cpu_is_info, + cpu_supports_info, builtin_hash_struct, builtin_hasher, + builtin_hash_table, rs6000_builtin_info_type, rs6000_builtin_info, + rs6000_aggregate_candidate, rs6000_discover_homogeneous_aggregate, + rs6000_return_in_memory, rs6000_return_in_msb, call_ABI_of_interest, + init_cumulative_args, rs6000_promote_function_mode, + rs6000_must_pass_in_stack, is_complex_IBM_long_double, + abi_v4_pass_in_fpr, rs6000_function_arg_padding, + rs6000_function_arg_boundary, rs6000_parm_offset, + rs6000_parm_start, rs6000_arg_size, + rs6000_darwin64_record_arg_advance_flush, + rs6000_darwin64_record_arg_advance_recurse, + rs6000_darwin64_struct_check_p, rs6000_function_arg_advance_1, + rs6000_function_arg_advance, rs6000_darwin64_record_arg_flush, + rs6000_darwin64_record_arg_recurse, rs6000_darwin64_record_arg, + rs6000_mixed_function_arg, rs6000_psave_function_arg, + rs6000_finish_function_arg, rs6000_function_arg, + rs6000_arg_partial_bytes, rs6000_pass_by_reference, + rs6000_parm_needs_stack, rs6000_function_parms_need_stack, + rs6000_reg_parm_stack_space, rs6000_move_block_from_reg, + setup_incoming_varargs, rs6000_build_builtin_va_list, rs6000_va_start, + rs6000_gimplify_va_arg, def_builtin, bdesc_3arg, bdesc_dst, + bdesc_2arg, bdesc_altivec_preds, bdesc_abs, bdesc_1arg, bdesc_0arg, + bdesc_htm, rs6000_overloaded_builtin_p, rs6000_overloaded_builtin_name, + rs6000_expand_zeroop_builtin, rs6000_expand_mtfsf_builtin, + rs6000_expand_mtfsb_builtin, rs6000_expand_set_fpscr_rn_builtin, + rs6000_expand_set_fpscr_drn_builtin, rs6000_expand_unop_builtin, + altivec_expand_abs_builtin, rs6000_expand_binop_builtin, + altivec_expand_predicate_builtin, swap_endian_selector_for_mode, + altivec_expand_lv_builtin, altivec_expand_stxvl_builtin, + altivec_expand_stv_builtin, htm_spr_num, rs6000_htm_spr_icode, + htm_expand_builtin, cpu_expand_builtin, rs6000_expand_ternop_builtin, + altivec_expand_dst_builtin, altivec_expand_vec_init_builtin, + get_element_number, altivec_expand_vec_set_builtin, + altivec_expand_vec_ext_builtin, altivec_expand_builtin, + rs6000_builtin_is_supported_p, rs6000_invalid_builtin, + rs6000_fold_builtin, rs6000_builtin_valid_without_lhs, + fold_build_vec_cmp, fold_compare_helper, fold_mergehl_helper, + fold_mergeeo_helper, rs6000_gimple_fold_builtin, + rs6000_expand_builtin, rs6000_vector_type, + rs6000_init_builtins, rs6000_builtin_decl, altivec_init_builtins, + htm_init_builtins, builtin_function_type, rs6000_common_init_builtins, + rs6000_internal_arg_pointer, rs6000_output_mi_thunk): Move + to rs6000-call.c. + * config/rs6000/rs6000-call.c (builtin_description, cpu_is_info, + cpu_supports_info, builtin_hash_struct, builtin_hasher, + builtin_hash_table, rs6000_builtin_info_type, rs6000_builtin_info, + rs6000_aggregate_candidate, rs6000_discover_homogeneous_aggregate, + rs6000_return_in_memory, rs6000_return_in_msb, call_ABI_of_interest, + init_cumulative_args, rs6000_promote_function_mode, + rs6000_must_pass_in_stack, is_complex_IBM_long_double, + abi_v4_pass_in_fpr, rs6000_function_arg_padding, + rs6000_function_arg_boundary, rs6000_parm_offset, + rs6000_parm_start, rs6000_arg_size, + rs6000_darwin64_record_arg_advance_flush, + rs6000_darwin64_record_arg_advance_recurse, + rs6000_darwin64_struct_check_p, rs6000_function_arg_advance_1, + rs6000_function_arg_advance, rs6000_darwin64_record_arg_flush, + rs6000_darwin64_record_arg_recurse, rs6000_darwin64_record_arg, + rs6000_mixed_function_arg, rs6000_psave_function_arg, + rs6000_finish_function_arg, rs6000_function_arg, + rs6000_arg_partial_bytes, rs6000_pass_by_reference, + rs6000_parm_needs_stack, rs6000_function_parms_need_stack, + rs6000_reg_parm_stack_space, rs6000_move_block_from_reg, + setup_incoming_varargs, rs6000_build_builtin_va_list, rs6000_va_start, + rs6000_gimplify_va_arg, def_builtin, bdesc_3arg, bdesc_dst, + bdesc_2arg, bdesc_altivec_preds, bdesc_abs, bdesc_1arg, bdesc_0arg, + bdesc_htm, rs6000_overloaded_builtin_p, rs6000_overloaded_builtin_name, + rs6000_expand_zeroop_builtin, rs6000_expand_mtfsf_builtin, + rs6000_expand_mtfsb_builtin, rs6000_expand_set_fpscr_rn_builtin, + rs6000_expand_set_fpscr_drn_builtin, rs6000_expand_unop_builtin, + altivec_expand_abs_builtin, rs6000_expand_binop_builtin, + altivec_expand_predicate_builtin, swap_endian_selector_for_mode, + altivec_expand_lv_builtin, altivec_expand_stxvl_builtin, + altivec_expand_stv_builtin, htm_spr_num, rs6000_htm_spr_icode, + htm_expand_builtin, cpu_expand_builtin, rs6000_expand_ternop_builtin, + altivec_expand_dst_builtin, altivec_expand_vec_init_builtin, + get_element_number, altivec_expand_vec_set_builtin, + altivec_expand_vec_ext_builtin, altivec_expand_builtin, + rs6000_builtin_is_supported_p, rs6000_invalid_builtin, + rs6000_fold_builtin, rs6000_builtin_valid_without_lhs, + fold_build_vec_cmp, fold_compare_helper, fold_mergehl_helper, + fold_mergeeo_helper, rs6000_gimple_fold_builtin, + rs6000_expand_builtin, rs6000_vector_type, + rs6000_init_builtins, rs6000_builtin_decl, altivec_init_builtins, + htm_init_builtins, builtin_function_type, rs6000_common_init_builtins, + rs6000_internal_arg_pointer, rs6000_output_mi_thunk: Move + to here from rs6000.c. + * config/rs6000/rs6000-internal.h: (rs6000_darwin64_struct_check_p, + rs6000_discover_homogeneous_aggregate, rs6000_output_mi_thunk, + rs6000_output_addr_const_extra, rs6000_gimple_fold_builtin, + rs6000_invalid_builtin, rs6000_build_builtin_va_list, rs6000_va_start, + rs6000_gimplify_va_arg, rs6000_promote_function_mode, + rs6000_return_in_memory, rs6000_return_in_msb, + rs6000_pass_by_reference, setup_incoming_varargs, + rs6000_function_arg_boundary, rs6000_must_pass_in_stack, + rs6000_arg_partial_bytes, rs6000_function_arg_advance, + rs6000_function_arg_padding, rs6000_function_arg, + rs6000_darwin64_record_arg, rs6000_internal_arg_pointer, + rs6000_init_builtins, rs6000_builtin_decl, rs6000_expand_builtin, + rs6000_fold_builtin, rs6000_passes_ieee128, rs6000_passes_float, + rs6000_passes_long_double, rs6000_passes_vector, + rs6000_returns_struct, cpu_builtin_p, tree builtin_mode_to_type, + altivec_builtin_mask_for_load) Add declarations. + * config/rs6000/t-rs6000: Add new source file rs6000-call.c. + * config/config.gcc: Add new source file rs6000-call.c to garbage + collector and extra_objs. + 2019-07-19 Jeff Law * tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle diff --git a/gcc/config.gcc b/gcc/config.gcc index c281c41..446a852 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -499,7 +499,7 @@ or1k*-*-*) ;; powerpc*-*-*) cpu_type=rs6000 - extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o" + extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o rs6000-call.o" extra_headers="ppc-asm.h altivec.h htmintrin.h htmxlintrin.h" extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h" extra_headers="${extra_headers} xmmintrin.h mm_malloc.h emmintrin.h" @@ -513,7 +513,7 @@ powerpc*-*-*) ;; esac extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt" - target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.c" + target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.c \$(srcdir)/config/rs6000/rs6000-call.c" ;; pru-*-*) cpu_type=pru @@ -525,8 +525,8 @@ riscv*) ;; rs6000*-*-*) extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt" - extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o" - target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.c" + extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o rs6000-call.o" + target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.c \$(srcdir)/config/rs6000/rs6000-call.c" ;; sparc*-*-*) cpu_type=sparc diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c new file mode 100644 index 0000000..ff48ff1 --- /dev/null +++ b/gcc/config/rs6000/rs6000-call.c @@ -0,0 +1,8124 @@ +/* Subroutines used to generate function calls and handle built-in + instructions on IBM RS/6000. + Copyright (C) 1991-2019 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 + . */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "rtl.h" +#include "tree.h" +#include "memmodel.h" +#include "gimple.h" +#include "cfghooks.h" +#include "cfgloop.h" +#include "df.h" +#include "tm_p.h" +#include "stringpool.h" +#include "expmed.h" +#include "optabs.h" +#include "regs.h" +#include "ira.h" +#include "recog.h" +#include "cgraph.h" +#include "diagnostic-core.h" +#include "insn-attr.h" +#include "flags.h" +#include "alias.h" +#include "fold-const.h" +#include "attribs.h" +#include "stor-layout.h" +#include "calls.h" +#include "print-tree.h" +#include "varasm.h" +#include "explow.h" +#include "expr.h" +#include "output.h" +#include "common/common-target.h" +#include "langhooks.h" +#include "gimplify.h" +#include "gimple-fold.h" +#include "gimple-iterator.h" +#include "gimple-ssa.h" +#include "builtins.h" +#include "tree-vector-builder.h" +#if TARGET_XCOFF +#include "xcoffout.h" /* get declarations of xcoff_*_section_name */ +#endif +#include "ppc-auxv.h" +#include "tree-ssa-propagate.h" +#include "tree-vrp.h" +#include "tree-ssanames.h" +#include "targhooks.h" + +#include "rs6000-internal.h" + +#if TARGET_MACHO +#include "gstab.h" /* for N_SLINE */ +#include "dbxout.h" /* dbxout_ */ +#endif + +#ifndef TARGET_PROFILE_KERNEL +#define TARGET_PROFILE_KERNEL 0 +#endif + +struct builtin_description +{ + const HOST_WIDE_INT mask; + const enum insn_code icode; + const char *const name; + const enum rs6000_builtins code; +}; + +/* Used by __builtin_cpu_is(), mapping from PLATFORM names to values. */ +static const struct +{ + const char *cpu; + unsigned int cpuid; +} cpu_is_info[] = { + { "power9", PPC_PLATFORM_POWER9 }, + { "power8", PPC_PLATFORM_POWER8 }, + { "power7", PPC_PLATFORM_POWER7 }, + { "power6x", PPC_PLATFORM_POWER6X }, + { "power6", PPC_PLATFORM_POWER6 }, + { "power5+", PPC_PLATFORM_POWER5_PLUS }, + { "power5", PPC_PLATFORM_POWER5 }, + { "ppc970", PPC_PLATFORM_PPC970 }, + { "power4", PPC_PLATFORM_POWER4 }, + { "ppca2", PPC_PLATFORM_PPCA2 }, + { "ppc476", PPC_PLATFORM_PPC476 }, + { "ppc464", PPC_PLATFORM_PPC464 }, + { "ppc440", PPC_PLATFORM_PPC440 }, + { "ppc405", PPC_PLATFORM_PPC405 }, + { "ppc-cell-be", PPC_PLATFORM_CELL_BE } +}; + +/* Used by __builtin_cpu_supports(), mapping from HWCAP names to masks. */ +static const struct +{ + const char *hwcap; + int mask; + unsigned int id; +} cpu_supports_info[] = { + /* AT_HWCAP masks. */ + { "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0 }, + { "altivec", PPC_FEATURE_HAS_ALTIVEC, 0 }, + { "arch_2_05", PPC_FEATURE_ARCH_2_05, 0 }, + { "arch_2_06", PPC_FEATURE_ARCH_2_06, 0 }, + { "archpmu", PPC_FEATURE_PERFMON_COMPAT, 0 }, + { "booke", PPC_FEATURE_BOOKE, 0 }, + { "cellbe", PPC_FEATURE_CELL_BE, 0 }, + { "dfp", PPC_FEATURE_HAS_DFP, 0 }, + { "efpdouble", PPC_FEATURE_HAS_EFP_DOUBLE, 0 }, + { "efpsingle", PPC_FEATURE_HAS_EFP_SINGLE, 0 }, + { "fpu", PPC_FEATURE_HAS_FPU, 0 }, + { "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, 0 }, + { "mmu", PPC_FEATURE_HAS_MMU, 0 }, + { "notb", PPC_FEATURE_NO_TB, 0 }, + { "pa6t", PPC_FEATURE_PA6T, 0 }, + { "power4", PPC_FEATURE_POWER4, 0 }, + { "power5", PPC_FEATURE_POWER5, 0 }, + { "power5+", PPC_FEATURE_POWER5_PLUS, 0 }, + { "power6x", PPC_FEATURE_POWER6_EXT, 0 }, + { "ppc32", PPC_FEATURE_32, 0 }, + { "ppc601", PPC_FEATURE_601_INSTR, 0 }, + { "ppc64", PPC_FEATURE_64, 0 }, + { "ppcle", PPC_FEATURE_PPC_LE, 0 }, + { "smt", PPC_FEATURE_SMT, 0 }, + { "spe", PPC_FEATURE_HAS_SPE, 0 }, + { "true_le", PPC_FEATURE_TRUE_LE, 0 }, + { "ucache", PPC_FEATURE_UNIFIED_CACHE, 0 }, + { "vsx", PPC_FEATURE_HAS_VSX, 0 }, + + /* AT_HWCAP2 masks. */ + { "arch_2_07", PPC_FEATURE2_ARCH_2_07, 1 }, + { "dscr", PPC_FEATURE2_HAS_DSCR, 1 }, + { "ebb", PPC_FEATURE2_HAS_EBB, 1 }, + { "htm", PPC_FEATURE2_HAS_HTM, 1 }, + { "htm-nosc", PPC_FEATURE2_HTM_NOSC, 1 }, + { "htm-no-suspend", PPC_FEATURE2_HTM_NO_SUSPEND, 1 }, + { "isel", PPC_FEATURE2_HAS_ISEL, 1 }, + { "tar", PPC_FEATURE2_HAS_TAR, 1 }, + { "vcrypto", PPC_FEATURE2_HAS_VEC_CRYPTO, 1 }, + { "arch_3_00", PPC_FEATURE2_ARCH_3_00, 1 }, + { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 }, + { "darn", PPC_FEATURE2_DARN, 1 }, + { "scv", PPC_FEATURE2_SCV, 1 } +}; + +static void altivec_init_builtins (void); +static tree builtin_function_type (machine_mode, machine_mode, + machine_mode, machine_mode, + enum rs6000_builtins, const char *name); +static void rs6000_common_init_builtins (void); +static void htm_init_builtins (void); + + +/* Hash table to keep track of the argument types for builtin functions. */ + +struct GTY((for_user)) builtin_hash_struct +{ + tree type; + machine_mode mode[4]; /* return value + 3 arguments. */ + unsigned char uns_p[4]; /* and whether the types are unsigned. */ +}; + +struct builtin_hasher : ggc_ptr_hash +{ + static hashval_t hash (builtin_hash_struct *); + static bool equal (builtin_hash_struct *, builtin_hash_struct *); +}; + +static GTY (()) hash_table *builtin_hash_table; + +/* Hash function for builtin functions with up to 3 arguments and a return + type. */ +hashval_t +builtin_hasher::hash (builtin_hash_struct *bh) +{ + unsigned ret = 0; + int i; + + for (i = 0; i < 4; i++) + { + ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]); + ret = (ret * 2) + bh->uns_p[i]; + } + + return ret; +} + +/* Compare builtin hash entries H1 and H2 for equivalence. */ +bool +builtin_hasher::equal (builtin_hash_struct *p1, builtin_hash_struct *p2) +{ + return ((p1->mode[0] == p2->mode[0]) + && (p1->mode[1] == p2->mode[1]) + && (p1->mode[2] == p2->mode[2]) + && (p1->mode[3] == p2->mode[3]) + && (p1->uns_p[0] == p2->uns_p[0]) + && (p1->uns_p[1] == p2->uns_p[1]) + && (p1->uns_p[2] == p2->uns_p[2]) + && (p1->uns_p[3] == p2->uns_p[3])); +} + + +/* Table that classifies rs6000 builtin functions (pure, const, etc.). */ +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + +struct rs6000_builtin_info_type { + const char *name; + const enum insn_code icode; + const HOST_WIDE_INT mask; + const unsigned attr; +}; + +const struct rs6000_builtin_info_type rs6000_builtin_info[] = +{ +#include "rs6000-builtin.def" +}; + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + + +/* Nonzero if we can use a floating-point register to pass this arg. */ +#define USE_FP_FOR_ARG_P(CUM,MODE) \ + (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE) \ + && (CUM)->fregno <= FP_ARG_MAX_REG \ + && TARGET_HARD_FLOAT) + +/* Nonzero if we can use an AltiVec register to pass this arg. */ +#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,NAMED) \ + (ALTIVEC_OR_VSX_VECTOR_MODE (MODE) \ + && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \ + && TARGET_ALTIVEC_ABI \ + && (NAMED)) + +/* Walk down the type tree of TYPE counting consecutive base elements. + If *MODEP is VOIDmode, then set it to the first valid floating point + or vector type. If a non-floating point or vector type is found, or + if a floating point or vector type that doesn't match a non-VOIDmode + *MODEP is found, then return -1, otherwise return the count in the + sub-tree. */ + +static int +rs6000_aggregate_candidate (const_tree type, machine_mode *modep) +{ + machine_mode mode; + HOST_WIDE_INT size; + + switch (TREE_CODE (type)) + { + case REAL_TYPE: + mode = TYPE_MODE (type); + if (!SCALAR_FLOAT_MODE_P (mode)) + return -1; + + if (*modep == VOIDmode) + *modep = mode; + + if (*modep == mode) + return 1; + + break; + + case COMPLEX_TYPE: + mode = TYPE_MODE (TREE_TYPE (type)); + if (!SCALAR_FLOAT_MODE_P (mode)) + return -1; + + if (*modep == VOIDmode) + *modep = mode; + + if (*modep == mode) + return 2; + + break; + + case VECTOR_TYPE: + if (!TARGET_ALTIVEC_ABI || !TARGET_ALTIVEC) + return -1; + + /* Use V4SImode as representative of all 128-bit vector types. */ + size = int_size_in_bytes (type); + switch (size) + { + case 16: + mode = V4SImode; + break; + default: + return -1; + } + + if (*modep == VOIDmode) + *modep = mode; + + /* Vector modes are considered to be opaque: two vectors are + equivalent for the purposes of being homogeneous aggregates + if they are the same size. */ + if (*modep == mode) + return 1; + + break; + + case ARRAY_TYPE: + { + int count; + tree index = TYPE_DOMAIN (type); + + /* Can't handle incomplete types nor sizes that are not + fixed. */ + if (!COMPLETE_TYPE_P (type) + || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + return -1; + + count = rs6000_aggregate_candidate (TREE_TYPE (type), modep); + if (count == -1 + || !index + || !TYPE_MAX_VALUE (index) + || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) + || !TYPE_MIN_VALUE (index) + || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) + || count < 0) + return -1; + + count *= (1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) + - tree_to_uhwi (TYPE_MIN_VALUE (index))); + + /* There must be no padding. */ + if (wi::to_wide (TYPE_SIZE (type)) + != count * GET_MODE_BITSIZE (*modep)) + return -1; + + return count; + } + + case RECORD_TYPE: + { + int count = 0; + int sub_count; + tree field; + + /* Can't handle incomplete types nor sizes that are not + fixed. */ + if (!COMPLETE_TYPE_P (type) + || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + return -1; + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + + sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep); + if (sub_count < 0) + return -1; + count += sub_count; + } + + /* There must be no padding. */ + if (wi::to_wide (TYPE_SIZE (type)) + != count * GET_MODE_BITSIZE (*modep)) + return -1; + + return count; + } + + case UNION_TYPE: + case QUAL_UNION_TYPE: + { + /* These aren't very interesting except in a degenerate case. */ + int count = 0; + int sub_count; + tree field; + + /* Can't handle incomplete types nor sizes that are not + fixed. */ + if (!COMPLETE_TYPE_P (type) + || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + return -1; + + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + + sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep); + if (sub_count < 0) + return -1; + count = count > sub_count ? count : sub_count; + } + + /* There must be no padding. */ + if (wi::to_wide (TYPE_SIZE (type)) + != count * GET_MODE_BITSIZE (*modep)) + return -1; + + return count; + } + + default: + break; + } + + return -1; +} + +/* If an argument, whose type is described by TYPE and MODE, is a homogeneous + float or vector aggregate that shall be passed in FP/vector registers + according to the ELFv2 ABI, return the homogeneous element mode in + *ELT_MODE and the number of elements in *N_ELTS, and return TRUE. + + Otherwise, set *ELT_MODE to MODE and *N_ELTS to 1, and return FALSE. */ + +bool +rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type, + machine_mode *elt_mode, + int *n_elts) +{ + /* Note that we do not accept complex types at the top level as + homogeneous aggregates; these types are handled via the + targetm.calls.split_complex_arg mechanism. Complex types + can be elements of homogeneous aggregates, however. */ + if (TARGET_HARD_FLOAT && DEFAULT_ABI == ABI_ELFv2 && type + && AGGREGATE_TYPE_P (type)) + { + machine_mode field_mode = VOIDmode; + int field_count = rs6000_aggregate_candidate (type, &field_mode); + + if (field_count > 0) + { + int reg_size = ALTIVEC_OR_VSX_VECTOR_MODE (field_mode) ? 16 : 8; + int field_size = ROUND_UP (GET_MODE_SIZE (field_mode), reg_size); + + /* The ELFv2 ABI allows homogeneous aggregates to occupy + up to AGGR_ARG_NUM_REG registers. */ + if (field_count * field_size <= AGGR_ARG_NUM_REG * reg_size) + { + if (elt_mode) + *elt_mode = field_mode; + if (n_elts) + *n_elts = field_count; + return true; + } + } + } + + if (elt_mode) + *elt_mode = mode; + if (n_elts) + *n_elts = 1; + return false; +} + +/* Return a nonzero value to say to return the function value in + memory, just as large structures are always returned. TYPE will be + the data type of the value, and FNTYPE will be the type of the + function doing the returning, or @code{NULL} for libcalls. + + The AIX ABI for the RS/6000 specifies that all structures are + returned in memory. The Darwin ABI does the same. + + For the Darwin 64 Bit ABI, a function result can be returned in + registers or in memory, depending on the size of the return data + type. If it is returned in registers, the value occupies the same + registers as it would if it were the first and only function + argument. Otherwise, the function places its result in memory at + the location pointed to by GPR3. + + The SVR4 ABI specifies that structures <= 8 bytes are returned in r3/r4, + but a draft put them in memory, and GCC used to implement the draft + instead of the final standard. Therefore, aix_struct_return + controls this instead of DEFAULT_ABI; V.4 targets needing backward + compatibility can change DRAFT_V4_STRUCT_RET to override the + default, and -m switches get the final word. See + rs6000_option_override_internal for more details. + + The PPC32 SVR4 ABI uses IEEE double extended for long double, if 128-bit + long double support is enabled. These values are returned in memory. + + int_size_in_bytes returns -1 for variable size objects, which go in + memory always. The cast to unsigned makes -1 > 8. */ + +bool +rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) +{ + /* For the Darwin64 ABI, test if we can fit the return value in regs. */ + if (TARGET_MACHO + && rs6000_darwin64_abi + && TREE_CODE (type) == RECORD_TYPE + && int_size_in_bytes (type) > 0) + { + CUMULATIVE_ARGS valcum; + rtx valret; + + valcum.words = 0; + valcum.fregno = FP_ARG_MIN_REG; + valcum.vregno = ALTIVEC_ARG_MIN_REG; + /* Do a trial code generation as if this were going to be passed + as an argument; if any part goes in memory, we return NULL. */ + valret = rs6000_darwin64_record_arg (&valcum, type, true, true); + if (valret) + return false; + /* Otherwise fall through to more conventional ABI rules. */ + } + + /* The ELFv2 ABI returns homogeneous VFP aggregates in registers */ + if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (type), type, + NULL, NULL)) + return false; + + /* The ELFv2 ABI returns aggregates up to 16B in registers */ + if (DEFAULT_ABI == ABI_ELFv2 && AGGREGATE_TYPE_P (type) + && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) <= 16) + return false; + + if (AGGREGATE_TYPE_P (type) + && (aix_struct_return + || (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8)) + return true; + + /* Allow -maltivec -mabi=no-altivec without warning. Altivec vector + modes only exist for GCC vector types if -maltivec. */ + if (TARGET_32BIT && !TARGET_ALTIVEC_ABI + && ALTIVEC_VECTOR_MODE (TYPE_MODE (type))) + return false; + + /* Return synthetic vectors in memory. */ + if (TREE_CODE (type) == VECTOR_TYPE + && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8)) + { + static bool warned_for_return_big_vectors = false; + if (!warned_for_return_big_vectors) + { + warning (OPT_Wpsabi, "GCC vector returned by reference: " + "non-standard ABI extension with no compatibility " + "guarantee"); + warned_for_return_big_vectors = true; + } + return true; + } + + if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD + && FLOAT128_IEEE_P (TYPE_MODE (type))) + return true; + + return false; +} + +/* Specify whether values returned in registers should be at the most + significant end of a register. We want aggregates returned by + value to match the way aggregates are passed to functions. */ + +bool +rs6000_return_in_msb (const_tree valtype) +{ + return (DEFAULT_ABI == ABI_ELFv2 + && BYTES_BIG_ENDIAN + && AGGREGATE_TYPE_P (valtype) + && (rs6000_function_arg_padding (TYPE_MODE (valtype), valtype) + == PAD_UPWARD)); +} + +#ifdef HAVE_AS_GNU_ATTRIBUTE +/* Return TRUE if a call to function FNDECL may be one that + potentially affects the function calling ABI of the object file. */ + +static bool +call_ABI_of_interest (tree fndecl) +{ + if (rs6000_gnu_attr && symtab->state == EXPANSION) + { + struct cgraph_node *c_node; + + /* Libcalls are always interesting. */ + if (fndecl == NULL_TREE) + return true; + + /* Any call to an external function is interesting. */ + if (DECL_EXTERNAL (fndecl)) + return true; + + /* Interesting functions that we are emitting in this object file. */ + c_node = cgraph_node::get (fndecl); + c_node = c_node->ultimate_alias_target (); + return !c_node->only_called_directly_p (); + } + return false; +} +#endif + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0 and RETURN_MODE the return value mode. + + For incoming args we set the number of arguments in the prototype large + so we never return a PARALLEL. */ + +void +init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, + rtx libname ATTRIBUTE_UNUSED, int incoming, + int libcall, int n_named_args, + tree fndecl, + machine_mode return_mode ATTRIBUTE_UNUSED) +{ + static CUMULATIVE_ARGS zero_cumulative; + + *cum = zero_cumulative; + cum->words = 0; + cum->fregno = FP_ARG_MIN_REG; + cum->vregno = ALTIVEC_ARG_MIN_REG; + cum->prototype = (fntype && prototype_p (fntype)); + cum->call_cookie = ((DEFAULT_ABI == ABI_V4 && libcall) + ? CALL_LIBCALL : CALL_NORMAL); + cum->sysv_gregno = GP_ARG_MIN_REG; + cum->stdarg = stdarg_p (fntype); + cum->libcall = libcall; + + cum->nargs_prototype = 0; + if (incoming || cum->prototype) + cum->nargs_prototype = n_named_args; + + /* Check for a longcall attribute. */ + if ((!fntype && rs6000_default_long_calls) + || (fntype + && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)) + && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))) + cum->call_cookie |= CALL_LONG; + else if (DEFAULT_ABI != ABI_DARWIN) + { + bool is_local = (fndecl + && !DECL_EXTERNAL (fndecl) + && !DECL_WEAK (fndecl) + && (*targetm.binds_local_p) (fndecl)); + if (is_local) + ; + else if (flag_plt) + { + if (fntype + && lookup_attribute ("noplt", TYPE_ATTRIBUTES (fntype))) + cum->call_cookie |= CALL_LONG; + } + else + { + if (!(fntype + && lookup_attribute ("plt", TYPE_ATTRIBUTES (fntype)))) + cum->call_cookie |= CALL_LONG; + } + } + + if (TARGET_DEBUG_ARG) + { + fprintf (stderr, "\ninit_cumulative_args:"); + if (fntype) + { + tree ret_type = TREE_TYPE (fntype); + fprintf (stderr, " ret code = %s,", + get_tree_code_name (TREE_CODE (ret_type))); + } + + if (cum->call_cookie & CALL_LONG) + fprintf (stderr, " longcall,"); + + fprintf (stderr, " proto = %d, nargs = %d\n", + cum->prototype, cum->nargs_prototype); + } + +#ifdef HAVE_AS_GNU_ATTRIBUTE + if (TARGET_ELF && (TARGET_64BIT || DEFAULT_ABI == ABI_V4)) + { + cum->escapes = call_ABI_of_interest (fndecl); + if (cum->escapes) + { + tree return_type; + + if (fntype) + { + return_type = TREE_TYPE (fntype); + return_mode = TYPE_MODE (return_type); + } + else + return_type = lang_hooks.types.type_for_mode (return_mode, 0); + + if (return_type != NULL) + { + if (TREE_CODE (return_type) == RECORD_TYPE + && TYPE_TRANSPARENT_AGGR (return_type)) + { + return_type = TREE_TYPE (first_field (return_type)); + return_mode = TYPE_MODE (return_type); + } + if (AGGREGATE_TYPE_P (return_type) + && ((unsigned HOST_WIDE_INT) int_size_in_bytes (return_type) + <= 8)) + rs6000_returns_struct = true; + } + if (SCALAR_FLOAT_MODE_P (return_mode)) + { + rs6000_passes_float = true; + if ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT) + && (FLOAT128_IBM_P (return_mode) + || FLOAT128_IEEE_P (return_mode) + || (return_type != NULL + && (TYPE_MAIN_VARIANT (return_type) + == long_double_type_node)))) + rs6000_passes_long_double = true; + + /* Note if we passed or return a IEEE 128-bit type. We changed + the mangling for these types, and we may need to make an alias + with the old mangling. */ + if (FLOAT128_IEEE_P (return_mode)) + rs6000_passes_ieee128 = true; + } + if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)) + rs6000_passes_vector = true; + } + } +#endif + + if (fntype + && !TARGET_ALTIVEC + && TARGET_ALTIVEC_ABI + && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype)))) + { + error ("cannot return value in vector register because" + " altivec instructions are disabled, use %qs" + " to enable them", "-maltivec"); + } +} + + +/* On rs6000, function arguments are promoted, as are function return + values. */ + +machine_mode +rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree, int) +{ + PROMOTE_MODE (mode, *punsignedp, type); + + return mode; +} + +/* Return true if TYPE must be passed on the stack and not in registers. */ + +bool +rs6000_must_pass_in_stack (machine_mode mode, const_tree type) +{ + if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 || TARGET_64BIT) + return must_pass_in_stack_var_size (mode, type); + else + return must_pass_in_stack_var_size_or_pad (mode, type); +} + +static inline bool +is_complex_IBM_long_double (machine_mode mode) +{ + return mode == ICmode || (mode == TCmode && FLOAT128_IBM_P (TCmode)); +} + +/* Whether ABI_V4 passes MODE args to a function in floating point + registers. */ + +static bool +abi_v4_pass_in_fpr (machine_mode mode, bool named) +{ + if (!TARGET_HARD_FLOAT) + return false; + if (mode == DFmode) + return true; + if (mode == SFmode && named) + return true; + /* ABI_V4 passes complex IBM long double in 8 gprs. + Stupid, but we can't change the ABI now. */ + if (is_complex_IBM_long_double (mode)) + return false; + if (FLOAT128_2REG_P (mode)) + return true; + if (DECIMAL_FLOAT_MODE_P (mode)) + return true; + return false; +} + +/* Implement TARGET_FUNCTION_ARG_PADDING. + + For the AIX ABI structs are always stored left shifted in their + argument slot. */ + +pad_direction +rs6000_function_arg_padding (machine_mode mode, const_tree type) +{ +#ifndef AGGREGATE_PADDING_FIXED +#define AGGREGATE_PADDING_FIXED 0 +#endif +#ifndef AGGREGATES_PAD_UPWARD_ALWAYS +#define AGGREGATES_PAD_UPWARD_ALWAYS 0 +#endif + + if (!AGGREGATE_PADDING_FIXED) + { + /* GCC used to pass structures of the same size as integer types as + if they were in fact integers, ignoring TARGET_FUNCTION_ARG_PADDING. + i.e. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were + passed padded downward, except that -mstrict-align further + muddied the water in that multi-component structures of 2 and 4 + bytes in size were passed padded upward. + + The following arranges for best compatibility with previous + versions of gcc, but removes the -mstrict-align dependency. */ + if (BYTES_BIG_ENDIAN) + { + HOST_WIDE_INT size = 0; + + if (mode == BLKmode) + { + if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) + size = int_size_in_bytes (type); + } + else + size = GET_MODE_SIZE (mode); + + if (size == 1 || size == 2 || size == 4) + return PAD_DOWNWARD; + } + return PAD_UPWARD; + } + + if (AGGREGATES_PAD_UPWARD_ALWAYS) + { + if (type != 0 && AGGREGATE_TYPE_P (type)) + return PAD_UPWARD; + } + + /* Fall back to the default. */ + return default_function_arg_padding (mode, type); +} + +/* If defined, a C expression that gives the alignment boundary, in bits, + of an argument with the specified mode and type. If it is not defined, + PARM_BOUNDARY is used for all arguments. + + V.4 wants long longs and doubles to be double word aligned. Just + testing the mode size is a boneheaded way to do this as it means + that other types such as complex int are also double word aligned. + However, we're stuck with this because changing the ABI might break + existing library interfaces. + + Quadword align Altivec/VSX vectors. + Quadword align large synthetic vector types. */ + +unsigned int +rs6000_function_arg_boundary (machine_mode mode, const_tree type) +{ + machine_mode elt_mode; + int n_elts; + + rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); + + if (DEFAULT_ABI == ABI_V4 + && (GET_MODE_SIZE (mode) == 8 + || (TARGET_HARD_FLOAT + && !is_complex_IBM_long_double (mode) + && FLOAT128_2REG_P (mode)))) + return 64; + else if (FLOAT128_VECTOR_P (mode)) + return 128; + else if (type && TREE_CODE (type) == VECTOR_TYPE + && int_size_in_bytes (type) >= 8 + && int_size_in_bytes (type) < 16) + return 64; + else if (ALTIVEC_OR_VSX_VECTOR_MODE (elt_mode) + || (type && TREE_CODE (type) == VECTOR_TYPE + && int_size_in_bytes (type) >= 16)) + return 128; + + /* Aggregate types that need > 8 byte alignment are quadword-aligned + in the parameter area in the ELFv2 ABI, and in the AIX ABI unless + -mcompat-align-parm is used. */ + if (((DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm) + || DEFAULT_ABI == ABI_ELFv2) + && type && TYPE_ALIGN (type) > 64) + { + /* "Aggregate" means any AGGREGATE_TYPE except for single-element + or homogeneous float/vector aggregates here. We already handled + vector aggregates above, but still need to check for float here. */ + bool aggregate_p = (AGGREGATE_TYPE_P (type) + && !SCALAR_FLOAT_MODE_P (elt_mode)); + + /* We used to check for BLKmode instead of the above aggregate type + check. Warn when this results in any difference to the ABI. */ + if (aggregate_p != (mode == BLKmode)) + { + static bool warned; + if (!warned && warn_psabi) + { + warned = true; + inform (input_location, + "the ABI of passing aggregates with %d-byte alignment" + " has changed in GCC 5", + (int) TYPE_ALIGN (type) / BITS_PER_UNIT); + } + } + + if (aggregate_p) + return 128; + } + + /* Similar for the Darwin64 ABI. Note that for historical reasons we + implement the "aggregate type" check as a BLKmode check here; this + means certain aggregate types are in fact not aligned. */ + if (TARGET_MACHO && rs6000_darwin64_abi + && mode == BLKmode + && type && TYPE_ALIGN (type) > 64) + return 128; + + return PARM_BOUNDARY; +} + +/* The offset in words to the start of the parameter save area. */ + +static unsigned int +rs6000_parm_offset (void) +{ + return (DEFAULT_ABI == ABI_V4 ? 2 + : DEFAULT_ABI == ABI_ELFv2 ? 4 + : 6); +} + +/* For a function parm of MODE and TYPE, return the starting word in + the parameter area. NWORDS of the parameter area are already used. */ + +static unsigned int +rs6000_parm_start (machine_mode mode, const_tree type, + unsigned int nwords) +{ + unsigned int align; + + align = rs6000_function_arg_boundary (mode, type) / PARM_BOUNDARY - 1; + return nwords + (-(rs6000_parm_offset () + nwords) & align); +} + +/* Compute the size (in words) of a function argument. */ + +static unsigned long +rs6000_arg_size (machine_mode mode, const_tree type) +{ + unsigned long size; + + if (mode != BLKmode) + size = GET_MODE_SIZE (mode); + else + size = int_size_in_bytes (type); + + if (TARGET_32BIT) + return (size + 3) >> 2; + else + return (size + 7) >> 3; +} + +/* Use this to flush pending int fields. */ + +static void +rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *cum, + HOST_WIDE_INT bitpos, int final) +{ + unsigned int startbit, endbit; + int intregs, intoffset; + + /* Handle the situations where a float is taking up the first half + of the GPR, and the other half is empty (typically due to + alignment restrictions). We can detect this by a 8-byte-aligned + int field, or by seeing that this is the final flush for this + argument. Count the word and continue on. */ + if (cum->floats_in_gpr == 1 + && (cum->intoffset % 64 == 0 + || (cum->intoffset == -1 && final))) + { + cum->words++; + cum->floats_in_gpr = 0; + } + + if (cum->intoffset == -1) + return; + + intoffset = cum->intoffset; + cum->intoffset = -1; + cum->floats_in_gpr = 0; + + if (intoffset % BITS_PER_WORD != 0) + { + unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD; + if (!int_mode_for_size (bits, 0).exists ()) + { + /* We couldn't find an appropriate mode, which happens, + e.g., in packed structs when there are 3 bytes to load. + Back intoffset back to the beginning of the word in this + case. */ + intoffset = ROUND_DOWN (intoffset, BITS_PER_WORD); + } + } + + startbit = ROUND_DOWN (intoffset, BITS_PER_WORD); + endbit = ROUND_UP (bitpos, BITS_PER_WORD); + intregs = (endbit - startbit) / BITS_PER_WORD; + cum->words += intregs; + /* words should be unsigned. */ + if ((unsigned)cum->words < (endbit/BITS_PER_WORD)) + { + int pad = (endbit/BITS_PER_WORD) - cum->words; + cum->words += pad; + } +} + +/* The darwin64 ABI calls for us to recurse down through structs, + looking for elements passed in registers. Unfortunately, we have + to track int register count here also because of misalignments + in powerpc alignment mode. */ + +static void +rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *cum, + const_tree type, + HOST_WIDE_INT startbitpos) +{ + tree f; + + for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + HOST_WIDE_INT bitpos = startbitpos; + tree ftype = TREE_TYPE (f); + machine_mode mode; + if (ftype == error_mark_node) + continue; + mode = TYPE_MODE (ftype); + + if (DECL_SIZE (f) != 0 + && tree_fits_uhwi_p (bit_position (f))) + bitpos += int_bit_position (f); + + /* ??? FIXME: else assume zero offset. */ + + if (TREE_CODE (ftype) == RECORD_TYPE) + rs6000_darwin64_record_arg_advance_recurse (cum, ftype, bitpos); + else if (USE_FP_FOR_ARG_P (cum, mode)) + { + unsigned n_fpregs = (GET_MODE_SIZE (mode) + 7) >> 3; + rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0); + cum->fregno += n_fpregs; + /* Single-precision floats present a special problem for + us, because they are smaller than an 8-byte GPR, and so + the structure-packing rules combined with the standard + varargs behavior mean that we want to pack float/float + and float/int combinations into a single register's + space. This is complicated by the arg advance flushing, + which works on arbitrarily large groups of int-type + fields. */ + if (mode == SFmode) + { + if (cum->floats_in_gpr == 1) + { + /* Two floats in a word; count the word and reset + the float count. */ + cum->words++; + cum->floats_in_gpr = 0; + } + else if (bitpos % 64 == 0) + { + /* A float at the beginning of an 8-byte word; + count it and put off adjusting cum->words until + we see if a arg advance flush is going to do it + for us. */ + cum->floats_in_gpr++; + } + else + { + /* The float is at the end of a word, preceded + by integer fields, so the arg advance flush + just above has already set cum->words and + everything is taken care of. */ + } + } + else + cum->words += n_fpregs; + } + else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, 1)) + { + rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0); + cum->vregno++; + cum->words += 2; + } + else if (cum->intoffset == -1) + cum->intoffset = bitpos; + } +} + +/* Check for an item that needs to be considered specially under the darwin 64 + bit ABI. These are record types where the mode is BLK or the structure is + 8 bytes in size. */ +int +rs6000_darwin64_struct_check_p (machine_mode mode, const_tree type) +{ + return rs6000_darwin64_abi + && ((mode == BLKmode + && TREE_CODE (type) == RECORD_TYPE + && int_size_in_bytes (type) > 0) + || (type && TREE_CODE (type) == RECORD_TYPE + && int_size_in_bytes (type) == 8)) ? 1 : 0; +} + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) + + Note that for args passed by reference, function_arg will be called + with MODE and TYPE set to that of the pointer to the arg, not the arg + itself. */ + +static void +rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode, + const_tree type, bool named, int depth) +{ + machine_mode elt_mode; + int n_elts; + + rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); + + /* Only tick off an argument if we're not recursing. */ + if (depth == 0) + cum->nargs_prototype--; + +#ifdef HAVE_AS_GNU_ATTRIBUTE + if (TARGET_ELF && (TARGET_64BIT || DEFAULT_ABI == ABI_V4) + && cum->escapes) + { + if (SCALAR_FLOAT_MODE_P (mode)) + { + rs6000_passes_float = true; + if ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT) + && (FLOAT128_IBM_P (mode) + || FLOAT128_IEEE_P (mode) + || (type != NULL + && TYPE_MAIN_VARIANT (type) == long_double_type_node))) + rs6000_passes_long_double = true; + + /* Note if we passed or return a IEEE 128-bit type. We changed the + mangling for these types, and we may need to make an alias with + the old mangling. */ + if (FLOAT128_IEEE_P (mode)) + rs6000_passes_ieee128 = true; + } + if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) + rs6000_passes_vector = true; + } +#endif + + if (TARGET_ALTIVEC_ABI + && (ALTIVEC_OR_VSX_VECTOR_MODE (elt_mode) + || (type && TREE_CODE (type) == VECTOR_TYPE + && int_size_in_bytes (type) == 16))) + { + bool stack = false; + + if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named)) + { + cum->vregno += n_elts; + + if (!TARGET_ALTIVEC) + error ("cannot pass argument in vector register because" + " altivec instructions are disabled, use %qs" + " to enable them", "-maltivec"); + + /* PowerPC64 Linux and AIX allocate GPRs for a vector argument + even if it is going to be passed in a vector register. + Darwin does the same for variable-argument functions. */ + if (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + && TARGET_64BIT) + || (cum->stdarg && DEFAULT_ABI != ABI_V4)) + stack = true; + } + else + stack = true; + + if (stack) + { + int align; + + /* Vector parameters must be 16-byte aligned. In 32-bit + mode this means we need to take into account the offset + to the parameter save area. In 64-bit mode, they just + have to start on an even word, since the parameter save + area is 16-byte aligned. */ + if (TARGET_32BIT) + align = -(rs6000_parm_offset () + cum->words) & 3; + else + align = cum->words & 1; + cum->words += align + rs6000_arg_size (mode, type); + + if (TARGET_DEBUG_ARG) + { + fprintf (stderr, "function_adv: words = %2d, align=%d, ", + cum->words, align); + fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n", + cum->nargs_prototype, cum->prototype, + GET_MODE_NAME (mode)); + } + } + } + else if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) + { + int size = int_size_in_bytes (type); + /* Variable sized types have size == -1 and are + treated as if consisting entirely of ints. + Pad to 16 byte boundary if needed. */ + if (TYPE_ALIGN (type) >= 2 * BITS_PER_WORD + && (cum->words % 2) != 0) + cum->words++; + /* For varargs, we can just go up by the size of the struct. */ + if (!named) + cum->words += (size + 7) / 8; + else + { + /* It is tempting to say int register count just goes up by + sizeof(type)/8, but this is wrong in a case such as + { int; double; int; } [powerpc alignment]. We have to + grovel through the fields for these too. */ + cum->intoffset = 0; + cum->floats_in_gpr = 0; + rs6000_darwin64_record_arg_advance_recurse (cum, type, 0); + rs6000_darwin64_record_arg_advance_flush (cum, + size * BITS_PER_UNIT, 1); + } + if (TARGET_DEBUG_ARG) + { + fprintf (stderr, "function_adv: words = %2d, align=%d, size=%d", + cum->words, TYPE_ALIGN (type), size); + fprintf (stderr, + "nargs = %4d, proto = %d, mode = %4s (darwin64 abi)\n", + cum->nargs_prototype, cum->prototype, + GET_MODE_NAME (mode)); + } + } + else if (DEFAULT_ABI == ABI_V4) + { + if (abi_v4_pass_in_fpr (mode, named)) + { + /* _Decimal128 must use an even/odd register pair. This assumes + that the register number is odd when fregno is odd. */ + if (mode == TDmode && (cum->fregno % 2) == 1) + cum->fregno++; + + if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0) + <= FP_ARG_V4_MAX_REG) + cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3; + else + { + cum->fregno = FP_ARG_V4_MAX_REG + 1; + if (mode == DFmode || FLOAT128_IBM_P (mode) + || mode == DDmode || mode == TDmode) + cum->words += cum->words & 1; + cum->words += rs6000_arg_size (mode, type); + } + } + else + { + int n_words = rs6000_arg_size (mode, type); + int gregno = cum->sysv_gregno; + + /* Long long is put in (r3,r4), (r5,r6), (r7,r8) or (r9,r10). + As does any other 2 word item such as complex int due to a + historical mistake. */ + if (n_words == 2) + gregno += (1 - gregno) & 1; + + /* Multi-reg args are not split between registers and stack. */ + if (gregno + n_words - 1 > GP_ARG_MAX_REG) + { + /* Long long is aligned on the stack. So are other 2 word + items such as complex int due to a historical mistake. */ + if (n_words == 2) + cum->words += cum->words & 1; + cum->words += n_words; + } + + /* Note: continuing to accumulate gregno past when we've started + spilling to the stack indicates the fact that we've started + spilling to the stack to expand_builtin_saveregs. */ + cum->sysv_gregno = gregno + n_words; + } + + if (TARGET_DEBUG_ARG) + { + fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ", + cum->words, cum->fregno); + fprintf (stderr, "gregno = %2d, nargs = %4d, proto = %d, ", + cum->sysv_gregno, cum->nargs_prototype, cum->prototype); + fprintf (stderr, "mode = %4s, named = %d\n", + GET_MODE_NAME (mode), named); + } + } + else + { + int n_words = rs6000_arg_size (mode, type); + int start_words = cum->words; + int align_words = rs6000_parm_start (mode, type, start_words); + + cum->words = align_words + n_words; + + if (SCALAR_FLOAT_MODE_P (elt_mode) && TARGET_HARD_FLOAT) + { + /* _Decimal128 must be passed in an even/odd float register pair. + This assumes that the register number is odd when fregno is + odd. */ + if (elt_mode == TDmode && (cum->fregno % 2) == 1) + cum->fregno++; + cum->fregno += n_elts * ((GET_MODE_SIZE (elt_mode) + 7) >> 3); + } + + if (TARGET_DEBUG_ARG) + { + fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ", + cum->words, cum->fregno); + fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s, ", + cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode)); + fprintf (stderr, "named = %d, align = %d, depth = %d\n", + named, align_words - start_words, depth); + } + } +} + +void +rs6000_function_arg_advance (cumulative_args_t cum, machine_mode mode, + const_tree type, bool named) +{ + rs6000_function_arg_advance_1 (get_cumulative_args (cum), mode, type, named, + 0); +} + +/* A subroutine of rs6000_darwin64_record_arg. Assign the bits of the + structure between cum->intoffset and bitpos to integer registers. */ + +static void +rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *cum, + HOST_WIDE_INT bitpos, rtx rvec[], int *k) +{ + machine_mode mode; + unsigned int regno; + unsigned int startbit, endbit; + int this_regno, intregs, intoffset; + rtx reg; + + if (cum->intoffset == -1) + return; + + intoffset = cum->intoffset; + cum->intoffset = -1; + + /* If this is the trailing part of a word, try to only load that + much into the register. Otherwise load the whole register. Note + that in the latter case we may pick up unwanted bits. It's not a + problem at the moment but may wish to revisit. */ + + if (intoffset % BITS_PER_WORD != 0) + { + unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD; + if (!int_mode_for_size (bits, 0).exists (&mode)) + { + /* We couldn't find an appropriate mode, which happens, + e.g., in packed structs when there are 3 bytes to load. + Back intoffset back to the beginning of the word in this + case. */ + intoffset = ROUND_DOWN (intoffset, BITS_PER_WORD); + mode = word_mode; + } + } + else + mode = word_mode; + + startbit = ROUND_DOWN (intoffset, BITS_PER_WORD); + endbit = ROUND_UP (bitpos, BITS_PER_WORD); + intregs = (endbit - startbit) / BITS_PER_WORD; + this_regno = cum->words + intoffset / BITS_PER_WORD; + + if (intregs > 0 && intregs > GP_ARG_NUM_REG - this_regno) + cum->use_stack = 1; + + intregs = MIN (intregs, GP_ARG_NUM_REG - this_regno); + if (intregs <= 0) + return; + + intoffset /= BITS_PER_UNIT; + do + { + regno = GP_ARG_MIN_REG + this_regno; + reg = gen_rtx_REG (mode, regno); + rvec[(*k)++] = + gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset)); + + this_regno += 1; + intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1; + mode = word_mode; + intregs -= 1; + } + while (intregs > 0); +} + +/* Recursive workhorse for the following. */ + +static void +rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, const_tree type, + HOST_WIDE_INT startbitpos, rtx rvec[], + int *k) +{ + tree f; + + for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + HOST_WIDE_INT bitpos = startbitpos; + tree ftype = TREE_TYPE (f); + machine_mode mode; + if (ftype == error_mark_node) + continue; + mode = TYPE_MODE (ftype); + + if (DECL_SIZE (f) != 0 + && tree_fits_uhwi_p (bit_position (f))) + bitpos += int_bit_position (f); + + /* ??? FIXME: else assume zero offset. */ + + if (TREE_CODE (ftype) == RECORD_TYPE) + rs6000_darwin64_record_arg_recurse (cum, ftype, bitpos, rvec, k); + else if (cum->named && USE_FP_FOR_ARG_P (cum, mode)) + { + unsigned n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3; +#if 0 + switch (mode) + { + case E_SCmode: mode = SFmode; break; + case E_DCmode: mode = DFmode; break; + case E_TCmode: mode = TFmode; break; + default: break; + } +#endif + rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k); + if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1) + { + gcc_assert (cum->fregno == FP_ARG_MAX_REG + && (mode == TFmode || mode == TDmode)); + /* Long double or _Decimal128 split over regs and memory. */ + mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode; + cum->use_stack=1; + } + rvec[(*k)++] + = gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_REG (mode, cum->fregno++), + GEN_INT (bitpos / BITS_PER_UNIT)); + if (FLOAT128_2REG_P (mode)) + cum->fregno++; + } + else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, 1)) + { + rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k); + rvec[(*k)++] + = gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_REG (mode, cum->vregno++), + GEN_INT (bitpos / BITS_PER_UNIT)); + } + else if (cum->intoffset == -1) + cum->intoffset = bitpos; + } +} + +/* For the darwin64 ABI, we want to construct a PARALLEL consisting of + the register(s) to be used for each field and subfield of a struct + being passed by value, along with the offset of where the + register's value may be found in the block. FP fields go in FP + register, vector fields go in vector registers, and everything + else goes in int registers, packed as in memory. + + This code is also used for function return values. RETVAL indicates + whether this is the case. + + Much of this is taken from the SPARC V9 port, which has a similar + calling convention. */ + +rtx +rs6000_darwin64_record_arg (CUMULATIVE_ARGS *orig_cum, const_tree type, + bool named, bool retval) +{ + rtx rvec[FIRST_PSEUDO_REGISTER]; + int k = 1, kbase = 1; + HOST_WIDE_INT typesize = int_size_in_bytes (type); + /* This is a copy; modifications are not visible to our caller. */ + CUMULATIVE_ARGS copy_cum = *orig_cum; + CUMULATIVE_ARGS *cum = ©_cum; + + /* Pad to 16 byte boundary if needed. */ + if (!retval && TYPE_ALIGN (type) >= 2 * BITS_PER_WORD + && (cum->words % 2) != 0) + cum->words++; + + cum->intoffset = 0; + cum->use_stack = 0; + cum->named = named; + + /* Put entries into rvec[] for individual FP and vector fields, and + for the chunks of memory that go in int regs. Note we start at + element 1; 0 is reserved for an indication of using memory, and + may or may not be filled in below. */ + rs6000_darwin64_record_arg_recurse (cum, type, /* startbit pos= */ 0, rvec, &k); + rs6000_darwin64_record_arg_flush (cum, typesize * BITS_PER_UNIT, rvec, &k); + + /* If any part of the struct went on the stack put all of it there. + This hack is because the generic code for + FUNCTION_ARG_PARTIAL_NREGS cannot handle cases where the register + parts of the struct are not at the beginning. */ + if (cum->use_stack) + { + if (retval) + return NULL_RTX; /* doesn't go in registers at all */ + kbase = 0; + rvec[0] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); + } + if (k > 1 || cum->use_stack) + return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (k - kbase, &rvec[kbase])); + else + return NULL_RTX; +} + +/* Determine where to place an argument in 64-bit mode with 32-bit ABI. */ + +static rtx +rs6000_mixed_function_arg (machine_mode mode, const_tree type, + int align_words) +{ + int n_units; + int i, k; + rtx rvec[GP_ARG_NUM_REG + 1]; + + if (align_words >= GP_ARG_NUM_REG) + return NULL_RTX; + + n_units = rs6000_arg_size (mode, type); + + /* Optimize the simple case where the arg fits in one gpr, except in + the case of BLKmode due to assign_parms assuming that registers are + BITS_PER_WORD wide. */ + if (n_units == 0 + || (n_units == 1 && mode != BLKmode)) + return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words); + + k = 0; + if (align_words + n_units > GP_ARG_NUM_REG) + /* Not all of the arg fits in gprs. Say that it goes in memory too, + using a magic NULL_RTX component. + This is not strictly correct. Only some of the arg belongs in + memory, not all of it. However, the normal scheme using + function_arg_partial_nregs can result in unusual subregs, eg. + (subreg:SI (reg:DF) 4), which are not handled well. The code to + store the whole arg to memory is often more efficient than code + to store pieces, and we know that space is available in the right + place for the whole arg. */ + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); + + i = 0; + do + { + rtx r = gen_rtx_REG (SImode, GP_ARG_MIN_REG + align_words); + rtx off = GEN_INT (i++ * 4); + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); + } + while (++align_words < GP_ARG_NUM_REG && --n_units != 0); + + return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec)); +} + +/* We have an argument of MODE and TYPE that goes into FPRs or VRs, + but must also be copied into the parameter save area starting at + offset ALIGN_WORDS. Fill in RVEC with the elements corresponding + to the GPRs and/or memory. Return the number of elements used. */ + +static int +rs6000_psave_function_arg (machine_mode mode, const_tree type, + int align_words, rtx *rvec) +{ + int k = 0; + + if (align_words < GP_ARG_NUM_REG) + { + int n_words = rs6000_arg_size (mode, type); + + if (align_words + n_words > GP_ARG_NUM_REG + || mode == BLKmode + || (TARGET_32BIT && TARGET_POWERPC64)) + { + /* If this is partially on the stack, then we only + include the portion actually in registers here. */ + machine_mode rmode = TARGET_32BIT ? SImode : DImode; + int i = 0; + + if (align_words + n_words > GP_ARG_NUM_REG) + { + /* Not all of the arg fits in gprs. Say that it goes in memory + too, using a magic NULL_RTX component. Also see comment in + rs6000_mixed_function_arg for why the normal + function_arg_partial_nregs scheme doesn't work in this case. */ + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); + } + + do + { + rtx r = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words); + rtx off = GEN_INT (i++ * GET_MODE_SIZE (rmode)); + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); + } + while (++align_words < GP_ARG_NUM_REG && --n_words != 0); + } + else + { + /* The whole arg fits in gprs. */ + rtx r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words); + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx); + } + } + else + { + /* It's entirely in memory. */ + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); + } + + return k; +} + +/* RVEC is a vector of K components of an argument of mode MODE. + Construct the final function_arg return value from it. */ + +static rtx +rs6000_finish_function_arg (machine_mode mode, rtx *rvec, int k) +{ + gcc_assert (k >= 1); + + /* Avoid returning a PARALLEL in the trivial cases. */ + if (k == 1) + { + if (XEXP (rvec[0], 0) == NULL_RTX) + return NULL_RTX; + + if (GET_MODE (XEXP (rvec[0], 0)) == mode) + return XEXP (rvec[0], 0); + } + + return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec)); +} + +/* Determine where to put an argument to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. It is + not modified in this routine. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). + + On RS/6000 the first eight words of non-FP are normally in registers + and the rest are pushed. Under AIX, the first 13 FP args are in registers. + Under V.4, the first 8 FP args are in registers. + + If this is floating-point and no prototype is specified, we use + both an FP and integer register (or possibly FP reg and stack). Library + functions (when CALL_LIBCALL is set) always have the proper types for args, + so we can pass the FP value just in one register. emit_library_function + doesn't support PARALLEL anyway. + + Note that for args passed by reference, function_arg will be called + with MODE and TYPE set to that of the pointer to the arg, not the arg + itself. */ + +rtx +rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode, + const_tree type, bool named) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + enum rs6000_abi abi = DEFAULT_ABI; + machine_mode elt_mode; + int n_elts; + + /* Return a marker to indicate whether CR1 needs to set or clear the + bit that V.4 uses to say fp args were passed in registers. + Assume that we don't need the marker for software floating point, + or compiler generated library calls. */ + if (mode == VOIDmode) + { + if (abi == ABI_V4 + && (cum->call_cookie & CALL_LIBCALL) == 0 + && (cum->stdarg + || (cum->nargs_prototype < 0 + && (cum->prototype || TARGET_NO_PROTOTYPE))) + && TARGET_HARD_FLOAT) + return GEN_INT (cum->call_cookie + | ((cum->fregno == FP_ARG_MIN_REG) + ? CALL_V4_SET_FP_ARGS + : CALL_V4_CLEAR_FP_ARGS)); + + return GEN_INT (cum->call_cookie & ~CALL_LIBCALL); + } + + rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); + + if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) + { + rtx rslt = rs6000_darwin64_record_arg (cum, type, named, /*retval= */false); + if (rslt != NULL_RTX) + return rslt; + /* Else fall through to usual handling. */ + } + + if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named)) + { + rtx rvec[GP_ARG_NUM_REG + AGGR_ARG_NUM_REG + 1]; + rtx r, off; + int i, k = 0; + + /* Do we also need to pass this argument in the parameter save area? + Library support functions for IEEE 128-bit are assumed to not need the + value passed both in GPRs and in vector registers. */ + if (TARGET_64BIT && !cum->prototype + && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode))) + { + int align_words = ROUND_UP (cum->words, 2); + k = rs6000_psave_function_arg (mode, type, align_words, rvec); + } + + /* Describe where this argument goes in the vector registers. */ + for (i = 0; i < n_elts && cum->vregno + i <= ALTIVEC_ARG_MAX_REG; i++) + { + r = gen_rtx_REG (elt_mode, cum->vregno + i); + off = GEN_INT (i * GET_MODE_SIZE (elt_mode)); + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); + } + + return rs6000_finish_function_arg (mode, rvec, k); + } + else if (TARGET_ALTIVEC_ABI + && (ALTIVEC_OR_VSX_VECTOR_MODE (mode) + || (type && TREE_CODE (type) == VECTOR_TYPE + && int_size_in_bytes (type) == 16))) + { + if (named || abi == ABI_V4) + return NULL_RTX; + else + { + /* Vector parameters to varargs functions under AIX or Darwin + get passed in memory and possibly also in GPRs. */ + int align, align_words, n_words; + machine_mode part_mode; + + /* Vector parameters must be 16-byte aligned. In 32-bit + mode this means we need to take into account the offset + to the parameter save area. In 64-bit mode, they just + have to start on an even word, since the parameter save + area is 16-byte aligned. */ + if (TARGET_32BIT) + align = -(rs6000_parm_offset () + cum->words) & 3; + else + align = cum->words & 1; + align_words = cum->words + align; + + /* Out of registers? Memory, then. */ + if (align_words >= GP_ARG_NUM_REG) + return NULL_RTX; + + if (TARGET_32BIT && TARGET_POWERPC64) + return rs6000_mixed_function_arg (mode, type, align_words); + + /* The vector value goes in GPRs. Only the part of the + value in GPRs is reported here. */ + part_mode = mode; + n_words = rs6000_arg_size (mode, type); + if (align_words + n_words > GP_ARG_NUM_REG) + /* Fortunately, there are only two possibilities, the value + is either wholly in GPRs or half in GPRs and half not. */ + part_mode = DImode; + + return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words); + } + } + + else if (abi == ABI_V4) + { + if (abi_v4_pass_in_fpr (mode, named)) + { + /* _Decimal128 must use an even/odd register pair. This assumes + that the register number is odd when fregno is odd. */ + if (mode == TDmode && (cum->fregno % 2) == 1) + cum->fregno++; + + if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0) + <= FP_ARG_V4_MAX_REG) + return gen_rtx_REG (mode, cum->fregno); + else + return NULL_RTX; + } + else + { + int n_words = rs6000_arg_size (mode, type); + int gregno = cum->sysv_gregno; + + /* Long long is put in (r3,r4), (r5,r6), (r7,r8) or (r9,r10). + As does any other 2 word item such as complex int due to a + historical mistake. */ + if (n_words == 2) + gregno += (1 - gregno) & 1; + + /* Multi-reg args are not split between registers and stack. */ + if (gregno + n_words - 1 > GP_ARG_MAX_REG) + return NULL_RTX; + + if (TARGET_32BIT && TARGET_POWERPC64) + return rs6000_mixed_function_arg (mode, type, + gregno - GP_ARG_MIN_REG); + return gen_rtx_REG (mode, gregno); + } + } + else + { + int align_words = rs6000_parm_start (mode, type, cum->words); + + /* _Decimal128 must be passed in an even/odd float register pair. + This assumes that the register number is odd when fregno is odd. */ + if (elt_mode == TDmode && (cum->fregno % 2) == 1) + cum->fregno++; + + if (USE_FP_FOR_ARG_P (cum, elt_mode) + && !(TARGET_AIX && !TARGET_ELF + && type != NULL && AGGREGATE_TYPE_P (type))) + { + rtx rvec[GP_ARG_NUM_REG + AGGR_ARG_NUM_REG + 1]; + rtx r, off; + int i, k = 0; + unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3; + int fpr_words; + + /* Do we also need to pass this argument in the parameter + save area? */ + if (type && (cum->nargs_prototype <= 0 + || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + && TARGET_XL_COMPAT + && align_words >= GP_ARG_NUM_REG))) + k = rs6000_psave_function_arg (mode, type, align_words, rvec); + + /* Describe where this argument goes in the fprs. */ + for (i = 0; i < n_elts + && cum->fregno + i * n_fpreg <= FP_ARG_MAX_REG; i++) + { + /* Check if the argument is split over registers and memory. + This can only ever happen for long double or _Decimal128; + complex types are handled via split_complex_arg. */ + machine_mode fmode = elt_mode; + if (cum->fregno + (i + 1) * n_fpreg > FP_ARG_MAX_REG + 1) + { + gcc_assert (FLOAT128_2REG_P (fmode)); + fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode; + } + + r = gen_rtx_REG (fmode, cum->fregno + i * n_fpreg); + off = GEN_INT (i * GET_MODE_SIZE (elt_mode)); + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); + } + + /* If there were not enough FPRs to hold the argument, the rest + usually goes into memory. However, if the current position + is still within the register parameter area, a portion may + actually have to go into GPRs. + + Note that it may happen that the portion of the argument + passed in the first "half" of the first GPR was already + passed in the last FPR as well. + + For unnamed arguments, we already set up GPRs to cover the + whole argument in rs6000_psave_function_arg, so there is + nothing further to do at this point. */ + fpr_words = (i * GET_MODE_SIZE (elt_mode)) / (TARGET_32BIT ? 4 : 8); + if (i < n_elts && align_words + fpr_words < GP_ARG_NUM_REG + && cum->nargs_prototype > 0) + { + static bool warned; + + machine_mode rmode = TARGET_32BIT ? SImode : DImode; + int n_words = rs6000_arg_size (mode, type); + + align_words += fpr_words; + n_words -= fpr_words; + + do + { + r = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words); + off = GEN_INT (fpr_words++ * GET_MODE_SIZE (rmode)); + rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); + } + while (++align_words < GP_ARG_NUM_REG && --n_words != 0); + + if (!warned && warn_psabi) + { + warned = true; + inform (input_location, + "the ABI of passing homogeneous % aggregates" + " has changed in GCC 5"); + } + } + + return rs6000_finish_function_arg (mode, rvec, k); + } + else if (align_words < GP_ARG_NUM_REG) + { + if (TARGET_32BIT && TARGET_POWERPC64) + return rs6000_mixed_function_arg (mode, type, align_words); + + return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words); + } + else + return NULL_RTX; + } +} + +/* For an arg passed partly in registers and partly in memory, this is + the number of bytes passed in registers. For args passed entirely in + registers or entirely in memory, zero. When an arg is described by a + PARALLEL, perhaps using more than one register type, this function + returns the number of bytes used by the first element of the PARALLEL. */ + +int +rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode, + tree type, bool named) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + bool passed_in_gprs = true; + int ret = 0; + int align_words; + machine_mode elt_mode; + int n_elts; + + rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); + + if (DEFAULT_ABI == ABI_V4) + return 0; + + if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named)) + { + /* If we are passing this arg in the fixed parameter save area (gprs or + memory) as well as VRs, we do not use the partial bytes mechanism; + instead, rs6000_function_arg will return a PARALLEL including a memory + element as necessary. Library support functions for IEEE 128-bit are + assumed to not need the value passed both in GPRs and in vector + registers. */ + if (TARGET_64BIT && !cum->prototype + && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode))) + return 0; + + /* Otherwise, we pass in VRs only. Check for partial copies. */ + passed_in_gprs = false; + if (cum->vregno + n_elts > ALTIVEC_ARG_MAX_REG + 1) + ret = (ALTIVEC_ARG_MAX_REG + 1 - cum->vregno) * 16; + } + + /* In this complicated case we just disable the partial_nregs code. */ + if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) + return 0; + + align_words = rs6000_parm_start (mode, type, cum->words); + + if (USE_FP_FOR_ARG_P (cum, elt_mode) + && !(TARGET_AIX && !TARGET_ELF + && type != NULL && AGGREGATE_TYPE_P (type))) + { + unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3; + + /* If we are passing this arg in the fixed parameter save area + (gprs or memory) as well as FPRs, we do not use the partial + bytes mechanism; instead, rs6000_function_arg will return a + PARALLEL including a memory element as necessary. */ + if (type + && (cum->nargs_prototype <= 0 + || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + && TARGET_XL_COMPAT + && align_words >= GP_ARG_NUM_REG))) + return 0; + + /* Otherwise, we pass in FPRs only. Check for partial copies. */ + passed_in_gprs = false; + if (cum->fregno + n_elts * n_fpreg > FP_ARG_MAX_REG + 1) + { + /* Compute number of bytes / words passed in FPRs. If there + is still space available in the register parameter area + *after* that amount, a part of the argument will be passed + in GPRs. In that case, the total amount passed in any + registers is equal to the amount that would have been passed + in GPRs if everything were passed there, so we fall back to + the GPR code below to compute the appropriate value. */ + int fpr = ((FP_ARG_MAX_REG + 1 - cum->fregno) + * MIN (8, GET_MODE_SIZE (elt_mode))); + int fpr_words = fpr / (TARGET_32BIT ? 4 : 8); + + if (align_words + fpr_words < GP_ARG_NUM_REG) + passed_in_gprs = true; + else + ret = fpr; + } + } + + if (passed_in_gprs + && align_words < GP_ARG_NUM_REG + && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type)) + ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8); + + if (ret != 0 && TARGET_DEBUG_ARG) + fprintf (stderr, "rs6000_arg_partial_bytes: %d\n", ret); + + return ret; +} + +/* A C expression that indicates when an argument must be passed by + reference. If nonzero for an argument, a copy of that argument is + made in memory and a pointer to the argument is passed instead of + the argument itself. The pointer is passed in whatever way is + appropriate for passing a pointer to that type. + + Under V.4, aggregates and long double are passed by reference. + + As an extension to all 32-bit ABIs, AltiVec vectors are passed by + reference unless the AltiVec vector extension ABI is in force. + + As an extension to all ABIs, variable sized types are passed by + reference. */ + +bool +rs6000_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, + machine_mode mode, const_tree type, + bool named ATTRIBUTE_UNUSED) +{ + if (!type) + return 0; + + if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD + && FLOAT128_IEEE_P (TYPE_MODE (type))) + { + if (TARGET_DEBUG_ARG) + fprintf (stderr, "function_arg_pass_by_reference: V4 IEEE 128-bit\n"); + return 1; + } + + if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (type)) + { + if (TARGET_DEBUG_ARG) + fprintf (stderr, "function_arg_pass_by_reference: V4 aggregate\n"); + return 1; + } + + if (int_size_in_bytes (type) < 0) + { + if (TARGET_DEBUG_ARG) + fprintf (stderr, "function_arg_pass_by_reference: variable size\n"); + return 1; + } + + /* Allow -maltivec -mabi=no-altivec without warning. Altivec vector + modes only exist for GCC vector types if -maltivec. */ + if (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) + { + if (TARGET_DEBUG_ARG) + fprintf (stderr, "function_arg_pass_by_reference: AltiVec\n"); + return 1; + } + + /* Pass synthetic vectors in memory. */ + if (TREE_CODE (type) == VECTOR_TYPE + && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8)) + { + static bool warned_for_pass_big_vectors = false; + if (TARGET_DEBUG_ARG) + fprintf (stderr, "function_arg_pass_by_reference: synthetic vector\n"); + if (!warned_for_pass_big_vectors) + { + warning (OPT_Wpsabi, "GCC vector passed by reference: " + "non-standard ABI extension with no compatibility " + "guarantee"); + warned_for_pass_big_vectors = true; + } + return 1; + } + + return 0; +} + +/* Process parameter of type TYPE after ARGS_SO_FAR parameters were + already processes. Return true if the parameter must be passed + (fully or partially) on the stack. */ + +static bool +rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type) +{ + machine_mode mode; + int unsignedp; + rtx entry_parm; + + /* Catch errors. */ + if (type == NULL || type == error_mark_node) + return true; + + /* Handle types with no storage requirement. */ + if (TYPE_MODE (type) == VOIDmode) + return false; + + /* Handle complex types. */ + if (TREE_CODE (type) == COMPLEX_TYPE) + return (rs6000_parm_needs_stack (args_so_far, TREE_TYPE (type)) + || rs6000_parm_needs_stack (args_so_far, TREE_TYPE (type))); + + /* Handle transparent aggregates. */ + if ((TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == RECORD_TYPE) + && TYPE_TRANSPARENT_AGGR (type)) + type = TREE_TYPE (first_field (type)); + + /* See if this arg was passed by invisible reference. */ + if (pass_by_reference (get_cumulative_args (args_so_far), + TYPE_MODE (type), type, true)) + type = build_pointer_type (type); + + /* Find mode as it is passed by the ABI. */ + unsignedp = TYPE_UNSIGNED (type); + mode = promote_mode (type, TYPE_MODE (type), &unsignedp); + + /* If we must pass in stack, we need a stack. */ + if (rs6000_must_pass_in_stack (mode, type)) + return true; + + /* If there is no incoming register, we need a stack. */ + entry_parm = rs6000_function_arg (args_so_far, mode, type, true); + if (entry_parm == NULL) + return true; + + /* Likewise if we need to pass both in registers and on the stack. */ + if (GET_CODE (entry_parm) == PARALLEL + && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX) + return true; + + /* Also true if we're partially in registers and partially not. */ + if (rs6000_arg_partial_bytes (args_so_far, mode, type, true) != 0) + return true; + + /* Update info on where next arg arrives in registers. */ + rs6000_function_arg_advance (args_so_far, mode, type, true); + return false; +} + +/* Return true if FUN has no prototype, has a variable argument + list, or passes any parameter in memory. */ + +static bool +rs6000_function_parms_need_stack (tree fun, bool incoming) +{ + tree fntype, result; + CUMULATIVE_ARGS args_so_far_v; + cumulative_args_t args_so_far; + + if (!fun) + /* Must be a libcall, all of which only use reg parms. */ + return false; + + fntype = fun; + if (!TYPE_P (fun)) + fntype = TREE_TYPE (fun); + + /* Varargs functions need the parameter save area. */ + if ((!incoming && !prototype_p (fntype)) || stdarg_p (fntype)) + return true; + + INIT_CUMULATIVE_INCOMING_ARGS (args_so_far_v, fntype, NULL_RTX); + args_so_far = pack_cumulative_args (&args_so_far_v); + + /* When incoming, we will have been passed the function decl. + It is necessary to use the decl to handle K&R style functions, + where TYPE_ARG_TYPES may not be available. */ + if (incoming) + { + gcc_assert (DECL_P (fun)); + result = DECL_RESULT (fun); + } + else + result = TREE_TYPE (fntype); + + if (result && aggregate_value_p (result, fntype)) + { + if (!TYPE_P (result)) + result = TREE_TYPE (result); + result = build_pointer_type (result); + rs6000_parm_needs_stack (args_so_far, result); + } + + if (incoming) + { + tree parm; + + for (parm = DECL_ARGUMENTS (fun); + parm && parm != void_list_node; + parm = TREE_CHAIN (parm)) + if (rs6000_parm_needs_stack (args_so_far, TREE_TYPE (parm))) + return true; + } + else + { + function_args_iterator args_iter; + tree arg_type; + + FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) + if (rs6000_parm_needs_stack (args_so_far, arg_type)) + return true; + } + + return false; +} + +/* Return the size of the REG_PARM_STACK_SPACE are for FUN. This is + usually a constant depending on the ABI. However, in the ELFv2 ABI + the register parameter area is optional when calling a function that + has a prototype is scope, has no variable argument list, and passes + all parameters in registers. */ + +int +rs6000_reg_parm_stack_space (tree fun, bool incoming) +{ + int reg_parm_stack_space; + + switch (DEFAULT_ABI) + { + default: + reg_parm_stack_space = 0; + break; + + case ABI_AIX: + case ABI_DARWIN: + reg_parm_stack_space = TARGET_64BIT ? 64 : 32; + break; + + case ABI_ELFv2: + /* ??? Recomputing this every time is a bit expensive. Is there + a place to cache this information? */ + if (rs6000_function_parms_need_stack (fun, incoming)) + reg_parm_stack_space = TARGET_64BIT ? 64 : 32; + else + reg_parm_stack_space = 0; + break; + } + + return reg_parm_stack_space; +} + +static void +rs6000_move_block_from_reg (int regno, rtx x, int nregs) +{ + int i; + machine_mode reg_mode = TARGET_32BIT ? SImode : DImode; + + if (nregs == 0) + return; + + for (i = 0; i < nregs; i++) + { + rtx tem = adjust_address_nv (x, reg_mode, i * GET_MODE_SIZE (reg_mode)); + if (reload_completed) + { + if (! strict_memory_address_p (reg_mode, XEXP (tem, 0))) + tem = NULL_RTX; + else + tem = simplify_gen_subreg (reg_mode, x, BLKmode, + i * GET_MODE_SIZE (reg_mode)); + } + else + tem = replace_equiv_address (tem, XEXP (tem, 0)); + + gcc_assert (tem); + + emit_move_insn (tem, gen_rtx_REG (reg_mode, regno + i)); + } +} + +/* Perform any needed actions needed for a function that is receiving a + variable number of arguments. + + CUM is as above. + + MODE and TYPE are the mode and type of the current parameter. + + PRETEND_SIZE is a variable that should be set to the amount of stack + that must be pushed by the prolog to pretend that our caller pushed + it. + + Normally, this macro will push all remaining incoming registers on the + stack and set PRETEND_SIZE to the length of the registers pushed. */ + +void +setup_incoming_varargs (cumulative_args_t cum, machine_mode mode, + tree type, int *pretend_size ATTRIBUTE_UNUSED, + int no_rtl) +{ + CUMULATIVE_ARGS next_cum; + int reg_size = TARGET_32BIT ? 4 : 8; + rtx save_area = NULL_RTX, mem; + int first_reg_offset; + alias_set_type set; + + /* Skip the last named argument. */ + next_cum = *get_cumulative_args (cum); + rs6000_function_arg_advance_1 (&next_cum, mode, type, true, 0); + + if (DEFAULT_ABI == ABI_V4) + { + first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG; + + if (! no_rtl) + { + int gpr_reg_num = 0, gpr_size = 0, fpr_size = 0; + HOST_WIDE_INT offset = 0; + + /* Try to optimize the size of the varargs save area. + The ABI requires that ap.reg_save_area is doubleword + aligned, but we don't need to allocate space for all + the bytes, only those to which we actually will save + anything. */ + if (cfun->va_list_gpr_size && first_reg_offset < GP_ARG_NUM_REG) + gpr_reg_num = GP_ARG_NUM_REG - first_reg_offset; + if (TARGET_HARD_FLOAT + && next_cum.fregno <= FP_ARG_V4_MAX_REG + && cfun->va_list_fpr_size) + { + if (gpr_reg_num) + fpr_size = (next_cum.fregno - FP_ARG_MIN_REG) + * UNITS_PER_FP_WORD; + if (cfun->va_list_fpr_size + < FP_ARG_V4_MAX_REG + 1 - next_cum.fregno) + fpr_size += cfun->va_list_fpr_size * UNITS_PER_FP_WORD; + else + fpr_size += (FP_ARG_V4_MAX_REG + 1 - next_cum.fregno) + * UNITS_PER_FP_WORD; + } + if (gpr_reg_num) + { + offset = -((first_reg_offset * reg_size) & ~7); + if (!fpr_size && gpr_reg_num > cfun->va_list_gpr_size) + { + gpr_reg_num = cfun->va_list_gpr_size; + if (reg_size == 4 && (first_reg_offset & 1)) + gpr_reg_num++; + } + gpr_size = (gpr_reg_num * reg_size + 7) & ~7; + } + else if (fpr_size) + offset = - (int) (next_cum.fregno - FP_ARG_MIN_REG) + * UNITS_PER_FP_WORD + - (int) (GP_ARG_NUM_REG * reg_size); + + if (gpr_size + fpr_size) + { + rtx reg_save_area + = assign_stack_local (BLKmode, gpr_size + fpr_size, 64); + gcc_assert (MEM_P (reg_save_area)); + reg_save_area = XEXP (reg_save_area, 0); + if (GET_CODE (reg_save_area) == PLUS) + { + gcc_assert (XEXP (reg_save_area, 0) + == virtual_stack_vars_rtx); + gcc_assert (CONST_INT_P (XEXP (reg_save_area, 1))); + offset += INTVAL (XEXP (reg_save_area, 1)); + } + else + gcc_assert (reg_save_area == virtual_stack_vars_rtx); + } + + cfun->machine->varargs_save_offset = offset; + save_area = plus_constant (Pmode, virtual_stack_vars_rtx, offset); + } + } + else + { + first_reg_offset = next_cum.words; + save_area = crtl->args.internal_arg_pointer; + + if (targetm.calls.must_pass_in_stack (mode, type)) + first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type); + } + + set = get_varargs_alias_set (); + if (! no_rtl && first_reg_offset < GP_ARG_NUM_REG + && cfun->va_list_gpr_size) + { + int n_gpr, nregs = GP_ARG_NUM_REG - first_reg_offset; + + if (va_list_gpr_counter_field) + /* V4 va_list_gpr_size counts number of registers needed. */ + n_gpr = cfun->va_list_gpr_size; + else + /* char * va_list instead counts number of bytes needed. */ + n_gpr = (cfun->va_list_gpr_size + reg_size - 1) / reg_size; + + if (nregs > n_gpr) + nregs = n_gpr; + + mem = gen_rtx_MEM (BLKmode, + plus_constant (Pmode, save_area, + first_reg_offset * reg_size)); + MEM_NOTRAP_P (mem) = 1; + set_mem_alias_set (mem, set); + set_mem_align (mem, BITS_PER_WORD); + + rs6000_move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem, + nregs); + } + + /* Save FP registers if needed. */ + if (DEFAULT_ABI == ABI_V4 + && TARGET_HARD_FLOAT + && ! no_rtl + && next_cum.fregno <= FP_ARG_V4_MAX_REG + && cfun->va_list_fpr_size) + { + int fregno = next_cum.fregno, nregs; + rtx cr1 = gen_rtx_REG (CCmode, CR1_REGNO); + rtx lab = gen_label_rtx (); + int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG) + * UNITS_PER_FP_WORD); + + emit_jump_insn + (gen_rtx_SET (pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, + gen_rtx_NE (VOIDmode, cr1, + const0_rtx), + gen_rtx_LABEL_REF (VOIDmode, lab), + pc_rtx))); + + for (nregs = 0; + fregno <= FP_ARG_V4_MAX_REG && nregs < cfun->va_list_fpr_size; + fregno++, off += UNITS_PER_FP_WORD, nregs++) + { + mem = gen_rtx_MEM (TARGET_HARD_FLOAT ? DFmode : SFmode, + plus_constant (Pmode, save_area, off)); + MEM_NOTRAP_P (mem) = 1; + set_mem_alias_set (mem, set); + set_mem_align (mem, GET_MODE_ALIGNMENT ( + TARGET_HARD_FLOAT ? DFmode : SFmode)); + emit_move_insn (mem, gen_rtx_REG ( + TARGET_HARD_FLOAT ? DFmode : SFmode, fregno)); + } + + emit_label (lab); + } +} + +/* Create the va_list data type. */ + +tree +rs6000_build_builtin_va_list (void) +{ + tree f_gpr, f_fpr, f_res, f_ovf, f_sav, record, type_decl; + + /* For AIX, prefer 'char *' because that's what the system + header files like. */ + if (DEFAULT_ABI != ABI_V4) + return build_pointer_type (char_type_node); + + record = (*lang_hooks.types.make_type) (RECORD_TYPE); + type_decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, + get_identifier ("__va_list_tag"), record); + + f_gpr = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("gpr"), + unsigned_char_type_node); + f_fpr = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("fpr"), + unsigned_char_type_node); + /* Give the two bytes of padding a name, so that -Wpadded won't warn on + every user file. */ + f_res = build_decl (BUILTINS_LOCATION, FIELD_DECL, + get_identifier ("reserved"), short_unsigned_type_node); + f_ovf = build_decl (BUILTINS_LOCATION, FIELD_DECL, + get_identifier ("overflow_arg_area"), + ptr_type_node); + f_sav = build_decl (BUILTINS_LOCATION, FIELD_DECL, + get_identifier ("reg_save_area"), + ptr_type_node); + + va_list_gpr_counter_field = f_gpr; + va_list_fpr_counter_field = f_fpr; + + DECL_FIELD_CONTEXT (f_gpr) = record; + DECL_FIELD_CONTEXT (f_fpr) = record; + DECL_FIELD_CONTEXT (f_res) = record; + DECL_FIELD_CONTEXT (f_ovf) = record; + DECL_FIELD_CONTEXT (f_sav) = record; + + TYPE_STUB_DECL (record) = type_decl; + TYPE_NAME (record) = type_decl; + TYPE_FIELDS (record) = f_gpr; + DECL_CHAIN (f_gpr) = f_fpr; + DECL_CHAIN (f_fpr) = f_res; + DECL_CHAIN (f_res) = f_ovf; + DECL_CHAIN (f_ovf) = f_sav; + + layout_type (record); + + /* The correct type is an array type of one element. */ + return build_array_type (record, build_index_type (size_zero_node)); +} + +/* Implement va_start. */ + +void +rs6000_va_start (tree valist, rtx nextarg) +{ + HOST_WIDE_INT words, n_gpr, n_fpr; + tree f_gpr, f_fpr, f_res, f_ovf, f_sav; + tree gpr, fpr, ovf, sav, t; + + /* Only SVR4 needs something special. */ + if (DEFAULT_ABI != ABI_V4) + { + std_expand_builtin_va_start (valist, nextarg); + return; + } + + f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); + f_fpr = DECL_CHAIN (f_gpr); + f_res = DECL_CHAIN (f_fpr); + f_ovf = DECL_CHAIN (f_res); + f_sav = DECL_CHAIN (f_ovf); + + valist = build_simple_mem_ref (valist); + gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), unshare_expr (valist), + f_fpr, NULL_TREE); + ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), unshare_expr (valist), + f_ovf, NULL_TREE); + sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist), + f_sav, NULL_TREE); + + /* Count number of gp and fp argument registers used. */ + words = crtl->args.info.words; + n_gpr = MIN (crtl->args.info.sysv_gregno - GP_ARG_MIN_REG, + GP_ARG_NUM_REG); + n_fpr = MIN (crtl->args.info.fregno - FP_ARG_MIN_REG, + FP_ARG_NUM_REG); + + if (TARGET_DEBUG_ARG) + fprintf (stderr, "va_start: words = " HOST_WIDE_INT_PRINT_DEC", n_gpr = " + HOST_WIDE_INT_PRINT_DEC", n_fpr = " HOST_WIDE_INT_PRINT_DEC"\n", + words, n_gpr, n_fpr); + + if (cfun->va_list_gpr_size) + { + t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr, + build_int_cst (NULL_TREE, n_gpr)); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); + } + + if (cfun->va_list_fpr_size) + { + t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr, + build_int_cst (NULL_TREE, n_fpr)); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); + +#ifdef HAVE_AS_GNU_ATTRIBUTE + if (call_ABI_of_interest (cfun->decl)) + rs6000_passes_float = true; +#endif + } + + /* Find the overflow area. */ + t = make_tree (TREE_TYPE (ovf), crtl->args.internal_arg_pointer); + if (words != 0) + t = fold_build_pointer_plus_hwi (t, words * MIN_UNITS_PER_WORD); + t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); + + /* If there were no va_arg invocations, don't set up the register + save area. */ + if (!cfun->va_list_gpr_size + && !cfun->va_list_fpr_size + && n_gpr < GP_ARG_NUM_REG + && n_fpr < FP_ARG_V4_MAX_REG) + return; + + /* Find the register save area. */ + t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx); + if (cfun->machine->varargs_save_offset) + t = fold_build_pointer_plus_hwi (t, cfun->machine->varargs_save_offset); + t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); +} + +/* Implement va_arg. */ + +tree +rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, + gimple_seq *post_p) +{ + tree f_gpr, f_fpr, f_res, f_ovf, f_sav; + tree gpr, fpr, ovf, sav, reg, t, u; + int size, rsize, n_reg, sav_ofs, sav_scale; + tree lab_false, lab_over, addr; + int align; + tree ptrtype = build_pointer_type_for_mode (type, ptr_mode, true); + int regalign = 0; + gimple *stmt; + + if (pass_by_reference (NULL, TYPE_MODE (type), type, false)) + { + t = rs6000_gimplify_va_arg (valist, ptrtype, pre_p, post_p); + return build_va_arg_indirect_ref (t); + } + + /* We need to deal with the fact that the darwin ppc64 ABI is defined by an + earlier version of gcc, with the property that it always applied alignment + adjustments to the va-args (even for zero-sized types). The cheapest way + to deal with this is to replicate the effect of the part of + std_gimplify_va_arg_expr that carries out the align adjust, for the case + of relevance. + We don't need to check for pass-by-reference because of the test above. + We can return a simplifed answer, since we know there's no offset to add. */ + + if (((TARGET_MACHO + && rs6000_darwin64_abi) + || DEFAULT_ABI == ABI_ELFv2 + || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm)) + && integer_zerop (TYPE_SIZE (type))) + { + unsigned HOST_WIDE_INT align, boundary; + tree valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL); + align = PARM_BOUNDARY / BITS_PER_UNIT; + boundary = rs6000_function_arg_boundary (TYPE_MODE (type), type); + if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) + boundary = MAX_SUPPORTED_STACK_ALIGNMENT; + boundary /= BITS_PER_UNIT; + if (boundary > align) + { + tree t ; + /* This updates arg ptr by the amount that would be necessary + to align the zero-sized (but not zero-alignment) item. */ + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, + fold_build_pointer_plus_hwi (valist_tmp, boundary - 1)); + gimplify_and_add (t, pre_p); + + t = fold_convert (sizetype, valist_tmp); + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, + fold_convert (TREE_TYPE (valist), + fold_build2 (BIT_AND_EXPR, sizetype, t, + size_int (-boundary)))); + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); + gimplify_and_add (t, pre_p); + } + /* Since it is zero-sized there's no increment for the item itself. */ + valist_tmp = fold_convert (build_pointer_type (type), valist_tmp); + return build_va_arg_indirect_ref (valist_tmp); + } + + if (DEFAULT_ABI != ABI_V4) + { + if (targetm.calls.split_complex_arg && TREE_CODE (type) == COMPLEX_TYPE) + { + tree elem_type = TREE_TYPE (type); + machine_mode elem_mode = TYPE_MODE (elem_type); + int elem_size = GET_MODE_SIZE (elem_mode); + + if (elem_size < UNITS_PER_WORD) + { + tree real_part, imag_part; + gimple_seq post = NULL; + + real_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p, + &post); + /* Copy the value into a temporary, lest the formal temporary + be reused out from under us. */ + real_part = get_initialized_tmp_var (real_part, pre_p, &post); + gimple_seq_add_seq (pre_p, post); + + imag_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p, + post_p); + + return build2 (COMPLEX_EXPR, type, real_part, imag_part); + } + } + + return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); + } + + f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); + f_fpr = DECL_CHAIN (f_gpr); + f_res = DECL_CHAIN (f_fpr); + f_ovf = DECL_CHAIN (f_res); + f_sav = DECL_CHAIN (f_ovf); + + gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); + fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), unshare_expr (valist), + f_fpr, NULL_TREE); + ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), unshare_expr (valist), + f_ovf, NULL_TREE); + sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist), + f_sav, NULL_TREE); + + size = int_size_in_bytes (type); + rsize = (size + 3) / 4; + int pad = 4 * rsize - size; + align = 1; + + machine_mode mode = TYPE_MODE (type); + if (abi_v4_pass_in_fpr (mode, false)) + { + /* FP args go in FP registers, if present. */ + reg = fpr; + n_reg = (size + 7) / 8; + sav_ofs = (TARGET_HARD_FLOAT ? 8 : 4) * 4; + sav_scale = (TARGET_HARD_FLOAT ? 8 : 4); + if (mode != SFmode && mode != SDmode) + align = 8; + } + else + { + /* Otherwise into GP registers. */ + reg = gpr; + n_reg = rsize; + sav_ofs = 0; + sav_scale = 4; + if (n_reg == 2) + align = 8; + } + + /* Pull the value out of the saved registers.... */ + + lab_over = NULL; + addr = create_tmp_var (ptr_type_node, "addr"); + + /* AltiVec vectors never go in registers when -mabi=altivec. */ + if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) + align = 16; + else + { + lab_false = create_artificial_label (input_location); + lab_over = create_artificial_label (input_location); + + /* Long long is aligned in the registers. As are any other 2 gpr + item such as complex int due to a historical mistake. */ + u = reg; + if (n_reg == 2 && reg == gpr) + { + regalign = 1; + u = build2 (BIT_AND_EXPR, TREE_TYPE (reg), unshare_expr (reg), + build_int_cst (TREE_TYPE (reg), n_reg - 1)); + u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), + unshare_expr (reg), u); + } + /* _Decimal128 is passed in even/odd fpr pairs; the stored + reg number is 0 for f1, so we want to make it odd. */ + else if (reg == fpr && mode == TDmode) + { + t = build2 (BIT_IOR_EXPR, TREE_TYPE (reg), unshare_expr (reg), + build_int_cst (TREE_TYPE (reg), 1)); + u = build2 (MODIFY_EXPR, void_type_node, unshare_expr (reg), t); + } + + t = fold_convert (TREE_TYPE (reg), size_int (8 - n_reg + 1)); + t = build2 (GE_EXPR, boolean_type_node, u, t); + u = build1 (GOTO_EXPR, void_type_node, lab_false); + t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE); + gimplify_and_add (t, pre_p); + + t = sav; + if (sav_ofs) + t = fold_build_pointer_plus_hwi (sav, sav_ofs); + + u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), unshare_expr (reg), + build_int_cst (TREE_TYPE (reg), n_reg)); + u = fold_convert (sizetype, u); + u = build2 (MULT_EXPR, sizetype, u, size_int (sav_scale)); + t = fold_build_pointer_plus (t, u); + + /* _Decimal32 varargs are located in the second word of the 64-bit + FP register for 32-bit binaries. */ + if (TARGET_32BIT && TARGET_HARD_FLOAT && mode == SDmode) + t = fold_build_pointer_plus_hwi (t, size); + + /* Args are passed right-aligned. */ + if (BYTES_BIG_ENDIAN) + t = fold_build_pointer_plus_hwi (t, pad); + + gimplify_assign (addr, t, pre_p); + + gimple_seq_add_stmt (pre_p, gimple_build_goto (lab_over)); + + stmt = gimple_build_label (lab_false); + gimple_seq_add_stmt (pre_p, stmt); + + if ((n_reg == 2 && !regalign) || n_reg > 2) + { + /* Ensure that we don't find any more args in regs. + Alignment has taken care of for special cases. */ + gimplify_assign (reg, build_int_cst (TREE_TYPE (reg), 8), pre_p); + } + } + + /* ... otherwise out of the overflow area. */ + + /* Care for on-stack alignment if needed. */ + t = ovf; + if (align != 1) + { + t = fold_build_pointer_plus_hwi (t, align - 1); + t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t, + build_int_cst (TREE_TYPE (t), -align)); + } + + /* Args are passed right-aligned. */ + if (BYTES_BIG_ENDIAN) + t = fold_build_pointer_plus_hwi (t, pad); + + gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue); + + gimplify_assign (unshare_expr (addr), t, pre_p); + + t = fold_build_pointer_plus_hwi (t, size); + gimplify_assign (unshare_expr (ovf), t, pre_p); + + if (lab_over) + { + stmt = gimple_build_label (lab_over); + gimple_seq_add_stmt (pre_p, stmt); + } + + if (STRICT_ALIGNMENT + && (TYPE_ALIGN (type) + > (unsigned) BITS_PER_UNIT * (align < 4 ? 4 : align))) + { + /* The value (of type complex double, for example) may not be + aligned in memory in the saved registers, so copy via a + temporary. (This is the same code as used for SPARC.) */ + tree tmp = create_tmp_var (type, "va_arg_tmp"); + tree dest_addr = build_fold_addr_expr (tmp); + + tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY), + 3, dest_addr, addr, size_int (rsize * 4)); + TREE_ADDRESSABLE (tmp) = 1; + + gimplify_and_add (copy, pre_p); + addr = dest_addr; + } + + addr = fold_convert (ptrtype, addr); + return build_va_arg_indirect_ref (addr); +} + +/* Builtins. */ + +static void +def_builtin (const char *name, tree type, enum rs6000_builtins code) +{ + tree t; + unsigned classify = rs6000_builtin_info[(int)code].attr; + const char *attr_string = ""; + + gcc_assert (name != NULL); + gcc_assert (IN_RANGE ((int)code, 0, (int)RS6000_BUILTIN_COUNT)); + + if (rs6000_builtin_decls[(int)code]) + fatal_error (input_location, + "internal error: builtin function %qs already processed", + name); + + rs6000_builtin_decls[(int)code] = t = + add_builtin_function (name, type, (int)code, BUILT_IN_MD, NULL, NULL_TREE); + + /* Set any special attributes. */ + if ((classify & RS6000_BTC_CONST) != 0) + { + /* const function, function only depends on the inputs. */ + TREE_READONLY (t) = 1; + TREE_NOTHROW (t) = 1; + attr_string = ", const"; + } + else if ((classify & RS6000_BTC_PURE) != 0) + { + /* pure function, function can read global memory, but does not set any + external state. */ + DECL_PURE_P (t) = 1; + TREE_NOTHROW (t) = 1; + attr_string = ", pure"; + } + else if ((classify & RS6000_BTC_FP) != 0) + { + /* Function is a math function. If rounding mode is on, then treat the + function as not reading global memory, but it can have arbitrary side + effects. If it is off, then assume the function is a const function. + This mimics the ATTR_MATHFN_FPROUNDING attribute in + builtin-attribute.def that is used for the math functions. */ + TREE_NOTHROW (t) = 1; + if (flag_rounding_math) + { + DECL_PURE_P (t) = 1; + DECL_IS_NOVOPS (t) = 1; + attr_string = ", fp, pure"; + } + else + { + TREE_READONLY (t) = 1; + attr_string = ", fp, const"; + } + } + else if ((classify & RS6000_BTC_ATTR_MASK) != 0) + gcc_unreachable (); + + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, code = %4d, %s%s\n", + (int)code, name, attr_string); +} + +/* Simple ternary operations: VECd = foo (VECa, VECb, VECc). */ + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_3arg[] = +{ +#include "rs6000-builtin.def" +}; + +/* DST operations: void foo (void *, const int, const char). */ + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_dst[] = +{ +#include "rs6000-builtin.def" +}; + +/* Simple binary operations: VECc = foo (VECa, VECb). */ + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_2arg[] = +{ +#include "rs6000-builtin.def" +}; + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +/* AltiVec predicates. */ + +static const struct builtin_description bdesc_altivec_preds[] = +{ +#include "rs6000-builtin.def" +}; + +/* ABS* operations. */ + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_abs[] = +{ +#include "rs6000-builtin.def" +}; + +/* Simple unary operations: VECb = foo (unsigned literal) or VECb = + foo (VECa). */ + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_1arg[] = +{ +#include "rs6000-builtin.def" +}; + +/* Simple no-argument operations: result = __builtin_darn_32 () */ + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_0arg[] = +{ +#include "rs6000-builtin.def" +}; + +/* HTM builtins. */ +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_htm[] = +{ +#include "rs6000-builtin.def" +}; + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_P + +/* Return true if a builtin function is overloaded. */ +bool +rs6000_overloaded_builtin_p (enum rs6000_builtins fncode) +{ + return (rs6000_builtin_info[(int)fncode].attr & RS6000_BTC_OVERLOADED) != 0; +} + +const char * +rs6000_overloaded_builtin_name (enum rs6000_builtins fncode) +{ + return rs6000_builtin_info[(int)fncode].name; +} + +/* Expand an expression EXP that calls a builtin without arguments. */ +static rtx +rs6000_expand_zeroop_builtin (enum insn_code icode, rtx target) +{ + rtx pat; + machine_mode tmode = insn_data[icode].operand[0].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + if (icode == CODE_FOR_rs6000_mffsl + && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) + { + error ("%<__builtin_mffsl%> not supported with %<-msoft-float%>"); + return const0_rtx; + } + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + pat = GEN_FCN (icode) (target); + if (! pat) + return 0; + emit_insn (pat); + + return target; +} + + +static rtx +rs6000_expand_mtfsf_builtin (enum insn_code icode, tree exp) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + machine_mode mode0 = insn_data[icode].operand[0].mode; + machine_mode mode1 = insn_data[icode].operand[1].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node || arg1 == error_mark_node) + return const0_rtx; + + if (!CONST_INT_P (op0) + || INTVAL (op0) > 255 + || INTVAL (op0) < 0) + { + error ("argument 1 must be an 8-bit field value"); + return const0_rtx; + } + + if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + if (! (*insn_data[icode].operand[1].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + pat = GEN_FCN (icode) (op0, op1); + if (!pat) + return const0_rtx; + emit_insn (pat); + + return NULL_RTX; +} + +static rtx +rs6000_expand_mtfsb_builtin (enum insn_code icode, tree exp) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + rtx op0 = expand_normal (arg0); + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + if (rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) + { + error ("%<__builtin_mtfsb0%> and %<__builtin_mtfsb1%> not supported with " + "%<-msoft-float%>"); + return const0_rtx; + } + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node) + return const0_rtx; + + /* Only allow bit numbers 0 to 31. */ + if (!u5bit_cint_operand (op0, VOIDmode)) + { + error ("Argument must be a constant between 0 and 31."); + return const0_rtx; + } + + pat = GEN_FCN (icode) (op0); + if (!pat) + return const0_rtx; + emit_insn (pat); + + return NULL_RTX; +} + +static rtx +rs6000_expand_set_fpscr_rn_builtin (enum insn_code icode, tree exp) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + rtx op0 = expand_normal (arg0); + machine_mode mode0 = insn_data[icode].operand[0].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + if (rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) + { + error ("%<__builtin_set_fpscr_rn%> not supported with %<-msoft-float%>"); + return const0_rtx; + } + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node) + return const0_rtx; + + /* If the argument is a constant, check the range. Argument can only be a + 2-bit value. Unfortunately, can't check the range of the value at + compile time if the argument is a variable. The least significant two + bits of the argument, regardless of type, are used to set the rounding + mode. All other bits are ignored. */ + if (CONST_INT_P (op0) && !const_0_to_3_operand(op0, VOIDmode)) + { + error ("Argument must be a value between 0 and 3."); + return const0_rtx; + } + + if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + pat = GEN_FCN (icode) (op0); + if (!pat) + return const0_rtx; + emit_insn (pat); + + return NULL_RTX; +} +static rtx +rs6000_expand_set_fpscr_drn_builtin (enum insn_code icode, tree exp) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + rtx op0 = expand_normal (arg0); + machine_mode mode0 = insn_data[icode].operand[0].mode; + + if (TARGET_32BIT) + /* Builtin not supported in 32-bit mode. */ + fatal_error (input_location, + "%<__builtin_set_fpscr_drn%> is not supported " + "in 32-bit mode"); + + if (rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) + { + error ("%<__builtin_set_fpscr_drn%> not supported with %<-msoft-float%>"); + return const0_rtx; + } + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node) + return const0_rtx; + + /* If the argument is a constant, check the range. Agrument can only be a + 3-bit value. Unfortunately, can't check the range of the value at + compile time if the argument is a variable. The least significant two + bits of the argument, regardless of type, are used to set the rounding + mode. All other bits are ignored. */ + if (CONST_INT_P (op0) && !const_0_to_7_operand(op0, VOIDmode)) + { + error ("Argument must be a value between 0 and 7."); + return const0_rtx; + } + + if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + pat = GEN_FCN (icode) (op0); + if (! pat) + return const0_rtx; + emit_insn (pat); + + return NULL_RTX; +} + +static rtx +rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + rtx op0 = expand_normal (arg0); + machine_mode tmode = insn_data[icode].operand[0].mode; + machine_mode mode0 = insn_data[icode].operand[1].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node) + return const0_rtx; + + if (icode == CODE_FOR_altivec_vspltisb + || icode == CODE_FOR_altivec_vspltish + || icode == CODE_FOR_altivec_vspltisw) + { + /* Only allow 5-bit *signed* literals. */ + if (!CONST_INT_P (op0) + || INTVAL (op0) > 15 + || INTVAL (op0) < -16) + { + error ("argument 1 must be a 5-bit signed literal"); + return CONST0_RTX (tmode); + } + } + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + pat = GEN_FCN (icode) (target, op0); + if (! pat) + return 0; + emit_insn (pat); + + return target; +} + +static rtx +altivec_expand_abs_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat, scratch1, scratch2; + tree arg0 = CALL_EXPR_ARG (exp, 0); + rtx op0 = expand_normal (arg0); + machine_mode tmode = insn_data[icode].operand[0].mode; + machine_mode mode0 = insn_data[icode].operand[1].mode; + + /* If we have invalid arguments, bail out before generating bad rtl. */ + if (arg0 == error_mark_node) + return const0_rtx; + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + scratch1 = gen_reg_rtx (mode0); + scratch2 = gen_reg_rtx (mode0); + + pat = GEN_FCN (icode) (target, op0, scratch1, scratch2); + if (! pat) + return 0; + emit_insn (pat); + + return target; +} + +static rtx +rs6000_expand_binop_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + machine_mode tmode = insn_data[icode].operand[0].mode; + machine_mode mode0 = insn_data[icode].operand[1].mode; + machine_mode mode1 = insn_data[icode].operand[2].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node || arg1 == error_mark_node) + return const0_rtx; + + if (icode == CODE_FOR_unpackv1ti + || icode == CODE_FOR_unpackkf + || icode == CODE_FOR_unpacktf + || icode == CODE_FOR_unpackif + || icode == CODE_FOR_unpacktd) + { + /* Only allow 1-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || !IN_RANGE (TREE_INT_CST_LOW (arg1), 0, 1)) + { + error ("argument 2 must be a 1-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_altivec_vspltw) + { + /* Only allow 2-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || TREE_INT_CST_LOW (arg1) & ~3) + { + error ("argument 2 must be a 2-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_altivec_vsplth) + { + /* Only allow 3-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || TREE_INT_CST_LOW (arg1) & ~7) + { + error ("argument 2 must be a 3-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_altivec_vspltb) + { + /* Only allow 4-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || TREE_INT_CST_LOW (arg1) & ~15) + { + error ("argument 2 must be a 4-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_altivec_vcfux + || icode == CODE_FOR_altivec_vcfsx + || icode == CODE_FOR_altivec_vctsxs + || icode == CODE_FOR_altivec_vctuxs) + { + /* Only allow 5-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || TREE_INT_CST_LOW (arg1) & ~0x1f) + { + error ("argument 2 must be a 5-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_dfptstsfi_eq_dd + || icode == CODE_FOR_dfptstsfi_lt_dd + || icode == CODE_FOR_dfptstsfi_gt_dd + || icode == CODE_FOR_dfptstsfi_unordered_dd + || icode == CODE_FOR_dfptstsfi_eq_td + || icode == CODE_FOR_dfptstsfi_lt_td + || icode == CODE_FOR_dfptstsfi_gt_td + || icode == CODE_FOR_dfptstsfi_unordered_td) + { + /* Only allow 6-bit unsigned literals. */ + STRIP_NOPS (arg0); + if (TREE_CODE (arg0) != INTEGER_CST + || !IN_RANGE (TREE_INT_CST_LOW (arg0), 0, 63)) + { + error ("argument 1 must be a 6-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_xststdcqp_kf + || icode == CODE_FOR_xststdcqp_tf + || icode == CODE_FOR_xststdcdp + || icode == CODE_FOR_xststdcsp + || icode == CODE_FOR_xvtstdcdp + || icode == CODE_FOR_xvtstdcsp) + { + /* Only allow 7-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || !IN_RANGE (TREE_INT_CST_LOW (arg1), 0, 127)) + { + error ("argument 2 must be a 7-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + pat = GEN_FCN (icode) (target, op0, op1); + if (! pat) + return 0; + emit_insn (pat); + + return target; +} + +static rtx +altivec_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat, scratch; + tree cr6_form = CALL_EXPR_ARG (exp, 0); + tree arg0 = CALL_EXPR_ARG (exp, 1); + tree arg1 = CALL_EXPR_ARG (exp, 2); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + machine_mode tmode = SImode; + machine_mode mode0 = insn_data[icode].operand[1].mode; + machine_mode mode1 = insn_data[icode].operand[2].mode; + int cr6_form_int; + + if (TREE_CODE (cr6_form) != INTEGER_CST) + { + error ("argument 1 of %qs must be a constant", + "__builtin_altivec_predicate"); + return const0_rtx; + } + else + cr6_form_int = TREE_INT_CST_LOW (cr6_form); + + gcc_assert (mode0 == mode1); + + /* If we have invalid arguments, bail out before generating bad rtl. */ + if (arg0 == error_mark_node || arg1 == error_mark_node) + return const0_rtx; + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + /* Note that for many of the relevant operations (e.g. cmpne or + cmpeq) with float or double operands, it makes more sense for the + mode of the allocated scratch register to select a vector of + integer. But the choice to copy the mode of operand 0 was made + long ago and there are no plans to change it. */ + scratch = gen_reg_rtx (mode0); + + pat = GEN_FCN (icode) (scratch, op0, op1); + if (! pat) + return 0; + emit_insn (pat); + + /* The vec_any* and vec_all* predicates use the same opcodes for two + different operations, but the bits in CR6 will be different + depending on what information we want. So we have to play tricks + with CR6 to get the right bits out. + + If you think this is disgusting, look at the specs for the + AltiVec predicates. */ + + switch (cr6_form_int) + { + case 0: + emit_insn (gen_cr6_test_for_zero (target)); + break; + case 1: + emit_insn (gen_cr6_test_for_zero_reverse (target)); + break; + case 2: + emit_insn (gen_cr6_test_for_lt (target)); + break; + case 3: + emit_insn (gen_cr6_test_for_lt_reverse (target)); + break; + default: + error ("argument 1 of %qs is out of range", + "__builtin_altivec_predicate"); + break; + } + + return target; +} + +rtx +swap_endian_selector_for_mode (machine_mode mode) +{ + unsigned int swap1[16] = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}; + unsigned int swap2[16] = {7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8}; + unsigned int swap4[16] = {3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12}; + unsigned int swap8[16] = {1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14}; + + unsigned int *swaparray, i; + rtx perm[16]; + + switch (mode) + { + case E_V1TImode: + swaparray = swap1; + break; + case E_V2DFmode: + case E_V2DImode: + swaparray = swap2; + break; + case E_V4SFmode: + case E_V4SImode: + swaparray = swap4; + break; + case E_V8HImode: + swaparray = swap8; + break; + default: + gcc_unreachable (); + } + + for (i = 0; i < 16; ++i) + perm[i] = GEN_INT (swaparray[i]); + + return force_reg (V16QImode, gen_rtx_CONST_VECTOR (V16QImode, + gen_rtvec_v (16, perm))); +} + +static rtx +altivec_expand_lv_builtin (enum insn_code icode, tree exp, rtx target, bool blk) +{ + rtx pat, addr; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + machine_mode tmode = insn_data[icode].operand[0].mode; + machine_mode mode0 = Pmode; + machine_mode mode1 = Pmode; + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node || arg1 == error_mark_node) + return const0_rtx; + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + op1 = copy_to_mode_reg (mode1, op1); + + /* For LVX, express the RTL accurately by ANDing the address with -16. + LVXL and LVE*X expand to use UNSPECs to hide their special behavior, + so the raw address is fine. */ + if (icode == CODE_FOR_altivec_lvx_v1ti + || icode == CODE_FOR_altivec_lvx_v2df + || icode == CODE_FOR_altivec_lvx_v2di + || icode == CODE_FOR_altivec_lvx_v4sf + || icode == CODE_FOR_altivec_lvx_v4si + || icode == CODE_FOR_altivec_lvx_v8hi + || icode == CODE_FOR_altivec_lvx_v16qi) + { + rtx rawaddr; + if (op0 == const0_rtx) + rawaddr = op1; + else + { + op0 = copy_to_mode_reg (mode0, op0); + rawaddr = gen_rtx_PLUS (Pmode, op1, op0); + } + addr = gen_rtx_AND (Pmode, rawaddr, gen_rtx_CONST_INT (Pmode, -16)); + addr = gen_rtx_MEM (blk ? BLKmode : tmode, addr); + + emit_insn (gen_rtx_SET (target, addr)); + } + else + { + if (op0 == const0_rtx) + addr = gen_rtx_MEM (blk ? BLKmode : tmode, op1); + else + { + op0 = copy_to_mode_reg (mode0, op0); + addr = gen_rtx_MEM (blk ? BLKmode : tmode, + gen_rtx_PLUS (Pmode, op1, op0)); + } + + pat = GEN_FCN (icode) (target, addr); + if (! pat) + return 0; + emit_insn (pat); + } + + return target; +} + +static rtx +altivec_expand_stxvl_builtin (enum insn_code icode, tree exp) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + rtx op2 = expand_normal (arg2); + machine_mode mode0 = insn_data[icode].operand[0].mode; + machine_mode mode1 = insn_data[icode].operand[1].mode; + machine_mode mode2 = insn_data[icode].operand[2].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return NULL_RTX; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node + || arg1 == error_mark_node + || arg2 == error_mark_node) + return NULL_RTX; + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + if (! (*insn_data[icode].operand[3].predicate) (op2, mode2)) + op2 = copy_to_mode_reg (mode2, op2); + + pat = GEN_FCN (icode) (op0, op1, op2); + if (pat) + emit_insn (pat); + + return NULL_RTX; +} + +static rtx +altivec_expand_stv_builtin (enum insn_code icode, tree exp) +{ + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + rtx op2 = expand_normal (arg2); + rtx pat, addr, rawaddr; + machine_mode tmode = insn_data[icode].operand[0].mode; + machine_mode smode = insn_data[icode].operand[1].mode; + machine_mode mode1 = Pmode; + machine_mode mode2 = Pmode; + + /* Invalid arguments. Bail before doing anything stoopid! */ + if (arg0 == error_mark_node + || arg1 == error_mark_node + || arg2 == error_mark_node) + return const0_rtx; + + op2 = copy_to_mode_reg (mode2, op2); + + /* For STVX, express the RTL accurately by ANDing the address with -16. + STVXL and STVE*X expand to use UNSPECs to hide their special behavior, + so the raw address is fine. */ + if (icode == CODE_FOR_altivec_stvx_v2df + || icode == CODE_FOR_altivec_stvx_v2di + || icode == CODE_FOR_altivec_stvx_v4sf + || icode == CODE_FOR_altivec_stvx_v4si + || icode == CODE_FOR_altivec_stvx_v8hi + || icode == CODE_FOR_altivec_stvx_v16qi) + { + if (op1 == const0_rtx) + rawaddr = op2; + else + { + op1 = copy_to_mode_reg (mode1, op1); + rawaddr = gen_rtx_PLUS (Pmode, op2, op1); + } + + addr = gen_rtx_AND (Pmode, rawaddr, gen_rtx_CONST_INT (Pmode, -16)); + addr = gen_rtx_MEM (tmode, addr); + + op0 = copy_to_mode_reg (tmode, op0); + + emit_insn (gen_rtx_SET (addr, op0)); + } + else + { + if (! (*insn_data[icode].operand[1].predicate) (op0, smode)) + op0 = copy_to_mode_reg (smode, op0); + + if (op1 == const0_rtx) + addr = gen_rtx_MEM (tmode, op2); + else + { + op1 = copy_to_mode_reg (mode1, op1); + addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op2, op1)); + } + + pat = GEN_FCN (icode) (addr, op0); + if (pat) + emit_insn (pat); + } + + return NULL_RTX; +} + +/* Return the appropriate SPR number associated with the given builtin. */ +static inline HOST_WIDE_INT +htm_spr_num (enum rs6000_builtins code) +{ + if (code == HTM_BUILTIN_GET_TFHAR + || code == HTM_BUILTIN_SET_TFHAR) + return TFHAR_SPR; + else if (code == HTM_BUILTIN_GET_TFIAR + || code == HTM_BUILTIN_SET_TFIAR) + return TFIAR_SPR; + else if (code == HTM_BUILTIN_GET_TEXASR + || code == HTM_BUILTIN_SET_TEXASR) + return TEXASR_SPR; + gcc_assert (code == HTM_BUILTIN_GET_TEXASRU + || code == HTM_BUILTIN_SET_TEXASRU); + return TEXASRU_SPR; +} + +/* Return the correct ICODE value depending on whether we are + setting or reading the HTM SPRs. */ +static inline enum insn_code +rs6000_htm_spr_icode (bool nonvoid) +{ + if (nonvoid) + return (TARGET_POWERPC64) ? CODE_FOR_htm_mfspr_di : CODE_FOR_htm_mfspr_si; + else + return (TARGET_POWERPC64) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si; +} + +/* Expand the HTM builtin in EXP and store the result in TARGET. + Store true in *EXPANDEDP if we found a builtin to expand. */ +static rtx +htm_expand_builtin (tree exp, rtx target, bool * expandedp) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; + enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); + const struct builtin_description *d; + size_t i; + + *expandedp = true; + + if (!TARGET_POWERPC64 + && (fcode == HTM_BUILTIN_TABORTDC + || fcode == HTM_BUILTIN_TABORTDCI)) + { + size_t uns_fcode = (size_t)fcode; + const char *name = rs6000_builtin_info[uns_fcode].name; + error ("builtin %qs is only valid in 64-bit mode", name); + return const0_rtx; + } + + /* Expand the HTM builtins. */ + d = bdesc_htm; + for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++) + if (d->code == fcode) + { + rtx op[MAX_HTM_OPERANDS], pat; + int nopnds = 0; + tree arg; + call_expr_arg_iterator iter; + unsigned attr = rs6000_builtin_info[fcode].attr; + enum insn_code icode = d->icode; + const struct insn_operand_data *insn_op; + bool uses_spr = (attr & RS6000_BTC_SPR); + rtx cr = NULL_RTX; + + if (uses_spr) + icode = rs6000_htm_spr_icode (nonvoid); + insn_op = &insn_data[icode].operand[0]; + + if (nonvoid) + { + machine_mode tmode = (uses_spr) ? insn_op->mode : E_SImode; + if (!target + || GET_MODE (target) != tmode + || (uses_spr && !(*insn_op->predicate) (target, tmode))) + target = gen_reg_rtx (tmode); + if (uses_spr) + op[nopnds++] = target; + } + + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + { + if (arg == error_mark_node || nopnds >= MAX_HTM_OPERANDS) + return const0_rtx; + + insn_op = &insn_data[icode].operand[nopnds]; + + op[nopnds] = expand_normal (arg); + + if (!(*insn_op->predicate) (op[nopnds], insn_op->mode)) + { + if (!strcmp (insn_op->constraint, "n")) + { + int arg_num = (nonvoid) ? nopnds : nopnds + 1; + if (!CONST_INT_P (op[nopnds])) + error ("argument %d must be an unsigned literal", arg_num); + else + error ("argument %d is an unsigned literal that is " + "out of range", arg_num); + return const0_rtx; + } + op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]); + } + + nopnds++; + } + + /* Handle the builtins for extended mnemonics. These accept + no arguments, but map to builtins that take arguments. */ + switch (fcode) + { + case HTM_BUILTIN_TENDALL: /* Alias for: tend. 1 */ + case HTM_BUILTIN_TRESUME: /* Alias for: tsr. 1 */ + op[nopnds++] = GEN_INT (1); + if (flag_checking) + attr |= RS6000_BTC_UNARY; + break; + case HTM_BUILTIN_TSUSPEND: /* Alias for: tsr. 0 */ + op[nopnds++] = GEN_INT (0); + if (flag_checking) + attr |= RS6000_BTC_UNARY; + break; + default: + break; + } + + /* If this builtin accesses SPRs, then pass in the appropriate + SPR number and SPR regno as the last two operands. */ + if (uses_spr) + { + machine_mode mode = (TARGET_POWERPC64) ? DImode : SImode; + op[nopnds++] = gen_rtx_CONST_INT (mode, htm_spr_num (fcode)); + } + /* If this builtin accesses a CR, then pass in a scratch + CR as the last operand. */ + else if (attr & RS6000_BTC_CR) + { cr = gen_reg_rtx (CCmode); + op[nopnds++] = cr; + } + + if (flag_checking) + { + int expected_nopnds = 0; + if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_UNARY) + expected_nopnds = 1; + else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_BINARY) + expected_nopnds = 2; + else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_TERNARY) + expected_nopnds = 3; + if (!(attr & RS6000_BTC_VOID)) + expected_nopnds += 1; + if (uses_spr) + expected_nopnds += 1; + + gcc_assert (nopnds == expected_nopnds + && nopnds <= MAX_HTM_OPERANDS); + } + + switch (nopnds) + { + case 1: + pat = GEN_FCN (icode) (op[0]); + break; + case 2: + pat = GEN_FCN (icode) (op[0], op[1]); + break; + case 3: + pat = GEN_FCN (icode) (op[0], op[1], op[2]); + break; + case 4: + pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]); + break; + default: + gcc_unreachable (); + } + if (!pat) + return NULL_RTX; + emit_insn (pat); + + if (attr & RS6000_BTC_CR) + { + if (fcode == HTM_BUILTIN_TBEGIN) + { + /* Emit code to set TARGET to true or false depending on + whether the tbegin. instruction successfully or failed + to start a transaction. We do this by placing the 1's + complement of CR's EQ bit into TARGET. */ + rtx scratch = gen_reg_rtx (SImode); + emit_insn (gen_rtx_SET (scratch, + gen_rtx_EQ (SImode, cr, + const0_rtx))); + emit_insn (gen_rtx_SET (target, + gen_rtx_XOR (SImode, scratch, + GEN_INT (1)))); + } + else + { + /* Emit code to copy the 4-bit condition register field + CR into the least significant end of register TARGET. */ + rtx scratch1 = gen_reg_rtx (SImode); + rtx scratch2 = gen_reg_rtx (SImode); + rtx subreg = simplify_gen_subreg (CCmode, scratch1, SImode, 0); + emit_insn (gen_movcc (subreg, cr)); + emit_insn (gen_lshrsi3 (scratch2, scratch1, GEN_INT (28))); + emit_insn (gen_andsi3 (target, scratch2, GEN_INT (0xf))); + } + } + + if (nonvoid) + return target; + return const0_rtx; + } + + *expandedp = false; + return NULL_RTX; +} + +/* Expand the CPU builtin in FCODE and store the result in TARGET. */ + +static rtx +cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED, + rtx target) +{ + /* __builtin_cpu_init () is a nop, so expand to nothing. */ + if (fcode == RS6000_BUILTIN_CPU_INIT) + return const0_rtx; + + if (target == 0 || GET_MODE (target) != SImode) + target = gen_reg_rtx (SImode); + +#ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB + tree arg = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0); + /* Target clones creates an ARRAY_REF instead of STRING_CST, convert it back + to a STRING_CST. */ + if (TREE_CODE (arg) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST + && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST + && compare_tree_int (TREE_OPERAND (arg, 1), 0) == 0) + arg = TREE_OPERAND (arg, 0); + + if (TREE_CODE (arg) != STRING_CST) + { + error ("builtin %qs only accepts a string argument", + rs6000_builtin_info[(size_t) fcode].name); + return const0_rtx; + } + + if (fcode == RS6000_BUILTIN_CPU_IS) + { + const char *cpu = TREE_STRING_POINTER (arg); + rtx cpuid = NULL_RTX; + for (size_t i = 0; i < ARRAY_SIZE (cpu_is_info); i++) + if (strcmp (cpu, cpu_is_info[i].cpu) == 0) + { + /* The CPUID value in the TCB is offset by _DL_FIRST_PLATFORM. */ + cpuid = GEN_INT (cpu_is_info[i].cpuid + _DL_FIRST_PLATFORM); + break; + } + if (cpuid == NULL_RTX) + { + /* Invalid CPU argument. */ + error ("cpu %qs is an invalid argument to builtin %qs", + cpu, rs6000_builtin_info[(size_t) fcode].name); + return const0_rtx; + } + + rtx platform = gen_reg_rtx (SImode); + rtx tcbmem = gen_const_mem (SImode, + gen_rtx_PLUS (Pmode, + gen_rtx_REG (Pmode, TLS_REGNUM), + GEN_INT (TCB_PLATFORM_OFFSET))); + emit_move_insn (platform, tcbmem); + emit_insn (gen_eqsi3 (target, platform, cpuid)); + } + else if (fcode == RS6000_BUILTIN_CPU_SUPPORTS) + { + const char *hwcap = TREE_STRING_POINTER (arg); + rtx mask = NULL_RTX; + int hwcap_offset; + for (size_t i = 0; i < ARRAY_SIZE (cpu_supports_info); i++) + if (strcmp (hwcap, cpu_supports_info[i].hwcap) == 0) + { + mask = GEN_INT (cpu_supports_info[i].mask); + hwcap_offset = TCB_HWCAP_OFFSET (cpu_supports_info[i].id); + break; + } + if (mask == NULL_RTX) + { + /* Invalid HWCAP argument. */ + error ("%s %qs is an invalid argument to builtin %qs", + "hwcap", hwcap, rs6000_builtin_info[(size_t) fcode].name); + return const0_rtx; + } + + rtx tcb_hwcap = gen_reg_rtx (SImode); + rtx tcbmem = gen_const_mem (SImode, + gen_rtx_PLUS (Pmode, + gen_rtx_REG (Pmode, TLS_REGNUM), + GEN_INT (hwcap_offset))); + emit_move_insn (tcb_hwcap, tcbmem); + rtx scratch1 = gen_reg_rtx (SImode); + emit_insn (gen_rtx_SET (scratch1, gen_rtx_AND (SImode, tcb_hwcap, mask))); + rtx scratch2 = gen_reg_rtx (SImode); + emit_insn (gen_eqsi3 (scratch2, scratch1, const0_rtx)); + emit_insn (gen_rtx_SET (target, gen_rtx_XOR (SImode, scratch2, const1_rtx))); + } + else + gcc_unreachable (); + + /* Record that we have expanded a CPU builtin, so that we can later + emit a reference to the special symbol exported by LIBC to ensure we + do not link against an old LIBC that doesn't support this feature. */ + cpu_builtin_p = true; + +#else + warning (0, "builtin %qs needs GLIBC (2.23 and newer) that exports hardware " + "capability bits", rs6000_builtin_info[(size_t) fcode].name); + + /* For old LIBCs, always return FALSE. */ + emit_move_insn (target, GEN_INT (0)); +#endif /* TARGET_LIBC_PROVIDES_HWCAP_IN_TCB */ + + return target; +} + +static rtx +rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + tree arg2 = CALL_EXPR_ARG (exp, 2); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + rtx op2 = expand_normal (arg2); + machine_mode tmode = insn_data[icode].operand[0].mode; + machine_mode mode0 = insn_data[icode].operand[1].mode; + machine_mode mode1 = insn_data[icode].operand[2].mode; + machine_mode mode2 = insn_data[icode].operand[3].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node + || arg1 == error_mark_node + || arg2 == error_mark_node) + return const0_rtx; + + /* Check and prepare argument depending on the instruction code. + + Note that a switch statement instead of the sequence of tests + would be incorrect as many of the CODE_FOR values could be + CODE_FOR_nothing and that would yield multiple alternatives + with identical values. We'd never reach here at runtime in + this case. */ + if (icode == CODE_FOR_altivec_vsldoi_v4sf + || icode == CODE_FOR_altivec_vsldoi_v2df + || icode == CODE_FOR_altivec_vsldoi_v4si + || icode == CODE_FOR_altivec_vsldoi_v8hi + || icode == CODE_FOR_altivec_vsldoi_v16qi) + { + /* Only allow 4-bit unsigned literals. */ + STRIP_NOPS (arg2); + if (TREE_CODE (arg2) != INTEGER_CST + || TREE_INT_CST_LOW (arg2) & ~0xf) + { + error ("argument 3 must be a 4-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_vsx_xxpermdi_v2df + || icode == CODE_FOR_vsx_xxpermdi_v2di + || icode == CODE_FOR_vsx_xxpermdi_v2df_be + || icode == CODE_FOR_vsx_xxpermdi_v2di_be + || icode == CODE_FOR_vsx_xxpermdi_v1ti + || icode == CODE_FOR_vsx_xxpermdi_v4sf + || icode == CODE_FOR_vsx_xxpermdi_v4si + || icode == CODE_FOR_vsx_xxpermdi_v8hi + || icode == CODE_FOR_vsx_xxpermdi_v16qi + || icode == CODE_FOR_vsx_xxsldwi_v16qi + || icode == CODE_FOR_vsx_xxsldwi_v8hi + || icode == CODE_FOR_vsx_xxsldwi_v4si + || icode == CODE_FOR_vsx_xxsldwi_v4sf + || icode == CODE_FOR_vsx_xxsldwi_v2di + || icode == CODE_FOR_vsx_xxsldwi_v2df) + { + /* Only allow 2-bit unsigned literals. */ + STRIP_NOPS (arg2); + if (TREE_CODE (arg2) != INTEGER_CST + || TREE_INT_CST_LOW (arg2) & ~0x3) + { + error ("argument 3 must be a 2-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_vsx_set_v2df + || icode == CODE_FOR_vsx_set_v2di + || icode == CODE_FOR_bcdadd + || icode == CODE_FOR_bcdadd_lt + || icode == CODE_FOR_bcdadd_eq + || icode == CODE_FOR_bcdadd_gt + || icode == CODE_FOR_bcdsub + || icode == CODE_FOR_bcdsub_lt + || icode == CODE_FOR_bcdsub_eq + || icode == CODE_FOR_bcdsub_gt) + { + /* Only allow 1-bit unsigned literals. */ + STRIP_NOPS (arg2); + if (TREE_CODE (arg2) != INTEGER_CST + || TREE_INT_CST_LOW (arg2) & ~0x1) + { + error ("argument 3 must be a 1-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_dfp_ddedpd_dd + || icode == CODE_FOR_dfp_ddedpd_td) + { + /* Only allow 2-bit unsigned literals where the value is 0 or 2. */ + STRIP_NOPS (arg0); + if (TREE_CODE (arg0) != INTEGER_CST + || TREE_INT_CST_LOW (arg2) & ~0x3) + { + error ("argument 1 must be 0 or 2"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_dfp_denbcd_dd + || icode == CODE_FOR_dfp_denbcd_td) + { + /* Only allow 1-bit unsigned literals. */ + STRIP_NOPS (arg0); + if (TREE_CODE (arg0) != INTEGER_CST + || TREE_INT_CST_LOW (arg0) & ~0x1) + { + error ("argument 1 must be a 1-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_dfp_dscli_dd + || icode == CODE_FOR_dfp_dscli_td + || icode == CODE_FOR_dfp_dscri_dd + || icode == CODE_FOR_dfp_dscri_td) + { + /* Only allow 6-bit unsigned literals. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST + || TREE_INT_CST_LOW (arg1) & ~0x3f) + { + error ("argument 2 must be a 6-bit unsigned literal"); + return CONST0_RTX (tmode); + } + } + else if (icode == CODE_FOR_crypto_vshasigmaw + || icode == CODE_FOR_crypto_vshasigmad) + { + /* Check whether the 2nd and 3rd arguments are integer constants and in + range and prepare arguments. */ + STRIP_NOPS (arg1); + if (TREE_CODE (arg1) != INTEGER_CST || wi::geu_p (wi::to_wide (arg1), 2)) + { + error ("argument 2 must be 0 or 1"); + return CONST0_RTX (tmode); + } + + STRIP_NOPS (arg2); + if (TREE_CODE (arg2) != INTEGER_CST + || wi::geu_p (wi::to_wide (arg2), 16)) + { + error ("argument 3 must be in the range [0, 15]"); + return CONST0_RTX (tmode); + } + } + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + if (! (*insn_data[icode].operand[3].predicate) (op2, mode2)) + op2 = copy_to_mode_reg (mode2, op2); + + pat = GEN_FCN (icode) (target, op0, op1, op2); + if (! pat) + return 0; + emit_insn (pat); + + return target; +} + + +/* Expand the dst builtins. */ +static rtx +altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, + bool *expandedp) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); + tree arg0, arg1, arg2; + machine_mode mode0, mode1; + rtx pat, op0, op1, op2; + const struct builtin_description *d; + size_t i; + + *expandedp = false; + + /* Handle DST variants. */ + d = bdesc_dst; + for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++) + if (d->code == fcode) + { + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); + op0 = expand_normal (arg0); + op1 = expand_normal (arg1); + op2 = expand_normal (arg2); + mode0 = insn_data[d->icode].operand[0].mode; + mode1 = insn_data[d->icode].operand[1].mode; + + /* Invalid arguments, bail out before generating bad rtl. */ + if (arg0 == error_mark_node + || arg1 == error_mark_node + || arg2 == error_mark_node) + return const0_rtx; + + *expandedp = true; + STRIP_NOPS (arg2); + if (TREE_CODE (arg2) != INTEGER_CST + || TREE_INT_CST_LOW (arg2) & ~0x3) + { + error ("argument to %qs must be a 2-bit unsigned literal", d->name); + return const0_rtx; + } + + if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (Pmode, op0); + if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + pat = GEN_FCN (d->icode) (op0, op1, op2); + if (pat != 0) + emit_insn (pat); + + return NULL_RTX; + } + + return NULL_RTX; +} + +/* Expand vec_init builtin. */ +static rtx +altivec_expand_vec_init_builtin (tree type, tree exp, rtx target) +{ + machine_mode tmode = TYPE_MODE (type); + machine_mode inner_mode = GET_MODE_INNER (tmode); + int i, n_elt = GET_MODE_NUNITS (tmode); + + gcc_assert (VECTOR_MODE_P (tmode)); + gcc_assert (n_elt == call_expr_nargs (exp)); + + if (!target || !register_operand (target, tmode)) + target = gen_reg_rtx (tmode); + + /* If we have a vector compromised of a single element, such as V1TImode, do + the initialization directly. */ + if (n_elt == 1 && GET_MODE_SIZE (tmode) == GET_MODE_SIZE (inner_mode)) + { + rtx x = expand_normal (CALL_EXPR_ARG (exp, 0)); + emit_move_insn (target, gen_lowpart (tmode, x)); + } + else + { + rtvec v = rtvec_alloc (n_elt); + + for (i = 0; i < n_elt; ++i) + { + rtx x = expand_normal (CALL_EXPR_ARG (exp, i)); + RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x); + } + + rs6000_expand_vector_init (target, gen_rtx_PARALLEL (tmode, v)); + } + + return target; +} + +/* Return the integer constant in ARG. Constrain it to be in the range + of the subparts of VEC_TYPE; issue an error if not. */ + +static int +get_element_number (tree vec_type, tree arg) +{ + unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1; + + if (!tree_fits_uhwi_p (arg) + || (elt = tree_to_uhwi (arg), elt > max)) + { + error ("selector must be an integer constant in the range [0, %wi]", max); + return 0; + } + + return elt; +} + +/* Expand vec_set builtin. */ +static rtx +altivec_expand_vec_set_builtin (tree exp) +{ + machine_mode tmode, mode1; + tree arg0, arg1, arg2; + int elt; + rtx op0, op1; + + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + arg2 = CALL_EXPR_ARG (exp, 2); + + tmode = TYPE_MODE (TREE_TYPE (arg0)); + mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))); + gcc_assert (VECTOR_MODE_P (tmode)); + + op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL); + op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL); + elt = get_element_number (TREE_TYPE (arg0), arg2); + + if (GET_MODE (op1) != mode1 && GET_MODE (op1) != VOIDmode) + op1 = convert_modes (mode1, GET_MODE (op1), op1, true); + + op0 = force_reg (tmode, op0); + op1 = force_reg (mode1, op1); + + rs6000_expand_vector_set (op0, op1, elt); + + return op0; +} + +/* Expand vec_ext builtin. */ +static rtx +altivec_expand_vec_ext_builtin (tree exp, rtx target) +{ + machine_mode tmode, mode0; + tree arg0, arg1; + rtx op0; + rtx op1; + + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + + op0 = expand_normal (arg0); + op1 = expand_normal (arg1); + + if (TREE_CODE (arg1) == INTEGER_CST) + { + unsigned HOST_WIDE_INT elt; + unsigned HOST_WIDE_INT size = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); + unsigned int truncated_selector; + /* Even if !tree_fits_uhwi_p (arg1)), TREE_INT_CST_LOW (arg0) + returns low-order bits of INTEGER_CST for modulo indexing. */ + elt = TREE_INT_CST_LOW (arg1); + truncated_selector = elt % size; + op1 = GEN_INT (truncated_selector); + } + + tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))); + mode0 = TYPE_MODE (TREE_TYPE (arg0)); + gcc_assert (VECTOR_MODE_P (mode0)); + + op0 = force_reg (mode0, op0); + + if (optimize || !target || !register_operand (target, tmode)) + target = gen_reg_rtx (tmode); + + rs6000_expand_vector_extract (target, op0, op1); + + return target; +} + +/* Expand the builtin in EXP and store the result in TARGET. Store + true in *EXPANDEDP if we found a builtin to expand. */ +static rtx +altivec_expand_builtin (tree exp, rtx target, bool *expandedp) +{ + const struct builtin_description *d; + size_t i; + enum insn_code icode; + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + tree arg0, arg1, arg2; + rtx op0, pat; + machine_mode tmode, mode0; + enum rs6000_builtins fcode + = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); + + if (rs6000_overloaded_builtin_p (fcode)) + { + *expandedp = true; + error ("unresolved overload for Altivec builtin %qF", fndecl); + + /* Given it is invalid, just generate a normal call. */ + return expand_call (exp, target, false); + } + + target = altivec_expand_dst_builtin (exp, target, expandedp); + if (*expandedp) + return target; + + *expandedp = true; + + switch (fcode) + { + case ALTIVEC_BUILTIN_STVX_V2DF: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v2df, exp); + case ALTIVEC_BUILTIN_STVX_V2DI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v2di, exp); + case ALTIVEC_BUILTIN_STVX_V4SF: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v4sf, exp); + case ALTIVEC_BUILTIN_STVX: + case ALTIVEC_BUILTIN_STVX_V4SI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v4si, exp); + case ALTIVEC_BUILTIN_STVX_V8HI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v8hi, exp); + case ALTIVEC_BUILTIN_STVX_V16QI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v16qi, exp); + case ALTIVEC_BUILTIN_STVEBX: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, exp); + case ALTIVEC_BUILTIN_STVEHX: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, exp); + case ALTIVEC_BUILTIN_STVEWX: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, exp); + case ALTIVEC_BUILTIN_STVXL_V2DF: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v2df, exp); + case ALTIVEC_BUILTIN_STVXL_V2DI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v2di, exp); + case ALTIVEC_BUILTIN_STVXL_V4SF: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v4sf, exp); + case ALTIVEC_BUILTIN_STVXL: + case ALTIVEC_BUILTIN_STVXL_V4SI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v4si, exp); + case ALTIVEC_BUILTIN_STVXL_V8HI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v8hi, exp); + case ALTIVEC_BUILTIN_STVXL_V16QI: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v16qi, exp); + + case ALTIVEC_BUILTIN_STVLX: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvlx, exp); + case ALTIVEC_BUILTIN_STVLXL: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvlxl, exp); + case ALTIVEC_BUILTIN_STVRX: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvrx, exp); + case ALTIVEC_BUILTIN_STVRXL: + return altivec_expand_stv_builtin (CODE_FOR_altivec_stvrxl, exp); + + case P9V_BUILTIN_STXVL: + return altivec_expand_stxvl_builtin (CODE_FOR_stxvl, exp); + + case P9V_BUILTIN_XST_LEN_R: + return altivec_expand_stxvl_builtin (CODE_FOR_xst_len_r, exp); + + case VSX_BUILTIN_STXVD2X_V1TI: + return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v1ti, exp); + case VSX_BUILTIN_STXVD2X_V2DF: + return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v2df, exp); + case VSX_BUILTIN_STXVD2X_V2DI: + return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v2di, exp); + case VSX_BUILTIN_STXVW4X_V4SF: + return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v4sf, exp); + case VSX_BUILTIN_STXVW4X_V4SI: + return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v4si, exp); + case VSX_BUILTIN_STXVW4X_V8HI: + return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v8hi, exp); + case VSX_BUILTIN_STXVW4X_V16QI: + return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v16qi, exp); + + /* For the following on big endian, it's ok to use any appropriate + unaligned-supporting store, so use a generic expander. For + little-endian, the exact element-reversing instruction must + be used. */ + case VSX_BUILTIN_ST_ELEMREV_V1TI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v1ti + : CODE_FOR_vsx_st_elemrev_v1ti); + return altivec_expand_stv_builtin (code, exp); + } + case VSX_BUILTIN_ST_ELEMREV_V2DF: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v2df + : CODE_FOR_vsx_st_elemrev_v2df); + return altivec_expand_stv_builtin (code, exp); + } + case VSX_BUILTIN_ST_ELEMREV_V2DI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v2di + : CODE_FOR_vsx_st_elemrev_v2di); + return altivec_expand_stv_builtin (code, exp); + } + case VSX_BUILTIN_ST_ELEMREV_V4SF: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v4sf + : CODE_FOR_vsx_st_elemrev_v4sf); + return altivec_expand_stv_builtin (code, exp); + } + case VSX_BUILTIN_ST_ELEMREV_V4SI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v4si + : CODE_FOR_vsx_st_elemrev_v4si); + return altivec_expand_stv_builtin (code, exp); + } + case VSX_BUILTIN_ST_ELEMREV_V8HI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v8hi + : CODE_FOR_vsx_st_elemrev_v8hi); + return altivec_expand_stv_builtin (code, exp); + } + case VSX_BUILTIN_ST_ELEMREV_V16QI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v16qi + : CODE_FOR_vsx_st_elemrev_v16qi); + return altivec_expand_stv_builtin (code, exp); + } + + case ALTIVEC_BUILTIN_MFVSCR: + icode = CODE_FOR_altivec_mfvscr; + tmode = insn_data[icode].operand[0].mode; + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + pat = GEN_FCN (icode) (target); + if (! pat) + return 0; + emit_insn (pat); + return target; + + case ALTIVEC_BUILTIN_MTVSCR: + icode = CODE_FOR_altivec_mtvscr; + arg0 = CALL_EXPR_ARG (exp, 0); + op0 = expand_normal (arg0); + mode0 = insn_data[icode].operand[0].mode; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node) + return const0_rtx; + + if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + pat = GEN_FCN (icode) (op0); + if (pat) + emit_insn (pat); + return NULL_RTX; + + case ALTIVEC_BUILTIN_DSSALL: + emit_insn (gen_altivec_dssall ()); + return NULL_RTX; + + case ALTIVEC_BUILTIN_DSS: + icode = CODE_FOR_altivec_dss; + arg0 = CALL_EXPR_ARG (exp, 0); + STRIP_NOPS (arg0); + op0 = expand_normal (arg0); + mode0 = insn_data[icode].operand[0].mode; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node) + return const0_rtx; + + if (TREE_CODE (arg0) != INTEGER_CST + || TREE_INT_CST_LOW (arg0) & ~0x3) + { + error ("argument to %qs must be a 2-bit unsigned literal", "dss"); + return const0_rtx; + } + + if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + emit_insn (gen_altivec_dss (op0)); + return NULL_RTX; + + case ALTIVEC_BUILTIN_VEC_INIT_V4SI: + case ALTIVEC_BUILTIN_VEC_INIT_V8HI: + case ALTIVEC_BUILTIN_VEC_INIT_V16QI: + case ALTIVEC_BUILTIN_VEC_INIT_V4SF: + case VSX_BUILTIN_VEC_INIT_V2DF: + case VSX_BUILTIN_VEC_INIT_V2DI: + case VSX_BUILTIN_VEC_INIT_V1TI: + return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target); + + case ALTIVEC_BUILTIN_VEC_SET_V4SI: + case ALTIVEC_BUILTIN_VEC_SET_V8HI: + case ALTIVEC_BUILTIN_VEC_SET_V16QI: + case ALTIVEC_BUILTIN_VEC_SET_V4SF: + case VSX_BUILTIN_VEC_SET_V2DF: + case VSX_BUILTIN_VEC_SET_V2DI: + case VSX_BUILTIN_VEC_SET_V1TI: + return altivec_expand_vec_set_builtin (exp); + + case ALTIVEC_BUILTIN_VEC_EXT_V4SI: + case ALTIVEC_BUILTIN_VEC_EXT_V8HI: + case ALTIVEC_BUILTIN_VEC_EXT_V16QI: + case ALTIVEC_BUILTIN_VEC_EXT_V4SF: + case VSX_BUILTIN_VEC_EXT_V2DF: + case VSX_BUILTIN_VEC_EXT_V2DI: + case VSX_BUILTIN_VEC_EXT_V1TI: + return altivec_expand_vec_ext_builtin (exp, target); + + case P9V_BUILTIN_VEC_EXTRACT4B: + arg1 = CALL_EXPR_ARG (exp, 1); + STRIP_NOPS (arg1); + + /* Generate a normal call if it is invalid. */ + if (arg1 == error_mark_node) + return expand_call (exp, target, false); + + if (TREE_CODE (arg1) != INTEGER_CST || TREE_INT_CST_LOW (arg1) > 12) + { + error ("second argument to %qs must be [0, 12]", "vec_vextract4b"); + return expand_call (exp, target, false); + } + break; + + case P9V_BUILTIN_VEC_INSERT4B: + arg2 = CALL_EXPR_ARG (exp, 2); + STRIP_NOPS (arg2); + + /* Generate a normal call if it is invalid. */ + if (arg2 == error_mark_node) + return expand_call (exp, target, false); + + if (TREE_CODE (arg2) != INTEGER_CST || TREE_INT_CST_LOW (arg2) > 12) + { + error ("third argument to %qs must be [0, 12]", "vec_vinsert4b"); + return expand_call (exp, target, false); + } + break; + + default: + break; + /* Fall through. */ + } + + /* Expand abs* operations. */ + d = bdesc_abs; + for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++) + if (d->code == fcode) + return altivec_expand_abs_builtin (d->icode, exp, target); + + /* Expand the AltiVec predicates. */ + d = bdesc_altivec_preds; + for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, d++) + if (d->code == fcode) + return altivec_expand_predicate_builtin (d->icode, exp, target); + + /* LV* are funky. We initialized them differently. */ + switch (fcode) + { + case ALTIVEC_BUILTIN_LVSL: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsl, + exp, target, false); + case ALTIVEC_BUILTIN_LVSR: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsr, + exp, target, false); + case ALTIVEC_BUILTIN_LVEBX: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvebx, + exp, target, false); + case ALTIVEC_BUILTIN_LVEHX: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvehx, + exp, target, false); + case ALTIVEC_BUILTIN_LVEWX: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvewx, + exp, target, false); + case ALTIVEC_BUILTIN_LVXL_V2DF: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v2df, + exp, target, false); + case ALTIVEC_BUILTIN_LVXL_V2DI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v2di, + exp, target, false); + case ALTIVEC_BUILTIN_LVXL_V4SF: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v4sf, + exp, target, false); + case ALTIVEC_BUILTIN_LVXL: + case ALTIVEC_BUILTIN_LVXL_V4SI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v4si, + exp, target, false); + case ALTIVEC_BUILTIN_LVXL_V8HI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v8hi, + exp, target, false); + case ALTIVEC_BUILTIN_LVXL_V16QI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v16qi, + exp, target, false); + case ALTIVEC_BUILTIN_LVX_V1TI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v1ti, + exp, target, false); + case ALTIVEC_BUILTIN_LVX_V2DF: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v2df, + exp, target, false); + case ALTIVEC_BUILTIN_LVX_V2DI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v2di, + exp, target, false); + case ALTIVEC_BUILTIN_LVX_V4SF: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v4sf, + exp, target, false); + case ALTIVEC_BUILTIN_LVX: + case ALTIVEC_BUILTIN_LVX_V4SI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v4si, + exp, target, false); + case ALTIVEC_BUILTIN_LVX_V8HI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v8hi, + exp, target, false); + case ALTIVEC_BUILTIN_LVX_V16QI: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v16qi, + exp, target, false); + case ALTIVEC_BUILTIN_LVLX: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvlx, + exp, target, true); + case ALTIVEC_BUILTIN_LVLXL: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvlxl, + exp, target, true); + case ALTIVEC_BUILTIN_LVRX: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvrx, + exp, target, true); + case ALTIVEC_BUILTIN_LVRXL: + return altivec_expand_lv_builtin (CODE_FOR_altivec_lvrxl, + exp, target, true); + case VSX_BUILTIN_LXVD2X_V1TI: + return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v1ti, + exp, target, false); + case VSX_BUILTIN_LXVD2X_V2DF: + return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v2df, + exp, target, false); + case VSX_BUILTIN_LXVD2X_V2DI: + return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v2di, + exp, target, false); + case VSX_BUILTIN_LXVW4X_V4SF: + return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v4sf, + exp, target, false); + case VSX_BUILTIN_LXVW4X_V4SI: + return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v4si, + exp, target, false); + case VSX_BUILTIN_LXVW4X_V8HI: + return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v8hi, + exp, target, false); + case VSX_BUILTIN_LXVW4X_V16QI: + return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v16qi, + exp, target, false); + /* For the following on big endian, it's ok to use any appropriate + unaligned-supporting load, so use a generic expander. For + little-endian, the exact element-reversing instruction must + be used. */ + case VSX_BUILTIN_LD_ELEMREV_V2DF: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v2df + : CODE_FOR_vsx_ld_elemrev_v2df); + return altivec_expand_lv_builtin (code, exp, target, false); + } + case VSX_BUILTIN_LD_ELEMREV_V1TI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v1ti + : CODE_FOR_vsx_ld_elemrev_v1ti); + return altivec_expand_lv_builtin (code, exp, target, false); + } + case VSX_BUILTIN_LD_ELEMREV_V2DI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v2di + : CODE_FOR_vsx_ld_elemrev_v2di); + return altivec_expand_lv_builtin (code, exp, target, false); + } + case VSX_BUILTIN_LD_ELEMREV_V4SF: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v4sf + : CODE_FOR_vsx_ld_elemrev_v4sf); + return altivec_expand_lv_builtin (code, exp, target, false); + } + case VSX_BUILTIN_LD_ELEMREV_V4SI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v4si + : CODE_FOR_vsx_ld_elemrev_v4si); + return altivec_expand_lv_builtin (code, exp, target, false); + } + case VSX_BUILTIN_LD_ELEMREV_V8HI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v8hi + : CODE_FOR_vsx_ld_elemrev_v8hi); + return altivec_expand_lv_builtin (code, exp, target, false); + } + case VSX_BUILTIN_LD_ELEMREV_V16QI: + { + enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v16qi + : CODE_FOR_vsx_ld_elemrev_v16qi); + return altivec_expand_lv_builtin (code, exp, target, false); + } + break; + default: + break; + /* Fall through. */ + } + + *expandedp = false; + return NULL_RTX; +} + +/* Check whether a builtin function is supported in this target + configuration. */ +bool +rs6000_builtin_is_supported_p (enum rs6000_builtins fncode) +{ + HOST_WIDE_INT fnmask = rs6000_builtin_info[fncode].mask; + if ((fnmask & rs6000_builtin_mask) != fnmask) + return false; + else + return true; +} + +/* Raise an error message for a builtin function that is called without the + appropriate target options being set. */ + +void +rs6000_invalid_builtin (enum rs6000_builtins fncode) +{ + size_t uns_fncode = (size_t) fncode; + const char *name = rs6000_builtin_info[uns_fncode].name; + HOST_WIDE_INT fnmask = rs6000_builtin_info[uns_fncode].mask; + + gcc_assert (name != NULL); + if ((fnmask & RS6000_BTM_CELL) != 0) + error ("%qs is only valid for the cell processor", name); + else if ((fnmask & RS6000_BTM_VSX) != 0) + error ("%qs requires the %qs option", name, "-mvsx"); + else if ((fnmask & RS6000_BTM_HTM) != 0) + error ("%qs requires the %qs option", name, "-mhtm"); + else if ((fnmask & RS6000_BTM_ALTIVEC) != 0) + error ("%qs requires the %qs option", name, "-maltivec"); + else if ((fnmask & (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) + == (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) + error ("%qs requires the %qs and %qs options", name, "-mhard-dfp", + "-mpower8-vector"); + else if ((fnmask & RS6000_BTM_DFP) != 0) + error ("%qs requires the %qs option", name, "-mhard-dfp"); + else if ((fnmask & RS6000_BTM_P8_VECTOR) != 0) + error ("%qs requires the %qs option", name, "-mpower8-vector"); + else if ((fnmask & (RS6000_BTM_P9_VECTOR | RS6000_BTM_64BIT)) + == (RS6000_BTM_P9_VECTOR | RS6000_BTM_64BIT)) + error ("%qs requires the %qs and %qs options", name, "-mcpu=power9", + "-m64"); + else if ((fnmask & RS6000_BTM_P9_VECTOR) != 0) + error ("%qs requires the %qs option", name, "-mcpu=power9"); + else if ((fnmask & (RS6000_BTM_P9_MISC | RS6000_BTM_64BIT)) + == (RS6000_BTM_P9_MISC | RS6000_BTM_64BIT)) + error ("%qs requires the %qs and %qs options", name, "-mcpu=power9", + "-m64"); + else if ((fnmask & RS6000_BTM_P9_MISC) == RS6000_BTM_P9_MISC) + error ("%qs requires the %qs option", name, "-mcpu=power9"); + else if ((fnmask & RS6000_BTM_LDBL128) == RS6000_BTM_LDBL128) + { + if (!TARGET_HARD_FLOAT) + error ("%qs requires the %qs option", name, "-mhard-float"); + else + error ("%qs requires the %qs option", name, + TARGET_IEEEQUAD ? "-mabi=ibmlongdouble" : "-mlong-double-128"); + } + else if ((fnmask & RS6000_BTM_HARD_FLOAT) != 0) + error ("%qs requires the %qs option", name, "-mhard-float"); + else if ((fnmask & RS6000_BTM_FLOAT128_HW) != 0) + error ("%qs requires ISA 3.0 IEEE 128-bit floating point", name); + else if ((fnmask & RS6000_BTM_FLOAT128) != 0) + error ("%qs requires the %qs option", name, "%<-mfloat128%>"); + else if ((fnmask & (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64)) + == (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64)) + error ("%qs requires the %qs (or newer), and %qs or %qs options", + name, "-mcpu=power7", "-m64", "-mpowerpc64"); + else + error ("%qs is not supported with the current options", name); +} + +/* Target hook for early folding of built-ins, shamelessly stolen + from ia64.c. */ + +tree +rs6000_fold_builtin (tree fndecl ATTRIBUTE_UNUSED, + int n_args ATTRIBUTE_UNUSED, + tree *args ATTRIBUTE_UNUSED, + bool ignore ATTRIBUTE_UNUSED) +{ +#ifdef SUBTARGET_FOLD_BUILTIN + return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore); +#else + return NULL_TREE; +#endif +} + +/* Helper function to sort out which built-ins may be valid without having + a LHS. */ +static bool +rs6000_builtin_valid_without_lhs (enum rs6000_builtins fn_code) +{ + switch (fn_code) + { + case ALTIVEC_BUILTIN_STVX_V16QI: + case ALTIVEC_BUILTIN_STVX_V8HI: + case ALTIVEC_BUILTIN_STVX_V4SI: + case ALTIVEC_BUILTIN_STVX_V4SF: + case ALTIVEC_BUILTIN_STVX_V2DI: + case ALTIVEC_BUILTIN_STVX_V2DF: + case VSX_BUILTIN_STXVW4X_V16QI: + case VSX_BUILTIN_STXVW4X_V8HI: + case VSX_BUILTIN_STXVW4X_V4SF: + case VSX_BUILTIN_STXVW4X_V4SI: + case VSX_BUILTIN_STXVD2X_V2DF: + case VSX_BUILTIN_STXVD2X_V2DI: + return true; + default: + return false; + } +} + +/* Helper function to handle the gimple folding of a vector compare + operation. This sets up true/false vectors, and uses the + VEC_COND_EXPR operation. + CODE indicates which comparison is to be made. (EQ, GT, ...). + TYPE indicates the type of the result. */ +static tree +fold_build_vec_cmp (tree_code code, tree type, + tree arg0, tree arg1) +{ + tree cmp_type = build_same_sized_truth_vector_type (type); + tree zero_vec = build_zero_cst (type); + tree minus_one_vec = build_minus_one_cst (type); + tree cmp = fold_build2 (code, cmp_type, arg0, arg1); + return fold_build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec); +} + +/* Helper function to handle the in-between steps for the + vector compare built-ins. */ +static void +fold_compare_helper (gimple_stmt_iterator *gsi, tree_code code, gimple *stmt) +{ + tree arg0 = gimple_call_arg (stmt, 0); + tree arg1 = gimple_call_arg (stmt, 1); + tree lhs = gimple_call_lhs (stmt); + tree cmp = fold_build_vec_cmp (code, TREE_TYPE (lhs), arg0, arg1); + gimple *g = gimple_build_assign (lhs, cmp); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); +} + +/* Helper function to map V2DF and V4SF types to their + integral equivalents (V2DI and V4SI). */ +tree map_to_integral_tree_type (tree input_tree_type) +{ + if (INTEGRAL_TYPE_P (TREE_TYPE (input_tree_type))) + return input_tree_type; + else + { + if (types_compatible_p (TREE_TYPE (input_tree_type), + TREE_TYPE (V2DF_type_node))) + return V2DI_type_node; + else if (types_compatible_p (TREE_TYPE (input_tree_type), + TREE_TYPE (V4SF_type_node))) + return V4SI_type_node; + else + gcc_unreachable (); + } +} + +/* Helper function to handle the vector merge[hl] built-ins. The + implementation difference between h and l versions for this code are in + the values used when building of the permute vector for high word versus + low word merge. The variance is keyed off the use_high parameter. */ +static void +fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high) +{ + tree arg0 = gimple_call_arg (stmt, 0); + tree arg1 = gimple_call_arg (stmt, 1); + tree lhs = gimple_call_lhs (stmt); + tree lhs_type = TREE_TYPE (lhs); + int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type); + int midpoint = n_elts / 2; + int offset = 0; + + if (use_high == 1) + offset = midpoint; + + /* The permute_type will match the lhs for integral types. For double and + float types, the permute type needs to map to the V2 or V4 type that + matches size. */ + tree permute_type; + permute_type = map_to_integral_tree_type (lhs_type); + tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1); + + for (int i = 0; i < midpoint; i++) + { + elts.safe_push (build_int_cst (TREE_TYPE (permute_type), + offset + i)); + elts.safe_push (build_int_cst (TREE_TYPE (permute_type), + offset + n_elts + i)); + } + + tree permute = elts.build (); + + gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); +} + +/* Helper function to handle the vector merge[eo] built-ins. */ +static void +fold_mergeeo_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_odd) +{ + tree arg0 = gimple_call_arg (stmt, 0); + tree arg1 = gimple_call_arg (stmt, 1); + tree lhs = gimple_call_lhs (stmt); + tree lhs_type = TREE_TYPE (lhs); + int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type); + + /* The permute_type will match the lhs for integral types. For double and + float types, the permute type needs to map to the V2 or V4 type that + matches size. */ + tree permute_type; + permute_type = map_to_integral_tree_type (lhs_type); + + tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1); + + /* Build the permute vector. */ + for (int i = 0; i < n_elts / 2; i++) + { + elts.safe_push (build_int_cst (TREE_TYPE (permute_type), + 2*i + use_odd)); + elts.safe_push (build_int_cst (TREE_TYPE (permute_type), + 2*i + use_odd + n_elts)); + } + + tree permute = elts.build (); + + gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); +} + +/* Fold a machine-dependent built-in in GIMPLE. (For folding into + a constant, use rs6000_fold_builtin.) */ + +bool +rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) +{ + gimple *stmt = gsi_stmt (*gsi); + tree fndecl = gimple_call_fndecl (stmt); + gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD); + enum rs6000_builtins fn_code + = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); + tree arg0, arg1, lhs, temp; + enum tree_code bcode; + gimple *g; + + size_t uns_fncode = (size_t) fn_code; + enum insn_code icode = rs6000_builtin_info[uns_fncode].icode; + const char *fn_name1 = rs6000_builtin_info[uns_fncode].name; + const char *fn_name2 = (icode != CODE_FOR_nothing) + ? get_insn_name ((int) icode) + : "nothing"; + + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_gimple_fold_builtin %d %s %s\n", + fn_code, fn_name1, fn_name2); + + if (!rs6000_fold_gimple) + return false; + + /* Prevent gimple folding for code that does not have a LHS, unless it is + allowed per the rs6000_builtin_valid_without_lhs helper function. */ + if (!gimple_call_lhs (stmt) && !rs6000_builtin_valid_without_lhs (fn_code)) + return false; + + /* Don't fold invalid builtins, let rs6000_expand_builtin diagnose it. */ + HOST_WIDE_INT mask = rs6000_builtin_info[uns_fncode].mask; + bool func_valid_p = (rs6000_builtin_mask & mask) == mask; + if (!func_valid_p) + return false; + + switch (fn_code) + { + /* Flavors of vec_add. We deliberately don't expand + P8V_BUILTIN_VADDUQM as it gets lowered from V1TImode to + TImode, resulting in much poorer code generation. */ + case ALTIVEC_BUILTIN_VADDUBM: + case ALTIVEC_BUILTIN_VADDUHM: + case ALTIVEC_BUILTIN_VADDUWM: + case P8V_BUILTIN_VADDUDM: + case ALTIVEC_BUILTIN_VADDFP: + case VSX_BUILTIN_XVADDDP: + bcode = PLUS_EXPR; + do_binary: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (lhs))) + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (lhs)))) + { + /* Ensure the binary operation is performed in a type + that wraps if it is integral type. */ + gimple_seq stmts = NULL; + tree type = unsigned_type_for (TREE_TYPE (lhs)); + tree uarg0 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + type, arg0); + tree uarg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + type, arg1); + tree res = gimple_build (&stmts, gimple_location (stmt), bcode, + type, uarg0, uarg1); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + g = gimple_build_assign (lhs, VIEW_CONVERT_EXPR, + build1 (VIEW_CONVERT_EXPR, + TREE_TYPE (lhs), res)); + gsi_replace (gsi, g, true); + return true; + } + g = gimple_build_assign (lhs, bcode, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_sub. We deliberately don't expand + P8V_BUILTIN_VSUBUQM. */ + case ALTIVEC_BUILTIN_VSUBUBM: + case ALTIVEC_BUILTIN_VSUBUHM: + case ALTIVEC_BUILTIN_VSUBUWM: + case P8V_BUILTIN_VSUBUDM: + case ALTIVEC_BUILTIN_VSUBFP: + case VSX_BUILTIN_XVSUBDP: + bcode = MINUS_EXPR; + goto do_binary; + case VSX_BUILTIN_XVMULSP: + case VSX_BUILTIN_XVMULDP: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, MULT_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Even element flavors of vec_mul (signed). */ + case ALTIVEC_BUILTIN_VMULESB: + case ALTIVEC_BUILTIN_VMULESH: + case P8V_BUILTIN_VMULESW: + /* Even element flavors of vec_mul (unsigned). */ + case ALTIVEC_BUILTIN_VMULEUB: + case ALTIVEC_BUILTIN_VMULEUH: + case P8V_BUILTIN_VMULEUW: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, VEC_WIDEN_MULT_EVEN_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Odd element flavors of vec_mul (signed). */ + case ALTIVEC_BUILTIN_VMULOSB: + case ALTIVEC_BUILTIN_VMULOSH: + case P8V_BUILTIN_VMULOSW: + /* Odd element flavors of vec_mul (unsigned). */ + case ALTIVEC_BUILTIN_VMULOUB: + case ALTIVEC_BUILTIN_VMULOUH: + case P8V_BUILTIN_VMULOUW: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, VEC_WIDEN_MULT_ODD_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_div (Integer). */ + case VSX_BUILTIN_DIV_V2DI: + case VSX_BUILTIN_UDIV_V2DI: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, TRUNC_DIV_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_div (Float). */ + case VSX_BUILTIN_XVDIVSP: + case VSX_BUILTIN_XVDIVDP: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, RDIV_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_and. */ + case ALTIVEC_BUILTIN_VAND: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_andc. */ + case ALTIVEC_BUILTIN_VANDC: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); + g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, temp); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_nand. */ + case P8V_BUILTIN_VEC_NAND: + case P8V_BUILTIN_NAND_V16QI: + case P8V_BUILTIN_NAND_V8HI: + case P8V_BUILTIN_NAND_V4SI: + case P8V_BUILTIN_NAND_V4SF: + case P8V_BUILTIN_NAND_V2DF: + case P8V_BUILTIN_NAND_V2DI: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); + g = gimple_build_assign (temp, BIT_AND_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_or. */ + case ALTIVEC_BUILTIN_VOR: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* flavors of vec_orc. */ + case P8V_BUILTIN_ORC_V16QI: + case P8V_BUILTIN_ORC_V8HI: + case P8V_BUILTIN_ORC_V4SI: + case P8V_BUILTIN_ORC_V4SF: + case P8V_BUILTIN_ORC_V2DF: + case P8V_BUILTIN_ORC_V2DI: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); + g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, temp); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_xor. */ + case ALTIVEC_BUILTIN_VXOR: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, BIT_XOR_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_nor. */ + case ALTIVEC_BUILTIN_VNOR: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); + g = gimple_build_assign (temp, BIT_IOR_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* flavors of vec_abs. */ + case ALTIVEC_BUILTIN_ABS_V16QI: + case ALTIVEC_BUILTIN_ABS_V8HI: + case ALTIVEC_BUILTIN_ABS_V4SI: + case ALTIVEC_BUILTIN_ABS_V4SF: + case P8V_BUILTIN_ABS_V2DI: + case VSX_BUILTIN_XVABSDP: + arg0 = gimple_call_arg (stmt, 0); + if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))) + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (arg0)))) + return false; + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, ABS_EXPR, arg0); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* flavors of vec_min. */ + case VSX_BUILTIN_XVMINDP: + case P8V_BUILTIN_VMINSD: + case P8V_BUILTIN_VMINUD: + case ALTIVEC_BUILTIN_VMINSB: + case ALTIVEC_BUILTIN_VMINSH: + case ALTIVEC_BUILTIN_VMINSW: + case ALTIVEC_BUILTIN_VMINUB: + case ALTIVEC_BUILTIN_VMINUH: + case ALTIVEC_BUILTIN_VMINUW: + case ALTIVEC_BUILTIN_VMINFP: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, MIN_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* flavors of vec_max. */ + case VSX_BUILTIN_XVMAXDP: + case P8V_BUILTIN_VMAXSD: + case P8V_BUILTIN_VMAXUD: + case ALTIVEC_BUILTIN_VMAXSB: + case ALTIVEC_BUILTIN_VMAXSH: + case ALTIVEC_BUILTIN_VMAXSW: + case ALTIVEC_BUILTIN_VMAXUB: + case ALTIVEC_BUILTIN_VMAXUH: + case ALTIVEC_BUILTIN_VMAXUW: + case ALTIVEC_BUILTIN_VMAXFP: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, MAX_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_eqv. */ + case P8V_BUILTIN_EQV_V16QI: + case P8V_BUILTIN_EQV_V8HI: + case P8V_BUILTIN_EQV_V4SI: + case P8V_BUILTIN_EQV_V4SF: + case P8V_BUILTIN_EQV_V2DF: + case P8V_BUILTIN_EQV_V2DI: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); + g = gimple_build_assign (temp, BIT_XOR_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vec_rotate_left. */ + case ALTIVEC_BUILTIN_VRLB: + case ALTIVEC_BUILTIN_VRLH: + case ALTIVEC_BUILTIN_VRLW: + case P8V_BUILTIN_VRLD: + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + g = gimple_build_assign (lhs, LROTATE_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + /* Flavors of vector shift right algebraic. + vec_sra{b,h,w} -> vsra{b,h,w}. */ + case ALTIVEC_BUILTIN_VSRAB: + case ALTIVEC_BUILTIN_VSRAH: + case ALTIVEC_BUILTIN_VSRAW: + case P8V_BUILTIN_VSRAD: + { + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + tree arg1_type = TREE_TYPE (arg1); + tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); + tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); + location_t loc = gimple_location (stmt); + /* Force arg1 into the range valid matching the arg0 type. */ + /* Build a vector consisting of the max valid bit-size values. */ + int n_elts = VECTOR_CST_NELTS (arg1); + tree element_size = build_int_cst (unsigned_element_type, + 128 / n_elts); + tree_vector_builder elts (unsigned_arg1_type, n_elts, 1); + for (int i = 0; i < n_elts; i++) + elts.safe_push (element_size); + tree modulo_tree = elts.build (); + /* Modulo the provided shift value against that vector. */ + gimple_seq stmts = NULL; + tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + unsigned_arg1_type, arg1); + tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, + unsigned_arg1_type, unsigned_arg1, + modulo_tree); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + /* And finally, do the shift. */ + g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, new_arg1); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } + /* Flavors of vector shift left. + builtin_altivec_vsl{b,h,w} -> vsl{b,h,w}. */ + case ALTIVEC_BUILTIN_VSLB: + case ALTIVEC_BUILTIN_VSLH: + case ALTIVEC_BUILTIN_VSLW: + case P8V_BUILTIN_VSLD: + { + location_t loc; + gimple_seq stmts = NULL; + arg0 = gimple_call_arg (stmt, 0); + tree arg0_type = TREE_TYPE (arg0); + if (INTEGRAL_TYPE_P (TREE_TYPE (arg0_type)) + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0_type))) + return false; + arg1 = gimple_call_arg (stmt, 1); + tree arg1_type = TREE_TYPE (arg1); + tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); + tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); + loc = gimple_location (stmt); + lhs = gimple_call_lhs (stmt); + /* Force arg1 into the range valid matching the arg0 type. */ + /* Build a vector consisting of the max valid bit-size values. */ + int n_elts = VECTOR_CST_NELTS (arg1); + int tree_size_in_bits = TREE_INT_CST_LOW (size_in_bytes (arg1_type)) + * BITS_PER_UNIT; + tree element_size = build_int_cst (unsigned_element_type, + tree_size_in_bits / n_elts); + tree_vector_builder elts (unsigned_type_for (arg1_type), n_elts, 1); + for (int i = 0; i < n_elts; i++) + elts.safe_push (element_size); + tree modulo_tree = elts.build (); + /* Modulo the provided shift value against that vector. */ + tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + unsigned_arg1_type, arg1); + tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, + unsigned_arg1_type, unsigned_arg1, + modulo_tree); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + /* And finally, do the shift. */ + g = gimple_build_assign (lhs, LSHIFT_EXPR, arg0, new_arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } + /* Flavors of vector shift right. */ + case ALTIVEC_BUILTIN_VSRB: + case ALTIVEC_BUILTIN_VSRH: + case ALTIVEC_BUILTIN_VSRW: + case P8V_BUILTIN_VSRD: + { + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + tree arg1_type = TREE_TYPE (arg1); + tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); + tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); + location_t loc = gimple_location (stmt); + gimple_seq stmts = NULL; + /* Convert arg0 to unsigned. */ + tree arg0_unsigned + = gimple_build (&stmts, VIEW_CONVERT_EXPR, + unsigned_type_for (TREE_TYPE (arg0)), arg0); + /* Force arg1 into the range valid matching the arg0 type. */ + /* Build a vector consisting of the max valid bit-size values. */ + int n_elts = VECTOR_CST_NELTS (arg1); + tree element_size = build_int_cst (unsigned_element_type, + 128 / n_elts); + tree_vector_builder elts (unsigned_arg1_type, n_elts, 1); + for (int i = 0; i < n_elts; i++) + elts.safe_push (element_size); + tree modulo_tree = elts.build (); + /* Modulo the provided shift value against that vector. */ + tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + unsigned_arg1_type, arg1); + tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, + unsigned_arg1_type, unsigned_arg1, + modulo_tree); + /* Do the shift. */ + tree res + = gimple_build (&stmts, RSHIFT_EXPR, + TREE_TYPE (arg0_unsigned), arg0_unsigned, new_arg1); + /* Convert result back to the lhs type. */ + res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + update_call_from_tree (gsi, res); + return true; + } + /* Vector loads. */ + case ALTIVEC_BUILTIN_LVX_V16QI: + case ALTIVEC_BUILTIN_LVX_V8HI: + case ALTIVEC_BUILTIN_LVX_V4SI: + case ALTIVEC_BUILTIN_LVX_V4SF: + case ALTIVEC_BUILTIN_LVX_V2DI: + case ALTIVEC_BUILTIN_LVX_V2DF: + case ALTIVEC_BUILTIN_LVX_V1TI: + { + arg0 = gimple_call_arg (stmt, 0); // offset + arg1 = gimple_call_arg (stmt, 1); // address + lhs = gimple_call_lhs (stmt); + location_t loc = gimple_location (stmt); + /* Since arg1 may be cast to a different type, just use ptr_type_node + here instead of trying to enforce TBAA on pointer types. */ + tree arg1_type = ptr_type_node; + tree lhs_type = TREE_TYPE (lhs); + /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create + the tree using the value from arg0. The resulting type will match + the type of arg1. */ + gimple_seq stmts = NULL; + tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0); + tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, + arg1_type, arg1, temp_offset); + /* Mask off any lower bits from the address. */ + tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR, + arg1_type, temp_addr, + build_int_cst (arg1_type, -16)); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + if (!is_gimple_mem_ref_addr (aligned_addr)) + { + tree t = make_ssa_name (TREE_TYPE (aligned_addr)); + gimple *g = gimple_build_assign (t, aligned_addr); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + aligned_addr = t; + } + /* Use the build2 helper to set up the mem_ref. The MEM_REF could also + take an offset, but since we've already incorporated the offset + above, here we just pass in a zero. */ + gimple *g + = gimple_build_assign (lhs, build2 (MEM_REF, lhs_type, aligned_addr, + build_int_cst (arg1_type, 0))); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } + /* Vector stores. */ + case ALTIVEC_BUILTIN_STVX_V16QI: + case ALTIVEC_BUILTIN_STVX_V8HI: + case ALTIVEC_BUILTIN_STVX_V4SI: + case ALTIVEC_BUILTIN_STVX_V4SF: + case ALTIVEC_BUILTIN_STVX_V2DI: + case ALTIVEC_BUILTIN_STVX_V2DF: + { + arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */ + arg1 = gimple_call_arg (stmt, 1); /* Offset. */ + tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */ + location_t loc = gimple_location (stmt); + tree arg0_type = TREE_TYPE (arg0); + /* Use ptr_type_node (no TBAA) for the arg2_type. + FIXME: (Richard) "A proper fix would be to transition this type as + seen from the frontend to GIMPLE, for example in a similar way we + do for MEM_REFs by piggy-backing that on an extra argument, a + constant zero pointer of the alias pointer type to use (which would + also serve as a type indicator of the store itself). I'd use a + target specific internal function for this (not sure if we can have + those target specific, but I guess if it's folded away then that's + fine) and get away with the overload set." */ + tree arg2_type = ptr_type_node; + /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create + the tree using the value from arg0. The resulting type will match + the type of arg2. */ + gimple_seq stmts = NULL; + tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1); + tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, + arg2_type, arg2, temp_offset); + /* Mask off any lower bits from the address. */ + tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR, + arg2_type, temp_addr, + build_int_cst (arg2_type, -16)); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + if (!is_gimple_mem_ref_addr (aligned_addr)) + { + tree t = make_ssa_name (TREE_TYPE (aligned_addr)); + gimple *g = gimple_build_assign (t, aligned_addr); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + aligned_addr = t; + } + /* The desired gimple result should be similar to: + MEM[(__vector floatD.1407 *)_1] = vf1D.2697; */ + gimple *g + = gimple_build_assign (build2 (MEM_REF, arg0_type, aligned_addr, + build_int_cst (arg2_type, 0)), arg0); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } + + /* unaligned Vector loads. */ + case VSX_BUILTIN_LXVW4X_V16QI: + case VSX_BUILTIN_LXVW4X_V8HI: + case VSX_BUILTIN_LXVW4X_V4SF: + case VSX_BUILTIN_LXVW4X_V4SI: + case VSX_BUILTIN_LXVD2X_V2DF: + case VSX_BUILTIN_LXVD2X_V2DI: + { + arg0 = gimple_call_arg (stmt, 0); // offset + arg1 = gimple_call_arg (stmt, 1); // address + lhs = gimple_call_lhs (stmt); + location_t loc = gimple_location (stmt); + /* Since arg1 may be cast to a different type, just use ptr_type_node + here instead of trying to enforce TBAA on pointer types. */ + tree arg1_type = ptr_type_node; + tree lhs_type = TREE_TYPE (lhs); + /* In GIMPLE the type of the MEM_REF specifies the alignment. The + required alignment (power) is 4 bytes regardless of data type. */ + tree align_ltype = build_aligned_type (lhs_type, 4); + /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create + the tree using the value from arg0. The resulting type will match + the type of arg1. */ + gimple_seq stmts = NULL; + tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0); + tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, + arg1_type, arg1, temp_offset); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + if (!is_gimple_mem_ref_addr (temp_addr)) + { + tree t = make_ssa_name (TREE_TYPE (temp_addr)); + gimple *g = gimple_build_assign (t, temp_addr); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + temp_addr = t; + } + /* Use the build2 helper to set up the mem_ref. The MEM_REF could also + take an offset, but since we've already incorporated the offset + above, here we just pass in a zero. */ + gimple *g; + g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr, + build_int_cst (arg1_type, 0))); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } + + /* unaligned Vector stores. */ + case VSX_BUILTIN_STXVW4X_V16QI: + case VSX_BUILTIN_STXVW4X_V8HI: + case VSX_BUILTIN_STXVW4X_V4SF: + case VSX_BUILTIN_STXVW4X_V4SI: + case VSX_BUILTIN_STXVD2X_V2DF: + case VSX_BUILTIN_STXVD2X_V2DI: + { + arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */ + arg1 = gimple_call_arg (stmt, 1); /* Offset. */ + tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */ + location_t loc = gimple_location (stmt); + tree arg0_type = TREE_TYPE (arg0); + /* Use ptr_type_node (no TBAA) for the arg2_type. */ + tree arg2_type = ptr_type_node; + /* In GIMPLE the type of the MEM_REF specifies the alignment. The + required alignment (power) is 4 bytes regardless of data type. */ + tree align_stype = build_aligned_type (arg0_type, 4); + /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create + the tree using the value from arg1. */ + gimple_seq stmts = NULL; + tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1); + tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, + arg2_type, arg2, temp_offset); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + if (!is_gimple_mem_ref_addr (temp_addr)) + { + tree t = make_ssa_name (TREE_TYPE (temp_addr)); + gimple *g = gimple_build_assign (t, temp_addr); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + temp_addr = t; + } + gimple *g; + g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr, + build_int_cst (arg2_type, 0)), arg0); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } + + /* Vector Fused multiply-add (fma). */ + case ALTIVEC_BUILTIN_VMADDFP: + case VSX_BUILTIN_XVMADDDP: + case ALTIVEC_BUILTIN_VMLADDUHM: + { + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + tree arg2 = gimple_call_arg (stmt, 2); + lhs = gimple_call_lhs (stmt); + gcall *g = gimple_build_call_internal (IFN_FMA, 3, arg0, arg1, arg2); + gimple_call_set_lhs (g, lhs); + gimple_call_set_nothrow (g, true); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } + + /* Vector compares; EQ, NE, GE, GT, LE. */ + case ALTIVEC_BUILTIN_VCMPEQUB: + case ALTIVEC_BUILTIN_VCMPEQUH: + case ALTIVEC_BUILTIN_VCMPEQUW: + case P8V_BUILTIN_VCMPEQUD: + fold_compare_helper (gsi, EQ_EXPR, stmt); + return true; + + case P9V_BUILTIN_CMPNEB: + case P9V_BUILTIN_CMPNEH: + case P9V_BUILTIN_CMPNEW: + fold_compare_helper (gsi, NE_EXPR, stmt); + return true; + + case VSX_BUILTIN_CMPGE_16QI: + case VSX_BUILTIN_CMPGE_U16QI: + case VSX_BUILTIN_CMPGE_8HI: + case VSX_BUILTIN_CMPGE_U8HI: + case VSX_BUILTIN_CMPGE_4SI: + case VSX_BUILTIN_CMPGE_U4SI: + case VSX_BUILTIN_CMPGE_2DI: + case VSX_BUILTIN_CMPGE_U2DI: + fold_compare_helper (gsi, GE_EXPR, stmt); + return true; + + case ALTIVEC_BUILTIN_VCMPGTSB: + case ALTIVEC_BUILTIN_VCMPGTUB: + case ALTIVEC_BUILTIN_VCMPGTSH: + case ALTIVEC_BUILTIN_VCMPGTUH: + case ALTIVEC_BUILTIN_VCMPGTSW: + case ALTIVEC_BUILTIN_VCMPGTUW: + case P8V_BUILTIN_VCMPGTUD: + case P8V_BUILTIN_VCMPGTSD: + fold_compare_helper (gsi, GT_EXPR, stmt); + return true; + + case VSX_BUILTIN_CMPLE_16QI: + case VSX_BUILTIN_CMPLE_U16QI: + case VSX_BUILTIN_CMPLE_8HI: + case VSX_BUILTIN_CMPLE_U8HI: + case VSX_BUILTIN_CMPLE_4SI: + case VSX_BUILTIN_CMPLE_U4SI: + case VSX_BUILTIN_CMPLE_2DI: + case VSX_BUILTIN_CMPLE_U2DI: + fold_compare_helper (gsi, LE_EXPR, stmt); + return true; + + /* flavors of vec_splat_[us]{8,16,32}. */ + case ALTIVEC_BUILTIN_VSPLTISB: + case ALTIVEC_BUILTIN_VSPLTISH: + case ALTIVEC_BUILTIN_VSPLTISW: + { + arg0 = gimple_call_arg (stmt, 0); + lhs = gimple_call_lhs (stmt); + + /* Only fold the vec_splat_*() if the lower bits of arg 0 is a + 5-bit signed constant in range -16 to +15. */ + if (TREE_CODE (arg0) != INTEGER_CST + || !IN_RANGE (TREE_INT_CST_LOW (arg0), -16, 15)) + return false; + gimple_seq stmts = NULL; + location_t loc = gimple_location (stmt); + tree splat_value = gimple_convert (&stmts, loc, + TREE_TYPE (TREE_TYPE (lhs)), arg0); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value); + g = gimple_build_assign (lhs, splat_tree); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } + + /* Flavors of vec_splat. */ + /* a = vec_splat (b, 0x3) becomes a = { b[3],b[3],b[3],...}; */ + case ALTIVEC_BUILTIN_VSPLTB: + case ALTIVEC_BUILTIN_VSPLTH: + case ALTIVEC_BUILTIN_VSPLTW: + case VSX_BUILTIN_XXSPLTD_V2DI: + case VSX_BUILTIN_XXSPLTD_V2DF: + { + arg0 = gimple_call_arg (stmt, 0); /* input vector. */ + arg1 = gimple_call_arg (stmt, 1); /* index into arg0. */ + /* Only fold the vec_splat_*() if arg1 is both a constant value and + is a valid index into the arg0 vector. */ + unsigned int n_elts = VECTOR_CST_NELTS (arg0); + if (TREE_CODE (arg1) != INTEGER_CST + || TREE_INT_CST_LOW (arg1) > (n_elts -1)) + return false; + lhs = gimple_call_lhs (stmt); + tree lhs_type = TREE_TYPE (lhs); + tree arg0_type = TREE_TYPE (arg0); + tree splat; + if (TREE_CODE (arg0) == VECTOR_CST) + splat = VECTOR_CST_ELT (arg0, TREE_INT_CST_LOW (arg1)); + else + { + /* Determine (in bits) the length and start location of the + splat value for a call to the tree_vec_extract helper. */ + int splat_elem_size = TREE_INT_CST_LOW (size_in_bytes (arg0_type)) + * BITS_PER_UNIT / n_elts; + int splat_start_bit = TREE_INT_CST_LOW (arg1) * splat_elem_size; + tree len = build_int_cst (bitsizetype, splat_elem_size); + tree start = build_int_cst (bitsizetype, splat_start_bit); + splat = tree_vec_extract (gsi, TREE_TYPE (lhs_type), arg0, + len, start); + } + /* And finally, build the new vector. */ + tree splat_tree = build_vector_from_val (lhs_type, splat); + g = gimple_build_assign (lhs, splat_tree); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } + + /* vec_mergel (integrals). */ + case ALTIVEC_BUILTIN_VMRGLH: + case ALTIVEC_BUILTIN_VMRGLW: + case VSX_BUILTIN_XXMRGLW_4SI: + case ALTIVEC_BUILTIN_VMRGLB: + case VSX_BUILTIN_VEC_MERGEL_V2DI: + case VSX_BUILTIN_XXMRGLW_4SF: + case VSX_BUILTIN_VEC_MERGEL_V2DF: + fold_mergehl_helper (gsi, stmt, 1); + return true; + /* vec_mergeh (integrals). */ + case ALTIVEC_BUILTIN_VMRGHH: + case ALTIVEC_BUILTIN_VMRGHW: + case VSX_BUILTIN_XXMRGHW_4SI: + case ALTIVEC_BUILTIN_VMRGHB: + case VSX_BUILTIN_VEC_MERGEH_V2DI: + case VSX_BUILTIN_XXMRGHW_4SF: + case VSX_BUILTIN_VEC_MERGEH_V2DF: + fold_mergehl_helper (gsi, stmt, 0); + return true; + + /* Flavors of vec_mergee. */ + case P8V_BUILTIN_VMRGEW_V4SI: + case P8V_BUILTIN_VMRGEW_V2DI: + case P8V_BUILTIN_VMRGEW_V4SF: + case P8V_BUILTIN_VMRGEW_V2DF: + fold_mergeeo_helper (gsi, stmt, 0); + return true; + /* Flavors of vec_mergeo. */ + case P8V_BUILTIN_VMRGOW_V4SI: + case P8V_BUILTIN_VMRGOW_V2DI: + case P8V_BUILTIN_VMRGOW_V4SF: + case P8V_BUILTIN_VMRGOW_V2DF: + fold_mergeeo_helper (gsi, stmt, 1); + return true; + + /* d = vec_pack (a, b) */ + case P8V_BUILTIN_VPKUDUM: + case ALTIVEC_BUILTIN_VPKUHUM: + case ALTIVEC_BUILTIN_VPKUWUM: + { + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } + + /* d = vec_unpackh (a) */ + /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call + in this code is sensitive to endian-ness, and needs to be inverted to + handle both LE and BE targets. */ + case ALTIVEC_BUILTIN_VUPKHSB: + case ALTIVEC_BUILTIN_VUPKHSH: + case P8V_BUILTIN_VUPKHSW: + { + arg0 = gimple_call_arg (stmt, 0); + lhs = gimple_call_lhs (stmt); + if (BYTES_BIG_ENDIAN) + g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); + else + g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } + /* d = vec_unpackl (a) */ + case ALTIVEC_BUILTIN_VUPKLSB: + case ALTIVEC_BUILTIN_VUPKLSH: + case P8V_BUILTIN_VUPKLSW: + { + arg0 = gimple_call_arg (stmt, 0); + lhs = gimple_call_lhs (stmt); + if (BYTES_BIG_ENDIAN) + g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); + else + g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); + gimple_set_location (g, gimple_location (stmt)); + gsi_replace (gsi, g, true); + return true; + } + /* There is no gimple type corresponding with pixel, so just return. */ + case ALTIVEC_BUILTIN_VUPKHPX: + case ALTIVEC_BUILTIN_VUPKLPX: + return false; + + /* vec_perm. */ + case ALTIVEC_BUILTIN_VPERM_16QI: + case ALTIVEC_BUILTIN_VPERM_8HI: + case ALTIVEC_BUILTIN_VPERM_4SI: + case ALTIVEC_BUILTIN_VPERM_2DI: + case ALTIVEC_BUILTIN_VPERM_4SF: + case ALTIVEC_BUILTIN_VPERM_2DF: + { + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + tree permute = gimple_call_arg (stmt, 2); + lhs = gimple_call_lhs (stmt); + location_t loc = gimple_location (stmt); + gimple_seq stmts = NULL; + // convert arg0 and arg1 to match the type of the permute + // for the VEC_PERM_EXPR operation. + tree permute_type = (TREE_TYPE (permute)); + tree arg0_ptype = gimple_convert (&stmts, loc, permute_type, arg0); + tree arg1_ptype = gimple_convert (&stmts, loc, permute_type, arg1); + tree lhs_ptype = gimple_build (&stmts, loc, VEC_PERM_EXPR, + permute_type, arg0_ptype, arg1_ptype, + permute); + // Convert the result back to the desired lhs type upon completion. + tree temp = gimple_convert (&stmts, loc, TREE_TYPE (lhs), lhs_ptype); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + g = gimple_build_assign (lhs, temp); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } + + default: + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "gimple builtin intrinsic not matched:%d %s %s\n", + fn_code, fn_name1, fn_name2); + break; + } + + return false; +} + +/* Expand an expression EXP that calls a built-in function, + with result going to TARGET if that's convenient + (and in mode MODE if that's convenient). + SUBTARGET may be used as the target for computing one of EXP's operands. + IGNORE is nonzero if the value is to be ignored. */ + +rtx +rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, + machine_mode mode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + enum rs6000_builtins fcode + = (enum rs6000_builtins)DECL_FUNCTION_CODE (fndecl); + size_t uns_fcode = (size_t)fcode; + const struct builtin_description *d; + size_t i; + rtx ret; + bool success; + HOST_WIDE_INT mask = rs6000_builtin_info[uns_fcode].mask; + bool func_valid_p = ((rs6000_builtin_mask & mask) == mask); + enum insn_code icode = rs6000_builtin_info[uns_fcode].icode; + + /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit + floating point type, depending on whether long double is the IBM extended + double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if + we only define one variant of the built-in function, and switch the code + when defining it, rather than defining two built-ins and using the + overload table in rs6000-c.c to switch between the two. If we don't have + the proper assembler, don't do this switch because CODE_FOR_*kf* and + CODE_FOR_*tf* will be CODE_FOR_nothing. */ + if (FLOAT128_IEEE_P (TFmode)) + switch (icode) + { + default: + break; + + case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break; + case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break; + case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break; + case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break; + case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break; + case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break; + case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break; + case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break; + case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break; + case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break; + case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break; + case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break; + case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break; + } + + if (TARGET_DEBUG_BUILTIN) + { + const char *name1 = rs6000_builtin_info[uns_fcode].name; + const char *name2 = (icode != CODE_FOR_nothing) + ? get_insn_name ((int) icode) + : "nothing"; + const char *name3; + + switch (rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK) + { + default: name3 = "unknown"; break; + case RS6000_BTC_SPECIAL: name3 = "special"; break; + case RS6000_BTC_UNARY: name3 = "unary"; break; + case RS6000_BTC_BINARY: name3 = "binary"; break; + case RS6000_BTC_TERNARY: name3 = "ternary"; break; + case RS6000_BTC_PREDICATE: name3 = "predicate"; break; + case RS6000_BTC_ABS: name3 = "abs"; break; + case RS6000_BTC_DST: name3 = "dst"; break; + } + + + fprintf (stderr, + "rs6000_expand_builtin, %s (%d), insn = %s (%d), type=%s%s\n", + (name1) ? name1 : "---", fcode, + (name2) ? name2 : "---", (int) icode, + name3, + func_valid_p ? "" : ", not valid"); + } + + if (!func_valid_p) + { + rs6000_invalid_builtin (fcode); + + /* Given it is invalid, just generate a normal call. */ + return expand_call (exp, target, ignore); + } + + switch (fcode) + { + case RS6000_BUILTIN_RECIP: + return rs6000_expand_binop_builtin (CODE_FOR_recipdf3, exp, target); + + case RS6000_BUILTIN_RECIPF: + return rs6000_expand_binop_builtin (CODE_FOR_recipsf3, exp, target); + + case RS6000_BUILTIN_RSQRTF: + return rs6000_expand_unop_builtin (CODE_FOR_rsqrtsf2, exp, target); + + case RS6000_BUILTIN_RSQRT: + return rs6000_expand_unop_builtin (CODE_FOR_rsqrtdf2, exp, target); + + case POWER7_BUILTIN_BPERMD: + return rs6000_expand_binop_builtin (((TARGET_64BIT) + ? CODE_FOR_bpermd_di + : CODE_FOR_bpermd_si), exp, target); + + case RS6000_BUILTIN_GET_TB: + return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_get_timebase, + target); + + case RS6000_BUILTIN_MFTB: + return rs6000_expand_zeroop_builtin (((TARGET_64BIT) + ? CODE_FOR_rs6000_mftb_di + : CODE_FOR_rs6000_mftb_si), + target); + + case RS6000_BUILTIN_MFFS: + return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_mffs, target); + + case RS6000_BUILTIN_MTFSB0: + return rs6000_expand_mtfsb_builtin (CODE_FOR_rs6000_mtfsb0, exp); + + case RS6000_BUILTIN_MTFSB1: + return rs6000_expand_mtfsb_builtin (CODE_FOR_rs6000_mtfsb1, exp); + + case RS6000_BUILTIN_SET_FPSCR_RN: + return rs6000_expand_set_fpscr_rn_builtin (CODE_FOR_rs6000_set_fpscr_rn, + exp); + + case RS6000_BUILTIN_SET_FPSCR_DRN: + return + rs6000_expand_set_fpscr_drn_builtin (CODE_FOR_rs6000_set_fpscr_drn, + exp); + + case RS6000_BUILTIN_MFFSL: + return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_mffsl, target); + + case RS6000_BUILTIN_MTFSF: + return rs6000_expand_mtfsf_builtin (CODE_FOR_rs6000_mtfsf, exp); + + case RS6000_BUILTIN_CPU_INIT: + case RS6000_BUILTIN_CPU_IS: + case RS6000_BUILTIN_CPU_SUPPORTS: + return cpu_expand_builtin (fcode, exp, target); + + case MISC_BUILTIN_SPEC_BARRIER: + { + emit_insn (gen_speculation_barrier ()); + return NULL_RTX; + } + + case ALTIVEC_BUILTIN_MASK_FOR_LOAD: + case ALTIVEC_BUILTIN_MASK_FOR_STORE: + { + int icode2 = (BYTES_BIG_ENDIAN ? (int) CODE_FOR_altivec_lvsr_direct + : (int) CODE_FOR_altivec_lvsl_direct); + machine_mode tmode = insn_data[icode2].operand[0].mode; + machine_mode mode = insn_data[icode2].operand[1].mode; + tree arg; + rtx op, addr, pat; + + gcc_assert (TARGET_ALTIVEC); + + arg = CALL_EXPR_ARG (exp, 0); + gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg))); + op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL); + addr = memory_address (mode, op); + if (fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE) + op = addr; + else + { + /* For the load case need to negate the address. */ + op = gen_reg_rtx (GET_MODE (addr)); + emit_insn (gen_rtx_SET (op, gen_rtx_NEG (GET_MODE (addr), addr))); + } + op = gen_rtx_MEM (mode, op); + + if (target == 0 + || GET_MODE (target) != tmode + || ! (*insn_data[icode2].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + + pat = GEN_FCN (icode2) (target, op); + if (!pat) + return 0; + emit_insn (pat); + + return target; + } + + case ALTIVEC_BUILTIN_VCFUX: + case ALTIVEC_BUILTIN_VCFSX: + case ALTIVEC_BUILTIN_VCTUXS: + case ALTIVEC_BUILTIN_VCTSXS: + /* FIXME: There's got to be a nicer way to handle this case than + constructing a new CALL_EXPR. */ + if (call_expr_nargs (exp) == 1) + { + exp = build_call_nary (TREE_TYPE (exp), CALL_EXPR_FN (exp), + 2, CALL_EXPR_ARG (exp, 0), integer_zero_node); + } + break; + + /* For the pack and unpack int128 routines, fix up the builtin so it + uses the correct IBM128 type. */ + case MISC_BUILTIN_PACK_IF: + if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD) + { + icode = CODE_FOR_packtf; + fcode = MISC_BUILTIN_PACK_TF; + uns_fcode = (size_t)fcode; + } + break; + + case MISC_BUILTIN_UNPACK_IF: + if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD) + { + icode = CODE_FOR_unpacktf; + fcode = MISC_BUILTIN_UNPACK_TF; + uns_fcode = (size_t)fcode; + } + break; + + default: + break; + } + + if (TARGET_ALTIVEC) + { + ret = altivec_expand_builtin (exp, target, &success); + + if (success) + return ret; + } + if (TARGET_HTM) + { + ret = htm_expand_builtin (exp, target, &success); + + if (success) + return ret; + } + + unsigned attr = rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK; + /* RS6000_BTC_SPECIAL represents no-operand operators. */ + gcc_assert (attr == RS6000_BTC_UNARY + || attr == RS6000_BTC_BINARY + || attr == RS6000_BTC_TERNARY + || attr == RS6000_BTC_SPECIAL); + + /* Handle simple unary operations. */ + d = bdesc_1arg; + for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++) + if (d->code == fcode) + return rs6000_expand_unop_builtin (icode, exp, target); + + /* Handle simple binary operations. */ + d = bdesc_2arg; + for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++) + if (d->code == fcode) + return rs6000_expand_binop_builtin (icode, exp, target); + + /* Handle simple ternary operations. */ + d = bdesc_3arg; + for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) + if (d->code == fcode) + return rs6000_expand_ternop_builtin (icode, exp, target); + + /* Handle simple no-argument operations. */ + d = bdesc_0arg; + for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++) + if (d->code == fcode) + return rs6000_expand_zeroop_builtin (icode, target); + + gcc_unreachable (); +} + +/* Create a builtin vector type with a name. Taking care not to give + the canonical type a name. */ + +static tree +rs6000_vector_type (const char *name, tree elt_type, unsigned num_elts) +{ + tree result = build_vector_type (elt_type, num_elts); + + /* Copy so we don't give the canonical type a name. */ + result = build_variant_type_copy (result); + + add_builtin_type (name, result); + + return result; +} + +void +rs6000_init_builtins (void) +{ + tree tdecl; + tree ftype; + machine_mode mode; + + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_init_builtins%s%s\n", + (TARGET_ALTIVEC) ? ", altivec" : "", + (TARGET_VSX) ? ", vsx" : ""); + + V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 ? "__vector long" + : "__vector long long", + intDI_type_node, 2); + V2DF_type_node = rs6000_vector_type ("__vector double", double_type_node, 2); + V4SI_type_node = rs6000_vector_type ("__vector signed int", + intSI_type_node, 4); + V4SF_type_node = rs6000_vector_type ("__vector float", float_type_node, 4); + V8HI_type_node = rs6000_vector_type ("__vector signed short", + intHI_type_node, 8); + V16QI_type_node = rs6000_vector_type ("__vector signed char", + intQI_type_node, 16); + + unsigned_V16QI_type_node = rs6000_vector_type ("__vector unsigned char", + unsigned_intQI_type_node, 16); + unsigned_V8HI_type_node = rs6000_vector_type ("__vector unsigned short", + unsigned_intHI_type_node, 8); + unsigned_V4SI_type_node = rs6000_vector_type ("__vector unsigned int", + unsigned_intSI_type_node, 4); + unsigned_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 + ? "__vector unsigned long" + : "__vector unsigned long long", + unsigned_intDI_type_node, 2); + + opaque_V4SI_type_node = build_opaque_vector_type (intSI_type_node, 4); + + const_str_type_node + = build_pointer_type (build_qualified_type (char_type_node, + TYPE_QUAL_CONST)); + + /* We use V1TI mode as a special container to hold __int128_t items that + must live in VSX registers. */ + if (intTI_type_node) + { + V1TI_type_node = rs6000_vector_type ("__vector __int128", + intTI_type_node, 1); + unsigned_V1TI_type_node + = rs6000_vector_type ("__vector unsigned __int128", + unsigned_intTI_type_node, 1); + } + + /* The 'vector bool ...' types must be kept distinct from 'vector unsigned ...' + types, especially in C++ land. Similarly, 'vector pixel' is distinct from + 'vector unsigned short'. */ + + bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node); + bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node); + bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node); + bool_long_long_type_node = build_distinct_type_copy (unsigned_intDI_type_node); + pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node); + + long_integer_type_internal_node = long_integer_type_node; + long_unsigned_type_internal_node = long_unsigned_type_node; + long_long_integer_type_internal_node = long_long_integer_type_node; + long_long_unsigned_type_internal_node = long_long_unsigned_type_node; + intQI_type_internal_node = intQI_type_node; + uintQI_type_internal_node = unsigned_intQI_type_node; + intHI_type_internal_node = intHI_type_node; + uintHI_type_internal_node = unsigned_intHI_type_node; + intSI_type_internal_node = intSI_type_node; + uintSI_type_internal_node = unsigned_intSI_type_node; + intDI_type_internal_node = intDI_type_node; + uintDI_type_internal_node = unsigned_intDI_type_node; + intTI_type_internal_node = intTI_type_node; + uintTI_type_internal_node = unsigned_intTI_type_node; + float_type_internal_node = float_type_node; + double_type_internal_node = double_type_node; + long_double_type_internal_node = long_double_type_node; + dfloat64_type_internal_node = dfloat64_type_node; + dfloat128_type_internal_node = dfloat128_type_node; + void_type_internal_node = void_type_node; + + /* 128-bit floating point support. KFmode is IEEE 128-bit floating point. + IFmode is the IBM extended 128-bit format that is a pair of doubles. + TFmode will be either IEEE 128-bit floating point or the IBM double-double + format that uses a pair of doubles, depending on the switches and + defaults. + + If we don't support for either 128-bit IBM double double or IEEE 128-bit + floating point, we need make sure the type is non-zero or else self-test + fails during bootstrap. + + Always create __ibm128 as a separate type, even if the current long double + format is IBM extended double. + + For IEEE 128-bit floating point, always create the type __ieee128. If the + user used -mfloat128, rs6000-c.c will create a define from __float128 to + __ieee128. */ + if (TARGET_FLOAT128_TYPE) + { + if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128) + ibm128_float_type_node = long_double_type_node; + else + { + ibm128_float_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (ibm128_float_type_node) = 128; + SET_TYPE_MODE (ibm128_float_type_node, IFmode); + layout_type (ibm128_float_type_node); + } + + lang_hooks.types.register_builtin_type (ibm128_float_type_node, + "__ibm128"); + + if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128) + ieee128_float_type_node = long_double_type_node; + else + ieee128_float_type_node = float128_type_node; + + lang_hooks.types.register_builtin_type (ieee128_float_type_node, + "__ieee128"); + } + + else + ieee128_float_type_node = ibm128_float_type_node = long_double_type_node; + + /* Initialize the modes for builtin_function_type, mapping a machine mode to + tree type node. */ + builtin_mode_to_type[QImode][0] = integer_type_node; + builtin_mode_to_type[HImode][0] = integer_type_node; + builtin_mode_to_type[SImode][0] = intSI_type_node; + builtin_mode_to_type[SImode][1] = unsigned_intSI_type_node; + builtin_mode_to_type[DImode][0] = intDI_type_node; + builtin_mode_to_type[DImode][1] = unsigned_intDI_type_node; + builtin_mode_to_type[TImode][0] = intTI_type_node; + builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node; + builtin_mode_to_type[SFmode][0] = float_type_node; + builtin_mode_to_type[DFmode][0] = double_type_node; + builtin_mode_to_type[IFmode][0] = ibm128_float_type_node; + builtin_mode_to_type[KFmode][0] = ieee128_float_type_node; + builtin_mode_to_type[TFmode][0] = long_double_type_node; + builtin_mode_to_type[DDmode][0] = dfloat64_type_node; + builtin_mode_to_type[TDmode][0] = dfloat128_type_node; + builtin_mode_to_type[V1TImode][0] = V1TI_type_node; + builtin_mode_to_type[V1TImode][1] = unsigned_V1TI_type_node; + builtin_mode_to_type[V2DImode][0] = V2DI_type_node; + builtin_mode_to_type[V2DImode][1] = unsigned_V2DI_type_node; + builtin_mode_to_type[V2DFmode][0] = V2DF_type_node; + builtin_mode_to_type[V4SImode][0] = V4SI_type_node; + builtin_mode_to_type[V4SImode][1] = unsigned_V4SI_type_node; + builtin_mode_to_type[V4SFmode][0] = V4SF_type_node; + builtin_mode_to_type[V8HImode][0] = V8HI_type_node; + builtin_mode_to_type[V8HImode][1] = unsigned_V8HI_type_node; + builtin_mode_to_type[V16QImode][0] = V16QI_type_node; + builtin_mode_to_type[V16QImode][1] = unsigned_V16QI_type_node; + + tdecl = add_builtin_type ("__bool char", bool_char_type_node); + TYPE_NAME (bool_char_type_node) = tdecl; + + tdecl = add_builtin_type ("__bool short", bool_short_type_node); + TYPE_NAME (bool_short_type_node) = tdecl; + + tdecl = add_builtin_type ("__bool int", bool_int_type_node); + TYPE_NAME (bool_int_type_node) = tdecl; + + tdecl = add_builtin_type ("__pixel", pixel_type_node); + TYPE_NAME (pixel_type_node) = tdecl; + + bool_V16QI_type_node = rs6000_vector_type ("__vector __bool char", + bool_char_type_node, 16); + bool_V8HI_type_node = rs6000_vector_type ("__vector __bool short", + bool_short_type_node, 8); + bool_V4SI_type_node = rs6000_vector_type ("__vector __bool int", + bool_int_type_node, 4); + bool_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 + ? "__vector __bool long" + : "__vector __bool long long", + bool_long_long_type_node, 2); + pixel_V8HI_type_node = rs6000_vector_type ("__vector __pixel", + pixel_type_node, 8); + + /* Create Altivec and VSX builtins on machines with at least the + general purpose extensions (970 and newer) to allow the use of + the target attribute. */ + if (TARGET_EXTRA_BUILTINS) + altivec_init_builtins (); + if (TARGET_HTM) + htm_init_builtins (); + + if (TARGET_EXTRA_BUILTINS) + rs6000_common_init_builtins (); + + ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode, + RS6000_BUILTIN_RECIP, "__builtin_recipdiv"); + def_builtin ("__builtin_recipdiv", ftype, RS6000_BUILTIN_RECIP); + + ftype = builtin_function_type (SFmode, SFmode, SFmode, VOIDmode, + RS6000_BUILTIN_RECIPF, "__builtin_recipdivf"); + def_builtin ("__builtin_recipdivf", ftype, RS6000_BUILTIN_RECIPF); + + ftype = builtin_function_type (DFmode, DFmode, VOIDmode, VOIDmode, + RS6000_BUILTIN_RSQRT, "__builtin_rsqrt"); + def_builtin ("__builtin_rsqrt", ftype, RS6000_BUILTIN_RSQRT); + + ftype = builtin_function_type (SFmode, SFmode, VOIDmode, VOIDmode, + RS6000_BUILTIN_RSQRTF, "__builtin_rsqrtf"); + def_builtin ("__builtin_rsqrtf", ftype, RS6000_BUILTIN_RSQRTF); + + mode = (TARGET_64BIT) ? DImode : SImode; + ftype = builtin_function_type (mode, mode, mode, VOIDmode, + POWER7_BUILTIN_BPERMD, "__builtin_bpermd"); + def_builtin ("__builtin_bpermd", ftype, POWER7_BUILTIN_BPERMD); + + ftype = build_function_type_list (unsigned_intDI_type_node, + NULL_TREE); + def_builtin ("__builtin_ppc_get_timebase", ftype, RS6000_BUILTIN_GET_TB); + + if (TARGET_64BIT) + ftype = build_function_type_list (unsigned_intDI_type_node, + NULL_TREE); + else + ftype = build_function_type_list (unsigned_intSI_type_node, + NULL_TREE); + def_builtin ("__builtin_ppc_mftb", ftype, RS6000_BUILTIN_MFTB); + + ftype = build_function_type_list (double_type_node, NULL_TREE); + def_builtin ("__builtin_mffs", ftype, RS6000_BUILTIN_MFFS); + + ftype = build_function_type_list (double_type_node, NULL_TREE); + def_builtin ("__builtin_mffsl", ftype, RS6000_BUILTIN_MFFSL); + + ftype = build_function_type_list (void_type_node, + intSI_type_node, + NULL_TREE); + def_builtin ("__builtin_mtfsb0", ftype, RS6000_BUILTIN_MTFSB0); + + ftype = build_function_type_list (void_type_node, + intSI_type_node, + NULL_TREE); + def_builtin ("__builtin_mtfsb1", ftype, RS6000_BUILTIN_MTFSB1); + + ftype = build_function_type_list (void_type_node, + intDI_type_node, + NULL_TREE); + def_builtin ("__builtin_set_fpscr_rn", ftype, RS6000_BUILTIN_SET_FPSCR_RN); + + ftype = build_function_type_list (void_type_node, + intDI_type_node, + NULL_TREE); + def_builtin ("__builtin_set_fpscr_drn", ftype, RS6000_BUILTIN_SET_FPSCR_DRN); + + ftype = build_function_type_list (void_type_node, + intSI_type_node, double_type_node, + NULL_TREE); + def_builtin ("__builtin_mtfsf", ftype, RS6000_BUILTIN_MTFSF); + + ftype = build_function_type_list (void_type_node, NULL_TREE); + def_builtin ("__builtin_cpu_init", ftype, RS6000_BUILTIN_CPU_INIT); + def_builtin ("__builtin_ppc_speculation_barrier", ftype, + MISC_BUILTIN_SPEC_BARRIER); + + ftype = build_function_type_list (bool_int_type_node, const_ptr_type_node, + NULL_TREE); + def_builtin ("__builtin_cpu_is", ftype, RS6000_BUILTIN_CPU_IS); + def_builtin ("__builtin_cpu_supports", ftype, RS6000_BUILTIN_CPU_SUPPORTS); + + /* AIX libm provides clog as __clog. */ + if (TARGET_XCOFF && + (tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE) + set_user_assembler_name (tdecl, "__clog"); + +#ifdef SUBTARGET_INIT_BUILTINS + SUBTARGET_INIT_BUILTINS; +#endif +} + +/* Returns the rs6000 builtin decl for CODE. */ + +tree +rs6000_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) +{ + HOST_WIDE_INT fnmask; + + if (code >= RS6000_BUILTIN_COUNT) + return error_mark_node; + + fnmask = rs6000_builtin_info[code].mask; + if ((fnmask & rs6000_builtin_mask) != fnmask) + { + rs6000_invalid_builtin ((enum rs6000_builtins)code); + return error_mark_node; + } + + return rs6000_builtin_decls[code]; +} + +static void +altivec_init_builtins (void) +{ + const struct builtin_description *d; + size_t i; + tree ftype; + tree decl; + HOST_WIDE_INT builtin_mask = rs6000_builtin_mask; + + tree pvoid_type_node = build_pointer_type (void_type_node); + + tree pcvoid_type_node + = build_pointer_type (build_qualified_type (void_type_node, + TYPE_QUAL_CONST)); + + tree int_ftype_opaque + = build_function_type_list (integer_type_node, + opaque_V4SI_type_node, NULL_TREE); + tree opaque_ftype_opaque + = build_function_type_list (integer_type_node, NULL_TREE); + tree opaque_ftype_opaque_int + = build_function_type_list (opaque_V4SI_type_node, + opaque_V4SI_type_node, integer_type_node, NULL_TREE); + tree opaque_ftype_opaque_opaque_int + = build_function_type_list (opaque_V4SI_type_node, + opaque_V4SI_type_node, opaque_V4SI_type_node, + integer_type_node, NULL_TREE); + tree opaque_ftype_opaque_opaque_opaque + = build_function_type_list (opaque_V4SI_type_node, + opaque_V4SI_type_node, opaque_V4SI_type_node, + opaque_V4SI_type_node, NULL_TREE); + tree opaque_ftype_opaque_opaque + = build_function_type_list (opaque_V4SI_type_node, + opaque_V4SI_type_node, opaque_V4SI_type_node, + NULL_TREE); + tree int_ftype_int_opaque_opaque + = build_function_type_list (integer_type_node, + integer_type_node, opaque_V4SI_type_node, + opaque_V4SI_type_node, NULL_TREE); + tree int_ftype_int_v4si_v4si + = build_function_type_list (integer_type_node, + integer_type_node, V4SI_type_node, + V4SI_type_node, NULL_TREE); + tree int_ftype_int_v2di_v2di + = build_function_type_list (integer_type_node, + integer_type_node, V2DI_type_node, + V2DI_type_node, NULL_TREE); + tree void_ftype_v4si + = build_function_type_list (void_type_node, V4SI_type_node, NULL_TREE); + tree v8hi_ftype_void + = build_function_type_list (V8HI_type_node, NULL_TREE); + tree void_ftype_void + = build_function_type_list (void_type_node, NULL_TREE); + tree void_ftype_int + = build_function_type_list (void_type_node, integer_type_node, NULL_TREE); + + tree opaque_ftype_long_pcvoid + = build_function_type_list (opaque_V4SI_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree v16qi_ftype_long_pcvoid + = build_function_type_list (V16QI_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree v8hi_ftype_long_pcvoid + = build_function_type_list (V8HI_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree v4si_ftype_long_pcvoid + = build_function_type_list (V4SI_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree v4sf_ftype_long_pcvoid + = build_function_type_list (V4SF_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree v2df_ftype_long_pcvoid + = build_function_type_list (V2DF_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree v2di_ftype_long_pcvoid + = build_function_type_list (V2DI_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree v1ti_ftype_long_pcvoid + = build_function_type_list (V1TI_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + + tree void_ftype_opaque_long_pvoid + = build_function_type_list (void_type_node, + opaque_V4SI_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + tree void_ftype_v4si_long_pvoid + = build_function_type_list (void_type_node, + V4SI_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + tree void_ftype_v16qi_long_pvoid + = build_function_type_list (void_type_node, + V16QI_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + + tree void_ftype_v16qi_pvoid_long + = build_function_type_list (void_type_node, + V16QI_type_node, pvoid_type_node, + long_integer_type_node, NULL_TREE); + + tree void_ftype_v8hi_long_pvoid + = build_function_type_list (void_type_node, + V8HI_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + tree void_ftype_v4sf_long_pvoid + = build_function_type_list (void_type_node, + V4SF_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + tree void_ftype_v2df_long_pvoid + = build_function_type_list (void_type_node, + V2DF_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + tree void_ftype_v1ti_long_pvoid + = build_function_type_list (void_type_node, + V1TI_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + tree void_ftype_v2di_long_pvoid + = build_function_type_list (void_type_node, + V2DI_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + tree int_ftype_int_v8hi_v8hi + = build_function_type_list (integer_type_node, + integer_type_node, V8HI_type_node, + V8HI_type_node, NULL_TREE); + tree int_ftype_int_v16qi_v16qi + = build_function_type_list (integer_type_node, + integer_type_node, V16QI_type_node, + V16QI_type_node, NULL_TREE); + tree int_ftype_int_v4sf_v4sf + = build_function_type_list (integer_type_node, + integer_type_node, V4SF_type_node, + V4SF_type_node, NULL_TREE); + tree int_ftype_int_v2df_v2df + = build_function_type_list (integer_type_node, + integer_type_node, V2DF_type_node, + V2DF_type_node, NULL_TREE); + tree v2di_ftype_v2di + = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE); + tree v4si_ftype_v4si + = build_function_type_list (V4SI_type_node, V4SI_type_node, NULL_TREE); + tree v8hi_ftype_v8hi + = build_function_type_list (V8HI_type_node, V8HI_type_node, NULL_TREE); + tree v16qi_ftype_v16qi + = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE); + tree v4sf_ftype_v4sf + = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE); + tree v2df_ftype_v2df + = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE); + tree void_ftype_pcvoid_int_int + = build_function_type_list (void_type_node, + pcvoid_type_node, integer_type_node, + integer_type_node, NULL_TREE); + + def_builtin ("__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR); + def_builtin ("__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR); + def_builtin ("__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL); + def_builtin ("__builtin_altivec_dss", void_ftype_int, ALTIVEC_BUILTIN_DSS); + def_builtin ("__builtin_altivec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSL); + def_builtin ("__builtin_altivec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSR); + def_builtin ("__builtin_altivec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEBX); + def_builtin ("__builtin_altivec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEHX); + def_builtin ("__builtin_altivec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEWX); + def_builtin ("__builtin_altivec_lvxl", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVXL); + def_builtin ("__builtin_altivec_lvxl_v2df", v2df_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVXL_V2DF); + def_builtin ("__builtin_altivec_lvxl_v2di", v2di_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVXL_V2DI); + def_builtin ("__builtin_altivec_lvxl_v4sf", v4sf_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVXL_V4SF); + def_builtin ("__builtin_altivec_lvxl_v4si", v4si_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVXL_V4SI); + def_builtin ("__builtin_altivec_lvxl_v8hi", v8hi_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVXL_V8HI); + def_builtin ("__builtin_altivec_lvxl_v16qi", v16qi_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVXL_V16QI); + def_builtin ("__builtin_altivec_lvx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVX); + def_builtin ("__builtin_altivec_lvx_v1ti", v1ti_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVX_V1TI); + def_builtin ("__builtin_altivec_lvx_v2df", v2df_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVX_V2DF); + def_builtin ("__builtin_altivec_lvx_v2di", v2di_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVX_V2DI); + def_builtin ("__builtin_altivec_lvx_v4sf", v4sf_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVX_V4SF); + def_builtin ("__builtin_altivec_lvx_v4si", v4si_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVX_V4SI); + def_builtin ("__builtin_altivec_lvx_v8hi", v8hi_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVX_V8HI); + def_builtin ("__builtin_altivec_lvx_v16qi", v16qi_ftype_long_pcvoid, + ALTIVEC_BUILTIN_LVX_V16QI); + def_builtin ("__builtin_altivec_stvx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVX); + def_builtin ("__builtin_altivec_stvx_v2df", void_ftype_v2df_long_pvoid, + ALTIVEC_BUILTIN_STVX_V2DF); + def_builtin ("__builtin_altivec_stvx_v2di", void_ftype_v2di_long_pvoid, + ALTIVEC_BUILTIN_STVX_V2DI); + def_builtin ("__builtin_altivec_stvx_v4sf", void_ftype_v4sf_long_pvoid, + ALTIVEC_BUILTIN_STVX_V4SF); + def_builtin ("__builtin_altivec_stvx_v4si", void_ftype_v4si_long_pvoid, + ALTIVEC_BUILTIN_STVX_V4SI); + def_builtin ("__builtin_altivec_stvx_v8hi", void_ftype_v8hi_long_pvoid, + ALTIVEC_BUILTIN_STVX_V8HI); + def_builtin ("__builtin_altivec_stvx_v16qi", void_ftype_v16qi_long_pvoid, + ALTIVEC_BUILTIN_STVX_V16QI); + def_builtin ("__builtin_altivec_stvewx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVEWX); + def_builtin ("__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL); + def_builtin ("__builtin_altivec_stvxl_v2df", void_ftype_v2df_long_pvoid, + ALTIVEC_BUILTIN_STVXL_V2DF); + def_builtin ("__builtin_altivec_stvxl_v2di", void_ftype_v2di_long_pvoid, + ALTIVEC_BUILTIN_STVXL_V2DI); + def_builtin ("__builtin_altivec_stvxl_v4sf", void_ftype_v4sf_long_pvoid, + ALTIVEC_BUILTIN_STVXL_V4SF); + def_builtin ("__builtin_altivec_stvxl_v4si", void_ftype_v4si_long_pvoid, + ALTIVEC_BUILTIN_STVXL_V4SI); + def_builtin ("__builtin_altivec_stvxl_v8hi", void_ftype_v8hi_long_pvoid, + ALTIVEC_BUILTIN_STVXL_V8HI); + def_builtin ("__builtin_altivec_stvxl_v16qi", void_ftype_v16qi_long_pvoid, + ALTIVEC_BUILTIN_STVXL_V16QI); + def_builtin ("__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX); + def_builtin ("__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX); + def_builtin ("__builtin_vec_ld", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LD); + def_builtin ("__builtin_vec_lde", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDE); + def_builtin ("__builtin_vec_ldl", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDL); + def_builtin ("__builtin_vec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSL); + def_builtin ("__builtin_vec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSR); + def_builtin ("__builtin_vec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEBX); + def_builtin ("__builtin_vec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEHX); + def_builtin ("__builtin_vec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEWX); + def_builtin ("__builtin_vec_st", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_ST); + def_builtin ("__builtin_vec_ste", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STE); + def_builtin ("__builtin_vec_stl", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STL); + def_builtin ("__builtin_vec_stvewx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEWX); + def_builtin ("__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX); + def_builtin ("__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX); + + def_builtin ("__builtin_vsx_lxvd2x_v2df", v2df_ftype_long_pcvoid, + VSX_BUILTIN_LXVD2X_V2DF); + def_builtin ("__builtin_vsx_lxvd2x_v2di", v2di_ftype_long_pcvoid, + VSX_BUILTIN_LXVD2X_V2DI); + def_builtin ("__builtin_vsx_lxvw4x_v4sf", v4sf_ftype_long_pcvoid, + VSX_BUILTIN_LXVW4X_V4SF); + def_builtin ("__builtin_vsx_lxvw4x_v4si", v4si_ftype_long_pcvoid, + VSX_BUILTIN_LXVW4X_V4SI); + def_builtin ("__builtin_vsx_lxvw4x_v8hi", v8hi_ftype_long_pcvoid, + VSX_BUILTIN_LXVW4X_V8HI); + def_builtin ("__builtin_vsx_lxvw4x_v16qi", v16qi_ftype_long_pcvoid, + VSX_BUILTIN_LXVW4X_V16QI); + def_builtin ("__builtin_vsx_stxvd2x_v2df", void_ftype_v2df_long_pvoid, + VSX_BUILTIN_STXVD2X_V2DF); + def_builtin ("__builtin_vsx_stxvd2x_v2di", void_ftype_v2di_long_pvoid, + VSX_BUILTIN_STXVD2X_V2DI); + def_builtin ("__builtin_vsx_stxvw4x_v4sf", void_ftype_v4sf_long_pvoid, + VSX_BUILTIN_STXVW4X_V4SF); + def_builtin ("__builtin_vsx_stxvw4x_v4si", void_ftype_v4si_long_pvoid, + VSX_BUILTIN_STXVW4X_V4SI); + def_builtin ("__builtin_vsx_stxvw4x_v8hi", void_ftype_v8hi_long_pvoid, + VSX_BUILTIN_STXVW4X_V8HI); + def_builtin ("__builtin_vsx_stxvw4x_v16qi", void_ftype_v16qi_long_pvoid, + VSX_BUILTIN_STXVW4X_V16QI); + + def_builtin ("__builtin_vsx_ld_elemrev_v2df", v2df_ftype_long_pcvoid, + VSX_BUILTIN_LD_ELEMREV_V2DF); + def_builtin ("__builtin_vsx_ld_elemrev_v2di", v2di_ftype_long_pcvoid, + VSX_BUILTIN_LD_ELEMREV_V2DI); + def_builtin ("__builtin_vsx_ld_elemrev_v4sf", v4sf_ftype_long_pcvoid, + VSX_BUILTIN_LD_ELEMREV_V4SF); + def_builtin ("__builtin_vsx_ld_elemrev_v4si", v4si_ftype_long_pcvoid, + VSX_BUILTIN_LD_ELEMREV_V4SI); + def_builtin ("__builtin_vsx_ld_elemrev_v8hi", v8hi_ftype_long_pcvoid, + VSX_BUILTIN_LD_ELEMREV_V8HI); + def_builtin ("__builtin_vsx_ld_elemrev_v16qi", v16qi_ftype_long_pcvoid, + VSX_BUILTIN_LD_ELEMREV_V16QI); + def_builtin ("__builtin_vsx_st_elemrev_v2df", void_ftype_v2df_long_pvoid, + VSX_BUILTIN_ST_ELEMREV_V2DF); + def_builtin ("__builtin_vsx_st_elemrev_v1ti", void_ftype_v1ti_long_pvoid, + VSX_BUILTIN_ST_ELEMREV_V1TI); + def_builtin ("__builtin_vsx_st_elemrev_v2di", void_ftype_v2di_long_pvoid, + VSX_BUILTIN_ST_ELEMREV_V2DI); + def_builtin ("__builtin_vsx_st_elemrev_v4sf", void_ftype_v4sf_long_pvoid, + VSX_BUILTIN_ST_ELEMREV_V4SF); + def_builtin ("__builtin_vsx_st_elemrev_v4si", void_ftype_v4si_long_pvoid, + VSX_BUILTIN_ST_ELEMREV_V4SI); + def_builtin ("__builtin_vsx_st_elemrev_v8hi", void_ftype_v8hi_long_pvoid, + VSX_BUILTIN_ST_ELEMREV_V8HI); + def_builtin ("__builtin_vsx_st_elemrev_v16qi", void_ftype_v16qi_long_pvoid, + VSX_BUILTIN_ST_ELEMREV_V16QI); + + def_builtin ("__builtin_vec_vsx_ld", opaque_ftype_long_pcvoid, + VSX_BUILTIN_VEC_LD); + def_builtin ("__builtin_vec_vsx_st", void_ftype_opaque_long_pvoid, + VSX_BUILTIN_VEC_ST); + def_builtin ("__builtin_vec_xl", opaque_ftype_long_pcvoid, + VSX_BUILTIN_VEC_XL); + def_builtin ("__builtin_vec_xl_be", opaque_ftype_long_pcvoid, + VSX_BUILTIN_VEC_XL_BE); + def_builtin ("__builtin_vec_xst", void_ftype_opaque_long_pvoid, + VSX_BUILTIN_VEC_XST); + def_builtin ("__builtin_vec_xst_be", void_ftype_opaque_long_pvoid, + VSX_BUILTIN_VEC_XST_BE); + + def_builtin ("__builtin_vec_step", int_ftype_opaque, ALTIVEC_BUILTIN_VEC_STEP); + def_builtin ("__builtin_vec_splats", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_SPLATS); + def_builtin ("__builtin_vec_promote", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_PROMOTE); + + def_builtin ("__builtin_vec_sld", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_SLD); + def_builtin ("__builtin_vec_splat", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_SPLAT); + def_builtin ("__builtin_vec_extract", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_EXTRACT); + def_builtin ("__builtin_vec_insert", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_INSERT); + def_builtin ("__builtin_vec_vspltw", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTW); + def_builtin ("__builtin_vec_vsplth", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTH); + def_builtin ("__builtin_vec_vspltb", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTB); + def_builtin ("__builtin_vec_ctf", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTF); + def_builtin ("__builtin_vec_vcfsx", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFSX); + def_builtin ("__builtin_vec_vcfux", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFUX); + def_builtin ("__builtin_vec_cts", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTS); + def_builtin ("__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU); + + def_builtin ("__builtin_vec_adde", opaque_ftype_opaque_opaque_opaque, + ALTIVEC_BUILTIN_VEC_ADDE); + def_builtin ("__builtin_vec_addec", opaque_ftype_opaque_opaque_opaque, + ALTIVEC_BUILTIN_VEC_ADDEC); + def_builtin ("__builtin_vec_cmpne", opaque_ftype_opaque_opaque, + ALTIVEC_BUILTIN_VEC_CMPNE); + def_builtin ("__builtin_vec_mul", opaque_ftype_opaque_opaque, + ALTIVEC_BUILTIN_VEC_MUL); + def_builtin ("__builtin_vec_sube", opaque_ftype_opaque_opaque_opaque, + ALTIVEC_BUILTIN_VEC_SUBE); + def_builtin ("__builtin_vec_subec", opaque_ftype_opaque_opaque_opaque, + ALTIVEC_BUILTIN_VEC_SUBEC); + + /* Cell builtins. */ + def_builtin ("__builtin_altivec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLX); + def_builtin ("__builtin_altivec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLXL); + def_builtin ("__builtin_altivec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRX); + def_builtin ("__builtin_altivec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRXL); + + def_builtin ("__builtin_vec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLX); + def_builtin ("__builtin_vec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLXL); + def_builtin ("__builtin_vec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRX); + def_builtin ("__builtin_vec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRXL); + + def_builtin ("__builtin_altivec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLX); + def_builtin ("__builtin_altivec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLXL); + def_builtin ("__builtin_altivec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRX); + def_builtin ("__builtin_altivec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRXL); + + def_builtin ("__builtin_vec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLX); + def_builtin ("__builtin_vec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLXL); + def_builtin ("__builtin_vec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRX); + def_builtin ("__builtin_vec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRXL); + + if (TARGET_P9_VECTOR) + { + def_builtin ("__builtin_altivec_stxvl", void_ftype_v16qi_pvoid_long, + P9V_BUILTIN_STXVL); + def_builtin ("__builtin_xst_len_r", void_ftype_v16qi_pvoid_long, + P9V_BUILTIN_XST_LEN_R); + } + + /* Add the DST variants. */ + d = bdesc_dst; + for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++) + { + HOST_WIDE_INT mask = d->mask; + + /* It is expected that these dst built-in functions may have + d->icode equal to CODE_FOR_nothing. */ + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "altivec_init_builtins, skip dst %s\n", + d->name); + continue; + } + def_builtin (d->name, void_ftype_pcvoid_int_int, d->code); + } + + /* Initialize the predicates. */ + d = bdesc_altivec_preds; + for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, d++) + { + machine_mode mode1; + tree type; + HOST_WIDE_INT mask = d->mask; + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "altivec_init_builtins, skip predicate %s\n", + d->name); + continue; + } + + if (rs6000_overloaded_builtin_p (d->code)) + mode1 = VOIDmode; + else + { + /* Cannot define builtin if the instruction is disabled. */ + gcc_assert (d->icode != CODE_FOR_nothing); + mode1 = insn_data[d->icode].operand[1].mode; + } + + switch (mode1) + { + case E_VOIDmode: + type = int_ftype_int_opaque_opaque; + break; + case E_V2DImode: + type = int_ftype_int_v2di_v2di; + break; + case E_V4SImode: + type = int_ftype_int_v4si_v4si; + break; + case E_V8HImode: + type = int_ftype_int_v8hi_v8hi; + break; + case E_V16QImode: + type = int_ftype_int_v16qi_v16qi; + break; + case E_V4SFmode: + type = int_ftype_int_v4sf_v4sf; + break; + case E_V2DFmode: + type = int_ftype_int_v2df_v2df; + break; + default: + gcc_unreachable (); + } + + def_builtin (d->name, type, d->code); + } + + /* Initialize the abs* operators. */ + d = bdesc_abs; + for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++) + { + machine_mode mode0; + tree type; + HOST_WIDE_INT mask = d->mask; + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "altivec_init_builtins, skip abs %s\n", + d->name); + continue; + } + + /* Cannot define builtin if the instruction is disabled. */ + gcc_assert (d->icode != CODE_FOR_nothing); + mode0 = insn_data[d->icode].operand[0].mode; + + switch (mode0) + { + case E_V2DImode: + type = v2di_ftype_v2di; + break; + case E_V4SImode: + type = v4si_ftype_v4si; + break; + case E_V8HImode: + type = v8hi_ftype_v8hi; + break; + case E_V16QImode: + type = v16qi_ftype_v16qi; + break; + case E_V4SFmode: + type = v4sf_ftype_v4sf; + break; + case E_V2DFmode: + type = v2df_ftype_v2df; + break; + default: + gcc_unreachable (); + } + + def_builtin (d->name, type, d->code); + } + + /* Initialize target builtin that implements + targetm.vectorize.builtin_mask_for_load. */ + + decl = add_builtin_function ("__builtin_altivec_mask_for_load", + v16qi_ftype_long_pcvoid, + ALTIVEC_BUILTIN_MASK_FOR_LOAD, + BUILT_IN_MD, NULL, NULL_TREE); + TREE_READONLY (decl) = 1; + /* Record the decl. Will be used by rs6000_builtin_mask_for_load. */ + altivec_builtin_mask_for_load = decl; + + /* Access to the vec_init patterns. */ + ftype = build_function_type_list (V4SI_type_node, integer_type_node, + integer_type_node, integer_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_init_v4si", ftype, ALTIVEC_BUILTIN_VEC_INIT_V4SI); + + ftype = build_function_type_list (V8HI_type_node, short_integer_type_node, + short_integer_type_node, + short_integer_type_node, + short_integer_type_node, + short_integer_type_node, + short_integer_type_node, + short_integer_type_node, + short_integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_init_v8hi", ftype, ALTIVEC_BUILTIN_VEC_INIT_V8HI); + + ftype = build_function_type_list (V16QI_type_node, char_type_node, + char_type_node, char_type_node, + char_type_node, char_type_node, + char_type_node, char_type_node, + char_type_node, char_type_node, + char_type_node, char_type_node, + char_type_node, char_type_node, + char_type_node, char_type_node, + char_type_node, NULL_TREE); + def_builtin ("__builtin_vec_init_v16qi", ftype, + ALTIVEC_BUILTIN_VEC_INIT_V16QI); + + ftype = build_function_type_list (V4SF_type_node, float_type_node, + float_type_node, float_type_node, + float_type_node, NULL_TREE); + def_builtin ("__builtin_vec_init_v4sf", ftype, ALTIVEC_BUILTIN_VEC_INIT_V4SF); + + /* VSX builtins. */ + ftype = build_function_type_list (V2DF_type_node, double_type_node, + double_type_node, NULL_TREE); + def_builtin ("__builtin_vec_init_v2df", ftype, VSX_BUILTIN_VEC_INIT_V2DF); + + ftype = build_function_type_list (V2DI_type_node, intDI_type_node, + intDI_type_node, NULL_TREE); + def_builtin ("__builtin_vec_init_v2di", ftype, VSX_BUILTIN_VEC_INIT_V2DI); + + /* Access to the vec_set patterns. */ + ftype = build_function_type_list (V4SI_type_node, V4SI_type_node, + intSI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_set_v4si", ftype, ALTIVEC_BUILTIN_VEC_SET_V4SI); + + ftype = build_function_type_list (V8HI_type_node, V8HI_type_node, + intHI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_set_v8hi", ftype, ALTIVEC_BUILTIN_VEC_SET_V8HI); + + ftype = build_function_type_list (V16QI_type_node, V16QI_type_node, + intQI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_set_v16qi", ftype, ALTIVEC_BUILTIN_VEC_SET_V16QI); + + ftype = build_function_type_list (V4SF_type_node, V4SF_type_node, + float_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_set_v4sf", ftype, ALTIVEC_BUILTIN_VEC_SET_V4SF); + + ftype = build_function_type_list (V2DF_type_node, V2DF_type_node, + double_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_set_v2df", ftype, VSX_BUILTIN_VEC_SET_V2DF); + + ftype = build_function_type_list (V2DI_type_node, V2DI_type_node, + intDI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_set_v2di", ftype, VSX_BUILTIN_VEC_SET_V2DI); + + /* Access to the vec_extract patterns. */ + ftype = build_function_type_list (intSI_type_node, V4SI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_ext_v4si", ftype, ALTIVEC_BUILTIN_VEC_EXT_V4SI); + + ftype = build_function_type_list (intHI_type_node, V8HI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_ext_v8hi", ftype, ALTIVEC_BUILTIN_VEC_EXT_V8HI); + + ftype = build_function_type_list (intQI_type_node, V16QI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_ext_v16qi", ftype, ALTIVEC_BUILTIN_VEC_EXT_V16QI); + + ftype = build_function_type_list (float_type_node, V4SF_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_ext_v4sf", ftype, ALTIVEC_BUILTIN_VEC_EXT_V4SF); + + ftype = build_function_type_list (double_type_node, V2DF_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_ext_v2df", ftype, VSX_BUILTIN_VEC_EXT_V2DF); + + ftype = build_function_type_list (intDI_type_node, V2DI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_ext_v2di", ftype, VSX_BUILTIN_VEC_EXT_V2DI); + + + if (V1TI_type_node) + { + tree v1ti_ftype_long_pcvoid + = build_function_type_list (V1TI_type_node, + long_integer_type_node, pcvoid_type_node, + NULL_TREE); + tree void_ftype_v1ti_long_pvoid + = build_function_type_list (void_type_node, + V1TI_type_node, long_integer_type_node, + pvoid_type_node, NULL_TREE); + def_builtin ("__builtin_vsx_ld_elemrev_v1ti", v1ti_ftype_long_pcvoid, + VSX_BUILTIN_LD_ELEMREV_V1TI); + def_builtin ("__builtin_vsx_lxvd2x_v1ti", v1ti_ftype_long_pcvoid, + VSX_BUILTIN_LXVD2X_V1TI); + def_builtin ("__builtin_vsx_stxvd2x_v1ti", void_ftype_v1ti_long_pvoid, + VSX_BUILTIN_STXVD2X_V1TI); + ftype = build_function_type_list (V1TI_type_node, intTI_type_node, + NULL_TREE, NULL_TREE); + def_builtin ("__builtin_vec_init_v1ti", ftype, VSX_BUILTIN_VEC_INIT_V1TI); + ftype = build_function_type_list (V1TI_type_node, V1TI_type_node, + intTI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_set_v1ti", ftype, VSX_BUILTIN_VEC_SET_V1TI); + ftype = build_function_type_list (intTI_type_node, V1TI_type_node, + integer_type_node, NULL_TREE); + def_builtin ("__builtin_vec_ext_v1ti", ftype, VSX_BUILTIN_VEC_EXT_V1TI); + } + +} + +static void +htm_init_builtins (void) +{ + HOST_WIDE_INT builtin_mask = rs6000_builtin_mask; + const struct builtin_description *d; + size_t i; + + d = bdesc_htm; + for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++) + { + tree op[MAX_HTM_OPERANDS], type; + HOST_WIDE_INT mask = d->mask; + unsigned attr = rs6000_builtin_info[d->code].attr; + bool void_func = (attr & RS6000_BTC_VOID); + int attr_args = (attr & RS6000_BTC_TYPE_MASK); + int nopnds = 0; + tree gpr_type_node; + tree rettype; + tree argtype; + + /* It is expected that these htm built-in functions may have + d->icode equal to CODE_FOR_nothing. */ + + if (TARGET_32BIT && TARGET_POWERPC64) + gpr_type_node = long_long_unsigned_type_node; + else + gpr_type_node = long_unsigned_type_node; + + if (attr & RS6000_BTC_SPR) + { + rettype = gpr_type_node; + argtype = gpr_type_node; + } + else if (d->code == HTM_BUILTIN_TABORTDC + || d->code == HTM_BUILTIN_TABORTDCI) + { + rettype = unsigned_type_node; + argtype = gpr_type_node; + } + else + { + rettype = unsigned_type_node; + argtype = unsigned_type_node; + } + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "htm_builtin, skip binary %s\n", d->name); + continue; + } + + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "htm_builtin, bdesc_htm[%ld] no name\n", + (long unsigned) i); + continue; + } + + op[nopnds++] = (void_func) ? void_type_node : rettype; + + if (attr_args == RS6000_BTC_UNARY) + op[nopnds++] = argtype; + else if (attr_args == RS6000_BTC_BINARY) + { + op[nopnds++] = argtype; + op[nopnds++] = argtype; + } + else if (attr_args == RS6000_BTC_TERNARY) + { + op[nopnds++] = argtype; + op[nopnds++] = argtype; + op[nopnds++] = argtype; + } + + switch (nopnds) + { + case 1: + type = build_function_type_list (op[0], NULL_TREE); + break; + case 2: + type = build_function_type_list (op[0], op[1], NULL_TREE); + break; + case 3: + type = build_function_type_list (op[0], op[1], op[2], NULL_TREE); + break; + case 4: + type = build_function_type_list (op[0], op[1], op[2], op[3], + NULL_TREE); + break; + default: + gcc_unreachable (); + } + + def_builtin (d->name, type, d->code); + } +} + +/* Map types for builtin functions with an explicit return type and up to 3 + arguments. Functions with fewer than 3 arguments use VOIDmode as the type + of the argument. */ +static tree +builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0, + machine_mode mode_arg1, machine_mode mode_arg2, + enum rs6000_builtins builtin, const char *name) +{ + struct builtin_hash_struct h; + struct builtin_hash_struct *h2; + int num_args = 3; + int i; + tree ret_type = NULL_TREE; + tree arg_type[3] = { NULL_TREE, NULL_TREE, NULL_TREE }; + + /* Create builtin_hash_table. */ + if (builtin_hash_table == NULL) + builtin_hash_table = hash_table::create_ggc (1500); + + h.type = NULL_TREE; + h.mode[0] = mode_ret; + h.mode[1] = mode_arg0; + h.mode[2] = mode_arg1; + h.mode[3] = mode_arg2; + h.uns_p[0] = 0; + h.uns_p[1] = 0; + h.uns_p[2] = 0; + h.uns_p[3] = 0; + + /* If the builtin is a type that produces unsigned results or takes unsigned + arguments, and it is returned as a decl for the vectorizer (such as + widening multiplies, permute), make sure the arguments and return value + are type correct. */ + switch (builtin) + { + /* unsigned 1 argument functions. */ + case CRYPTO_BUILTIN_VSBOX: + case CRYPTO_BUILTIN_VSBOX_BE: + case P8V_BUILTIN_VGBBD: + case MISC_BUILTIN_CDTBCD: + case MISC_BUILTIN_CBCDTD: + h.uns_p[0] = 1; + h.uns_p[1] = 1; + break; + + /* unsigned 2 argument functions. */ + case ALTIVEC_BUILTIN_VMULEUB: + case ALTIVEC_BUILTIN_VMULEUH: + case P8V_BUILTIN_VMULEUW: + case ALTIVEC_BUILTIN_VMULOUB: + case ALTIVEC_BUILTIN_VMULOUH: + case P8V_BUILTIN_VMULOUW: + case CRYPTO_BUILTIN_VCIPHER: + case CRYPTO_BUILTIN_VCIPHER_BE: + case CRYPTO_BUILTIN_VCIPHERLAST: + case CRYPTO_BUILTIN_VCIPHERLAST_BE: + case CRYPTO_BUILTIN_VNCIPHER: + case CRYPTO_BUILTIN_VNCIPHER_BE: + case CRYPTO_BUILTIN_VNCIPHERLAST: + case CRYPTO_BUILTIN_VNCIPHERLAST_BE: + case CRYPTO_BUILTIN_VPMSUMB: + case CRYPTO_BUILTIN_VPMSUMH: + case CRYPTO_BUILTIN_VPMSUMW: + case CRYPTO_BUILTIN_VPMSUMD: + case CRYPTO_BUILTIN_VPMSUM: + case MISC_BUILTIN_ADDG6S: + case MISC_BUILTIN_DIVWEU: + case MISC_BUILTIN_DIVDEU: + case VSX_BUILTIN_UDIV_V2DI: + case ALTIVEC_BUILTIN_VMAXUB: + case ALTIVEC_BUILTIN_VMINUB: + case ALTIVEC_BUILTIN_VMAXUH: + case ALTIVEC_BUILTIN_VMINUH: + case ALTIVEC_BUILTIN_VMAXUW: + case ALTIVEC_BUILTIN_VMINUW: + case P8V_BUILTIN_VMAXUD: + case P8V_BUILTIN_VMINUD: + h.uns_p[0] = 1; + h.uns_p[1] = 1; + h.uns_p[2] = 1; + break; + + /* unsigned 3 argument functions. */ + case ALTIVEC_BUILTIN_VPERM_16QI_UNS: + case ALTIVEC_BUILTIN_VPERM_8HI_UNS: + case ALTIVEC_BUILTIN_VPERM_4SI_UNS: + case ALTIVEC_BUILTIN_VPERM_2DI_UNS: + case ALTIVEC_BUILTIN_VSEL_16QI_UNS: + case ALTIVEC_BUILTIN_VSEL_8HI_UNS: + case ALTIVEC_BUILTIN_VSEL_4SI_UNS: + case ALTIVEC_BUILTIN_VSEL_2DI_UNS: + case VSX_BUILTIN_VPERM_16QI_UNS: + case VSX_BUILTIN_VPERM_8HI_UNS: + case VSX_BUILTIN_VPERM_4SI_UNS: + case VSX_BUILTIN_VPERM_2DI_UNS: + case VSX_BUILTIN_XXSEL_16QI_UNS: + case VSX_BUILTIN_XXSEL_8HI_UNS: + case VSX_BUILTIN_XXSEL_4SI_UNS: + case VSX_BUILTIN_XXSEL_2DI_UNS: + case CRYPTO_BUILTIN_VPERMXOR: + case CRYPTO_BUILTIN_VPERMXOR_V2DI: + case CRYPTO_BUILTIN_VPERMXOR_V4SI: + case CRYPTO_BUILTIN_VPERMXOR_V8HI: + case CRYPTO_BUILTIN_VPERMXOR_V16QI: + case CRYPTO_BUILTIN_VSHASIGMAW: + case CRYPTO_BUILTIN_VSHASIGMAD: + case CRYPTO_BUILTIN_VSHASIGMA: + h.uns_p[0] = 1; + h.uns_p[1] = 1; + h.uns_p[2] = 1; + h.uns_p[3] = 1; + break; + + /* signed permute functions with unsigned char mask. */ + case ALTIVEC_BUILTIN_VPERM_16QI: + case ALTIVEC_BUILTIN_VPERM_8HI: + case ALTIVEC_BUILTIN_VPERM_4SI: + case ALTIVEC_BUILTIN_VPERM_4SF: + case ALTIVEC_BUILTIN_VPERM_2DI: + case ALTIVEC_BUILTIN_VPERM_2DF: + case VSX_BUILTIN_VPERM_16QI: + case VSX_BUILTIN_VPERM_8HI: + case VSX_BUILTIN_VPERM_4SI: + case VSX_BUILTIN_VPERM_4SF: + case VSX_BUILTIN_VPERM_2DI: + case VSX_BUILTIN_VPERM_2DF: + h.uns_p[3] = 1; + break; + + /* unsigned args, signed return. */ + case VSX_BUILTIN_XVCVUXDSP: + case VSX_BUILTIN_XVCVUXDDP_UNS: + case ALTIVEC_BUILTIN_UNSFLOAT_V4SI_V4SF: + h.uns_p[1] = 1; + break; + + /* signed args, unsigned return. */ + case VSX_BUILTIN_XVCVDPUXDS_UNS: + case ALTIVEC_BUILTIN_FIXUNS_V4SF_V4SI: + case MISC_BUILTIN_UNPACK_TD: + case MISC_BUILTIN_UNPACK_V1TI: + h.uns_p[0] = 1; + break; + + /* unsigned arguments, bool return (compares). */ + case ALTIVEC_BUILTIN_VCMPEQUB: + case ALTIVEC_BUILTIN_VCMPEQUH: + case ALTIVEC_BUILTIN_VCMPEQUW: + case P8V_BUILTIN_VCMPEQUD: + case VSX_BUILTIN_CMPGE_U16QI: + case VSX_BUILTIN_CMPGE_U8HI: + case VSX_BUILTIN_CMPGE_U4SI: + case VSX_BUILTIN_CMPGE_U2DI: + case ALTIVEC_BUILTIN_VCMPGTUB: + case ALTIVEC_BUILTIN_VCMPGTUH: + case ALTIVEC_BUILTIN_VCMPGTUW: + case P8V_BUILTIN_VCMPGTUD: + h.uns_p[1] = 1; + h.uns_p[2] = 1; + break; + + /* unsigned arguments for 128-bit pack instructions. */ + case MISC_BUILTIN_PACK_TD: + case MISC_BUILTIN_PACK_V1TI: + h.uns_p[1] = 1; + h.uns_p[2] = 1; + break; + + /* unsigned second arguments (vector shift right). */ + case ALTIVEC_BUILTIN_VSRB: + case ALTIVEC_BUILTIN_VSRH: + case ALTIVEC_BUILTIN_VSRW: + case P8V_BUILTIN_VSRD: + h.uns_p[2] = 1; + break; + + default: + break; + } + + /* Figure out how many args are present. */ + while (num_args > 0 && h.mode[num_args] == VOIDmode) + num_args--; + + ret_type = builtin_mode_to_type[h.mode[0]][h.uns_p[0]]; + if (!ret_type && h.uns_p[0]) + ret_type = builtin_mode_to_type[h.mode[0]][0]; + + if (!ret_type) + fatal_error (input_location, + "internal error: builtin function %qs had an unexpected " + "return type %qs", name, GET_MODE_NAME (h.mode[0])); + + for (i = 0; i < (int) ARRAY_SIZE (arg_type); i++) + arg_type[i] = NULL_TREE; + + for (i = 0; i < num_args; i++) + { + int m = (int) h.mode[i+1]; + int uns_p = h.uns_p[i+1]; + + arg_type[i] = builtin_mode_to_type[m][uns_p]; + if (!arg_type[i] && uns_p) + arg_type[i] = builtin_mode_to_type[m][0]; + + if (!arg_type[i]) + fatal_error (input_location, + "internal error: builtin function %qs, argument %d " + "had unexpected argument type %qs", name, i, + GET_MODE_NAME (m)); + } + + builtin_hash_struct **found = builtin_hash_table->find_slot (&h, INSERT); + if (*found == NULL) + { + h2 = ggc_alloc (); + *h2 = h; + *found = h2; + + h2->type = build_function_type_list (ret_type, arg_type[0], arg_type[1], + arg_type[2], NULL_TREE); + } + + return (*found)->type; +} + +static void +rs6000_common_init_builtins (void) +{ + const struct builtin_description *d; + size_t i; + + tree opaque_ftype_opaque = NULL_TREE; + tree opaque_ftype_opaque_opaque = NULL_TREE; + tree opaque_ftype_opaque_opaque_opaque = NULL_TREE; + HOST_WIDE_INT builtin_mask = rs6000_builtin_mask; + + /* Create Altivec and VSX builtins on machines with at least the + general purpose extensions (970 and newer) to allow the use of + the target attribute. */ + + if (TARGET_EXTRA_BUILTINS) + builtin_mask |= RS6000_BTM_COMMON; + + /* Add the ternary operators. */ + d = bdesc_3arg; + for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) + { + tree type; + HOST_WIDE_INT mask = d->mask; + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip ternary %s\n", d->name); + continue; + } + + if (rs6000_overloaded_builtin_p (d->code)) + { + if (! (type = opaque_ftype_opaque_opaque_opaque)) + type = opaque_ftype_opaque_opaque_opaque + = build_function_type_list (opaque_V4SI_type_node, + opaque_V4SI_type_node, + opaque_V4SI_type_node, + opaque_V4SI_type_node, + NULL_TREE); + } + else + { + enum insn_code icode = d->icode; + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, bdesc_3arg[%ld] no name\n", + (long unsigned)i); + + continue; + } + + if (icode == CODE_FOR_nothing) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip ternary %s (no code)\n", + d->name); + + continue; + } + + type = builtin_function_type (insn_data[icode].operand[0].mode, + insn_data[icode].operand[1].mode, + insn_data[icode].operand[2].mode, + insn_data[icode].operand[3].mode, + d->code, d->name); + } + + def_builtin (d->name, type, d->code); + } + + /* Add the binary operators. */ + d = bdesc_2arg; + for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++) + { + machine_mode mode0, mode1, mode2; + tree type; + HOST_WIDE_INT mask = d->mask; + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip binary %s\n", d->name); + continue; + } + + if (rs6000_overloaded_builtin_p (d->code)) + { + if (! (type = opaque_ftype_opaque_opaque)) + type = opaque_ftype_opaque_opaque + = build_function_type_list (opaque_V4SI_type_node, + opaque_V4SI_type_node, + opaque_V4SI_type_node, + NULL_TREE); + } + else + { + enum insn_code icode = d->icode; + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, bdesc_2arg[%ld] no name\n", + (long unsigned)i); + + continue; + } + + if (icode == CODE_FOR_nothing) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip binary %s (no code)\n", + d->name); + + continue; + } + + mode0 = insn_data[icode].operand[0].mode; + mode1 = insn_data[icode].operand[1].mode; + mode2 = insn_data[icode].operand[2].mode; + + type = builtin_function_type (mode0, mode1, mode2, VOIDmode, + d->code, d->name); + } + + def_builtin (d->name, type, d->code); + } + + /* Add the simple unary operators. */ + d = bdesc_1arg; + for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++) + { + machine_mode mode0, mode1; + tree type; + HOST_WIDE_INT mask = d->mask; + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip unary %s\n", d->name); + continue; + } + + if (rs6000_overloaded_builtin_p (d->code)) + { + if (! (type = opaque_ftype_opaque)) + type = opaque_ftype_opaque + = build_function_type_list (opaque_V4SI_type_node, + opaque_V4SI_type_node, + NULL_TREE); + } + else + { + enum insn_code icode = d->icode; + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, bdesc_1arg[%ld] no name\n", + (long unsigned)i); + + continue; + } + + if (icode == CODE_FOR_nothing) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip unary %s (no code)\n", + d->name); + + continue; + } + + mode0 = insn_data[icode].operand[0].mode; + mode1 = insn_data[icode].operand[1].mode; + + type = builtin_function_type (mode0, mode1, VOIDmode, VOIDmode, + d->code, d->name); + } + + def_builtin (d->name, type, d->code); + } + + /* Add the simple no-argument operators. */ + d = bdesc_0arg; + for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++) + { + machine_mode mode0; + tree type; + HOST_WIDE_INT mask = d->mask; + + if ((mask & builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip no-argument %s\n", d->name); + continue; + } + if (rs6000_overloaded_builtin_p (d->code)) + { + if (!opaque_ftype_opaque) + opaque_ftype_opaque + = build_function_type_list (opaque_V4SI_type_node, NULL_TREE); + type = opaque_ftype_opaque; + } + else + { + enum insn_code icode = d->icode; + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, bdesc_0arg[%lu] no name\n", + (long unsigned) i); + continue; + } + if (icode == CODE_FOR_nothing) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, + "rs6000_builtin, skip no-argument %s (no code)\n", + d->name); + continue; + } + mode0 = insn_data[icode].operand[0].mode; + type = builtin_function_type (mode0, VOIDmode, VOIDmode, VOIDmode, + d->code, d->name); + } + def_builtin (d->name, type, d->code); + } +} + +/* Return the internal arg pointer used for function incoming + arguments. When -fsplit-stack, the arg pointer is r12 so we need + to copy it to a pseudo in order for it to be preserved over calls + and suchlike. We'd really like to use a pseudo here for the + internal arg pointer but data-flow analysis is not prepared to + accept pseudos as live at the beginning of a function. */ + +rtx +rs6000_internal_arg_pointer (void) +{ + if (flag_split_stack + && (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (cfun->decl)) + == NULL)) + + { + if (cfun->machine->split_stack_arg_pointer == NULL_RTX) + { + rtx pat; + + cfun->machine->split_stack_arg_pointer = gen_reg_rtx (Pmode); + REG_POINTER (cfun->machine->split_stack_arg_pointer) = 1; + + /* Put the pseudo initialization right after the note at the + beginning of the function. */ + pat = gen_rtx_SET (cfun->machine->split_stack_arg_pointer, + gen_rtx_REG (Pmode, 12)); + push_topmost_sequence (); + emit_insn_after (pat, get_insns ()); + pop_topmost_sequence (); + } + rtx ret = plus_constant (Pmode, cfun->machine->split_stack_arg_pointer, + FIRST_PARM_OFFSET (current_function_decl)); + return copy_to_reg (ret); + } + return virtual_incoming_args_rtx; +} + + +/* A C compound statement that outputs the assembler code for a thunk + function, used to implement C++ virtual function calls with + multiple inheritance. The thunk acts as a wrapper around a virtual + function, adjusting the implicit object parameter before handing + control off to the real function. + + First, emit code to add the integer DELTA to the location that + contains the incoming first argument. Assume that this argument + contains a pointer, and is the one used to pass the `this' pointer + in C++. This is the incoming argument *before* the function + prologue, e.g. `%o0' on a sparc. The addition must preserve the + values of all other incoming arguments. + + After the addition, emit code to jump to FUNCTION, which is a + `FUNCTION_DECL'. This is a direct pure jump, not a call, and does + not touch the return address. Hence returning from FUNCTION will + return to whoever called the current `thunk'. + + The effect must be as if FUNCTION had been called directly with the + adjusted first argument. This macro is responsible for emitting + all of the code for a thunk function; output_function_prologue() + and output_function_epilogue() are not invoked. + + The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already + been extracted from it.) It might possibly be useful on some + targets, but probably not. + + If you do not define this macro, the target-independent code in the + C++ frontend will generate a less efficient heavyweight thunk that + calls FUNCTION instead of jumping to it. The generic approach does + not support varargs. */ + +void +rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, + tree function) +{ + const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl)); + rtx this_rtx, funexp; + rtx_insn *insn; + + reload_completed = 1; + epilogue_completed = 1; + + /* Mark the end of the (empty) prologue. */ + emit_note (NOTE_INSN_PROLOGUE_END); + + /* Find the "this" pointer. If the function returns a structure, + the structure return pointer is in r3. */ + if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) + this_rtx = gen_rtx_REG (Pmode, 4); + else + this_rtx = gen_rtx_REG (Pmode, 3); + + /* Apply the constant offset, if required. */ + if (delta) + emit_insn (gen_add3_insn (this_rtx, this_rtx, GEN_INT (delta))); + + /* Apply the offset from the vtable, if required. */ + if (vcall_offset) + { + rtx vcall_offset_rtx = GEN_INT (vcall_offset); + rtx tmp = gen_rtx_REG (Pmode, 12); + + emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx)); + if (((unsigned HOST_WIDE_INT) vcall_offset) + 0x8000 >= 0x10000) + { + emit_insn (gen_add3_insn (tmp, tmp, vcall_offset_rtx)); + emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp)); + } + else + { + rtx loc = gen_rtx_PLUS (Pmode, tmp, vcall_offset_rtx); + + emit_move_insn (tmp, gen_rtx_MEM (Pmode, loc)); + } + emit_insn (gen_add3_insn (this_rtx, this_rtx, tmp)); + } + + /* Generate a tail call to the target function. */ + if (!TREE_USED (function)) + { + assemble_external (function); + TREE_USED (function) = 1; + } + funexp = XEXP (DECL_RTL (function), 0); + funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); + +#if TARGET_MACHO + if (MACHOPIC_INDIRECT) + funexp = machopic_indirect_call_target (funexp); +#endif + + /* gen_sibcall expects reload to convert scratch pseudo to LR so we must + generate sibcall RTL explicitly. */ + insn = emit_call_insn ( + gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (3, + gen_rtx_CALL (VOIDmode, + funexp, const0_rtx), + gen_rtx_USE (VOIDmode, const0_rtx), + simple_return_rtx))); + SIBLING_CALL_P (insn) = 1; + emit_barrier (); + + /* Run just enough of rest_of_compilation to get the insns emitted. + There's not really enough bulk here to make other passes such as + instruction scheduling worth while. */ + insn = get_insns (); + shorten_branches (insn); + assemble_start_function (thunk_fndecl, fnname); + final_start_function (insn, file, 1); + final (insn, file, 1); + final_end_function (); + assemble_end_function (thunk_fndecl, fnname); + + reload_completed = 0; + epilogue_completed = 0; +} + +#include "gt-rs6000-call.h" diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h index c526967..0da040c 100644 --- a/gcc/config/rs6000/rs6000-internal.h +++ b/gcc/config/rs6000/rs6000-internal.h @@ -99,6 +99,7 @@ extern const char * rs6000_machine_from_flags (void); extern void emit_asm_machine (void); extern bool rs6000_global_entry_point_prologue_needed_p (void); extern bool rs6000_keep_leaf_when_profiled (void); +extern void rs6000_live_on_entry (bitmap regs); /* Return true if the OFFSET is valid for the quad address instructions that use d-form (register + offset) addressing. */ @@ -123,4 +124,76 @@ extern vec *branch_islands; #endif +/* Declare functions in rs6000-call.c or called in rs6000.c + from rs6000-call.c */ +extern int rs6000_darwin64_struct_check_p (machine_mode mode, const_tree type); +extern bool rs6000_discover_homogeneous_aggregate (machine_mode mode, + const_tree type, + machine_mode *elt_mode, + int *n_elts); +extern void rs6000_output_mi_thunk (FILE *file, + tree thunk_fndecl ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, + HOST_WIDE_INT vcall_offset, + tree function); +extern bool rs6000_output_addr_const_extra (FILE *file, rtx x); +extern bool rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi); +extern void rs6000_invalid_builtin (enum rs6000_builtins fncode); +extern tree rs6000_build_builtin_va_list (void); +extern void rs6000_va_start (tree valist, rtx nextarg); +extern tree rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, + gimple_seq *post_p); +extern machine_mode rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree, int); +extern bool rs6000_return_in_memory (const_tree type, + const_tree fntype ATTRIBUTE_UNUSED); +extern bool rs6000_return_in_msb (const_tree valtype); +extern bool rs6000_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, + machine_mode mode, const_tree type, + bool named ATTRIBUTE_UNUSED); +extern void setup_incoming_varargs (cumulative_args_t cum, machine_mode mode, + tree type, int *pretend_size ATTRIBUTE_UNUSED, + int no_rtl); +extern unsigned int rs6000_function_arg_boundary (machine_mode mode, + const_tree type); +extern bool rs6000_must_pass_in_stack (machine_mode mode, const_tree type); +extern int rs6000_arg_partial_bytes (cumulative_args_t cum_v, + machine_mode mode, tree type, + bool named); +extern void rs6000_function_arg_advance (cumulative_args_t cum, + machine_mode mode, + const_tree type, bool named); +extern pad_direction rs6000_function_arg_padding (machine_mode mode, + const_tree type); +extern rtx rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode, + const_tree type, bool named); +extern rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree, + bool, bool); +extern rtx rs6000_internal_arg_pointer (void); + +extern void rs6000_init_builtins (void); +extern tree rs6000_builtin_decl (unsigned code, + bool initialize_p ATTRIBUTE_UNUSED); +extern rtx rs6000_expand_builtin (tree exp, rtx target, + rtx subtarget ATTRIBUTE_UNUSED, + machine_mode mode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED); +extern tree rs6000_fold_builtin (tree fndecl ATTRIBUTE_UNUSED, + int n_args ATTRIBUTE_UNUSED, + tree *args ATTRIBUTE_UNUSED, + bool ignore ATTRIBUTE_UNUSED); + +#if TARGET_ELF +extern bool rs6000_passes_ieee128; +#endif +extern bool rs6000_passes_float; +extern bool rs6000_passes_long_double; +extern bool rs6000_passes_vector; +extern bool rs6000_returns_struct; +extern bool cpu_builtin_p; +extern GTY(()) tree builtin_mode_to_type[MAX_MACHINE_MODE][2]; +extern GTY(()) tree altivec_builtin_mask_for_load; + #endif diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 0013b39..dbb6a0f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -102,10 +102,8 @@ #endif #endif -static pad_direction rs6000_function_arg_padding (machine_mode, const_tree); - /* Support targetm.vectorize.builtin_mask_for_load. */ -static GTY(()) tree altivec_builtin_mask_for_load; +GTY(()) tree altivec_builtin_mask_for_load; /* Set to nonzero once AIX common-mode calls have been defined. */ static GTY(()) int common_mode_defined; @@ -129,7 +127,7 @@ scalar_int_mode rs6000_pmode; floating point. We changed the default C++ mangling for these types and we may want to generate a weak alias of the old mangling (U10__float128) to the new mangling (u9__ieee128). */ -static bool rs6000_passes_ieee128; +bool rs6000_passes_ieee128 = false; #endif /* Generate the manged name (i.e. U10__float128) used in GCC 8.1, and not the @@ -148,12 +146,12 @@ unsigned rs6000_pointer_size; Tag_GNU_Power_ABI_FP .gnu.attributes value this flag controls should be set for soft-float values passed in gprs and ieee128 values passed in vsx registers. */ -static bool rs6000_passes_float; -static bool rs6000_passes_long_double; +bool rs6000_passes_float = false; +bool rs6000_passes_long_double = false; /* Flag whether vector values have been passed/returned. */ -static bool rs6000_passes_vector; +bool rs6000_passes_vector = false; /* Flag whether small (<= 8 byte) structures have been returned. */ -static bool rs6000_returns_struct; +bool rs6000_returns_struct = false; #endif /* Value is TRUE if register/mode pair is acceptable. */ @@ -193,14 +191,6 @@ static GTY(()) section *sdata2_section; extern GTY(()) section *toc_section; section *toc_section = 0; -struct builtin_description -{ - const HOST_WIDE_INT mask; - const enum insn_code icode; - const char *const name; - const enum rs6000_builtins code; -}; - /* Describe the vector unit used for modes. */ enum rs6000_vector rs6000_vector_unit[NUM_MACHINE_MODES]; enum rs6000_vector rs6000_vector_mem[NUM_MACHINE_MODES]; @@ -213,7 +203,7 @@ enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX]; int rs6000_vector_align[NUM_MACHINE_MODES]; /* Map selected modes to types for builtins. */ -static GTY(()) tree builtin_mode_to_type[MAX_MACHINE_MODE][2]; +GTY(()) tree builtin_mode_to_type[MAX_MACHINE_MODE][2]; /* What modes to automatically generate reciprocal divide estimate (fre) and reciprocal sqrt (frsqrte) for. */ @@ -263,82 +253,6 @@ static struct { "rsqrtd", (RECIP_DF_RSQRT | RECIP_V2DF_RSQRT) }, }; -/* Used by __builtin_cpu_is(), mapping from PLATFORM names to values. */ -static const struct -{ - const char *cpu; - unsigned int cpuid; -} cpu_is_info[] = { - { "power9", PPC_PLATFORM_POWER9 }, - { "power8", PPC_PLATFORM_POWER8 }, - { "power7", PPC_PLATFORM_POWER7 }, - { "power6x", PPC_PLATFORM_POWER6X }, - { "power6", PPC_PLATFORM_POWER6 }, - { "power5+", PPC_PLATFORM_POWER5_PLUS }, - { "power5", PPC_PLATFORM_POWER5 }, - { "ppc970", PPC_PLATFORM_PPC970 }, - { "power4", PPC_PLATFORM_POWER4 }, - { "ppca2", PPC_PLATFORM_PPCA2 }, - { "ppc476", PPC_PLATFORM_PPC476 }, - { "ppc464", PPC_PLATFORM_PPC464 }, - { "ppc440", PPC_PLATFORM_PPC440 }, - { "ppc405", PPC_PLATFORM_PPC405 }, - { "ppc-cell-be", PPC_PLATFORM_CELL_BE } -}; - -/* Used by __builtin_cpu_supports(), mapping from HWCAP names to masks. */ -static const struct -{ - const char *hwcap; - int mask; - unsigned int id; -} cpu_supports_info[] = { - /* AT_HWCAP masks. */ - { "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0 }, - { "altivec", PPC_FEATURE_HAS_ALTIVEC, 0 }, - { "arch_2_05", PPC_FEATURE_ARCH_2_05, 0 }, - { "arch_2_06", PPC_FEATURE_ARCH_2_06, 0 }, - { "archpmu", PPC_FEATURE_PERFMON_COMPAT, 0 }, - { "booke", PPC_FEATURE_BOOKE, 0 }, - { "cellbe", PPC_FEATURE_CELL_BE, 0 }, - { "dfp", PPC_FEATURE_HAS_DFP, 0 }, - { "efpdouble", PPC_FEATURE_HAS_EFP_DOUBLE, 0 }, - { "efpsingle", PPC_FEATURE_HAS_EFP_SINGLE, 0 }, - { "fpu", PPC_FEATURE_HAS_FPU, 0 }, - { "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, 0 }, - { "mmu", PPC_FEATURE_HAS_MMU, 0 }, - { "notb", PPC_FEATURE_NO_TB, 0 }, - { "pa6t", PPC_FEATURE_PA6T, 0 }, - { "power4", PPC_FEATURE_POWER4, 0 }, - { "power5", PPC_FEATURE_POWER5, 0 }, - { "power5+", PPC_FEATURE_POWER5_PLUS, 0 }, - { "power6x", PPC_FEATURE_POWER6_EXT, 0 }, - { "ppc32", PPC_FEATURE_32, 0 }, - { "ppc601", PPC_FEATURE_601_INSTR, 0 }, - { "ppc64", PPC_FEATURE_64, 0 }, - { "ppcle", PPC_FEATURE_PPC_LE, 0 }, - { "smt", PPC_FEATURE_SMT, 0 }, - { "spe", PPC_FEATURE_HAS_SPE, 0 }, - { "true_le", PPC_FEATURE_TRUE_LE, 0 }, - { "ucache", PPC_FEATURE_UNIFIED_CACHE, 0 }, - { "vsx", PPC_FEATURE_HAS_VSX, 0 }, - - /* AT_HWCAP2 masks. */ - { "arch_2_07", PPC_FEATURE2_ARCH_2_07, 1 }, - { "dscr", PPC_FEATURE2_HAS_DSCR, 1 }, - { "ebb", PPC_FEATURE2_HAS_EBB, 1 }, - { "htm", PPC_FEATURE2_HAS_HTM, 1 }, - { "htm-nosc", PPC_FEATURE2_HTM_NOSC, 1 }, - { "htm-no-suspend", PPC_FEATURE2_HTM_NO_SUSPEND, 1 }, - { "isel", PPC_FEATURE2_HAS_ISEL, 1 }, - { "tar", PPC_FEATURE2_HAS_TAR, 1 }, - { "vcrypto", PPC_FEATURE2_HAS_VEC_CRYPTO, 1 }, - { "arch_3_00", PPC_FEATURE2_ARCH_3_00, 1 }, - { "ieee128", PPC_FEATURE2_HAS_IEEE128, 1 }, - { "darn", PPC_FEATURE2_DARN, 1 }, - { "scv", PPC_FEATURE2_SCV, 1 } -}; - /* On PowerPC, we have a limited number of target clones that we care about which means we can use an array to hold the options, rather than having more elaborate data structures to identify each possible variation. Order the @@ -374,7 +288,7 @@ static const struct clone_map rs6000_clone_map[CLONE_MAX] = { const char *tcb_verification_symbol = "__parse_hwcap_and_convert_at_platform"; /* True if we have expanded a CPU builtin. */ -bool cpu_builtin_p; +bool cpu_builtin_p = false; /* Pointer to function (in rs6000-c.c) that can define or undefine target macros that have changed. Languages that don't support the preprocessor @@ -1189,67 +1103,6 @@ struct processor_costs ppca2_cost = { 0, /* SF->DF convert */ }; - -/* Table that classifies rs6000 builtin functions (pure, const, etc.). */ -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) \ - { NAME, ICODE, MASK, ATTR }, - -struct rs6000_builtin_info_type { - const char *name; - const enum insn_code icode; - const HOST_WIDE_INT mask; - const unsigned attr; -}; - -static const struct rs6000_builtin_info_type rs6000_builtin_info[] = -{ -#include "rs6000-builtin.def" -}; - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - /* Support for -mveclibabi= to control which vector library to use. */ static tree (*rs6000_veclib_handler) (combined_fn, tree, tree); @@ -1275,17 +1128,9 @@ static bool set_to_load_agen (rtx_insn *,rtx_insn *); static bool insn_terminates_group_p (rtx_insn *, enum group_termination); static bool insn_must_be_first_in_group (rtx_insn *); static bool insn_must_be_last_in_group (rtx_insn *); -static void altivec_init_builtins (void); -static tree builtin_function_type (machine_mode, machine_mode, - machine_mode, machine_mode, - enum rs6000_builtins, const char *name); -static void rs6000_common_init_builtins (void); -static void htm_init_builtins (void); int easy_vector_constant (rtx, machine_mode); static rtx rs6000_debug_legitimize_address (rtx, rtx, machine_mode); static rtx rs6000_legitimize_tls_address (rtx, enum tls_model); -static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree, - bool, bool); #if TARGET_MACHO static tree get_prev_label (tree); #endif @@ -1306,7 +1151,6 @@ static bool rs6000_debug_secondary_memory_needed (machine_mode, static bool rs6000_debug_can_change_mode_class (machine_mode, machine_mode, reg_class_t); -static rtx rs6000_internal_arg_pointer (void); static bool (*rs6000_mode_dependent_address_ptr) (const_rtx) = rs6000_mode_dependent_address; @@ -1333,7 +1177,6 @@ static bool rs6000_secondary_reload_move (enum rs6000_reg_type, secondary_reload_info *, bool); rtl_opt_pass *make_pass_analyze_swaps (gcc::context*); -static tree rs6000_fold_builtin (tree, int, tree *, bool); /* Hash table stuff for keeping track of TOC entries. */ @@ -1354,22 +1197,6 @@ struct toc_hasher : ggc_ptr_hash static GTY (()) hash_table *toc_hash_table; -/* Hash table to keep track of the argument types for builtin functions. */ - -struct GTY((for_user)) builtin_hash_struct -{ - tree type; - machine_mode mode[4]; /* return value + 3 arguments. */ - unsigned char uns_p[4]; /* and whether the types are unsigned. */ -}; - -struct builtin_hasher : ggc_ptr_hash -{ - static hashval_t hash (builtin_hash_struct *); - static bool equal (builtin_hash_struct *, builtin_hash_struct *); -}; - -static GTY (()) hash_table *builtin_hash_table; /* Default register names. */ @@ -9967,7943 +9794,214 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode) emit_insn (gen_rtx_SET (operands[0], operands[1])); } -/* Nonzero if we can use a floating-point register to pass this arg. */ -#define USE_FP_FOR_ARG_P(CUM,MODE) \ - (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE) \ - && (CUM)->fregno <= FP_ARG_MAX_REG \ - && TARGET_HARD_FLOAT) - -/* Nonzero if we can use an AltiVec register to pass this arg. */ -#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,NAMED) \ - (ALTIVEC_OR_VSX_VECTOR_MODE (MODE) \ - && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \ - && TARGET_ALTIVEC_ABI \ - && (NAMED)) - -/* Walk down the type tree of TYPE counting consecutive base elements. - If *MODEP is VOIDmode, then set it to the first valid floating point - or vector type. If a non-floating point or vector type is found, or - if a floating point or vector type that doesn't match a non-VOIDmode - *MODEP is found, then return -1, otherwise return the count in the - sub-tree. */ -static int -rs6000_aggregate_candidate (const_tree type, machine_mode *modep) +/* Set up AIX/Darwin/64-bit Linux quad floating point routines. */ +static void +init_float128_ibm (machine_mode mode) { - machine_mode mode; - HOST_WIDE_INT size; - - switch (TREE_CODE (type)) + if (!TARGET_XL_COMPAT) { - case REAL_TYPE: - mode = TYPE_MODE (type); - if (!SCALAR_FLOAT_MODE_P (mode)) - return -1; - - if (*modep == VOIDmode) - *modep = mode; - - if (*modep == mode) - return 1; - - break; - - case COMPLEX_TYPE: - mode = TYPE_MODE (TREE_TYPE (type)); - if (!SCALAR_FLOAT_MODE_P (mode)) - return -1; - - if (*modep == VOIDmode) - *modep = mode; + set_optab_libfunc (add_optab, mode, "__gcc_qadd"); + set_optab_libfunc (sub_optab, mode, "__gcc_qsub"); + set_optab_libfunc (smul_optab, mode, "__gcc_qmul"); + set_optab_libfunc (sdiv_optab, mode, "__gcc_qdiv"); - if (*modep == mode) - return 2; + if (!TARGET_HARD_FLOAT) + { + set_optab_libfunc (neg_optab, mode, "__gcc_qneg"); + set_optab_libfunc (eq_optab, mode, "__gcc_qeq"); + set_optab_libfunc (ne_optab, mode, "__gcc_qne"); + set_optab_libfunc (gt_optab, mode, "__gcc_qgt"); + set_optab_libfunc (ge_optab, mode, "__gcc_qge"); + set_optab_libfunc (lt_optab, mode, "__gcc_qlt"); + set_optab_libfunc (le_optab, mode, "__gcc_qle"); + set_optab_libfunc (unord_optab, mode, "__gcc_qunord"); - break; + set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq"); + set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq"); + set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos"); + set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod"); + set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi"); + set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou"); + set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq"); + set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq"); + } + } + else + { + set_optab_libfunc (add_optab, mode, "_xlqadd"); + set_optab_libfunc (sub_optab, mode, "_xlqsub"); + set_optab_libfunc (smul_optab, mode, "_xlqmul"); + set_optab_libfunc (sdiv_optab, mode, "_xlqdiv"); + } - case VECTOR_TYPE: - if (!TARGET_ALTIVEC_ABI || !TARGET_ALTIVEC) - return -1; + /* Add various conversions for IFmode to use the traditional TFmode + names. */ + if (mode == IFmode) + { + set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdtf"); + set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddtf"); + set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunctdtf"); + set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunctfsd"); + set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunctfdd"); + set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendtftd"); - /* Use V4SImode as representative of all 128-bit vector types. */ - size = int_size_in_bytes (type); - switch (size) + if (TARGET_POWERPC64) { - case 16: - mode = V4SImode; - break; - default: - return -1; + set_conv_libfunc (sfix_optab, TImode, mode, "__fixtfti"); + set_conv_libfunc (ufix_optab, TImode, mode, "__fixunstfti"); + set_conv_libfunc (sfloat_optab, mode, TImode, "__floattitf"); + set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntitf"); } + } +} - if (*modep == VOIDmode) - *modep = mode; - - /* Vector modes are considered to be opaque: two vectors are - equivalent for the purposes of being homogeneous aggregates - if they are the same size. */ - if (*modep == mode) - return 1; +/* Create a decl for either complex long double multiply or complex long double + divide when long double is IEEE 128-bit floating point. We can't use + __multc3 and __divtc3 because the original long double using IBM extended + double used those names. The complex multiply/divide functions are encoded + as builtin functions with a complex result and 4 scalar inputs. */ - break; +static void +create_complex_muldiv (const char *name, built_in_function fncode, tree fntype) +{ + tree fndecl = add_builtin_function (name, fntype, fncode, BUILT_IN_NORMAL, + name, NULL_TREE); - case ARRAY_TYPE: - { - int count; - tree index = TYPE_DOMAIN (type); - - /* Can't handle incomplete types nor sizes that are not - fixed. */ - if (!COMPLETE_TYPE_P (type) - || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) - return -1; - - count = rs6000_aggregate_candidate (TREE_TYPE (type), modep); - if (count == -1 - || !index - || !TYPE_MAX_VALUE (index) - || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) - || !TYPE_MIN_VALUE (index) - || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) - || count < 0) - return -1; - - count *= (1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) - - tree_to_uhwi (TYPE_MIN_VALUE (index))); - - /* There must be no padding. */ - if (wi::to_wide (TYPE_SIZE (type)) - != count * GET_MODE_BITSIZE (*modep)) - return -1; - - return count; - } + set_builtin_decl (fncode, fndecl, true); - case RECORD_TYPE: - { - int count = 0; - int sub_count; - tree field; + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "create complex %s, fncode: %d\n", name, (int) fncode); - /* Can't handle incomplete types nor sizes that are not - fixed. */ - if (!COMPLETE_TYPE_P (type) - || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) - return -1; + return; +} - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - { - if (TREE_CODE (field) != FIELD_DECL) - continue; +/* Set up IEEE 128-bit floating point routines. Use different names if the + arguments can be passed in a vector register. The historical PowerPC + implementation of IEEE 128-bit floating point used _q_ for the names, so + continue to use that if we aren't using vector registers to pass IEEE + 128-bit floating point. */ - sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep); - if (sub_count < 0) - return -1; - count += sub_count; - } +static void +init_float128_ieee (machine_mode mode) +{ + if (FLOAT128_VECTOR_P (mode)) + { + static bool complex_muldiv_init_p = false; - /* There must be no padding. */ - if (wi::to_wide (TYPE_SIZE (type)) - != count * GET_MODE_BITSIZE (*modep)) - return -1; + /* Set up to call __mulkc3 and __divkc3 under -mabi=ieeelongdouble. If + we have clone or target attributes, this will be called a second + time. We want to create the built-in function only once. */ + if (mode == TFmode && TARGET_IEEEQUAD && !complex_muldiv_init_p) + { + complex_muldiv_init_p = true; + built_in_function fncode_mul = + (built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + TCmode + - MIN_MODE_COMPLEX_FLOAT); + built_in_function fncode_div = + (built_in_function) (BUILT_IN_COMPLEX_DIV_MIN + TCmode + - MIN_MODE_COMPLEX_FLOAT); - return count; - } + tree fntype = build_function_type_list (complex_long_double_type_node, + long_double_type_node, + long_double_type_node, + long_double_type_node, + long_double_type_node, + NULL_TREE); - case UNION_TYPE: - case QUAL_UNION_TYPE: - { - /* These aren't very interesting except in a degenerate case. */ - int count = 0; - int sub_count; - tree field; - - /* Can't handle incomplete types nor sizes that are not - fixed. */ - if (!COMPLETE_TYPE_P (type) - || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) - return -1; - - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - { - if (TREE_CODE (field) != FIELD_DECL) - continue; + create_complex_muldiv ("__mulkc3", fncode_mul, fntype); + create_complex_muldiv ("__divkc3", fncode_div, fntype); + } - sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep); - if (sub_count < 0) - return -1; - count = count > sub_count ? count : sub_count; - } + set_optab_libfunc (add_optab, mode, "__addkf3"); + set_optab_libfunc (sub_optab, mode, "__subkf3"); + set_optab_libfunc (neg_optab, mode, "__negkf2"); + set_optab_libfunc (smul_optab, mode, "__mulkf3"); + set_optab_libfunc (sdiv_optab, mode, "__divkf3"); + set_optab_libfunc (sqrt_optab, mode, "__sqrtkf2"); + set_optab_libfunc (abs_optab, mode, "__abskf2"); + set_optab_libfunc (powi_optab, mode, "__powikf2"); - /* There must be no padding. */ - if (wi::to_wide (TYPE_SIZE (type)) - != count * GET_MODE_BITSIZE (*modep)) - return -1; + set_optab_libfunc (eq_optab, mode, "__eqkf2"); + set_optab_libfunc (ne_optab, mode, "__nekf2"); + set_optab_libfunc (gt_optab, mode, "__gtkf2"); + set_optab_libfunc (ge_optab, mode, "__gekf2"); + set_optab_libfunc (lt_optab, mode, "__ltkf2"); + set_optab_libfunc (le_optab, mode, "__lekf2"); + set_optab_libfunc (unord_optab, mode, "__unordkf2"); - return count; - } + set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2"); + set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2"); + set_conv_libfunc (trunc_optab, SFmode, mode, "__trunckfsf2"); + set_conv_libfunc (trunc_optab, DFmode, mode, "__trunckfdf2"); - default: - break; - } + set_conv_libfunc (sext_optab, mode, IFmode, "__trunctfkf2"); + if (mode != TFmode && FLOAT128_IBM_P (TFmode)) + set_conv_libfunc (sext_optab, mode, TFmode, "__trunctfkf2"); - return -1; -} + set_conv_libfunc (trunc_optab, IFmode, mode, "__extendkftf2"); + if (mode != TFmode && FLOAT128_IBM_P (TFmode)) + set_conv_libfunc (trunc_optab, TFmode, mode, "__extendkftf2"); -/* If an argument, whose type is described by TYPE and MODE, is a homogeneous - float or vector aggregate that shall be passed in FP/vector registers - according to the ELFv2 ABI, return the homogeneous element mode in - *ELT_MODE and the number of elements in *N_ELTS, and return TRUE. + set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdkf"); + set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddkf"); + set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunctdkf"); + set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunckfsd"); + set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunckfdd"); + set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendkftd"); - Otherwise, set *ELT_MODE to MODE and *N_ELTS to 1, and return FALSE. */ + set_conv_libfunc (sfix_optab, SImode, mode, "__fixkfsi"); + set_conv_libfunc (ufix_optab, SImode, mode, "__fixunskfsi"); + set_conv_libfunc (sfix_optab, DImode, mode, "__fixkfdi"); + set_conv_libfunc (ufix_optab, DImode, mode, "__fixunskfdi"); -static bool -rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type, - machine_mode *elt_mode, - int *n_elts) -{ - /* Note that we do not accept complex types at the top level as - homogeneous aggregates; these types are handled via the - targetm.calls.split_complex_arg mechanism. Complex types - can be elements of homogeneous aggregates, however. */ - if (TARGET_HARD_FLOAT && DEFAULT_ABI == ABI_ELFv2 && type - && AGGREGATE_TYPE_P (type)) - { - machine_mode field_mode = VOIDmode; - int field_count = rs6000_aggregate_candidate (type, &field_mode); + set_conv_libfunc (sfloat_optab, mode, SImode, "__floatsikf"); + set_conv_libfunc (ufloat_optab, mode, SImode, "__floatunsikf"); + set_conv_libfunc (sfloat_optab, mode, DImode, "__floatdikf"); + set_conv_libfunc (ufloat_optab, mode, DImode, "__floatundikf"); - if (field_count > 0) + if (TARGET_POWERPC64) { - int reg_size = ALTIVEC_OR_VSX_VECTOR_MODE (field_mode) ? 16 : 8; - int field_size = ROUND_UP (GET_MODE_SIZE (field_mode), reg_size); - - /* The ELFv2 ABI allows homogeneous aggregates to occupy - up to AGGR_ARG_NUM_REG registers. */ - if (field_count * field_size <= AGGR_ARG_NUM_REG * reg_size) - { - if (elt_mode) - *elt_mode = field_mode; - if (n_elts) - *n_elts = field_count; - return true; - } + set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti"); + set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti"); + set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf"); + set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf"); } } - if (elt_mode) - *elt_mode = mode; - if (n_elts) - *n_elts = 1; - return false; -} - -/* Return a nonzero value to say to return the function value in - memory, just as large structures are always returned. TYPE will be - the data type of the value, and FNTYPE will be the type of the - function doing the returning, or @code{NULL} for libcalls. - - The AIX ABI for the RS/6000 specifies that all structures are - returned in memory. The Darwin ABI does the same. - - For the Darwin 64 Bit ABI, a function result can be returned in - registers or in memory, depending on the size of the return data - type. If it is returned in registers, the value occupies the same - registers as it would if it were the first and only function - argument. Otherwise, the function places its result in memory at - the location pointed to by GPR3. - - The SVR4 ABI specifies that structures <= 8 bytes are returned in r3/r4, - but a draft put them in memory, and GCC used to implement the draft - instead of the final standard. Therefore, aix_struct_return - controls this instead of DEFAULT_ABI; V.4 targets needing backward - compatibility can change DRAFT_V4_STRUCT_RET to override the - default, and -m switches get the final word. See - rs6000_option_override_internal for more details. + else + { + set_optab_libfunc (add_optab, mode, "_q_add"); + set_optab_libfunc (sub_optab, mode, "_q_sub"); + set_optab_libfunc (neg_optab, mode, "_q_neg"); + set_optab_libfunc (smul_optab, mode, "_q_mul"); + set_optab_libfunc (sdiv_optab, mode, "_q_div"); + if (TARGET_PPC_GPOPT) + set_optab_libfunc (sqrt_optab, mode, "_q_sqrt"); - The PPC32 SVR4 ABI uses IEEE double extended for long double, if 128-bit - long double support is enabled. These values are returned in memory. + set_optab_libfunc (eq_optab, mode, "_q_feq"); + set_optab_libfunc (ne_optab, mode, "_q_fne"); + set_optab_libfunc (gt_optab, mode, "_q_fgt"); + set_optab_libfunc (ge_optab, mode, "_q_fge"); + set_optab_libfunc (lt_optab, mode, "_q_flt"); + set_optab_libfunc (le_optab, mode, "_q_fle"); - int_size_in_bytes returns -1 for variable size objects, which go in - memory always. The cast to unsigned makes -1 > 8. */ + set_conv_libfunc (sext_optab, mode, SFmode, "_q_stoq"); + set_conv_libfunc (sext_optab, mode, DFmode, "_q_dtoq"); + set_conv_libfunc (trunc_optab, SFmode, mode, "_q_qtos"); + set_conv_libfunc (trunc_optab, DFmode, mode, "_q_qtod"); + set_conv_libfunc (sfix_optab, SImode, mode, "_q_qtoi"); + set_conv_libfunc (ufix_optab, SImode, mode, "_q_qtou"); + set_conv_libfunc (sfloat_optab, mode, SImode, "_q_itoq"); + set_conv_libfunc (ufloat_optab, mode, SImode, "_q_utoq"); + } +} -static bool -rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) +static void +rs6000_init_libfuncs (void) { - /* For the Darwin64 ABI, test if we can fit the return value in regs. */ - if (TARGET_MACHO - && rs6000_darwin64_abi - && TREE_CODE (type) == RECORD_TYPE - && int_size_in_bytes (type) > 0) - { - CUMULATIVE_ARGS valcum; - rtx valret; - - valcum.words = 0; - valcum.fregno = FP_ARG_MIN_REG; - valcum.vregno = ALTIVEC_ARG_MIN_REG; - /* Do a trial code generation as if this were going to be passed - as an argument; if any part goes in memory, we return NULL. */ - valret = rs6000_darwin64_record_arg (&valcum, type, true, true); - if (valret) - return false; - /* Otherwise fall through to more conventional ABI rules. */ - } - - /* The ELFv2 ABI returns homogeneous VFP aggregates in registers */ - if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (type), type, - NULL, NULL)) - return false; - - /* The ELFv2 ABI returns aggregates up to 16B in registers */ - if (DEFAULT_ABI == ABI_ELFv2 && AGGREGATE_TYPE_P (type) - && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) <= 16) - return false; - - if (AGGREGATE_TYPE_P (type) - && (aix_struct_return - || (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8)) - return true; - - /* Allow -maltivec -mabi=no-altivec without warning. Altivec vector - modes only exist for GCC vector types if -maltivec. */ - if (TARGET_32BIT && !TARGET_ALTIVEC_ABI - && ALTIVEC_VECTOR_MODE (TYPE_MODE (type))) - return false; - - /* Return synthetic vectors in memory. */ - if (TREE_CODE (type) == VECTOR_TYPE - && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8)) - { - static bool warned_for_return_big_vectors = false; - if (!warned_for_return_big_vectors) - { - warning (OPT_Wpsabi, "GCC vector returned by reference: " - "non-standard ABI extension with no compatibility " - "guarantee"); - warned_for_return_big_vectors = true; - } - return true; - } - - if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD - && FLOAT128_IEEE_P (TYPE_MODE (type))) - return true; - - return false; -} - -/* Specify whether values returned in registers should be at the most - significant end of a register. We want aggregates returned by - value to match the way aggregates are passed to functions. */ - -static bool -rs6000_return_in_msb (const_tree valtype) -{ - return (DEFAULT_ABI == ABI_ELFv2 - && BYTES_BIG_ENDIAN - && AGGREGATE_TYPE_P (valtype) - && (rs6000_function_arg_padding (TYPE_MODE (valtype), valtype) - == PAD_UPWARD)); -} - -#ifdef HAVE_AS_GNU_ATTRIBUTE -/* Return TRUE if a call to function FNDECL may be one that - potentially affects the function calling ABI of the object file. */ - -static bool -call_ABI_of_interest (tree fndecl) -{ - if (rs6000_gnu_attr && symtab->state == EXPANSION) - { - struct cgraph_node *c_node; - - /* Libcalls are always interesting. */ - if (fndecl == NULL_TREE) - return true; - - /* Any call to an external function is interesting. */ - if (DECL_EXTERNAL (fndecl)) - return true; - - /* Interesting functions that we are emitting in this object file. */ - c_node = cgraph_node::get (fndecl); - c_node = c_node->ultimate_alias_target (); - return !c_node->only_called_directly_p (); - } - return false; -} -#endif - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0 and RETURN_MODE the return value mode. - - For incoming args we set the number of arguments in the prototype large - so we never return a PARALLEL. */ - -void -init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, - rtx libname ATTRIBUTE_UNUSED, int incoming, - int libcall, int n_named_args, - tree fndecl, - machine_mode return_mode ATTRIBUTE_UNUSED) -{ - static CUMULATIVE_ARGS zero_cumulative; - - *cum = zero_cumulative; - cum->words = 0; - cum->fregno = FP_ARG_MIN_REG; - cum->vregno = ALTIVEC_ARG_MIN_REG; - cum->prototype = (fntype && prototype_p (fntype)); - cum->call_cookie = ((DEFAULT_ABI == ABI_V4 && libcall) - ? CALL_LIBCALL : CALL_NORMAL); - cum->sysv_gregno = GP_ARG_MIN_REG; - cum->stdarg = stdarg_p (fntype); - cum->libcall = libcall; - - cum->nargs_prototype = 0; - if (incoming || cum->prototype) - cum->nargs_prototype = n_named_args; - - /* Check for a longcall attribute. */ - if ((!fntype && rs6000_default_long_calls) - || (fntype - && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)) - && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))) - cum->call_cookie |= CALL_LONG; - else if (DEFAULT_ABI != ABI_DARWIN) - { - bool is_local = (fndecl - && !DECL_EXTERNAL (fndecl) - && !DECL_WEAK (fndecl) - && (*targetm.binds_local_p) (fndecl)); - if (is_local) - ; - else if (flag_plt) - { - if (fntype - && lookup_attribute ("noplt", TYPE_ATTRIBUTES (fntype))) - cum->call_cookie |= CALL_LONG; - } - else - { - if (!(fntype - && lookup_attribute ("plt", TYPE_ATTRIBUTES (fntype)))) - cum->call_cookie |= CALL_LONG; - } - } - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "\ninit_cumulative_args:"); - if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - fprintf (stderr, " ret code = %s,", - get_tree_code_name (TREE_CODE (ret_type))); - } - - if (cum->call_cookie & CALL_LONG) - fprintf (stderr, " longcall,"); - - fprintf (stderr, " proto = %d, nargs = %d\n", - cum->prototype, cum->nargs_prototype); - } - -#ifdef HAVE_AS_GNU_ATTRIBUTE - if (TARGET_ELF && (TARGET_64BIT || DEFAULT_ABI == ABI_V4)) - { - cum->escapes = call_ABI_of_interest (fndecl); - if (cum->escapes) - { - tree return_type; - - if (fntype) - { - return_type = TREE_TYPE (fntype); - return_mode = TYPE_MODE (return_type); - } - else - return_type = lang_hooks.types.type_for_mode (return_mode, 0); - - if (return_type != NULL) - { - if (TREE_CODE (return_type) == RECORD_TYPE - && TYPE_TRANSPARENT_AGGR (return_type)) - { - return_type = TREE_TYPE (first_field (return_type)); - return_mode = TYPE_MODE (return_type); - } - if (AGGREGATE_TYPE_P (return_type) - && ((unsigned HOST_WIDE_INT) int_size_in_bytes (return_type) - <= 8)) - rs6000_returns_struct = true; - } - if (SCALAR_FLOAT_MODE_P (return_mode)) - { - rs6000_passes_float = true; - if ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT) - && (FLOAT128_IBM_P (return_mode) - || FLOAT128_IEEE_P (return_mode) - || (return_type != NULL - && (TYPE_MAIN_VARIANT (return_type) - == long_double_type_node)))) - rs6000_passes_long_double = true; - - /* Note if we passed or return a IEEE 128-bit type. We changed - the mangling for these types, and we may need to make an alias - with the old mangling. */ - if (FLOAT128_IEEE_P (return_mode)) - rs6000_passes_ieee128 = true; - } - if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)) - rs6000_passes_vector = true; - } - } -#endif - - if (fntype - && !TARGET_ALTIVEC - && TARGET_ALTIVEC_ABI - && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype)))) - { - error ("cannot return value in vector register because" - " altivec instructions are disabled, use %qs" - " to enable them", "-maltivec"); - } -} - -/* The mode the ABI uses for a word. This is not the same as word_mode - for -m32 -mpowerpc64. This is used to implement various target hooks. */ - -static scalar_int_mode -rs6000_abi_word_mode (void) -{ - return TARGET_32BIT ? SImode : DImode; -} - -/* Implement the TARGET_OFFLOAD_OPTIONS hook. */ -static char * -rs6000_offload_options (void) -{ - if (TARGET_64BIT) - return xstrdup ("-foffload-abi=lp64"); - else - return xstrdup ("-foffload-abi=ilp32"); -} - -/* On rs6000, function arguments are promoted, as are function return - values. */ - -static machine_mode -rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, - machine_mode mode, - int *punsignedp ATTRIBUTE_UNUSED, - const_tree, int) -{ - PROMOTE_MODE (mode, *punsignedp, type); - - return mode; -} - -/* Return true if TYPE must be passed on the stack and not in registers. */ - -static bool -rs6000_must_pass_in_stack (machine_mode mode, const_tree type) -{ - if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2 || TARGET_64BIT) - return must_pass_in_stack_var_size (mode, type); - else - return must_pass_in_stack_var_size_or_pad (mode, type); -} - -static inline bool -is_complex_IBM_long_double (machine_mode mode) -{ - return mode == ICmode || (mode == TCmode && FLOAT128_IBM_P (TCmode)); -} - -/* Whether ABI_V4 passes MODE args to a function in floating point - registers. */ - -static bool -abi_v4_pass_in_fpr (machine_mode mode, bool named) -{ - if (!TARGET_HARD_FLOAT) - return false; - if (mode == DFmode) - return true; - if (mode == SFmode && named) - return true; - /* ABI_V4 passes complex IBM long double in 8 gprs. - Stupid, but we can't change the ABI now. */ - if (is_complex_IBM_long_double (mode)) - return false; - if (FLOAT128_2REG_P (mode)) - return true; - if (DECIMAL_FLOAT_MODE_P (mode)) - return true; - return false; -} - -/* Implement TARGET_FUNCTION_ARG_PADDING. - - For the AIX ABI structs are always stored left shifted in their - argument slot. */ - -static pad_direction -rs6000_function_arg_padding (machine_mode mode, const_tree type) -{ -#ifndef AGGREGATE_PADDING_FIXED -#define AGGREGATE_PADDING_FIXED 0 -#endif -#ifndef AGGREGATES_PAD_UPWARD_ALWAYS -#define AGGREGATES_PAD_UPWARD_ALWAYS 0 -#endif - - if (!AGGREGATE_PADDING_FIXED) - { - /* GCC used to pass structures of the same size as integer types as - if they were in fact integers, ignoring TARGET_FUNCTION_ARG_PADDING. - i.e. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were - passed padded downward, except that -mstrict-align further - muddied the water in that multi-component structures of 2 and 4 - bytes in size were passed padded upward. - - The following arranges for best compatibility with previous - versions of gcc, but removes the -mstrict-align dependency. */ - if (BYTES_BIG_ENDIAN) - { - HOST_WIDE_INT size = 0; - - if (mode == BLKmode) - { - if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) - size = int_size_in_bytes (type); - } - else - size = GET_MODE_SIZE (mode); - - if (size == 1 || size == 2 || size == 4) - return PAD_DOWNWARD; - } - return PAD_UPWARD; - } - - if (AGGREGATES_PAD_UPWARD_ALWAYS) - { - if (type != 0 && AGGREGATE_TYPE_P (type)) - return PAD_UPWARD; - } - - /* Fall back to the default. */ - return default_function_arg_padding (mode, type); -} - -/* If defined, a C expression that gives the alignment boundary, in bits, - of an argument with the specified mode and type. If it is not defined, - PARM_BOUNDARY is used for all arguments. - - V.4 wants long longs and doubles to be double word aligned. Just - testing the mode size is a boneheaded way to do this as it means - that other types such as complex int are also double word aligned. - However, we're stuck with this because changing the ABI might break - existing library interfaces. - - Quadword align Altivec/VSX vectors. - Quadword align large synthetic vector types. */ - -static unsigned int -rs6000_function_arg_boundary (machine_mode mode, const_tree type) -{ - machine_mode elt_mode; - int n_elts; - - rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); - - if (DEFAULT_ABI == ABI_V4 - && (GET_MODE_SIZE (mode) == 8 - || (TARGET_HARD_FLOAT - && !is_complex_IBM_long_double (mode) - && FLOAT128_2REG_P (mode)))) - return 64; - else if (FLOAT128_VECTOR_P (mode)) - return 128; - else if (type && TREE_CODE (type) == VECTOR_TYPE - && int_size_in_bytes (type) >= 8 - && int_size_in_bytes (type) < 16) - return 64; - else if (ALTIVEC_OR_VSX_VECTOR_MODE (elt_mode) - || (type && TREE_CODE (type) == VECTOR_TYPE - && int_size_in_bytes (type) >= 16)) - return 128; - - /* Aggregate types that need > 8 byte alignment are quadword-aligned - in the parameter area in the ELFv2 ABI, and in the AIX ABI unless - -mcompat-align-parm is used. */ - if (((DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm) - || DEFAULT_ABI == ABI_ELFv2) - && type && TYPE_ALIGN (type) > 64) - { - /* "Aggregate" means any AGGREGATE_TYPE except for single-element - or homogeneous float/vector aggregates here. We already handled - vector aggregates above, but still need to check for float here. */ - bool aggregate_p = (AGGREGATE_TYPE_P (type) - && !SCALAR_FLOAT_MODE_P (elt_mode)); - - /* We used to check for BLKmode instead of the above aggregate type - check. Warn when this results in any difference to the ABI. */ - if (aggregate_p != (mode == BLKmode)) - { - static bool warned; - if (!warned && warn_psabi) - { - warned = true; - inform (input_location, - "the ABI of passing aggregates with %d-byte alignment" - " has changed in GCC 5", - (int) TYPE_ALIGN (type) / BITS_PER_UNIT); - } - } - - if (aggregate_p) - return 128; - } - - /* Similar for the Darwin64 ABI. Note that for historical reasons we - implement the "aggregate type" check as a BLKmode check here; this - means certain aggregate types are in fact not aligned. */ - if (TARGET_MACHO && rs6000_darwin64_abi - && mode == BLKmode - && type && TYPE_ALIGN (type) > 64) - return 128; - - return PARM_BOUNDARY; -} - -/* The offset in words to the start of the parameter save area. */ - -static unsigned int -rs6000_parm_offset (void) -{ - return (DEFAULT_ABI == ABI_V4 ? 2 - : DEFAULT_ABI == ABI_ELFv2 ? 4 - : 6); -} - -/* For a function parm of MODE and TYPE, return the starting word in - the parameter area. NWORDS of the parameter area are already used. */ - -static unsigned int -rs6000_parm_start (machine_mode mode, const_tree type, - unsigned int nwords) -{ - unsigned int align; - - align = rs6000_function_arg_boundary (mode, type) / PARM_BOUNDARY - 1; - return nwords + (-(rs6000_parm_offset () + nwords) & align); -} - -/* Compute the size (in words) of a function argument. */ - -static unsigned long -rs6000_arg_size (machine_mode mode, const_tree type) -{ - unsigned long size; - - if (mode != BLKmode) - size = GET_MODE_SIZE (mode); - else - size = int_size_in_bytes (type); - - if (TARGET_32BIT) - return (size + 3) >> 2; - else - return (size + 7) >> 3; -} - -/* Use this to flush pending int fields. */ - -static void -rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *cum, - HOST_WIDE_INT bitpos, int final) -{ - unsigned int startbit, endbit; - int intregs, intoffset; - - /* Handle the situations where a float is taking up the first half - of the GPR, and the other half is empty (typically due to - alignment restrictions). We can detect this by a 8-byte-aligned - int field, or by seeing that this is the final flush for this - argument. Count the word and continue on. */ - if (cum->floats_in_gpr == 1 - && (cum->intoffset % 64 == 0 - || (cum->intoffset == -1 && final))) - { - cum->words++; - cum->floats_in_gpr = 0; - } - - if (cum->intoffset == -1) - return; - - intoffset = cum->intoffset; - cum->intoffset = -1; - cum->floats_in_gpr = 0; - - if (intoffset % BITS_PER_WORD != 0) - { - unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD; - if (!int_mode_for_size (bits, 0).exists ()) - { - /* We couldn't find an appropriate mode, which happens, - e.g., in packed structs when there are 3 bytes to load. - Back intoffset back to the beginning of the word in this - case. */ - intoffset = ROUND_DOWN (intoffset, BITS_PER_WORD); - } - } - - startbit = ROUND_DOWN (intoffset, BITS_PER_WORD); - endbit = ROUND_UP (bitpos, BITS_PER_WORD); - intregs = (endbit - startbit) / BITS_PER_WORD; - cum->words += intregs; - /* words should be unsigned. */ - if ((unsigned)cum->words < (endbit/BITS_PER_WORD)) - { - int pad = (endbit/BITS_PER_WORD) - cum->words; - cum->words += pad; - } -} - -/* The darwin64 ABI calls for us to recurse down through structs, - looking for elements passed in registers. Unfortunately, we have - to track int register count here also because of misalignments - in powerpc alignment mode. */ - -static void -rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *cum, - const_tree type, - HOST_WIDE_INT startbitpos) -{ - tree f; - - for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f)) - if (TREE_CODE (f) == FIELD_DECL) - { - HOST_WIDE_INT bitpos = startbitpos; - tree ftype = TREE_TYPE (f); - machine_mode mode; - if (ftype == error_mark_node) - continue; - mode = TYPE_MODE (ftype); - - if (DECL_SIZE (f) != 0 - && tree_fits_uhwi_p (bit_position (f))) - bitpos += int_bit_position (f); - - /* ??? FIXME: else assume zero offset. */ - - if (TREE_CODE (ftype) == RECORD_TYPE) - rs6000_darwin64_record_arg_advance_recurse (cum, ftype, bitpos); - else if (USE_FP_FOR_ARG_P (cum, mode)) - { - unsigned n_fpregs = (GET_MODE_SIZE (mode) + 7) >> 3; - rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0); - cum->fregno += n_fpregs; - /* Single-precision floats present a special problem for - us, because they are smaller than an 8-byte GPR, and so - the structure-packing rules combined with the standard - varargs behavior mean that we want to pack float/float - and float/int combinations into a single register's - space. This is complicated by the arg advance flushing, - which works on arbitrarily large groups of int-type - fields. */ - if (mode == SFmode) - { - if (cum->floats_in_gpr == 1) - { - /* Two floats in a word; count the word and reset - the float count. */ - cum->words++; - cum->floats_in_gpr = 0; - } - else if (bitpos % 64 == 0) - { - /* A float at the beginning of an 8-byte word; - count it and put off adjusting cum->words until - we see if a arg advance flush is going to do it - for us. */ - cum->floats_in_gpr++; - } - else - { - /* The float is at the end of a word, preceded - by integer fields, so the arg advance flush - just above has already set cum->words and - everything is taken care of. */ - } - } - else - cum->words += n_fpregs; - } - else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, 1)) - { - rs6000_darwin64_record_arg_advance_flush (cum, bitpos, 0); - cum->vregno++; - cum->words += 2; - } - else if (cum->intoffset == -1) - cum->intoffset = bitpos; - } -} - -/* Check for an item that needs to be considered specially under the darwin 64 - bit ABI. These are record types where the mode is BLK or the structure is - 8 bytes in size. */ -static int -rs6000_darwin64_struct_check_p (machine_mode mode, const_tree type) -{ - return rs6000_darwin64_abi - && ((mode == BLKmode - && TREE_CODE (type) == RECORD_TYPE - && int_size_in_bytes (type) > 0) - || (type && TREE_CODE (type) == RECORD_TYPE - && int_size_in_bytes (type) == 8)) ? 1 : 0; -} - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) - - Note that for args passed by reference, function_arg will be called - with MODE and TYPE set to that of the pointer to the arg, not the arg - itself. */ - -static void -rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode, - const_tree type, bool named, int depth) -{ - machine_mode elt_mode; - int n_elts; - - rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); - - /* Only tick off an argument if we're not recursing. */ - if (depth == 0) - cum->nargs_prototype--; - -#ifdef HAVE_AS_GNU_ATTRIBUTE - if (TARGET_ELF && (TARGET_64BIT || DEFAULT_ABI == ABI_V4) - && cum->escapes) - { - if (SCALAR_FLOAT_MODE_P (mode)) - { - rs6000_passes_float = true; - if ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT) - && (FLOAT128_IBM_P (mode) - || FLOAT128_IEEE_P (mode) - || (type != NULL - && TYPE_MAIN_VARIANT (type) == long_double_type_node))) - rs6000_passes_long_double = true; - - /* Note if we passed or return a IEEE 128-bit type. We changed the - mangling for these types, and we may need to make an alias with - the old mangling. */ - if (FLOAT128_IEEE_P (mode)) - rs6000_passes_ieee128 = true; - } - if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) - rs6000_passes_vector = true; - } -#endif - - if (TARGET_ALTIVEC_ABI - && (ALTIVEC_OR_VSX_VECTOR_MODE (elt_mode) - || (type && TREE_CODE (type) == VECTOR_TYPE - && int_size_in_bytes (type) == 16))) - { - bool stack = false; - - if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named)) - { - cum->vregno += n_elts; - - if (!TARGET_ALTIVEC) - error ("cannot pass argument in vector register because" - " altivec instructions are disabled, use %qs" - " to enable them", "-maltivec"); - - /* PowerPC64 Linux and AIX allocate GPRs for a vector argument - even if it is going to be passed in a vector register. - Darwin does the same for variable-argument functions. */ - if (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) - && TARGET_64BIT) - || (cum->stdarg && DEFAULT_ABI != ABI_V4)) - stack = true; - } - else - stack = true; - - if (stack) - { - int align; - - /* Vector parameters must be 16-byte aligned. In 32-bit - mode this means we need to take into account the offset - to the parameter save area. In 64-bit mode, they just - have to start on an even word, since the parameter save - area is 16-byte aligned. */ - if (TARGET_32BIT) - align = -(rs6000_parm_offset () + cum->words) & 3; - else - align = cum->words & 1; - cum->words += align + rs6000_arg_size (mode, type); - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "function_adv: words = %2d, align=%d, ", - cum->words, align); - fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n", - cum->nargs_prototype, cum->prototype, - GET_MODE_NAME (mode)); - } - } - } - else if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) - { - int size = int_size_in_bytes (type); - /* Variable sized types have size == -1 and are - treated as if consisting entirely of ints. - Pad to 16 byte boundary if needed. */ - if (TYPE_ALIGN (type) >= 2 * BITS_PER_WORD - && (cum->words % 2) != 0) - cum->words++; - /* For varargs, we can just go up by the size of the struct. */ - if (!named) - cum->words += (size + 7) / 8; - else - { - /* It is tempting to say int register count just goes up by - sizeof(type)/8, but this is wrong in a case such as - { int; double; int; } [powerpc alignment]. We have to - grovel through the fields for these too. */ - cum->intoffset = 0; - cum->floats_in_gpr = 0; - rs6000_darwin64_record_arg_advance_recurse (cum, type, 0); - rs6000_darwin64_record_arg_advance_flush (cum, - size * BITS_PER_UNIT, 1); - } - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "function_adv: words = %2d, align=%d, size=%d", - cum->words, TYPE_ALIGN (type), size); - fprintf (stderr, - "nargs = %4d, proto = %d, mode = %4s (darwin64 abi)\n", - cum->nargs_prototype, cum->prototype, - GET_MODE_NAME (mode)); - } - } - else if (DEFAULT_ABI == ABI_V4) - { - if (abi_v4_pass_in_fpr (mode, named)) - { - /* _Decimal128 must use an even/odd register pair. This assumes - that the register number is odd when fregno is odd. */ - if (mode == TDmode && (cum->fregno % 2) == 1) - cum->fregno++; - - if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0) - <= FP_ARG_V4_MAX_REG) - cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3; - else - { - cum->fregno = FP_ARG_V4_MAX_REG + 1; - if (mode == DFmode || FLOAT128_IBM_P (mode) - || mode == DDmode || mode == TDmode) - cum->words += cum->words & 1; - cum->words += rs6000_arg_size (mode, type); - } - } - else - { - int n_words = rs6000_arg_size (mode, type); - int gregno = cum->sysv_gregno; - - /* Long long is put in (r3,r4), (r5,r6), (r7,r8) or (r9,r10). - As does any other 2 word item such as complex int due to a - historical mistake. */ - if (n_words == 2) - gregno += (1 - gregno) & 1; - - /* Multi-reg args are not split between registers and stack. */ - if (gregno + n_words - 1 > GP_ARG_MAX_REG) - { - /* Long long is aligned on the stack. So are other 2 word - items such as complex int due to a historical mistake. */ - if (n_words == 2) - cum->words += cum->words & 1; - cum->words += n_words; - } - - /* Note: continuing to accumulate gregno past when we've started - spilling to the stack indicates the fact that we've started - spilling to the stack to expand_builtin_saveregs. */ - cum->sysv_gregno = gregno + n_words; - } - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ", - cum->words, cum->fregno); - fprintf (stderr, "gregno = %2d, nargs = %4d, proto = %d, ", - cum->sysv_gregno, cum->nargs_prototype, cum->prototype); - fprintf (stderr, "mode = %4s, named = %d\n", - GET_MODE_NAME (mode), named); - } - } - else - { - int n_words = rs6000_arg_size (mode, type); - int start_words = cum->words; - int align_words = rs6000_parm_start (mode, type, start_words); - - cum->words = align_words + n_words; - - if (SCALAR_FLOAT_MODE_P (elt_mode) && TARGET_HARD_FLOAT) - { - /* _Decimal128 must be passed in an even/odd float register pair. - This assumes that the register number is odd when fregno is - odd. */ - if (elt_mode == TDmode && (cum->fregno % 2) == 1) - cum->fregno++; - cum->fregno += n_elts * ((GET_MODE_SIZE (elt_mode) + 7) >> 3); - } - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ", - cum->words, cum->fregno); - fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s, ", - cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode)); - fprintf (stderr, "named = %d, align = %d, depth = %d\n", - named, align_words - start_words, depth); - } - } -} - -static void -rs6000_function_arg_advance (cumulative_args_t cum, machine_mode mode, - const_tree type, bool named) -{ - rs6000_function_arg_advance_1 (get_cumulative_args (cum), mode, type, named, - 0); -} - -/* A subroutine of rs6000_darwin64_record_arg. Assign the bits of the - structure between cum->intoffset and bitpos to integer registers. */ - -static void -rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *cum, - HOST_WIDE_INT bitpos, rtx rvec[], int *k) -{ - machine_mode mode; - unsigned int regno; - unsigned int startbit, endbit; - int this_regno, intregs, intoffset; - rtx reg; - - if (cum->intoffset == -1) - return; - - intoffset = cum->intoffset; - cum->intoffset = -1; - - /* If this is the trailing part of a word, try to only load that - much into the register. Otherwise load the whole register. Note - that in the latter case we may pick up unwanted bits. It's not a - problem at the moment but may wish to revisit. */ - - if (intoffset % BITS_PER_WORD != 0) - { - unsigned int bits = BITS_PER_WORD - intoffset % BITS_PER_WORD; - if (!int_mode_for_size (bits, 0).exists (&mode)) - { - /* We couldn't find an appropriate mode, which happens, - e.g., in packed structs when there are 3 bytes to load. - Back intoffset back to the beginning of the word in this - case. */ - intoffset = ROUND_DOWN (intoffset, BITS_PER_WORD); - mode = word_mode; - } - } - else - mode = word_mode; - - startbit = ROUND_DOWN (intoffset, BITS_PER_WORD); - endbit = ROUND_UP (bitpos, BITS_PER_WORD); - intregs = (endbit - startbit) / BITS_PER_WORD; - this_regno = cum->words + intoffset / BITS_PER_WORD; - - if (intregs > 0 && intregs > GP_ARG_NUM_REG - this_regno) - cum->use_stack = 1; - - intregs = MIN (intregs, GP_ARG_NUM_REG - this_regno); - if (intregs <= 0) - return; - - intoffset /= BITS_PER_UNIT; - do - { - regno = GP_ARG_MIN_REG + this_regno; - reg = gen_rtx_REG (mode, regno); - rvec[(*k)++] = - gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset)); - - this_regno += 1; - intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1; - mode = word_mode; - intregs -= 1; - } - while (intregs > 0); -} - -/* Recursive workhorse for the following. */ - -static void -rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, const_tree type, - HOST_WIDE_INT startbitpos, rtx rvec[], - int *k) -{ - tree f; - - for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f)) - if (TREE_CODE (f) == FIELD_DECL) - { - HOST_WIDE_INT bitpos = startbitpos; - tree ftype = TREE_TYPE (f); - machine_mode mode; - if (ftype == error_mark_node) - continue; - mode = TYPE_MODE (ftype); - - if (DECL_SIZE (f) != 0 - && tree_fits_uhwi_p (bit_position (f))) - bitpos += int_bit_position (f); - - /* ??? FIXME: else assume zero offset. */ - - if (TREE_CODE (ftype) == RECORD_TYPE) - rs6000_darwin64_record_arg_recurse (cum, ftype, bitpos, rvec, k); - else if (cum->named && USE_FP_FOR_ARG_P (cum, mode)) - { - unsigned n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3; -#if 0 - switch (mode) - { - case E_SCmode: mode = SFmode; break; - case E_DCmode: mode = DFmode; break; - case E_TCmode: mode = TFmode; break; - default: break; - } -#endif - rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k); - if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1) - { - gcc_assert (cum->fregno == FP_ARG_MAX_REG - && (mode == TFmode || mode == TDmode)); - /* Long double or _Decimal128 split over regs and memory. */ - mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode; - cum->use_stack=1; - } - rvec[(*k)++] - = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_REG (mode, cum->fregno++), - GEN_INT (bitpos / BITS_PER_UNIT)); - if (FLOAT128_2REG_P (mode)) - cum->fregno++; - } - else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, 1)) - { - rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k); - rvec[(*k)++] - = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_REG (mode, cum->vregno++), - GEN_INT (bitpos / BITS_PER_UNIT)); - } - else if (cum->intoffset == -1) - cum->intoffset = bitpos; - } -} - -/* For the darwin64 ABI, we want to construct a PARALLEL consisting of - the register(s) to be used for each field and subfield of a struct - being passed by value, along with the offset of where the - register's value may be found in the block. FP fields go in FP - register, vector fields go in vector registers, and everything - else goes in int registers, packed as in memory. - - This code is also used for function return values. RETVAL indicates - whether this is the case. - - Much of this is taken from the SPARC V9 port, which has a similar - calling convention. */ - -static rtx -rs6000_darwin64_record_arg (CUMULATIVE_ARGS *orig_cum, const_tree type, - bool named, bool retval) -{ - rtx rvec[FIRST_PSEUDO_REGISTER]; - int k = 1, kbase = 1; - HOST_WIDE_INT typesize = int_size_in_bytes (type); - /* This is a copy; modifications are not visible to our caller. */ - CUMULATIVE_ARGS copy_cum = *orig_cum; - CUMULATIVE_ARGS *cum = ©_cum; - - /* Pad to 16 byte boundary if needed. */ - if (!retval && TYPE_ALIGN (type) >= 2 * BITS_PER_WORD - && (cum->words % 2) != 0) - cum->words++; - - cum->intoffset = 0; - cum->use_stack = 0; - cum->named = named; - - /* Put entries into rvec[] for individual FP and vector fields, and - for the chunks of memory that go in int regs. Note we start at - element 1; 0 is reserved for an indication of using memory, and - may or may not be filled in below. */ - rs6000_darwin64_record_arg_recurse (cum, type, /* startbit pos= */ 0, rvec, &k); - rs6000_darwin64_record_arg_flush (cum, typesize * BITS_PER_UNIT, rvec, &k); - - /* If any part of the struct went on the stack put all of it there. - This hack is because the generic code for - FUNCTION_ARG_PARTIAL_NREGS cannot handle cases where the register - parts of the struct are not at the beginning. */ - if (cum->use_stack) - { - if (retval) - return NULL_RTX; /* doesn't go in registers at all */ - kbase = 0; - rvec[0] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); - } - if (k > 1 || cum->use_stack) - return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (k - kbase, &rvec[kbase])); - else - return NULL_RTX; -} - -/* Determine where to place an argument in 64-bit mode with 32-bit ABI. */ - -static rtx -rs6000_mixed_function_arg (machine_mode mode, const_tree type, - int align_words) -{ - int n_units; - int i, k; - rtx rvec[GP_ARG_NUM_REG + 1]; - - if (align_words >= GP_ARG_NUM_REG) - return NULL_RTX; - - n_units = rs6000_arg_size (mode, type); - - /* Optimize the simple case where the arg fits in one gpr, except in - the case of BLKmode due to assign_parms assuming that registers are - BITS_PER_WORD wide. */ - if (n_units == 0 - || (n_units == 1 && mode != BLKmode)) - return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words); - - k = 0; - if (align_words + n_units > GP_ARG_NUM_REG) - /* Not all of the arg fits in gprs. Say that it goes in memory too, - using a magic NULL_RTX component. - This is not strictly correct. Only some of the arg belongs in - memory, not all of it. However, the normal scheme using - function_arg_partial_nregs can result in unusual subregs, eg. - (subreg:SI (reg:DF) 4), which are not handled well. The code to - store the whole arg to memory is often more efficient than code - to store pieces, and we know that space is available in the right - place for the whole arg. */ - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); - - i = 0; - do - { - rtx r = gen_rtx_REG (SImode, GP_ARG_MIN_REG + align_words); - rtx off = GEN_INT (i++ * 4); - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); - } - while (++align_words < GP_ARG_NUM_REG && --n_units != 0); - - return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec)); -} - -/* We have an argument of MODE and TYPE that goes into FPRs or VRs, - but must also be copied into the parameter save area starting at - offset ALIGN_WORDS. Fill in RVEC with the elements corresponding - to the GPRs and/or memory. Return the number of elements used. */ - -static int -rs6000_psave_function_arg (machine_mode mode, const_tree type, - int align_words, rtx *rvec) -{ - int k = 0; - - if (align_words < GP_ARG_NUM_REG) - { - int n_words = rs6000_arg_size (mode, type); - - if (align_words + n_words > GP_ARG_NUM_REG - || mode == BLKmode - || (TARGET_32BIT && TARGET_POWERPC64)) - { - /* If this is partially on the stack, then we only - include the portion actually in registers here. */ - machine_mode rmode = TARGET_32BIT ? SImode : DImode; - int i = 0; - - if (align_words + n_words > GP_ARG_NUM_REG) - { - /* Not all of the arg fits in gprs. Say that it goes in memory - too, using a magic NULL_RTX component. Also see comment in - rs6000_mixed_function_arg for why the normal - function_arg_partial_nregs scheme doesn't work in this case. */ - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); - } - - do - { - rtx r = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words); - rtx off = GEN_INT (i++ * GET_MODE_SIZE (rmode)); - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); - } - while (++align_words < GP_ARG_NUM_REG && --n_words != 0); - } - else - { - /* The whole arg fits in gprs. */ - rtx r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words); - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx); - } - } - else - { - /* It's entirely in memory. */ - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); - } - - return k; -} - -/* RVEC is a vector of K components of an argument of mode MODE. - Construct the final function_arg return value from it. */ - -static rtx -rs6000_finish_function_arg (machine_mode mode, rtx *rvec, int k) -{ - gcc_assert (k >= 1); - - /* Avoid returning a PARALLEL in the trivial cases. */ - if (k == 1) - { - if (XEXP (rvec[0], 0) == NULL_RTX) - return NULL_RTX; - - if (GET_MODE (XEXP (rvec[0], 0)) == mode) - return XEXP (rvec[0], 0); - } - - return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec)); -} - -/* Determine where to put an argument to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. It is - not modified in this routine. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). - - On RS/6000 the first eight words of non-FP are normally in registers - and the rest are pushed. Under AIX, the first 13 FP args are in registers. - Under V.4, the first 8 FP args are in registers. - - If this is floating-point and no prototype is specified, we use - both an FP and integer register (or possibly FP reg and stack). Library - functions (when CALL_LIBCALL is set) always have the proper types for args, - so we can pass the FP value just in one register. emit_library_function - doesn't support PARALLEL anyway. - - Note that for args passed by reference, function_arg will be called - with MODE and TYPE set to that of the pointer to the arg, not the arg - itself. */ - -static rtx -rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode, - const_tree type, bool named) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - enum rs6000_abi abi = DEFAULT_ABI; - machine_mode elt_mode; - int n_elts; - - /* Return a marker to indicate whether CR1 needs to set or clear the - bit that V.4 uses to say fp args were passed in registers. - Assume that we don't need the marker for software floating point, - or compiler generated library calls. */ - if (mode == VOIDmode) - { - if (abi == ABI_V4 - && (cum->call_cookie & CALL_LIBCALL) == 0 - && (cum->stdarg - || (cum->nargs_prototype < 0 - && (cum->prototype || TARGET_NO_PROTOTYPE))) - && TARGET_HARD_FLOAT) - return GEN_INT (cum->call_cookie - | ((cum->fregno == FP_ARG_MIN_REG) - ? CALL_V4_SET_FP_ARGS - : CALL_V4_CLEAR_FP_ARGS)); - - return GEN_INT (cum->call_cookie & ~CALL_LIBCALL); - } - - rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); - - if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) - { - rtx rslt = rs6000_darwin64_record_arg (cum, type, named, /*retval= */false); - if (rslt != NULL_RTX) - return rslt; - /* Else fall through to usual handling. */ - } - - if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named)) - { - rtx rvec[GP_ARG_NUM_REG + AGGR_ARG_NUM_REG + 1]; - rtx r, off; - int i, k = 0; - - /* Do we also need to pass this argument in the parameter save area? - Library support functions for IEEE 128-bit are assumed to not need the - value passed both in GPRs and in vector registers. */ - if (TARGET_64BIT && !cum->prototype - && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode))) - { - int align_words = ROUND_UP (cum->words, 2); - k = rs6000_psave_function_arg (mode, type, align_words, rvec); - } - - /* Describe where this argument goes in the vector registers. */ - for (i = 0; i < n_elts && cum->vregno + i <= ALTIVEC_ARG_MAX_REG; i++) - { - r = gen_rtx_REG (elt_mode, cum->vregno + i); - off = GEN_INT (i * GET_MODE_SIZE (elt_mode)); - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); - } - - return rs6000_finish_function_arg (mode, rvec, k); - } - else if (TARGET_ALTIVEC_ABI - && (ALTIVEC_OR_VSX_VECTOR_MODE (mode) - || (type && TREE_CODE (type) == VECTOR_TYPE - && int_size_in_bytes (type) == 16))) - { - if (named || abi == ABI_V4) - return NULL_RTX; - else - { - /* Vector parameters to varargs functions under AIX or Darwin - get passed in memory and possibly also in GPRs. */ - int align, align_words, n_words; - machine_mode part_mode; - - /* Vector parameters must be 16-byte aligned. In 32-bit - mode this means we need to take into account the offset - to the parameter save area. In 64-bit mode, they just - have to start on an even word, since the parameter save - area is 16-byte aligned. */ - if (TARGET_32BIT) - align = -(rs6000_parm_offset () + cum->words) & 3; - else - align = cum->words & 1; - align_words = cum->words + align; - - /* Out of registers? Memory, then. */ - if (align_words >= GP_ARG_NUM_REG) - return NULL_RTX; - - if (TARGET_32BIT && TARGET_POWERPC64) - return rs6000_mixed_function_arg (mode, type, align_words); - - /* The vector value goes in GPRs. Only the part of the - value in GPRs is reported here. */ - part_mode = mode; - n_words = rs6000_arg_size (mode, type); - if (align_words + n_words > GP_ARG_NUM_REG) - /* Fortunately, there are only two possibilities, the value - is either wholly in GPRs or half in GPRs and half not. */ - part_mode = DImode; - - return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words); - } - } - - else if (abi == ABI_V4) - { - if (abi_v4_pass_in_fpr (mode, named)) - { - /* _Decimal128 must use an even/odd register pair. This assumes - that the register number is odd when fregno is odd. */ - if (mode == TDmode && (cum->fregno % 2) == 1) - cum->fregno++; - - if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0) - <= FP_ARG_V4_MAX_REG) - return gen_rtx_REG (mode, cum->fregno); - else - return NULL_RTX; - } - else - { - int n_words = rs6000_arg_size (mode, type); - int gregno = cum->sysv_gregno; - - /* Long long is put in (r3,r4), (r5,r6), (r7,r8) or (r9,r10). - As does any other 2 word item such as complex int due to a - historical mistake. */ - if (n_words == 2) - gregno += (1 - gregno) & 1; - - /* Multi-reg args are not split between registers and stack. */ - if (gregno + n_words - 1 > GP_ARG_MAX_REG) - return NULL_RTX; - - if (TARGET_32BIT && TARGET_POWERPC64) - return rs6000_mixed_function_arg (mode, type, - gregno - GP_ARG_MIN_REG); - return gen_rtx_REG (mode, gregno); - } - } - else - { - int align_words = rs6000_parm_start (mode, type, cum->words); - - /* _Decimal128 must be passed in an even/odd float register pair. - This assumes that the register number is odd when fregno is odd. */ - if (elt_mode == TDmode && (cum->fregno % 2) == 1) - cum->fregno++; - - if (USE_FP_FOR_ARG_P (cum, elt_mode) - && !(TARGET_AIX && !TARGET_ELF - && type != NULL && AGGREGATE_TYPE_P (type))) - { - rtx rvec[GP_ARG_NUM_REG + AGGR_ARG_NUM_REG + 1]; - rtx r, off; - int i, k = 0; - unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3; - int fpr_words; - - /* Do we also need to pass this argument in the parameter - save area? */ - if (type && (cum->nargs_prototype <= 0 - || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) - && TARGET_XL_COMPAT - && align_words >= GP_ARG_NUM_REG))) - k = rs6000_psave_function_arg (mode, type, align_words, rvec); - - /* Describe where this argument goes in the fprs. */ - for (i = 0; i < n_elts - && cum->fregno + i * n_fpreg <= FP_ARG_MAX_REG; i++) - { - /* Check if the argument is split over registers and memory. - This can only ever happen for long double or _Decimal128; - complex types are handled via split_complex_arg. */ - machine_mode fmode = elt_mode; - if (cum->fregno + (i + 1) * n_fpreg > FP_ARG_MAX_REG + 1) - { - gcc_assert (FLOAT128_2REG_P (fmode)); - fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode; - } - - r = gen_rtx_REG (fmode, cum->fregno + i * n_fpreg); - off = GEN_INT (i * GET_MODE_SIZE (elt_mode)); - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); - } - - /* If there were not enough FPRs to hold the argument, the rest - usually goes into memory. However, if the current position - is still within the register parameter area, a portion may - actually have to go into GPRs. - - Note that it may happen that the portion of the argument - passed in the first "half" of the first GPR was already - passed in the last FPR as well. - - For unnamed arguments, we already set up GPRs to cover the - whole argument in rs6000_psave_function_arg, so there is - nothing further to do at this point. */ - fpr_words = (i * GET_MODE_SIZE (elt_mode)) / (TARGET_32BIT ? 4 : 8); - if (i < n_elts && align_words + fpr_words < GP_ARG_NUM_REG - && cum->nargs_prototype > 0) - { - static bool warned; - - machine_mode rmode = TARGET_32BIT ? SImode : DImode; - int n_words = rs6000_arg_size (mode, type); - - align_words += fpr_words; - n_words -= fpr_words; - - do - { - r = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words); - off = GEN_INT (fpr_words++ * GET_MODE_SIZE (rmode)); - rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off); - } - while (++align_words < GP_ARG_NUM_REG && --n_words != 0); - - if (!warned && warn_psabi) - { - warned = true; - inform (input_location, - "the ABI of passing homogeneous % aggregates" - " has changed in GCC 5"); - } - } - - return rs6000_finish_function_arg (mode, rvec, k); - } - else if (align_words < GP_ARG_NUM_REG) - { - if (TARGET_32BIT && TARGET_POWERPC64) - return rs6000_mixed_function_arg (mode, type, align_words); - - return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words); - } - else - return NULL_RTX; - } -} - -/* For an arg passed partly in registers and partly in memory, this is - the number of bytes passed in registers. For args passed entirely in - registers or entirely in memory, zero. When an arg is described by a - PARALLEL, perhaps using more than one register type, this function - returns the number of bytes used by the first element of the PARALLEL. */ - -static int -rs6000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode, - tree type, bool named) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - bool passed_in_gprs = true; - int ret = 0; - int align_words; - machine_mode elt_mode; - int n_elts; - - rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); - - if (DEFAULT_ABI == ABI_V4) - return 0; - - if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named)) - { - /* If we are passing this arg in the fixed parameter save area (gprs or - memory) as well as VRs, we do not use the partial bytes mechanism; - instead, rs6000_function_arg will return a PARALLEL including a memory - element as necessary. Library support functions for IEEE 128-bit are - assumed to not need the value passed both in GPRs and in vector - registers. */ - if (TARGET_64BIT && !cum->prototype - && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode))) - return 0; - - /* Otherwise, we pass in VRs only. Check for partial copies. */ - passed_in_gprs = false; - if (cum->vregno + n_elts > ALTIVEC_ARG_MAX_REG + 1) - ret = (ALTIVEC_ARG_MAX_REG + 1 - cum->vregno) * 16; - } - - /* In this complicated case we just disable the partial_nregs code. */ - if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) - return 0; - - align_words = rs6000_parm_start (mode, type, cum->words); - - if (USE_FP_FOR_ARG_P (cum, elt_mode) - && !(TARGET_AIX && !TARGET_ELF - && type != NULL && AGGREGATE_TYPE_P (type))) - { - unsigned long n_fpreg = (GET_MODE_SIZE (elt_mode) + 7) >> 3; - - /* If we are passing this arg in the fixed parameter save area - (gprs or memory) as well as FPRs, we do not use the partial - bytes mechanism; instead, rs6000_function_arg will return a - PARALLEL including a memory element as necessary. */ - if (type - && (cum->nargs_prototype <= 0 - || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) - && TARGET_XL_COMPAT - && align_words >= GP_ARG_NUM_REG))) - return 0; - - /* Otherwise, we pass in FPRs only. Check for partial copies. */ - passed_in_gprs = false; - if (cum->fregno + n_elts * n_fpreg > FP_ARG_MAX_REG + 1) - { - /* Compute number of bytes / words passed in FPRs. If there - is still space available in the register parameter area - *after* that amount, a part of the argument will be passed - in GPRs. In that case, the total amount passed in any - registers is equal to the amount that would have been passed - in GPRs if everything were passed there, so we fall back to - the GPR code below to compute the appropriate value. */ - int fpr = ((FP_ARG_MAX_REG + 1 - cum->fregno) - * MIN (8, GET_MODE_SIZE (elt_mode))); - int fpr_words = fpr / (TARGET_32BIT ? 4 : 8); - - if (align_words + fpr_words < GP_ARG_NUM_REG) - passed_in_gprs = true; - else - ret = fpr; - } - } - - if (passed_in_gprs - && align_words < GP_ARG_NUM_REG - && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type)) - ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8); - - if (ret != 0 && TARGET_DEBUG_ARG) - fprintf (stderr, "rs6000_arg_partial_bytes: %d\n", ret); - - return ret; -} - -/* A C expression that indicates when an argument must be passed by - reference. If nonzero for an argument, a copy of that argument is - made in memory and a pointer to the argument is passed instead of - the argument itself. The pointer is passed in whatever way is - appropriate for passing a pointer to that type. - - Under V.4, aggregates and long double are passed by reference. - - As an extension to all 32-bit ABIs, AltiVec vectors are passed by - reference unless the AltiVec vector extension ABI is in force. - - As an extension to all ABIs, variable sized types are passed by - reference. */ - -static bool -rs6000_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, - machine_mode mode, const_tree type, - bool named ATTRIBUTE_UNUSED) -{ - if (!type) - return 0; - - if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD - && FLOAT128_IEEE_P (TYPE_MODE (type))) - { - if (TARGET_DEBUG_ARG) - fprintf (stderr, "function_arg_pass_by_reference: V4 IEEE 128-bit\n"); - return 1; - } - - if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (type)) - { - if (TARGET_DEBUG_ARG) - fprintf (stderr, "function_arg_pass_by_reference: V4 aggregate\n"); - return 1; - } - - if (int_size_in_bytes (type) < 0) - { - if (TARGET_DEBUG_ARG) - fprintf (stderr, "function_arg_pass_by_reference: variable size\n"); - return 1; - } - - /* Allow -maltivec -mabi=no-altivec without warning. Altivec vector - modes only exist for GCC vector types if -maltivec. */ - if (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) - { - if (TARGET_DEBUG_ARG) - fprintf (stderr, "function_arg_pass_by_reference: AltiVec\n"); - return 1; - } - - /* Pass synthetic vectors in memory. */ - if (TREE_CODE (type) == VECTOR_TYPE - && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8)) - { - static bool warned_for_pass_big_vectors = false; - if (TARGET_DEBUG_ARG) - fprintf (stderr, "function_arg_pass_by_reference: synthetic vector\n"); - if (!warned_for_pass_big_vectors) - { - warning (OPT_Wpsabi, "GCC vector passed by reference: " - "non-standard ABI extension with no compatibility " - "guarantee"); - warned_for_pass_big_vectors = true; - } - return 1; - } - - return 0; -} - -/* Process parameter of type TYPE after ARGS_SO_FAR parameters were - already processes. Return true if the parameter must be passed - (fully or partially) on the stack. */ - -static bool -rs6000_parm_needs_stack (cumulative_args_t args_so_far, tree type) -{ - machine_mode mode; - int unsignedp; - rtx entry_parm; - - /* Catch errors. */ - if (type == NULL || type == error_mark_node) - return true; - - /* Handle types with no storage requirement. */ - if (TYPE_MODE (type) == VOIDmode) - return false; - - /* Handle complex types. */ - if (TREE_CODE (type) == COMPLEX_TYPE) - return (rs6000_parm_needs_stack (args_so_far, TREE_TYPE (type)) - || rs6000_parm_needs_stack (args_so_far, TREE_TYPE (type))); - - /* Handle transparent aggregates. */ - if ((TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == RECORD_TYPE) - && TYPE_TRANSPARENT_AGGR (type)) - type = TREE_TYPE (first_field (type)); - - /* See if this arg was passed by invisible reference. */ - if (pass_by_reference (get_cumulative_args (args_so_far), - TYPE_MODE (type), type, true)) - type = build_pointer_type (type); - - /* Find mode as it is passed by the ABI. */ - unsignedp = TYPE_UNSIGNED (type); - mode = promote_mode (type, TYPE_MODE (type), &unsignedp); - - /* If we must pass in stack, we need a stack. */ - if (rs6000_must_pass_in_stack (mode, type)) - return true; - - /* If there is no incoming register, we need a stack. */ - entry_parm = rs6000_function_arg (args_so_far, mode, type, true); - if (entry_parm == NULL) - return true; - - /* Likewise if we need to pass both in registers and on the stack. */ - if (GET_CODE (entry_parm) == PARALLEL - && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX) - return true; - - /* Also true if we're partially in registers and partially not. */ - if (rs6000_arg_partial_bytes (args_so_far, mode, type, true) != 0) - return true; - - /* Update info on where next arg arrives in registers. */ - rs6000_function_arg_advance (args_so_far, mode, type, true); - return false; -} - -/* Return true if FUN has no prototype, has a variable argument - list, or passes any parameter in memory. */ - -static bool -rs6000_function_parms_need_stack (tree fun, bool incoming) -{ - tree fntype, result; - CUMULATIVE_ARGS args_so_far_v; - cumulative_args_t args_so_far; - - if (!fun) - /* Must be a libcall, all of which only use reg parms. */ - return false; - - fntype = fun; - if (!TYPE_P (fun)) - fntype = TREE_TYPE (fun); - - /* Varargs functions need the parameter save area. */ - if ((!incoming && !prototype_p (fntype)) || stdarg_p (fntype)) - return true; - - INIT_CUMULATIVE_INCOMING_ARGS (args_so_far_v, fntype, NULL_RTX); - args_so_far = pack_cumulative_args (&args_so_far_v); - - /* When incoming, we will have been passed the function decl. - It is necessary to use the decl to handle K&R style functions, - where TYPE_ARG_TYPES may not be available. */ - if (incoming) - { - gcc_assert (DECL_P (fun)); - result = DECL_RESULT (fun); - } - else - result = TREE_TYPE (fntype); - - if (result && aggregate_value_p (result, fntype)) - { - if (!TYPE_P (result)) - result = TREE_TYPE (result); - result = build_pointer_type (result); - rs6000_parm_needs_stack (args_so_far, result); - } - - if (incoming) - { - tree parm; - - for (parm = DECL_ARGUMENTS (fun); - parm && parm != void_list_node; - parm = TREE_CHAIN (parm)) - if (rs6000_parm_needs_stack (args_so_far, TREE_TYPE (parm))) - return true; - } - else - { - function_args_iterator args_iter; - tree arg_type; - - FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) - if (rs6000_parm_needs_stack (args_so_far, arg_type)) - return true; - } - - return false; -} - -/* Return the size of the REG_PARM_STACK_SPACE are for FUN. This is - usually a constant depending on the ABI. However, in the ELFv2 ABI - the register parameter area is optional when calling a function that - has a prototype is scope, has no variable argument list, and passes - all parameters in registers. */ - -int -rs6000_reg_parm_stack_space (tree fun, bool incoming) -{ - int reg_parm_stack_space; - - switch (DEFAULT_ABI) - { - default: - reg_parm_stack_space = 0; - break; - - case ABI_AIX: - case ABI_DARWIN: - reg_parm_stack_space = TARGET_64BIT ? 64 : 32; - break; - - case ABI_ELFv2: - /* ??? Recomputing this every time is a bit expensive. Is there - a place to cache this information? */ - if (rs6000_function_parms_need_stack (fun, incoming)) - reg_parm_stack_space = TARGET_64BIT ? 64 : 32; - else - reg_parm_stack_space = 0; - break; - } - - return reg_parm_stack_space; -} - -static void -rs6000_move_block_from_reg (int regno, rtx x, int nregs) -{ - int i; - machine_mode reg_mode = TARGET_32BIT ? SImode : DImode; - - if (nregs == 0) - return; - - for (i = 0; i < nregs; i++) - { - rtx tem = adjust_address_nv (x, reg_mode, i * GET_MODE_SIZE (reg_mode)); - if (reload_completed) - { - if (! strict_memory_address_p (reg_mode, XEXP (tem, 0))) - tem = NULL_RTX; - else - tem = simplify_gen_subreg (reg_mode, x, BLKmode, - i * GET_MODE_SIZE (reg_mode)); - } - else - tem = replace_equiv_address (tem, XEXP (tem, 0)); - - gcc_assert (tem); - - emit_move_insn (tem, gen_rtx_REG (reg_mode, regno + i)); - } -} - -/* Perform any needed actions needed for a function that is receiving a - variable number of arguments. - - CUM is as above. - - MODE and TYPE are the mode and type of the current parameter. - - PRETEND_SIZE is a variable that should be set to the amount of stack - that must be pushed by the prolog to pretend that our caller pushed - it. - - Normally, this macro will push all remaining incoming registers on the - stack and set PRETEND_SIZE to the length of the registers pushed. */ - -static void -setup_incoming_varargs (cumulative_args_t cum, machine_mode mode, - tree type, int *pretend_size ATTRIBUTE_UNUSED, - int no_rtl) -{ - CUMULATIVE_ARGS next_cum; - int reg_size = TARGET_32BIT ? 4 : 8; - rtx save_area = NULL_RTX, mem; - int first_reg_offset; - alias_set_type set; - - /* Skip the last named argument. */ - next_cum = *get_cumulative_args (cum); - rs6000_function_arg_advance_1 (&next_cum, mode, type, true, 0); - - if (DEFAULT_ABI == ABI_V4) - { - first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG; - - if (! no_rtl) - { - int gpr_reg_num = 0, gpr_size = 0, fpr_size = 0; - HOST_WIDE_INT offset = 0; - - /* Try to optimize the size of the varargs save area. - The ABI requires that ap.reg_save_area is doubleword - aligned, but we don't need to allocate space for all - the bytes, only those to which we actually will save - anything. */ - if (cfun->va_list_gpr_size && first_reg_offset < GP_ARG_NUM_REG) - gpr_reg_num = GP_ARG_NUM_REG - first_reg_offset; - if (TARGET_HARD_FLOAT - && next_cum.fregno <= FP_ARG_V4_MAX_REG - && cfun->va_list_fpr_size) - { - if (gpr_reg_num) - fpr_size = (next_cum.fregno - FP_ARG_MIN_REG) - * UNITS_PER_FP_WORD; - if (cfun->va_list_fpr_size - < FP_ARG_V4_MAX_REG + 1 - next_cum.fregno) - fpr_size += cfun->va_list_fpr_size * UNITS_PER_FP_WORD; - else - fpr_size += (FP_ARG_V4_MAX_REG + 1 - next_cum.fregno) - * UNITS_PER_FP_WORD; - } - if (gpr_reg_num) - { - offset = -((first_reg_offset * reg_size) & ~7); - if (!fpr_size && gpr_reg_num > cfun->va_list_gpr_size) - { - gpr_reg_num = cfun->va_list_gpr_size; - if (reg_size == 4 && (first_reg_offset & 1)) - gpr_reg_num++; - } - gpr_size = (gpr_reg_num * reg_size + 7) & ~7; - } - else if (fpr_size) - offset = - (int) (next_cum.fregno - FP_ARG_MIN_REG) - * UNITS_PER_FP_WORD - - (int) (GP_ARG_NUM_REG * reg_size); - - if (gpr_size + fpr_size) - { - rtx reg_save_area - = assign_stack_local (BLKmode, gpr_size + fpr_size, 64); - gcc_assert (MEM_P (reg_save_area)); - reg_save_area = XEXP (reg_save_area, 0); - if (GET_CODE (reg_save_area) == PLUS) - { - gcc_assert (XEXP (reg_save_area, 0) - == virtual_stack_vars_rtx); - gcc_assert (CONST_INT_P (XEXP (reg_save_area, 1))); - offset += INTVAL (XEXP (reg_save_area, 1)); - } - else - gcc_assert (reg_save_area == virtual_stack_vars_rtx); - } - - cfun->machine->varargs_save_offset = offset; - save_area = plus_constant (Pmode, virtual_stack_vars_rtx, offset); - } - } - else - { - first_reg_offset = next_cum.words; - save_area = crtl->args.internal_arg_pointer; - - if (targetm.calls.must_pass_in_stack (mode, type)) - first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type); - } - - set = get_varargs_alias_set (); - if (! no_rtl && first_reg_offset < GP_ARG_NUM_REG - && cfun->va_list_gpr_size) - { - int n_gpr, nregs = GP_ARG_NUM_REG - first_reg_offset; - - if (va_list_gpr_counter_field) - /* V4 va_list_gpr_size counts number of registers needed. */ - n_gpr = cfun->va_list_gpr_size; - else - /* char * va_list instead counts number of bytes needed. */ - n_gpr = (cfun->va_list_gpr_size + reg_size - 1) / reg_size; - - if (nregs > n_gpr) - nregs = n_gpr; - - mem = gen_rtx_MEM (BLKmode, - plus_constant (Pmode, save_area, - first_reg_offset * reg_size)); - MEM_NOTRAP_P (mem) = 1; - set_mem_alias_set (mem, set); - set_mem_align (mem, BITS_PER_WORD); - - rs6000_move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem, - nregs); - } - - /* Save FP registers if needed. */ - if (DEFAULT_ABI == ABI_V4 - && TARGET_HARD_FLOAT - && ! no_rtl - && next_cum.fregno <= FP_ARG_V4_MAX_REG - && cfun->va_list_fpr_size) - { - int fregno = next_cum.fregno, nregs; - rtx cr1 = gen_rtx_REG (CCmode, CR1_REGNO); - rtx lab = gen_label_rtx (); - int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG) - * UNITS_PER_FP_WORD); - - emit_jump_insn - (gen_rtx_SET (pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_NE (VOIDmode, cr1, - const0_rtx), - gen_rtx_LABEL_REF (VOIDmode, lab), - pc_rtx))); - - for (nregs = 0; - fregno <= FP_ARG_V4_MAX_REG && nregs < cfun->va_list_fpr_size; - fregno++, off += UNITS_PER_FP_WORD, nregs++) - { - mem = gen_rtx_MEM (TARGET_HARD_FLOAT ? DFmode : SFmode, - plus_constant (Pmode, save_area, off)); - MEM_NOTRAP_P (mem) = 1; - set_mem_alias_set (mem, set); - set_mem_align (mem, GET_MODE_ALIGNMENT ( - TARGET_HARD_FLOAT ? DFmode : SFmode)); - emit_move_insn (mem, gen_rtx_REG ( - TARGET_HARD_FLOAT ? DFmode : SFmode, fregno)); - } - - emit_label (lab); - } -} - -/* Create the va_list data type. */ - -static tree -rs6000_build_builtin_va_list (void) -{ - tree f_gpr, f_fpr, f_res, f_ovf, f_sav, record, type_decl; - - /* For AIX, prefer 'char *' because that's what the system - header files like. */ - if (DEFAULT_ABI != ABI_V4) - return build_pointer_type (char_type_node); - - record = (*lang_hooks.types.make_type) (RECORD_TYPE); - type_decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, - get_identifier ("__va_list_tag"), record); - - f_gpr = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("gpr"), - unsigned_char_type_node); - f_fpr = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("fpr"), - unsigned_char_type_node); - /* Give the two bytes of padding a name, so that -Wpadded won't warn on - every user file. */ - f_res = build_decl (BUILTINS_LOCATION, FIELD_DECL, - get_identifier ("reserved"), short_unsigned_type_node); - f_ovf = build_decl (BUILTINS_LOCATION, FIELD_DECL, - get_identifier ("overflow_arg_area"), - ptr_type_node); - f_sav = build_decl (BUILTINS_LOCATION, FIELD_DECL, - get_identifier ("reg_save_area"), - ptr_type_node); - - va_list_gpr_counter_field = f_gpr; - va_list_fpr_counter_field = f_fpr; - - DECL_FIELD_CONTEXT (f_gpr) = record; - DECL_FIELD_CONTEXT (f_fpr) = record; - DECL_FIELD_CONTEXT (f_res) = record; - DECL_FIELD_CONTEXT (f_ovf) = record; - DECL_FIELD_CONTEXT (f_sav) = record; - - TYPE_STUB_DECL (record) = type_decl; - TYPE_NAME (record) = type_decl; - TYPE_FIELDS (record) = f_gpr; - DECL_CHAIN (f_gpr) = f_fpr; - DECL_CHAIN (f_fpr) = f_res; - DECL_CHAIN (f_res) = f_ovf; - DECL_CHAIN (f_ovf) = f_sav; - - layout_type (record); - - /* The correct type is an array type of one element. */ - return build_array_type (record, build_index_type (size_zero_node)); -} - -/* Implement va_start. */ - -static void -rs6000_va_start (tree valist, rtx nextarg) -{ - HOST_WIDE_INT words, n_gpr, n_fpr; - tree f_gpr, f_fpr, f_res, f_ovf, f_sav; - tree gpr, fpr, ovf, sav, t; - - /* Only SVR4 needs something special. */ - if (DEFAULT_ABI != ABI_V4) - { - std_expand_builtin_va_start (valist, nextarg); - return; - } - - f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); - f_fpr = DECL_CHAIN (f_gpr); - f_res = DECL_CHAIN (f_fpr); - f_ovf = DECL_CHAIN (f_res); - f_sav = DECL_CHAIN (f_ovf); - - valist = build_simple_mem_ref (valist); - gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); - fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), unshare_expr (valist), - f_fpr, NULL_TREE); - ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), unshare_expr (valist), - f_ovf, NULL_TREE); - sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist), - f_sav, NULL_TREE); - - /* Count number of gp and fp argument registers used. */ - words = crtl->args.info.words; - n_gpr = MIN (crtl->args.info.sysv_gregno - GP_ARG_MIN_REG, - GP_ARG_NUM_REG); - n_fpr = MIN (crtl->args.info.fregno - FP_ARG_MIN_REG, - FP_ARG_NUM_REG); - - if (TARGET_DEBUG_ARG) - fprintf (stderr, "va_start: words = " HOST_WIDE_INT_PRINT_DEC", n_gpr = " - HOST_WIDE_INT_PRINT_DEC", n_fpr = " HOST_WIDE_INT_PRINT_DEC"\n", - words, n_gpr, n_fpr); - - if (cfun->va_list_gpr_size) - { - t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr, - build_int_cst (NULL_TREE, n_gpr)); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - } - - if (cfun->va_list_fpr_size) - { - t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr, - build_int_cst (NULL_TREE, n_fpr)); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - -#ifdef HAVE_AS_GNU_ATTRIBUTE - if (call_ABI_of_interest (cfun->decl)) - rs6000_passes_float = true; -#endif - } - - /* Find the overflow area. */ - t = make_tree (TREE_TYPE (ovf), crtl->args.internal_arg_pointer); - if (words != 0) - t = fold_build_pointer_plus_hwi (t, words * MIN_UNITS_PER_WORD); - t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - /* If there were no va_arg invocations, don't set up the register - save area. */ - if (!cfun->va_list_gpr_size - && !cfun->va_list_fpr_size - && n_gpr < GP_ARG_NUM_REG - && n_fpr < FP_ARG_V4_MAX_REG) - return; - - /* Find the register save area. */ - t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx); - if (cfun->machine->varargs_save_offset) - t = fold_build_pointer_plus_hwi (t, cfun->machine->varargs_save_offset); - t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); -} - -/* Implement va_arg. */ - -static tree -rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, - gimple_seq *post_p) -{ - tree f_gpr, f_fpr, f_res, f_ovf, f_sav; - tree gpr, fpr, ovf, sav, reg, t, u; - int size, rsize, n_reg, sav_ofs, sav_scale; - tree lab_false, lab_over, addr; - int align; - tree ptrtype = build_pointer_type_for_mode (type, ptr_mode, true); - int regalign = 0; - gimple *stmt; - - if (pass_by_reference (NULL, TYPE_MODE (type), type, false)) - { - t = rs6000_gimplify_va_arg (valist, ptrtype, pre_p, post_p); - return build_va_arg_indirect_ref (t); - } - - /* We need to deal with the fact that the darwin ppc64 ABI is defined by an - earlier version of gcc, with the property that it always applied alignment - adjustments to the va-args (even for zero-sized types). The cheapest way - to deal with this is to replicate the effect of the part of - std_gimplify_va_arg_expr that carries out the align adjust, for the case - of relevance. - We don't need to check for pass-by-reference because of the test above. - We can return a simplifed answer, since we know there's no offset to add. */ - - if (((TARGET_MACHO - && rs6000_darwin64_abi) - || DEFAULT_ABI == ABI_ELFv2 - || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm)) - && integer_zerop (TYPE_SIZE (type))) - { - unsigned HOST_WIDE_INT align, boundary; - tree valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL); - align = PARM_BOUNDARY / BITS_PER_UNIT; - boundary = rs6000_function_arg_boundary (TYPE_MODE (type), type); - if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) - boundary = MAX_SUPPORTED_STACK_ALIGNMENT; - boundary /= BITS_PER_UNIT; - if (boundary > align) - { - tree t ; - /* This updates arg ptr by the amount that would be necessary - to align the zero-sized (but not zero-alignment) item. */ - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - fold_build_pointer_plus_hwi (valist_tmp, boundary - 1)); - gimplify_and_add (t, pre_p); - - t = fold_convert (sizetype, valist_tmp); - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - fold_convert (TREE_TYPE (valist), - fold_build2 (BIT_AND_EXPR, sizetype, t, - size_int (-boundary)))); - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); - gimplify_and_add (t, pre_p); - } - /* Since it is zero-sized there's no increment for the item itself. */ - valist_tmp = fold_convert (build_pointer_type (type), valist_tmp); - return build_va_arg_indirect_ref (valist_tmp); - } - - if (DEFAULT_ABI != ABI_V4) - { - if (targetm.calls.split_complex_arg && TREE_CODE (type) == COMPLEX_TYPE) - { - tree elem_type = TREE_TYPE (type); - machine_mode elem_mode = TYPE_MODE (elem_type); - int elem_size = GET_MODE_SIZE (elem_mode); - - if (elem_size < UNITS_PER_WORD) - { - tree real_part, imag_part; - gimple_seq post = NULL; - - real_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p, - &post); - /* Copy the value into a temporary, lest the formal temporary - be reused out from under us. */ - real_part = get_initialized_tmp_var (real_part, pre_p, &post); - gimple_seq_add_seq (pre_p, post); - - imag_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p, - post_p); - - return build2 (COMPLEX_EXPR, type, real_part, imag_part); - } - } - - return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); - } - - f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); - f_fpr = DECL_CHAIN (f_gpr); - f_res = DECL_CHAIN (f_fpr); - f_ovf = DECL_CHAIN (f_res); - f_sav = DECL_CHAIN (f_ovf); - - gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE); - fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), unshare_expr (valist), - f_fpr, NULL_TREE); - ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), unshare_expr (valist), - f_ovf, NULL_TREE); - sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), unshare_expr (valist), - f_sav, NULL_TREE); - - size = int_size_in_bytes (type); - rsize = (size + 3) / 4; - int pad = 4 * rsize - size; - align = 1; - - machine_mode mode = TYPE_MODE (type); - if (abi_v4_pass_in_fpr (mode, false)) - { - /* FP args go in FP registers, if present. */ - reg = fpr; - n_reg = (size + 7) / 8; - sav_ofs = (TARGET_HARD_FLOAT ? 8 : 4) * 4; - sav_scale = (TARGET_HARD_FLOAT ? 8 : 4); - if (mode != SFmode && mode != SDmode) - align = 8; - } - else - { - /* Otherwise into GP registers. */ - reg = gpr; - n_reg = rsize; - sav_ofs = 0; - sav_scale = 4; - if (n_reg == 2) - align = 8; - } - - /* Pull the value out of the saved registers.... */ - - lab_over = NULL; - addr = create_tmp_var (ptr_type_node, "addr"); - - /* AltiVec vectors never go in registers when -mabi=altivec. */ - if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) - align = 16; - else - { - lab_false = create_artificial_label (input_location); - lab_over = create_artificial_label (input_location); - - /* Long long is aligned in the registers. As are any other 2 gpr - item such as complex int due to a historical mistake. */ - u = reg; - if (n_reg == 2 && reg == gpr) - { - regalign = 1; - u = build2 (BIT_AND_EXPR, TREE_TYPE (reg), unshare_expr (reg), - build_int_cst (TREE_TYPE (reg), n_reg - 1)); - u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), - unshare_expr (reg), u); - } - /* _Decimal128 is passed in even/odd fpr pairs; the stored - reg number is 0 for f1, so we want to make it odd. */ - else if (reg == fpr && mode == TDmode) - { - t = build2 (BIT_IOR_EXPR, TREE_TYPE (reg), unshare_expr (reg), - build_int_cst (TREE_TYPE (reg), 1)); - u = build2 (MODIFY_EXPR, void_type_node, unshare_expr (reg), t); - } - - t = fold_convert (TREE_TYPE (reg), size_int (8 - n_reg + 1)); - t = build2 (GE_EXPR, boolean_type_node, u, t); - u = build1 (GOTO_EXPR, void_type_node, lab_false); - t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE); - gimplify_and_add (t, pre_p); - - t = sav; - if (sav_ofs) - t = fold_build_pointer_plus_hwi (sav, sav_ofs); - - u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), unshare_expr (reg), - build_int_cst (TREE_TYPE (reg), n_reg)); - u = fold_convert (sizetype, u); - u = build2 (MULT_EXPR, sizetype, u, size_int (sav_scale)); - t = fold_build_pointer_plus (t, u); - - /* _Decimal32 varargs are located in the second word of the 64-bit - FP register for 32-bit binaries. */ - if (TARGET_32BIT && TARGET_HARD_FLOAT && mode == SDmode) - t = fold_build_pointer_plus_hwi (t, size); - - /* Args are passed right-aligned. */ - if (BYTES_BIG_ENDIAN) - t = fold_build_pointer_plus_hwi (t, pad); - - gimplify_assign (addr, t, pre_p); - - gimple_seq_add_stmt (pre_p, gimple_build_goto (lab_over)); - - stmt = gimple_build_label (lab_false); - gimple_seq_add_stmt (pre_p, stmt); - - if ((n_reg == 2 && !regalign) || n_reg > 2) - { - /* Ensure that we don't find any more args in regs. - Alignment has taken care of for special cases. */ - gimplify_assign (reg, build_int_cst (TREE_TYPE (reg), 8), pre_p); - } - } - - /* ... otherwise out of the overflow area. */ - - /* Care for on-stack alignment if needed. */ - t = ovf; - if (align != 1) - { - t = fold_build_pointer_plus_hwi (t, align - 1); - t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t, - build_int_cst (TREE_TYPE (t), -align)); - } - - /* Args are passed right-aligned. */ - if (BYTES_BIG_ENDIAN) - t = fold_build_pointer_plus_hwi (t, pad); - - gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue); - - gimplify_assign (unshare_expr (addr), t, pre_p); - - t = fold_build_pointer_plus_hwi (t, size); - gimplify_assign (unshare_expr (ovf), t, pre_p); - - if (lab_over) - { - stmt = gimple_build_label (lab_over); - gimple_seq_add_stmt (pre_p, stmt); - } - - if (STRICT_ALIGNMENT - && (TYPE_ALIGN (type) - > (unsigned) BITS_PER_UNIT * (align < 4 ? 4 : align))) - { - /* The value (of type complex double, for example) may not be - aligned in memory in the saved registers, so copy via a - temporary. (This is the same code as used for SPARC.) */ - tree tmp = create_tmp_var (type, "va_arg_tmp"); - tree dest_addr = build_fold_addr_expr (tmp); - - tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY), - 3, dest_addr, addr, size_int (rsize * 4)); - TREE_ADDRESSABLE (tmp) = 1; - - gimplify_and_add (copy, pre_p); - addr = dest_addr; - } - - addr = fold_convert (ptrtype, addr); - return build_va_arg_indirect_ref (addr); -} - -/* Builtins. */ - -static void -def_builtin (const char *name, tree type, enum rs6000_builtins code) -{ - tree t; - unsigned classify = rs6000_builtin_info[(int)code].attr; - const char *attr_string = ""; - - gcc_assert (name != NULL); - gcc_assert (IN_RANGE ((int)code, 0, (int)RS6000_BUILTIN_COUNT)); - - if (rs6000_builtin_decls[(int)code]) - fatal_error (input_location, - "internal error: builtin function %qs already processed", - name); - - rs6000_builtin_decls[(int)code] = t = - add_builtin_function (name, type, (int)code, BUILT_IN_MD, NULL, NULL_TREE); - - /* Set any special attributes. */ - if ((classify & RS6000_BTC_CONST) != 0) - { - /* const function, function only depends on the inputs. */ - TREE_READONLY (t) = 1; - TREE_NOTHROW (t) = 1; - attr_string = ", const"; - } - else if ((classify & RS6000_BTC_PURE) != 0) - { - /* pure function, function can read global memory, but does not set any - external state. */ - DECL_PURE_P (t) = 1; - TREE_NOTHROW (t) = 1; - attr_string = ", pure"; - } - else if ((classify & RS6000_BTC_FP) != 0) - { - /* Function is a math function. If rounding mode is on, then treat the - function as not reading global memory, but it can have arbitrary side - effects. If it is off, then assume the function is a const function. - This mimics the ATTR_MATHFN_FPROUNDING attribute in - builtin-attribute.def that is used for the math functions. */ - TREE_NOTHROW (t) = 1; - if (flag_rounding_math) - { - DECL_PURE_P (t) = 1; - DECL_IS_NOVOPS (t) = 1; - attr_string = ", fp, pure"; - } - else - { - TREE_READONLY (t) = 1; - attr_string = ", fp, const"; - } - } - else if ((classify & RS6000_BTC_ATTR_MASK) != 0) - gcc_unreachable (); - - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, code = %4d, %s%s\n", - (int)code, name, attr_string); -} - -/* Simple ternary operations: VECd = foo (VECa, VECb, VECc). */ - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -static const struct builtin_description bdesc_3arg[] = -{ -#include "rs6000-builtin.def" -}; - -/* DST operations: void foo (void *, const int, const char). */ - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -static const struct builtin_description bdesc_dst[] = -{ -#include "rs6000-builtin.def" -}; - -/* Simple binary operations: VECc = foo (VECa, VECb). */ - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -static const struct builtin_description bdesc_2arg[] = -{ -#include "rs6000-builtin.def" -}; - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -/* AltiVec predicates. */ - -static const struct builtin_description bdesc_altivec_preds[] = -{ -#include "rs6000-builtin.def" -}; - -/* ABS* operations. */ - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -static const struct builtin_description bdesc_abs[] = -{ -#include "rs6000-builtin.def" -}; - -/* Simple unary operations: VECb = foo (unsigned literal) or VECb = - foo (VECa). */ - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -static const struct builtin_description bdesc_1arg[] = -{ -#include "rs6000-builtin.def" -}; - -/* Simple no-argument operations: result = __builtin_darn_32 () */ - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -static const struct builtin_description bdesc_0arg[] = -{ -#include "rs6000-builtin.def" -}; - -/* HTM builtins. */ -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P -#undef RS6000_BUILTIN_X - -#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ - { MASK, ICODE, NAME, ENUM }, - -#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) -#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) - -static const struct builtin_description bdesc_htm[] = -{ -#include "rs6000-builtin.def" -}; - -#undef RS6000_BUILTIN_0 -#undef RS6000_BUILTIN_1 -#undef RS6000_BUILTIN_2 -#undef RS6000_BUILTIN_3 -#undef RS6000_BUILTIN_A -#undef RS6000_BUILTIN_D -#undef RS6000_BUILTIN_H -#undef RS6000_BUILTIN_P - -/* Return true if a builtin function is overloaded. */ -bool -rs6000_overloaded_builtin_p (enum rs6000_builtins fncode) -{ - return (rs6000_builtin_info[(int)fncode].attr & RS6000_BTC_OVERLOADED) != 0; -} - -const char * -rs6000_overloaded_builtin_name (enum rs6000_builtins fncode) -{ - return rs6000_builtin_info[(int)fncode].name; -} - -/* Expand an expression EXP that calls a builtin without arguments. */ -static rtx -rs6000_expand_zeroop_builtin (enum insn_code icode, rtx target) -{ - rtx pat; - machine_mode tmode = insn_data[icode].operand[0].mode; - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - if (icode == CODE_FOR_rs6000_mffsl - && rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) - { - error ("%<__builtin_mffsl%> not supported with %<-msoft-float%>"); - return const0_rtx; - } - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - pat = GEN_FCN (icode) (target); - if (! pat) - return 0; - emit_insn (pat); - - return target; -} - - -static rtx -rs6000_expand_mtfsf_builtin (enum insn_code icode, tree exp) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - tree arg1 = CALL_EXPR_ARG (exp, 1); - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - machine_mode mode0 = insn_data[icode].operand[0].mode; - machine_mode mode1 = insn_data[icode].operand[1].mode; - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node || arg1 == error_mark_node) - return const0_rtx; - - if (!CONST_INT_P (op0) - || INTVAL (op0) > 255 - || INTVAL (op0) < 0) - { - error ("argument 1 must be an 8-bit field value"); - return const0_rtx; - } - - if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - if (! (*insn_data[icode].operand[1].predicate) (op1, mode1)) - op1 = copy_to_mode_reg (mode1, op1); - - pat = GEN_FCN (icode) (op0, op1); - if (!pat) - return const0_rtx; - emit_insn (pat); - - return NULL_RTX; -} - -static rtx -rs6000_expand_mtfsb_builtin (enum insn_code icode, tree exp) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - rtx op0 = expand_normal (arg0); - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - if (rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) - { - error ("%<__builtin_mtfsb0%> and %<__builtin_mtfsb1%> not supported with " - "%<-msoft-float%>"); - return const0_rtx; - } - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node) - return const0_rtx; - - /* Only allow bit numbers 0 to 31. */ - if (!u5bit_cint_operand (op0, VOIDmode)) - { - error ("Argument must be a constant between 0 and 31."); - return const0_rtx; - } - - pat = GEN_FCN (icode) (op0); - if (!pat) - return const0_rtx; - emit_insn (pat); - - return NULL_RTX; -} - -static rtx -rs6000_expand_set_fpscr_rn_builtin (enum insn_code icode, tree exp) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - rtx op0 = expand_normal (arg0); - machine_mode mode0 = insn_data[icode].operand[0].mode; - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - if (rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) - { - error ("%<__builtin_set_fpscr_rn%> not supported with %<-msoft-float%>"); - return const0_rtx; - } - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node) - return const0_rtx; - - /* If the argument is a constant, check the range. Argument can only be a - 2-bit value. Unfortunately, can't check the range of the value at - compile time if the argument is a variable. The least significant two - bits of the argument, regardless of type, are used to set the rounding - mode. All other bits are ignored. */ - if (CONST_INT_P (op0) && !const_0_to_3_operand(op0, VOIDmode)) - { - error ("Argument must be a value between 0 and 3."); - return const0_rtx; - } - - if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - pat = GEN_FCN (icode) (op0); - if (!pat) - return const0_rtx; - emit_insn (pat); - - return NULL_RTX; -} -static rtx -rs6000_expand_set_fpscr_drn_builtin (enum insn_code icode, tree exp) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - rtx op0 = expand_normal (arg0); - machine_mode mode0 = insn_data[icode].operand[0].mode; - - if (TARGET_32BIT) - /* Builtin not supported in 32-bit mode. */ - fatal_error (input_location, - "%<__builtin_set_fpscr_drn%> is not supported " - "in 32-bit mode"); - - if (rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT) - { - error ("%<__builtin_set_fpscr_drn%> not supported with %<-msoft-float%>"); - return const0_rtx; - } - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node) - return const0_rtx; - - /* If the argument is a constant, check the range. Agrument can only be a - 3-bit value. Unfortunately, can't check the range of the value at - compile time if the argument is a variable. The least significant two - bits of the argument, regardless of type, are used to set the rounding - mode. All other bits are ignored. */ - if (CONST_INT_P (op0) && !const_0_to_7_operand(op0, VOIDmode)) - { - error ("Argument must be a value between 0 and 7."); - return const0_rtx; - } - - if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - pat = GEN_FCN (icode) (op0); - if (! pat) - return const0_rtx; - emit_insn (pat); - - return NULL_RTX; -} - -static rtx -rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - rtx op0 = expand_normal (arg0); - machine_mode tmode = insn_data[icode].operand[0].mode; - machine_mode mode0 = insn_data[icode].operand[1].mode; - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node) - return const0_rtx; - - if (icode == CODE_FOR_altivec_vspltisb - || icode == CODE_FOR_altivec_vspltish - || icode == CODE_FOR_altivec_vspltisw) - { - /* Only allow 5-bit *signed* literals. */ - if (!CONST_INT_P (op0) - || INTVAL (op0) > 15 - || INTVAL (op0) < -16) - { - error ("argument 1 must be a 5-bit signed literal"); - return CONST0_RTX (tmode); - } - } - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - pat = GEN_FCN (icode) (target, op0); - if (! pat) - return 0; - emit_insn (pat); - - return target; -} - -static rtx -altivec_expand_abs_builtin (enum insn_code icode, tree exp, rtx target) -{ - rtx pat, scratch1, scratch2; - tree arg0 = CALL_EXPR_ARG (exp, 0); - rtx op0 = expand_normal (arg0); - machine_mode tmode = insn_data[icode].operand[0].mode; - machine_mode mode0 = insn_data[icode].operand[1].mode; - - /* If we have invalid arguments, bail out before generating bad rtl. */ - if (arg0 == error_mark_node) - return const0_rtx; - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - scratch1 = gen_reg_rtx (mode0); - scratch2 = gen_reg_rtx (mode0); - - pat = GEN_FCN (icode) (target, op0, scratch1, scratch2); - if (! pat) - return 0; - emit_insn (pat); - - return target; -} - -static rtx -rs6000_expand_binop_builtin (enum insn_code icode, tree exp, rtx target) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - tree arg1 = CALL_EXPR_ARG (exp, 1); - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - machine_mode tmode = insn_data[icode].operand[0].mode; - machine_mode mode0 = insn_data[icode].operand[1].mode; - machine_mode mode1 = insn_data[icode].operand[2].mode; - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node || arg1 == error_mark_node) - return const0_rtx; - - if (icode == CODE_FOR_unpackv1ti - || icode == CODE_FOR_unpackkf - || icode == CODE_FOR_unpacktf - || icode == CODE_FOR_unpackif - || icode == CODE_FOR_unpacktd) - { - /* Only allow 1-bit unsigned literals. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST - || !IN_RANGE (TREE_INT_CST_LOW (arg1), 0, 1)) - { - error ("argument 2 must be a 1-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_altivec_vspltw) - { - /* Only allow 2-bit unsigned literals. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST - || TREE_INT_CST_LOW (arg1) & ~3) - { - error ("argument 2 must be a 2-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_altivec_vsplth) - { - /* Only allow 3-bit unsigned literals. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST - || TREE_INT_CST_LOW (arg1) & ~7) - { - error ("argument 2 must be a 3-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_altivec_vspltb) - { - /* Only allow 4-bit unsigned literals. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST - || TREE_INT_CST_LOW (arg1) & ~15) - { - error ("argument 2 must be a 4-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_altivec_vcfux - || icode == CODE_FOR_altivec_vcfsx - || icode == CODE_FOR_altivec_vctsxs - || icode == CODE_FOR_altivec_vctuxs) - { - /* Only allow 5-bit unsigned literals. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST - || TREE_INT_CST_LOW (arg1) & ~0x1f) - { - error ("argument 2 must be a 5-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_dfptstsfi_eq_dd - || icode == CODE_FOR_dfptstsfi_lt_dd - || icode == CODE_FOR_dfptstsfi_gt_dd - || icode == CODE_FOR_dfptstsfi_unordered_dd - || icode == CODE_FOR_dfptstsfi_eq_td - || icode == CODE_FOR_dfptstsfi_lt_td - || icode == CODE_FOR_dfptstsfi_gt_td - || icode == CODE_FOR_dfptstsfi_unordered_td) - { - /* Only allow 6-bit unsigned literals. */ - STRIP_NOPS (arg0); - if (TREE_CODE (arg0) != INTEGER_CST - || !IN_RANGE (TREE_INT_CST_LOW (arg0), 0, 63)) - { - error ("argument 1 must be a 6-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_xststdcqp_kf - || icode == CODE_FOR_xststdcqp_tf - || icode == CODE_FOR_xststdcdp - || icode == CODE_FOR_xststdcsp - || icode == CODE_FOR_xvtstdcdp - || icode == CODE_FOR_xvtstdcsp) - { - /* Only allow 7-bit unsigned literals. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST - || !IN_RANGE (TREE_INT_CST_LOW (arg1), 0, 127)) - { - error ("argument 2 must be a 7-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) - op1 = copy_to_mode_reg (mode1, op1); - - pat = GEN_FCN (icode) (target, op0, op1); - if (! pat) - return 0; - emit_insn (pat); - - return target; -} - -static rtx -altivec_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target) -{ - rtx pat, scratch; - tree cr6_form = CALL_EXPR_ARG (exp, 0); - tree arg0 = CALL_EXPR_ARG (exp, 1); - tree arg1 = CALL_EXPR_ARG (exp, 2); - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - machine_mode tmode = SImode; - machine_mode mode0 = insn_data[icode].operand[1].mode; - machine_mode mode1 = insn_data[icode].operand[2].mode; - int cr6_form_int; - - if (TREE_CODE (cr6_form) != INTEGER_CST) - { - error ("argument 1 of %qs must be a constant", - "__builtin_altivec_predicate"); - return const0_rtx; - } - else - cr6_form_int = TREE_INT_CST_LOW (cr6_form); - - gcc_assert (mode0 == mode1); - - /* If we have invalid arguments, bail out before generating bad rtl. */ - if (arg0 == error_mark_node || arg1 == error_mark_node) - return const0_rtx; - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) - op1 = copy_to_mode_reg (mode1, op1); - - /* Note that for many of the relevant operations (e.g. cmpne or - cmpeq) with float or double operands, it makes more sense for the - mode of the allocated scratch register to select a vector of - integer. But the choice to copy the mode of operand 0 was made - long ago and there are no plans to change it. */ - scratch = gen_reg_rtx (mode0); - - pat = GEN_FCN (icode) (scratch, op0, op1); - if (! pat) - return 0; - emit_insn (pat); - - /* The vec_any* and vec_all* predicates use the same opcodes for two - different operations, but the bits in CR6 will be different - depending on what information we want. So we have to play tricks - with CR6 to get the right bits out. - - If you think this is disgusting, look at the specs for the - AltiVec predicates. */ - - switch (cr6_form_int) - { - case 0: - emit_insn (gen_cr6_test_for_zero (target)); - break; - case 1: - emit_insn (gen_cr6_test_for_zero_reverse (target)); - break; - case 2: - emit_insn (gen_cr6_test_for_lt (target)); - break; - case 3: - emit_insn (gen_cr6_test_for_lt_reverse (target)); - break; - default: - error ("argument 1 of %qs is out of range", - "__builtin_altivec_predicate"); - break; - } - - return target; -} - -rtx -swap_endian_selector_for_mode (machine_mode mode) -{ - unsigned int swap1[16] = {15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}; - unsigned int swap2[16] = {7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8}; - unsigned int swap4[16] = {3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12}; - unsigned int swap8[16] = {1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14}; - - unsigned int *swaparray, i; - rtx perm[16]; - - switch (mode) - { - case E_V1TImode: - swaparray = swap1; - break; - case E_V2DFmode: - case E_V2DImode: - swaparray = swap2; - break; - case E_V4SFmode: - case E_V4SImode: - swaparray = swap4; - break; - case E_V8HImode: - swaparray = swap8; - break; - default: - gcc_unreachable (); - } - - for (i = 0; i < 16; ++i) - perm[i] = GEN_INT (swaparray[i]); - - return force_reg (V16QImode, gen_rtx_CONST_VECTOR (V16QImode, - gen_rtvec_v (16, perm))); -} - -static rtx -altivec_expand_lv_builtin (enum insn_code icode, tree exp, rtx target, bool blk) -{ - rtx pat, addr; - tree arg0 = CALL_EXPR_ARG (exp, 0); - tree arg1 = CALL_EXPR_ARG (exp, 1); - machine_mode tmode = insn_data[icode].operand[0].mode; - machine_mode mode0 = Pmode; - machine_mode mode1 = Pmode; - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node || arg1 == error_mark_node) - return const0_rtx; - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - op1 = copy_to_mode_reg (mode1, op1); - - /* For LVX, express the RTL accurately by ANDing the address with -16. - LVXL and LVE*X expand to use UNSPECs to hide their special behavior, - so the raw address is fine. */ - if (icode == CODE_FOR_altivec_lvx_v1ti - || icode == CODE_FOR_altivec_lvx_v2df - || icode == CODE_FOR_altivec_lvx_v2di - || icode == CODE_FOR_altivec_lvx_v4sf - || icode == CODE_FOR_altivec_lvx_v4si - || icode == CODE_FOR_altivec_lvx_v8hi - || icode == CODE_FOR_altivec_lvx_v16qi) - { - rtx rawaddr; - if (op0 == const0_rtx) - rawaddr = op1; - else - { - op0 = copy_to_mode_reg (mode0, op0); - rawaddr = gen_rtx_PLUS (Pmode, op1, op0); - } - addr = gen_rtx_AND (Pmode, rawaddr, gen_rtx_CONST_INT (Pmode, -16)); - addr = gen_rtx_MEM (blk ? BLKmode : tmode, addr); - - emit_insn (gen_rtx_SET (target, addr)); - } - else - { - if (op0 == const0_rtx) - addr = gen_rtx_MEM (blk ? BLKmode : tmode, op1); - else - { - op0 = copy_to_mode_reg (mode0, op0); - addr = gen_rtx_MEM (blk ? BLKmode : tmode, - gen_rtx_PLUS (Pmode, op1, op0)); - } - - pat = GEN_FCN (icode) (target, addr); - if (! pat) - return 0; - emit_insn (pat); - } - - return target; -} - -static rtx -altivec_expand_stxvl_builtin (enum insn_code icode, tree exp) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - tree arg1 = CALL_EXPR_ARG (exp, 1); - tree arg2 = CALL_EXPR_ARG (exp, 2); - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - rtx op2 = expand_normal (arg2); - machine_mode mode0 = insn_data[icode].operand[0].mode; - machine_mode mode1 = insn_data[icode].operand[1].mode; - machine_mode mode2 = insn_data[icode].operand[2].mode; - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return NULL_RTX; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node - || arg1 == error_mark_node - || arg2 == error_mark_node) - return NULL_RTX; - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) - op1 = copy_to_mode_reg (mode1, op1); - if (! (*insn_data[icode].operand[3].predicate) (op2, mode2)) - op2 = copy_to_mode_reg (mode2, op2); - - pat = GEN_FCN (icode) (op0, op1, op2); - if (pat) - emit_insn (pat); - - return NULL_RTX; -} - -static rtx -altivec_expand_stv_builtin (enum insn_code icode, tree exp) -{ - tree arg0 = CALL_EXPR_ARG (exp, 0); - tree arg1 = CALL_EXPR_ARG (exp, 1); - tree arg2 = CALL_EXPR_ARG (exp, 2); - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - rtx op2 = expand_normal (arg2); - rtx pat, addr, rawaddr; - machine_mode tmode = insn_data[icode].operand[0].mode; - machine_mode smode = insn_data[icode].operand[1].mode; - machine_mode mode1 = Pmode; - machine_mode mode2 = Pmode; - - /* Invalid arguments. Bail before doing anything stoopid! */ - if (arg0 == error_mark_node - || arg1 == error_mark_node - || arg2 == error_mark_node) - return const0_rtx; - - op2 = copy_to_mode_reg (mode2, op2); - - /* For STVX, express the RTL accurately by ANDing the address with -16. - STVXL and STVE*X expand to use UNSPECs to hide their special behavior, - so the raw address is fine. */ - if (icode == CODE_FOR_altivec_stvx_v2df - || icode == CODE_FOR_altivec_stvx_v2di - || icode == CODE_FOR_altivec_stvx_v4sf - || icode == CODE_FOR_altivec_stvx_v4si - || icode == CODE_FOR_altivec_stvx_v8hi - || icode == CODE_FOR_altivec_stvx_v16qi) - { - if (op1 == const0_rtx) - rawaddr = op2; - else - { - op1 = copy_to_mode_reg (mode1, op1); - rawaddr = gen_rtx_PLUS (Pmode, op2, op1); - } - - addr = gen_rtx_AND (Pmode, rawaddr, gen_rtx_CONST_INT (Pmode, -16)); - addr = gen_rtx_MEM (tmode, addr); - - op0 = copy_to_mode_reg (tmode, op0); - - emit_insn (gen_rtx_SET (addr, op0)); - } - else - { - if (! (*insn_data[icode].operand[1].predicate) (op0, smode)) - op0 = copy_to_mode_reg (smode, op0); - - if (op1 == const0_rtx) - addr = gen_rtx_MEM (tmode, op2); - else - { - op1 = copy_to_mode_reg (mode1, op1); - addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op2, op1)); - } - - pat = GEN_FCN (icode) (addr, op0); - if (pat) - emit_insn (pat); - } - - return NULL_RTX; -} - -/* Return the appropriate SPR number associated with the given builtin. */ -static inline HOST_WIDE_INT -htm_spr_num (enum rs6000_builtins code) -{ - if (code == HTM_BUILTIN_GET_TFHAR - || code == HTM_BUILTIN_SET_TFHAR) - return TFHAR_SPR; - else if (code == HTM_BUILTIN_GET_TFIAR - || code == HTM_BUILTIN_SET_TFIAR) - return TFIAR_SPR; - else if (code == HTM_BUILTIN_GET_TEXASR - || code == HTM_BUILTIN_SET_TEXASR) - return TEXASR_SPR; - gcc_assert (code == HTM_BUILTIN_GET_TEXASRU - || code == HTM_BUILTIN_SET_TEXASRU); - return TEXASRU_SPR; -} - -/* Return the correct ICODE value depending on whether we are - setting or reading the HTM SPRs. */ -static inline enum insn_code -rs6000_htm_spr_icode (bool nonvoid) -{ - if (nonvoid) - return (TARGET_POWERPC64) ? CODE_FOR_htm_mfspr_di : CODE_FOR_htm_mfspr_si; - else - return (TARGET_POWERPC64) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si; -} - -/* Expand the HTM builtin in EXP and store the result in TARGET. - Store true in *EXPANDEDP if we found a builtin to expand. */ -static rtx -htm_expand_builtin (tree exp, rtx target, bool * expandedp) -{ - tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; - enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); - const struct builtin_description *d; - size_t i; - - *expandedp = true; - - if (!TARGET_POWERPC64 - && (fcode == HTM_BUILTIN_TABORTDC - || fcode == HTM_BUILTIN_TABORTDCI)) - { - size_t uns_fcode = (size_t)fcode; - const char *name = rs6000_builtin_info[uns_fcode].name; - error ("builtin %qs is only valid in 64-bit mode", name); - return const0_rtx; - } - - /* Expand the HTM builtins. */ - d = bdesc_htm; - for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++) - if (d->code == fcode) - { - rtx op[MAX_HTM_OPERANDS], pat; - int nopnds = 0; - tree arg; - call_expr_arg_iterator iter; - unsigned attr = rs6000_builtin_info[fcode].attr; - enum insn_code icode = d->icode; - const struct insn_operand_data *insn_op; - bool uses_spr = (attr & RS6000_BTC_SPR); - rtx cr = NULL_RTX; - - if (uses_spr) - icode = rs6000_htm_spr_icode (nonvoid); - insn_op = &insn_data[icode].operand[0]; - - if (nonvoid) - { - machine_mode tmode = (uses_spr) ? insn_op->mode : E_SImode; - if (!target - || GET_MODE (target) != tmode - || (uses_spr && !(*insn_op->predicate) (target, tmode))) - target = gen_reg_rtx (tmode); - if (uses_spr) - op[nopnds++] = target; - } - - FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) - { - if (arg == error_mark_node || nopnds >= MAX_HTM_OPERANDS) - return const0_rtx; - - insn_op = &insn_data[icode].operand[nopnds]; - - op[nopnds] = expand_normal (arg); - - if (!(*insn_op->predicate) (op[nopnds], insn_op->mode)) - { - if (!strcmp (insn_op->constraint, "n")) - { - int arg_num = (nonvoid) ? nopnds : nopnds + 1; - if (!CONST_INT_P (op[nopnds])) - error ("argument %d must be an unsigned literal", arg_num); - else - error ("argument %d is an unsigned literal that is " - "out of range", arg_num); - return const0_rtx; - } - op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]); - } - - nopnds++; - } - - /* Handle the builtins for extended mnemonics. These accept - no arguments, but map to builtins that take arguments. */ - switch (fcode) - { - case HTM_BUILTIN_TENDALL: /* Alias for: tend. 1 */ - case HTM_BUILTIN_TRESUME: /* Alias for: tsr. 1 */ - op[nopnds++] = GEN_INT (1); - if (flag_checking) - attr |= RS6000_BTC_UNARY; - break; - case HTM_BUILTIN_TSUSPEND: /* Alias for: tsr. 0 */ - op[nopnds++] = GEN_INT (0); - if (flag_checking) - attr |= RS6000_BTC_UNARY; - break; - default: - break; - } - - /* If this builtin accesses SPRs, then pass in the appropriate - SPR number and SPR regno as the last two operands. */ - if (uses_spr) - { - machine_mode mode = (TARGET_POWERPC64) ? DImode : SImode; - op[nopnds++] = gen_rtx_CONST_INT (mode, htm_spr_num (fcode)); - } - /* If this builtin accesses a CR, then pass in a scratch - CR as the last operand. */ - else if (attr & RS6000_BTC_CR) - { cr = gen_reg_rtx (CCmode); - op[nopnds++] = cr; - } - - if (flag_checking) - { - int expected_nopnds = 0; - if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_UNARY) - expected_nopnds = 1; - else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_BINARY) - expected_nopnds = 2; - else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_TERNARY) - expected_nopnds = 3; - if (!(attr & RS6000_BTC_VOID)) - expected_nopnds += 1; - if (uses_spr) - expected_nopnds += 1; - - gcc_assert (nopnds == expected_nopnds - && nopnds <= MAX_HTM_OPERANDS); - } - - switch (nopnds) - { - case 1: - pat = GEN_FCN (icode) (op[0]); - break; - case 2: - pat = GEN_FCN (icode) (op[0], op[1]); - break; - case 3: - pat = GEN_FCN (icode) (op[0], op[1], op[2]); - break; - case 4: - pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]); - break; - default: - gcc_unreachable (); - } - if (!pat) - return NULL_RTX; - emit_insn (pat); - - if (attr & RS6000_BTC_CR) - { - if (fcode == HTM_BUILTIN_TBEGIN) - { - /* Emit code to set TARGET to true or false depending on - whether the tbegin. instruction successfully or failed - to start a transaction. We do this by placing the 1's - complement of CR's EQ bit into TARGET. */ - rtx scratch = gen_reg_rtx (SImode); - emit_insn (gen_rtx_SET (scratch, - gen_rtx_EQ (SImode, cr, - const0_rtx))); - emit_insn (gen_rtx_SET (target, - gen_rtx_XOR (SImode, scratch, - GEN_INT (1)))); - } - else - { - /* Emit code to copy the 4-bit condition register field - CR into the least significant end of register TARGET. */ - rtx scratch1 = gen_reg_rtx (SImode); - rtx scratch2 = gen_reg_rtx (SImode); - rtx subreg = simplify_gen_subreg (CCmode, scratch1, SImode, 0); - emit_insn (gen_movcc (subreg, cr)); - emit_insn (gen_lshrsi3 (scratch2, scratch1, GEN_INT (28))); - emit_insn (gen_andsi3 (target, scratch2, GEN_INT (0xf))); - } - } - - if (nonvoid) - return target; - return const0_rtx; - } - - *expandedp = false; - return NULL_RTX; -} - -/* Expand the CPU builtin in FCODE and store the result in TARGET. */ - -static rtx -cpu_expand_builtin (enum rs6000_builtins fcode, tree exp ATTRIBUTE_UNUSED, - rtx target) -{ - /* __builtin_cpu_init () is a nop, so expand to nothing. */ - if (fcode == RS6000_BUILTIN_CPU_INIT) - return const0_rtx; - - if (target == 0 || GET_MODE (target) != SImode) - target = gen_reg_rtx (SImode); - -#ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB - tree arg = TREE_OPERAND (CALL_EXPR_ARG (exp, 0), 0); - /* Target clones creates an ARRAY_REF instead of STRING_CST, convert it back - to a STRING_CST. */ - if (TREE_CODE (arg) == ARRAY_REF - && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST - && TREE_CODE (TREE_OPERAND (arg, 1)) == INTEGER_CST - && compare_tree_int (TREE_OPERAND (arg, 1), 0) == 0) - arg = TREE_OPERAND (arg, 0); - - if (TREE_CODE (arg) != STRING_CST) - { - error ("builtin %qs only accepts a string argument", - rs6000_builtin_info[(size_t) fcode].name); - return const0_rtx; - } - - if (fcode == RS6000_BUILTIN_CPU_IS) - { - const char *cpu = TREE_STRING_POINTER (arg); - rtx cpuid = NULL_RTX; - for (size_t i = 0; i < ARRAY_SIZE (cpu_is_info); i++) - if (strcmp (cpu, cpu_is_info[i].cpu) == 0) - { - /* The CPUID value in the TCB is offset by _DL_FIRST_PLATFORM. */ - cpuid = GEN_INT (cpu_is_info[i].cpuid + _DL_FIRST_PLATFORM); - break; - } - if (cpuid == NULL_RTX) - { - /* Invalid CPU argument. */ - error ("cpu %qs is an invalid argument to builtin %qs", - cpu, rs6000_builtin_info[(size_t) fcode].name); - return const0_rtx; - } - - rtx platform = gen_reg_rtx (SImode); - rtx tcbmem = gen_const_mem (SImode, - gen_rtx_PLUS (Pmode, - gen_rtx_REG (Pmode, TLS_REGNUM), - GEN_INT (TCB_PLATFORM_OFFSET))); - emit_move_insn (platform, tcbmem); - emit_insn (gen_eqsi3 (target, platform, cpuid)); - } - else if (fcode == RS6000_BUILTIN_CPU_SUPPORTS) - { - const char *hwcap = TREE_STRING_POINTER (arg); - rtx mask = NULL_RTX; - int hwcap_offset; - for (size_t i = 0; i < ARRAY_SIZE (cpu_supports_info); i++) - if (strcmp (hwcap, cpu_supports_info[i].hwcap) == 0) - { - mask = GEN_INT (cpu_supports_info[i].mask); - hwcap_offset = TCB_HWCAP_OFFSET (cpu_supports_info[i].id); - break; - } - if (mask == NULL_RTX) - { - /* Invalid HWCAP argument. */ - error ("%s %qs is an invalid argument to builtin %qs", - "hwcap", hwcap, rs6000_builtin_info[(size_t) fcode].name); - return const0_rtx; - } - - rtx tcb_hwcap = gen_reg_rtx (SImode); - rtx tcbmem = gen_const_mem (SImode, - gen_rtx_PLUS (Pmode, - gen_rtx_REG (Pmode, TLS_REGNUM), - GEN_INT (hwcap_offset))); - emit_move_insn (tcb_hwcap, tcbmem); - rtx scratch1 = gen_reg_rtx (SImode); - emit_insn (gen_rtx_SET (scratch1, gen_rtx_AND (SImode, tcb_hwcap, mask))); - rtx scratch2 = gen_reg_rtx (SImode); - emit_insn (gen_eqsi3 (scratch2, scratch1, const0_rtx)); - emit_insn (gen_rtx_SET (target, gen_rtx_XOR (SImode, scratch2, const1_rtx))); - } - else - gcc_unreachable (); - - /* Record that we have expanded a CPU builtin, so that we can later - emit a reference to the special symbol exported by LIBC to ensure we - do not link against an old LIBC that doesn't support this feature. */ - cpu_builtin_p = true; - -#else - warning (0, "builtin %qs needs GLIBC (2.23 and newer) that exports hardware " - "capability bits", rs6000_builtin_info[(size_t) fcode].name); - - /* For old LIBCs, always return FALSE. */ - emit_move_insn (target, GEN_INT (0)); -#endif /* TARGET_LIBC_PROVIDES_HWCAP_IN_TCB */ - - return target; -} - -static rtx -rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target) -{ - rtx pat; - tree arg0 = CALL_EXPR_ARG (exp, 0); - tree arg1 = CALL_EXPR_ARG (exp, 1); - tree arg2 = CALL_EXPR_ARG (exp, 2); - rtx op0 = expand_normal (arg0); - rtx op1 = expand_normal (arg1); - rtx op2 = expand_normal (arg2); - machine_mode tmode = insn_data[icode].operand[0].mode; - machine_mode mode0 = insn_data[icode].operand[1].mode; - machine_mode mode1 = insn_data[icode].operand[2].mode; - machine_mode mode2 = insn_data[icode].operand[3].mode; - - if (icode == CODE_FOR_nothing) - /* Builtin not supported on this processor. */ - return 0; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node - || arg1 == error_mark_node - || arg2 == error_mark_node) - return const0_rtx; - - /* Check and prepare argument depending on the instruction code. - - Note that a switch statement instead of the sequence of tests - would be incorrect as many of the CODE_FOR values could be - CODE_FOR_nothing and that would yield multiple alternatives - with identical values. We'd never reach here at runtime in - this case. */ - if (icode == CODE_FOR_altivec_vsldoi_v4sf - || icode == CODE_FOR_altivec_vsldoi_v2df - || icode == CODE_FOR_altivec_vsldoi_v4si - || icode == CODE_FOR_altivec_vsldoi_v8hi - || icode == CODE_FOR_altivec_vsldoi_v16qi) - { - /* Only allow 4-bit unsigned literals. */ - STRIP_NOPS (arg2); - if (TREE_CODE (arg2) != INTEGER_CST - || TREE_INT_CST_LOW (arg2) & ~0xf) - { - error ("argument 3 must be a 4-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_vsx_xxpermdi_v2df - || icode == CODE_FOR_vsx_xxpermdi_v2di - || icode == CODE_FOR_vsx_xxpermdi_v2df_be - || icode == CODE_FOR_vsx_xxpermdi_v2di_be - || icode == CODE_FOR_vsx_xxpermdi_v1ti - || icode == CODE_FOR_vsx_xxpermdi_v4sf - || icode == CODE_FOR_vsx_xxpermdi_v4si - || icode == CODE_FOR_vsx_xxpermdi_v8hi - || icode == CODE_FOR_vsx_xxpermdi_v16qi - || icode == CODE_FOR_vsx_xxsldwi_v16qi - || icode == CODE_FOR_vsx_xxsldwi_v8hi - || icode == CODE_FOR_vsx_xxsldwi_v4si - || icode == CODE_FOR_vsx_xxsldwi_v4sf - || icode == CODE_FOR_vsx_xxsldwi_v2di - || icode == CODE_FOR_vsx_xxsldwi_v2df) - { - /* Only allow 2-bit unsigned literals. */ - STRIP_NOPS (arg2); - if (TREE_CODE (arg2) != INTEGER_CST - || TREE_INT_CST_LOW (arg2) & ~0x3) - { - error ("argument 3 must be a 2-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_vsx_set_v2df - || icode == CODE_FOR_vsx_set_v2di - || icode == CODE_FOR_bcdadd - || icode == CODE_FOR_bcdadd_lt - || icode == CODE_FOR_bcdadd_eq - || icode == CODE_FOR_bcdadd_gt - || icode == CODE_FOR_bcdsub - || icode == CODE_FOR_bcdsub_lt - || icode == CODE_FOR_bcdsub_eq - || icode == CODE_FOR_bcdsub_gt) - { - /* Only allow 1-bit unsigned literals. */ - STRIP_NOPS (arg2); - if (TREE_CODE (arg2) != INTEGER_CST - || TREE_INT_CST_LOW (arg2) & ~0x1) - { - error ("argument 3 must be a 1-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_dfp_ddedpd_dd - || icode == CODE_FOR_dfp_ddedpd_td) - { - /* Only allow 2-bit unsigned literals where the value is 0 or 2. */ - STRIP_NOPS (arg0); - if (TREE_CODE (arg0) != INTEGER_CST - || TREE_INT_CST_LOW (arg2) & ~0x3) - { - error ("argument 1 must be 0 or 2"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_dfp_denbcd_dd - || icode == CODE_FOR_dfp_denbcd_td) - { - /* Only allow 1-bit unsigned literals. */ - STRIP_NOPS (arg0); - if (TREE_CODE (arg0) != INTEGER_CST - || TREE_INT_CST_LOW (arg0) & ~0x1) - { - error ("argument 1 must be a 1-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_dfp_dscli_dd - || icode == CODE_FOR_dfp_dscli_td - || icode == CODE_FOR_dfp_dscri_dd - || icode == CODE_FOR_dfp_dscri_td) - { - /* Only allow 6-bit unsigned literals. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST - || TREE_INT_CST_LOW (arg1) & ~0x3f) - { - error ("argument 2 must be a 6-bit unsigned literal"); - return CONST0_RTX (tmode); - } - } - else if (icode == CODE_FOR_crypto_vshasigmaw - || icode == CODE_FOR_crypto_vshasigmad) - { - /* Check whether the 2nd and 3rd arguments are integer constants and in - range and prepare arguments. */ - STRIP_NOPS (arg1); - if (TREE_CODE (arg1) != INTEGER_CST || wi::geu_p (wi::to_wide (arg1), 2)) - { - error ("argument 2 must be 0 or 1"); - return CONST0_RTX (tmode); - } - - STRIP_NOPS (arg2); - if (TREE_CODE (arg2) != INTEGER_CST - || wi::geu_p (wi::to_wide (arg2), 16)) - { - error ("argument 3 must be in the range [0, 15]"); - return CONST0_RTX (tmode); - } - } - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) - op1 = copy_to_mode_reg (mode1, op1); - if (! (*insn_data[icode].operand[3].predicate) (op2, mode2)) - op2 = copy_to_mode_reg (mode2, op2); - - pat = GEN_FCN (icode) (target, op0, op1, op2); - if (! pat) - return 0; - emit_insn (pat); - - return target; -} - - -/* Expand the dst builtins. */ -static rtx -altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, - bool *expandedp) -{ - tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); - tree arg0, arg1, arg2; - machine_mode mode0, mode1; - rtx pat, op0, op1, op2; - const struct builtin_description *d; - size_t i; - - *expandedp = false; - - /* Handle DST variants. */ - d = bdesc_dst; - for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++) - if (d->code == fcode) - { - arg0 = CALL_EXPR_ARG (exp, 0); - arg1 = CALL_EXPR_ARG (exp, 1); - arg2 = CALL_EXPR_ARG (exp, 2); - op0 = expand_normal (arg0); - op1 = expand_normal (arg1); - op2 = expand_normal (arg2); - mode0 = insn_data[d->icode].operand[0].mode; - mode1 = insn_data[d->icode].operand[1].mode; - - /* Invalid arguments, bail out before generating bad rtl. */ - if (arg0 == error_mark_node - || arg1 == error_mark_node - || arg2 == error_mark_node) - return const0_rtx; - - *expandedp = true; - STRIP_NOPS (arg2); - if (TREE_CODE (arg2) != INTEGER_CST - || TREE_INT_CST_LOW (arg2) & ~0x3) - { - error ("argument to %qs must be a 2-bit unsigned literal", d->name); - return const0_rtx; - } - - if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (Pmode, op0); - if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1)) - op1 = copy_to_mode_reg (mode1, op1); - - pat = GEN_FCN (d->icode) (op0, op1, op2); - if (pat != 0) - emit_insn (pat); - - return NULL_RTX; - } - - return NULL_RTX; -} - -/* Expand vec_init builtin. */ -static rtx -altivec_expand_vec_init_builtin (tree type, tree exp, rtx target) -{ - machine_mode tmode = TYPE_MODE (type); - machine_mode inner_mode = GET_MODE_INNER (tmode); - int i, n_elt = GET_MODE_NUNITS (tmode); - - gcc_assert (VECTOR_MODE_P (tmode)); - gcc_assert (n_elt == call_expr_nargs (exp)); - - if (!target || !register_operand (target, tmode)) - target = gen_reg_rtx (tmode); - - /* If we have a vector compromised of a single element, such as V1TImode, do - the initialization directly. */ - if (n_elt == 1 && GET_MODE_SIZE (tmode) == GET_MODE_SIZE (inner_mode)) - { - rtx x = expand_normal (CALL_EXPR_ARG (exp, 0)); - emit_move_insn (target, gen_lowpart (tmode, x)); - } - else - { - rtvec v = rtvec_alloc (n_elt); - - for (i = 0; i < n_elt; ++i) - { - rtx x = expand_normal (CALL_EXPR_ARG (exp, i)); - RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x); - } - - rs6000_expand_vector_init (target, gen_rtx_PARALLEL (tmode, v)); - } - - return target; -} - -/* Return the integer constant in ARG. Constrain it to be in the range - of the subparts of VEC_TYPE; issue an error if not. */ - -static int -get_element_number (tree vec_type, tree arg) -{ - unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1; - - if (!tree_fits_uhwi_p (arg) - || (elt = tree_to_uhwi (arg), elt > max)) - { - error ("selector must be an integer constant in the range [0, %wi]", max); - return 0; - } - - return elt; -} - -/* Expand vec_set builtin. */ -static rtx -altivec_expand_vec_set_builtin (tree exp) -{ - machine_mode tmode, mode1; - tree arg0, arg1, arg2; - int elt; - rtx op0, op1; - - arg0 = CALL_EXPR_ARG (exp, 0); - arg1 = CALL_EXPR_ARG (exp, 1); - arg2 = CALL_EXPR_ARG (exp, 2); - - tmode = TYPE_MODE (TREE_TYPE (arg0)); - mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))); - gcc_assert (VECTOR_MODE_P (tmode)); - - op0 = expand_expr (arg0, NULL_RTX, tmode, EXPAND_NORMAL); - op1 = expand_expr (arg1, NULL_RTX, mode1, EXPAND_NORMAL); - elt = get_element_number (TREE_TYPE (arg0), arg2); - - if (GET_MODE (op1) != mode1 && GET_MODE (op1) != VOIDmode) - op1 = convert_modes (mode1, GET_MODE (op1), op1, true); - - op0 = force_reg (tmode, op0); - op1 = force_reg (mode1, op1); - - rs6000_expand_vector_set (op0, op1, elt); - - return op0; -} - -/* Expand vec_ext builtin. */ -static rtx -altivec_expand_vec_ext_builtin (tree exp, rtx target) -{ - machine_mode tmode, mode0; - tree arg0, arg1; - rtx op0; - rtx op1; - - arg0 = CALL_EXPR_ARG (exp, 0); - arg1 = CALL_EXPR_ARG (exp, 1); - - op0 = expand_normal (arg0); - op1 = expand_normal (arg1); - - if (TREE_CODE (arg1) == INTEGER_CST) - { - unsigned HOST_WIDE_INT elt; - unsigned HOST_WIDE_INT size = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); - unsigned int truncated_selector; - /* Even if !tree_fits_uhwi_p (arg1)), TREE_INT_CST_LOW (arg0) - returns low-order bits of INTEGER_CST for modulo indexing. */ - elt = TREE_INT_CST_LOW (arg1); - truncated_selector = elt % size; - op1 = GEN_INT (truncated_selector); - } - - tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))); - mode0 = TYPE_MODE (TREE_TYPE (arg0)); - gcc_assert (VECTOR_MODE_P (mode0)); - - op0 = force_reg (mode0, op0); - - if (optimize || !target || !register_operand (target, tmode)) - target = gen_reg_rtx (tmode); - - rs6000_expand_vector_extract (target, op0, op1); - - return target; -} - -/* Expand the builtin in EXP and store the result in TARGET. Store - true in *EXPANDEDP if we found a builtin to expand. */ -static rtx -altivec_expand_builtin (tree exp, rtx target, bool *expandedp) -{ - const struct builtin_description *d; - size_t i; - enum insn_code icode; - tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - tree arg0, arg1, arg2; - rtx op0, pat; - machine_mode tmode, mode0; - enum rs6000_builtins fcode - = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); - - if (rs6000_overloaded_builtin_p (fcode)) - { - *expandedp = true; - error ("unresolved overload for Altivec builtin %qF", fndecl); - - /* Given it is invalid, just generate a normal call. */ - return expand_call (exp, target, false); - } - - target = altivec_expand_dst_builtin (exp, target, expandedp); - if (*expandedp) - return target; - - *expandedp = true; - - switch (fcode) - { - case ALTIVEC_BUILTIN_STVX_V2DF: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v2df, exp); - case ALTIVEC_BUILTIN_STVX_V2DI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v2di, exp); - case ALTIVEC_BUILTIN_STVX_V4SF: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v4sf, exp); - case ALTIVEC_BUILTIN_STVX: - case ALTIVEC_BUILTIN_STVX_V4SI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v4si, exp); - case ALTIVEC_BUILTIN_STVX_V8HI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v8hi, exp); - case ALTIVEC_BUILTIN_STVX_V16QI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx_v16qi, exp); - case ALTIVEC_BUILTIN_STVEBX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, exp); - case ALTIVEC_BUILTIN_STVEHX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, exp); - case ALTIVEC_BUILTIN_STVEWX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, exp); - case ALTIVEC_BUILTIN_STVXL_V2DF: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v2df, exp); - case ALTIVEC_BUILTIN_STVXL_V2DI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v2di, exp); - case ALTIVEC_BUILTIN_STVXL_V4SF: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v4sf, exp); - case ALTIVEC_BUILTIN_STVXL: - case ALTIVEC_BUILTIN_STVXL_V4SI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v4si, exp); - case ALTIVEC_BUILTIN_STVXL_V8HI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v8hi, exp); - case ALTIVEC_BUILTIN_STVXL_V16QI: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl_v16qi, exp); - - case ALTIVEC_BUILTIN_STVLX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvlx, exp); - case ALTIVEC_BUILTIN_STVLXL: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvlxl, exp); - case ALTIVEC_BUILTIN_STVRX: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvrx, exp); - case ALTIVEC_BUILTIN_STVRXL: - return altivec_expand_stv_builtin (CODE_FOR_altivec_stvrxl, exp); - - case P9V_BUILTIN_STXVL: - return altivec_expand_stxvl_builtin (CODE_FOR_stxvl, exp); - - case P9V_BUILTIN_XST_LEN_R: - return altivec_expand_stxvl_builtin (CODE_FOR_xst_len_r, exp); - - case VSX_BUILTIN_STXVD2X_V1TI: - return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v1ti, exp); - case VSX_BUILTIN_STXVD2X_V2DF: - return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v2df, exp); - case VSX_BUILTIN_STXVD2X_V2DI: - return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v2di, exp); - case VSX_BUILTIN_STXVW4X_V4SF: - return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v4sf, exp); - case VSX_BUILTIN_STXVW4X_V4SI: - return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v4si, exp); - case VSX_BUILTIN_STXVW4X_V8HI: - return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v8hi, exp); - case VSX_BUILTIN_STXVW4X_V16QI: - return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v16qi, exp); - - /* For the following on big endian, it's ok to use any appropriate - unaligned-supporting store, so use a generic expander. For - little-endian, the exact element-reversing instruction must - be used. */ - case VSX_BUILTIN_ST_ELEMREV_V1TI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v1ti - : CODE_FOR_vsx_st_elemrev_v1ti); - return altivec_expand_stv_builtin (code, exp); - } - case VSX_BUILTIN_ST_ELEMREV_V2DF: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v2df - : CODE_FOR_vsx_st_elemrev_v2df); - return altivec_expand_stv_builtin (code, exp); - } - case VSX_BUILTIN_ST_ELEMREV_V2DI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v2di - : CODE_FOR_vsx_st_elemrev_v2di); - return altivec_expand_stv_builtin (code, exp); - } - case VSX_BUILTIN_ST_ELEMREV_V4SF: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v4sf - : CODE_FOR_vsx_st_elemrev_v4sf); - return altivec_expand_stv_builtin (code, exp); - } - case VSX_BUILTIN_ST_ELEMREV_V4SI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v4si - : CODE_FOR_vsx_st_elemrev_v4si); - return altivec_expand_stv_builtin (code, exp); - } - case VSX_BUILTIN_ST_ELEMREV_V8HI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v8hi - : CODE_FOR_vsx_st_elemrev_v8hi); - return altivec_expand_stv_builtin (code, exp); - } - case VSX_BUILTIN_ST_ELEMREV_V16QI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_store_v16qi - : CODE_FOR_vsx_st_elemrev_v16qi); - return altivec_expand_stv_builtin (code, exp); - } - - case ALTIVEC_BUILTIN_MFVSCR: - icode = CODE_FOR_altivec_mfvscr; - tmode = insn_data[icode].operand[0].mode; - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - pat = GEN_FCN (icode) (target); - if (! pat) - return 0; - emit_insn (pat); - return target; - - case ALTIVEC_BUILTIN_MTVSCR: - icode = CODE_FOR_altivec_mtvscr; - arg0 = CALL_EXPR_ARG (exp, 0); - op0 = expand_normal (arg0); - mode0 = insn_data[icode].operand[0].mode; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node) - return const0_rtx; - - if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - pat = GEN_FCN (icode) (op0); - if (pat) - emit_insn (pat); - return NULL_RTX; - - case ALTIVEC_BUILTIN_DSSALL: - emit_insn (gen_altivec_dssall ()); - return NULL_RTX; - - case ALTIVEC_BUILTIN_DSS: - icode = CODE_FOR_altivec_dss; - arg0 = CALL_EXPR_ARG (exp, 0); - STRIP_NOPS (arg0); - op0 = expand_normal (arg0); - mode0 = insn_data[icode].operand[0].mode; - - /* If we got invalid arguments bail out before generating bad rtl. */ - if (arg0 == error_mark_node) - return const0_rtx; - - if (TREE_CODE (arg0) != INTEGER_CST - || TREE_INT_CST_LOW (arg0) & ~0x3) - { - error ("argument to %qs must be a 2-bit unsigned literal", "dss"); - return const0_rtx; - } - - if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) - op0 = copy_to_mode_reg (mode0, op0); - - emit_insn (gen_altivec_dss (op0)); - return NULL_RTX; - - case ALTIVEC_BUILTIN_VEC_INIT_V4SI: - case ALTIVEC_BUILTIN_VEC_INIT_V8HI: - case ALTIVEC_BUILTIN_VEC_INIT_V16QI: - case ALTIVEC_BUILTIN_VEC_INIT_V4SF: - case VSX_BUILTIN_VEC_INIT_V2DF: - case VSX_BUILTIN_VEC_INIT_V2DI: - case VSX_BUILTIN_VEC_INIT_V1TI: - return altivec_expand_vec_init_builtin (TREE_TYPE (exp), exp, target); - - case ALTIVEC_BUILTIN_VEC_SET_V4SI: - case ALTIVEC_BUILTIN_VEC_SET_V8HI: - case ALTIVEC_BUILTIN_VEC_SET_V16QI: - case ALTIVEC_BUILTIN_VEC_SET_V4SF: - case VSX_BUILTIN_VEC_SET_V2DF: - case VSX_BUILTIN_VEC_SET_V2DI: - case VSX_BUILTIN_VEC_SET_V1TI: - return altivec_expand_vec_set_builtin (exp); - - case ALTIVEC_BUILTIN_VEC_EXT_V4SI: - case ALTIVEC_BUILTIN_VEC_EXT_V8HI: - case ALTIVEC_BUILTIN_VEC_EXT_V16QI: - case ALTIVEC_BUILTIN_VEC_EXT_V4SF: - case VSX_BUILTIN_VEC_EXT_V2DF: - case VSX_BUILTIN_VEC_EXT_V2DI: - case VSX_BUILTIN_VEC_EXT_V1TI: - return altivec_expand_vec_ext_builtin (exp, target); - - case P9V_BUILTIN_VEC_EXTRACT4B: - arg1 = CALL_EXPR_ARG (exp, 1); - STRIP_NOPS (arg1); - - /* Generate a normal call if it is invalid. */ - if (arg1 == error_mark_node) - return expand_call (exp, target, false); - - if (TREE_CODE (arg1) != INTEGER_CST || TREE_INT_CST_LOW (arg1) > 12) - { - error ("second argument to %qs must be [0, 12]", "vec_vextract4b"); - return expand_call (exp, target, false); - } - break; - - case P9V_BUILTIN_VEC_INSERT4B: - arg2 = CALL_EXPR_ARG (exp, 2); - STRIP_NOPS (arg2); - - /* Generate a normal call if it is invalid. */ - if (arg2 == error_mark_node) - return expand_call (exp, target, false); - - if (TREE_CODE (arg2) != INTEGER_CST || TREE_INT_CST_LOW (arg2) > 12) - { - error ("third argument to %qs must be [0, 12]", "vec_vinsert4b"); - return expand_call (exp, target, false); - } - break; - - default: - break; - /* Fall through. */ - } - - /* Expand abs* operations. */ - d = bdesc_abs; - for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++) - if (d->code == fcode) - return altivec_expand_abs_builtin (d->icode, exp, target); - - /* Expand the AltiVec predicates. */ - d = bdesc_altivec_preds; - for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, d++) - if (d->code == fcode) - return altivec_expand_predicate_builtin (d->icode, exp, target); - - /* LV* are funky. We initialized them differently. */ - switch (fcode) - { - case ALTIVEC_BUILTIN_LVSL: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsl, - exp, target, false); - case ALTIVEC_BUILTIN_LVSR: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsr, - exp, target, false); - case ALTIVEC_BUILTIN_LVEBX: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvebx, - exp, target, false); - case ALTIVEC_BUILTIN_LVEHX: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvehx, - exp, target, false); - case ALTIVEC_BUILTIN_LVEWX: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvewx, - exp, target, false); - case ALTIVEC_BUILTIN_LVXL_V2DF: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v2df, - exp, target, false); - case ALTIVEC_BUILTIN_LVXL_V2DI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v2di, - exp, target, false); - case ALTIVEC_BUILTIN_LVXL_V4SF: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v4sf, - exp, target, false); - case ALTIVEC_BUILTIN_LVXL: - case ALTIVEC_BUILTIN_LVXL_V4SI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v4si, - exp, target, false); - case ALTIVEC_BUILTIN_LVXL_V8HI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v8hi, - exp, target, false); - case ALTIVEC_BUILTIN_LVXL_V16QI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl_v16qi, - exp, target, false); - case ALTIVEC_BUILTIN_LVX_V1TI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v1ti, - exp, target, false); - case ALTIVEC_BUILTIN_LVX_V2DF: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v2df, - exp, target, false); - case ALTIVEC_BUILTIN_LVX_V2DI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v2di, - exp, target, false); - case ALTIVEC_BUILTIN_LVX_V4SF: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v4sf, - exp, target, false); - case ALTIVEC_BUILTIN_LVX: - case ALTIVEC_BUILTIN_LVX_V4SI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v4si, - exp, target, false); - case ALTIVEC_BUILTIN_LVX_V8HI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v8hi, - exp, target, false); - case ALTIVEC_BUILTIN_LVX_V16QI: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx_v16qi, - exp, target, false); - case ALTIVEC_BUILTIN_LVLX: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvlx, - exp, target, true); - case ALTIVEC_BUILTIN_LVLXL: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvlxl, - exp, target, true); - case ALTIVEC_BUILTIN_LVRX: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvrx, - exp, target, true); - case ALTIVEC_BUILTIN_LVRXL: - return altivec_expand_lv_builtin (CODE_FOR_altivec_lvrxl, - exp, target, true); - case VSX_BUILTIN_LXVD2X_V1TI: - return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v1ti, - exp, target, false); - case VSX_BUILTIN_LXVD2X_V2DF: - return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v2df, - exp, target, false); - case VSX_BUILTIN_LXVD2X_V2DI: - return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v2di, - exp, target, false); - case VSX_BUILTIN_LXVW4X_V4SF: - return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v4sf, - exp, target, false); - case VSX_BUILTIN_LXVW4X_V4SI: - return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v4si, - exp, target, false); - case VSX_BUILTIN_LXVW4X_V8HI: - return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v8hi, - exp, target, false); - case VSX_BUILTIN_LXVW4X_V16QI: - return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v16qi, - exp, target, false); - /* For the following on big endian, it's ok to use any appropriate - unaligned-supporting load, so use a generic expander. For - little-endian, the exact element-reversing instruction must - be used. */ - case VSX_BUILTIN_LD_ELEMREV_V2DF: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v2df - : CODE_FOR_vsx_ld_elemrev_v2df); - return altivec_expand_lv_builtin (code, exp, target, false); - } - case VSX_BUILTIN_LD_ELEMREV_V1TI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v1ti - : CODE_FOR_vsx_ld_elemrev_v1ti); - return altivec_expand_lv_builtin (code, exp, target, false); - } - case VSX_BUILTIN_LD_ELEMREV_V2DI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v2di - : CODE_FOR_vsx_ld_elemrev_v2di); - return altivec_expand_lv_builtin (code, exp, target, false); - } - case VSX_BUILTIN_LD_ELEMREV_V4SF: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v4sf - : CODE_FOR_vsx_ld_elemrev_v4sf); - return altivec_expand_lv_builtin (code, exp, target, false); - } - case VSX_BUILTIN_LD_ELEMREV_V4SI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v4si - : CODE_FOR_vsx_ld_elemrev_v4si); - return altivec_expand_lv_builtin (code, exp, target, false); - } - case VSX_BUILTIN_LD_ELEMREV_V8HI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v8hi - : CODE_FOR_vsx_ld_elemrev_v8hi); - return altivec_expand_lv_builtin (code, exp, target, false); - } - case VSX_BUILTIN_LD_ELEMREV_V16QI: - { - enum insn_code code = (BYTES_BIG_ENDIAN ? CODE_FOR_vsx_load_v16qi - : CODE_FOR_vsx_ld_elemrev_v16qi); - return altivec_expand_lv_builtin (code, exp, target, false); - } - break; - default: - break; - /* Fall through. */ - } - - *expandedp = false; - return NULL_RTX; -} - -/* Check whether a builtin function is supported in this target - configuration. */ -bool -rs6000_builtin_is_supported_p (enum rs6000_builtins fncode) -{ - HOST_WIDE_INT fnmask = rs6000_builtin_info[fncode].mask; - if ((fnmask & rs6000_builtin_mask) != fnmask) - return false; - else - return true; -} - -/* Raise an error message for a builtin function that is called without the - appropriate target options being set. */ - -static void -rs6000_invalid_builtin (enum rs6000_builtins fncode) -{ - size_t uns_fncode = (size_t) fncode; - const char *name = rs6000_builtin_info[uns_fncode].name; - HOST_WIDE_INT fnmask = rs6000_builtin_info[uns_fncode].mask; - - gcc_assert (name != NULL); - if ((fnmask & RS6000_BTM_CELL) != 0) - error ("%qs is only valid for the cell processor", name); - else if ((fnmask & RS6000_BTM_VSX) != 0) - error ("%qs requires the %qs option", name, "-mvsx"); - else if ((fnmask & RS6000_BTM_HTM) != 0) - error ("%qs requires the %qs option", name, "-mhtm"); - else if ((fnmask & RS6000_BTM_ALTIVEC) != 0) - error ("%qs requires the %qs option", name, "-maltivec"); - else if ((fnmask & (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) - == (RS6000_BTM_DFP | RS6000_BTM_P8_VECTOR)) - error ("%qs requires the %qs and %qs options", name, "-mhard-dfp", - "-mpower8-vector"); - else if ((fnmask & RS6000_BTM_DFP) != 0) - error ("%qs requires the %qs option", name, "-mhard-dfp"); - else if ((fnmask & RS6000_BTM_P8_VECTOR) != 0) - error ("%qs requires the %qs option", name, "-mpower8-vector"); - else if ((fnmask & (RS6000_BTM_P9_VECTOR | RS6000_BTM_64BIT)) - == (RS6000_BTM_P9_VECTOR | RS6000_BTM_64BIT)) - error ("%qs requires the %qs and %qs options", name, "-mcpu=power9", - "-m64"); - else if ((fnmask & RS6000_BTM_P9_VECTOR) != 0) - error ("%qs requires the %qs option", name, "-mcpu=power9"); - else if ((fnmask & (RS6000_BTM_P9_MISC | RS6000_BTM_64BIT)) - == (RS6000_BTM_P9_MISC | RS6000_BTM_64BIT)) - error ("%qs requires the %qs and %qs options", name, "-mcpu=power9", - "-m64"); - else if ((fnmask & RS6000_BTM_P9_MISC) == RS6000_BTM_P9_MISC) - error ("%qs requires the %qs option", name, "-mcpu=power9"); - else if ((fnmask & RS6000_BTM_LDBL128) == RS6000_BTM_LDBL128) - { - if (!TARGET_HARD_FLOAT) - error ("%qs requires the %qs option", name, "-mhard-float"); - else - error ("%qs requires the %qs option", name, - TARGET_IEEEQUAD ? "-mabi=ibmlongdouble" : "-mlong-double-128"); - } - else if ((fnmask & RS6000_BTM_HARD_FLOAT) != 0) - error ("%qs requires the %qs option", name, "-mhard-float"); - else if ((fnmask & RS6000_BTM_FLOAT128_HW) != 0) - error ("%qs requires ISA 3.0 IEEE 128-bit floating point", name); - else if ((fnmask & RS6000_BTM_FLOAT128) != 0) - error ("%qs requires the %qs option", name, "%<-mfloat128%>"); - else if ((fnmask & (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64)) - == (RS6000_BTM_POPCNTD | RS6000_BTM_POWERPC64)) - error ("%qs requires the %qs (or newer), and %qs or %qs options", - name, "-mcpu=power7", "-m64", "-mpowerpc64"); - else - error ("%qs is not supported with the current options", name); -} - -/* Target hook for early folding of built-ins, shamelessly stolen - from ia64.c. */ - -static tree -rs6000_fold_builtin (tree fndecl ATTRIBUTE_UNUSED, - int n_args ATTRIBUTE_UNUSED, - tree *args ATTRIBUTE_UNUSED, - bool ignore ATTRIBUTE_UNUSED) -{ -#ifdef SUBTARGET_FOLD_BUILTIN - return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore); -#else - return NULL_TREE; -#endif -} - -/* Helper function to sort out which built-ins may be valid without having - a LHS. */ -static bool -rs6000_builtin_valid_without_lhs (enum rs6000_builtins fn_code) -{ - switch (fn_code) - { - case ALTIVEC_BUILTIN_STVX_V16QI: - case ALTIVEC_BUILTIN_STVX_V8HI: - case ALTIVEC_BUILTIN_STVX_V4SI: - case ALTIVEC_BUILTIN_STVX_V4SF: - case ALTIVEC_BUILTIN_STVX_V2DI: - case ALTIVEC_BUILTIN_STVX_V2DF: - case VSX_BUILTIN_STXVW4X_V16QI: - case VSX_BUILTIN_STXVW4X_V8HI: - case VSX_BUILTIN_STXVW4X_V4SF: - case VSX_BUILTIN_STXVW4X_V4SI: - case VSX_BUILTIN_STXVD2X_V2DF: - case VSX_BUILTIN_STXVD2X_V2DI: - return true; - default: - return false; - } -} - -/* Helper function to handle the gimple folding of a vector compare - operation. This sets up true/false vectors, and uses the - VEC_COND_EXPR operation. - CODE indicates which comparison is to be made. (EQ, GT, ...). - TYPE indicates the type of the result. */ -static tree -fold_build_vec_cmp (tree_code code, tree type, - tree arg0, tree arg1) -{ - tree cmp_type = build_same_sized_truth_vector_type (type); - tree zero_vec = build_zero_cst (type); - tree minus_one_vec = build_minus_one_cst (type); - tree cmp = fold_build2 (code, cmp_type, arg0, arg1); - return fold_build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec); -} - -/* Helper function to handle the in-between steps for the - vector compare built-ins. */ -static void -fold_compare_helper (gimple_stmt_iterator *gsi, tree_code code, gimple *stmt) -{ - tree arg0 = gimple_call_arg (stmt, 0); - tree arg1 = gimple_call_arg (stmt, 1); - tree lhs = gimple_call_lhs (stmt); - tree cmp = fold_build_vec_cmp (code, TREE_TYPE (lhs), arg0, arg1); - gimple *g = gimple_build_assign (lhs, cmp); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); -} - -/* Helper function to map V2DF and V4SF types to their - integral equivalents (V2DI and V4SI). */ -tree map_to_integral_tree_type (tree input_tree_type) -{ - if (INTEGRAL_TYPE_P (TREE_TYPE (input_tree_type))) - return input_tree_type; - else - { - if (types_compatible_p (TREE_TYPE (input_tree_type), - TREE_TYPE (V2DF_type_node))) - return V2DI_type_node; - else if (types_compatible_p (TREE_TYPE (input_tree_type), - TREE_TYPE (V4SF_type_node))) - return V4SI_type_node; - else - gcc_unreachable (); - } -} - -/* Helper function to handle the vector merge[hl] built-ins. The - implementation difference between h and l versions for this code are in - the values used when building of the permute vector for high word versus - low word merge. The variance is keyed off the use_high parameter. */ -static void -fold_mergehl_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_high) -{ - tree arg0 = gimple_call_arg (stmt, 0); - tree arg1 = gimple_call_arg (stmt, 1); - tree lhs = gimple_call_lhs (stmt); - tree lhs_type = TREE_TYPE (lhs); - int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type); - int midpoint = n_elts / 2; - int offset = 0; - - if (use_high == 1) - offset = midpoint; - - /* The permute_type will match the lhs for integral types. For double and - float types, the permute type needs to map to the V2 or V4 type that - matches size. */ - tree permute_type; - permute_type = map_to_integral_tree_type (lhs_type); - tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1); - - for (int i = 0; i < midpoint; i++) - { - elts.safe_push (build_int_cst (TREE_TYPE (permute_type), - offset + i)); - elts.safe_push (build_int_cst (TREE_TYPE (permute_type), - offset + n_elts + i)); - } - - tree permute = elts.build (); - - gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); -} - -/* Helper function to handle the vector merge[eo] built-ins. */ -static void -fold_mergeeo_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_odd) -{ - tree arg0 = gimple_call_arg (stmt, 0); - tree arg1 = gimple_call_arg (stmt, 1); - tree lhs = gimple_call_lhs (stmt); - tree lhs_type = TREE_TYPE (lhs); - int n_elts = TYPE_VECTOR_SUBPARTS (lhs_type); - - /* The permute_type will match the lhs for integral types. For double and - float types, the permute type needs to map to the V2 or V4 type that - matches size. */ - tree permute_type; - permute_type = map_to_integral_tree_type (lhs_type); - - tree_vector_builder elts (permute_type, VECTOR_CST_NELTS (arg0), 1); - - /* Build the permute vector. */ - for (int i = 0; i < n_elts / 2; i++) - { - elts.safe_push (build_int_cst (TREE_TYPE (permute_type), - 2*i + use_odd)); - elts.safe_push (build_int_cst (TREE_TYPE (permute_type), - 2*i + use_odd + n_elts)); - } - - tree permute = elts.build (); - - gimple *g = gimple_build_assign (lhs, VEC_PERM_EXPR, arg0, arg1, permute); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); -} - -/* Fold a machine-dependent built-in in GIMPLE. (For folding into - a constant, use rs6000_fold_builtin.) */ - -bool -rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) -{ - gimple *stmt = gsi_stmt (*gsi); - tree fndecl = gimple_call_fndecl (stmt); - gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD); - enum rs6000_builtins fn_code - = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); - tree arg0, arg1, lhs, temp; - enum tree_code bcode; - gimple *g; - - size_t uns_fncode = (size_t) fn_code; - enum insn_code icode = rs6000_builtin_info[uns_fncode].icode; - const char *fn_name1 = rs6000_builtin_info[uns_fncode].name; - const char *fn_name2 = (icode != CODE_FOR_nothing) - ? get_insn_name ((int) icode) - : "nothing"; - - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_gimple_fold_builtin %d %s %s\n", - fn_code, fn_name1, fn_name2); - - if (!rs6000_fold_gimple) - return false; - - /* Prevent gimple folding for code that does not have a LHS, unless it is - allowed per the rs6000_builtin_valid_without_lhs helper function. */ - if (!gimple_call_lhs (stmt) && !rs6000_builtin_valid_without_lhs (fn_code)) - return false; - - /* Don't fold invalid builtins, let rs6000_expand_builtin diagnose it. */ - HOST_WIDE_INT mask = rs6000_builtin_info[uns_fncode].mask; - bool func_valid_p = (rs6000_builtin_mask & mask) == mask; - if (!func_valid_p) - return false; - - switch (fn_code) - { - /* Flavors of vec_add. We deliberately don't expand - P8V_BUILTIN_VADDUQM as it gets lowered from V1TImode to - TImode, resulting in much poorer code generation. */ - case ALTIVEC_BUILTIN_VADDUBM: - case ALTIVEC_BUILTIN_VADDUHM: - case ALTIVEC_BUILTIN_VADDUWM: - case P8V_BUILTIN_VADDUDM: - case ALTIVEC_BUILTIN_VADDFP: - case VSX_BUILTIN_XVADDDP: - bcode = PLUS_EXPR; - do_binary: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (lhs))) - && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (lhs)))) - { - /* Ensure the binary operation is performed in a type - that wraps if it is integral type. */ - gimple_seq stmts = NULL; - tree type = unsigned_type_for (TREE_TYPE (lhs)); - tree uarg0 = gimple_build (&stmts, VIEW_CONVERT_EXPR, - type, arg0); - tree uarg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, - type, arg1); - tree res = gimple_build (&stmts, gimple_location (stmt), bcode, - type, uarg0, uarg1); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - g = gimple_build_assign (lhs, VIEW_CONVERT_EXPR, - build1 (VIEW_CONVERT_EXPR, - TREE_TYPE (lhs), res)); - gsi_replace (gsi, g, true); - return true; - } - g = gimple_build_assign (lhs, bcode, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_sub. We deliberately don't expand - P8V_BUILTIN_VSUBUQM. */ - case ALTIVEC_BUILTIN_VSUBUBM: - case ALTIVEC_BUILTIN_VSUBUHM: - case ALTIVEC_BUILTIN_VSUBUWM: - case P8V_BUILTIN_VSUBUDM: - case ALTIVEC_BUILTIN_VSUBFP: - case VSX_BUILTIN_XVSUBDP: - bcode = MINUS_EXPR; - goto do_binary; - case VSX_BUILTIN_XVMULSP: - case VSX_BUILTIN_XVMULDP: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, MULT_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Even element flavors of vec_mul (signed). */ - case ALTIVEC_BUILTIN_VMULESB: - case ALTIVEC_BUILTIN_VMULESH: - case P8V_BUILTIN_VMULESW: - /* Even element flavors of vec_mul (unsigned). */ - case ALTIVEC_BUILTIN_VMULEUB: - case ALTIVEC_BUILTIN_VMULEUH: - case P8V_BUILTIN_VMULEUW: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, VEC_WIDEN_MULT_EVEN_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Odd element flavors of vec_mul (signed). */ - case ALTIVEC_BUILTIN_VMULOSB: - case ALTIVEC_BUILTIN_VMULOSH: - case P8V_BUILTIN_VMULOSW: - /* Odd element flavors of vec_mul (unsigned). */ - case ALTIVEC_BUILTIN_VMULOUB: - case ALTIVEC_BUILTIN_VMULOUH: - case P8V_BUILTIN_VMULOUW: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, VEC_WIDEN_MULT_ODD_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_div (Integer). */ - case VSX_BUILTIN_DIV_V2DI: - case VSX_BUILTIN_UDIV_V2DI: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, TRUNC_DIV_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_div (Float). */ - case VSX_BUILTIN_XVDIVSP: - case VSX_BUILTIN_XVDIVDP: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, RDIV_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_and. */ - case ALTIVEC_BUILTIN_VAND: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_andc. */ - case ALTIVEC_BUILTIN_VANDC: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); - g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - g = gimple_build_assign (lhs, BIT_AND_EXPR, arg0, temp); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_nand. */ - case P8V_BUILTIN_VEC_NAND: - case P8V_BUILTIN_NAND_V16QI: - case P8V_BUILTIN_NAND_V8HI: - case P8V_BUILTIN_NAND_V4SI: - case P8V_BUILTIN_NAND_V4SF: - case P8V_BUILTIN_NAND_V2DF: - case P8V_BUILTIN_NAND_V2DI: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); - g = gimple_build_assign (temp, BIT_AND_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_or. */ - case ALTIVEC_BUILTIN_VOR: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* flavors of vec_orc. */ - case P8V_BUILTIN_ORC_V16QI: - case P8V_BUILTIN_ORC_V8HI: - case P8V_BUILTIN_ORC_V4SI: - case P8V_BUILTIN_ORC_V4SF: - case P8V_BUILTIN_ORC_V2DF: - case P8V_BUILTIN_ORC_V2DI: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); - g = gimple_build_assign (temp, BIT_NOT_EXPR, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - g = gimple_build_assign (lhs, BIT_IOR_EXPR, arg0, temp); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_xor. */ - case ALTIVEC_BUILTIN_VXOR: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, BIT_XOR_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_nor. */ - case ALTIVEC_BUILTIN_VNOR: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); - g = gimple_build_assign (temp, BIT_IOR_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* flavors of vec_abs. */ - case ALTIVEC_BUILTIN_ABS_V16QI: - case ALTIVEC_BUILTIN_ABS_V8HI: - case ALTIVEC_BUILTIN_ABS_V4SI: - case ALTIVEC_BUILTIN_ABS_V4SF: - case P8V_BUILTIN_ABS_V2DI: - case VSX_BUILTIN_XVABSDP: - arg0 = gimple_call_arg (stmt, 0); - if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))) - && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (arg0)))) - return false; - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, ABS_EXPR, arg0); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* flavors of vec_min. */ - case VSX_BUILTIN_XVMINDP: - case P8V_BUILTIN_VMINSD: - case P8V_BUILTIN_VMINUD: - case ALTIVEC_BUILTIN_VMINSB: - case ALTIVEC_BUILTIN_VMINSH: - case ALTIVEC_BUILTIN_VMINSW: - case ALTIVEC_BUILTIN_VMINUB: - case ALTIVEC_BUILTIN_VMINUH: - case ALTIVEC_BUILTIN_VMINUW: - case ALTIVEC_BUILTIN_VMINFP: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, MIN_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* flavors of vec_max. */ - case VSX_BUILTIN_XVMAXDP: - case P8V_BUILTIN_VMAXSD: - case P8V_BUILTIN_VMAXUD: - case ALTIVEC_BUILTIN_VMAXSB: - case ALTIVEC_BUILTIN_VMAXSH: - case ALTIVEC_BUILTIN_VMAXSW: - case ALTIVEC_BUILTIN_VMAXUB: - case ALTIVEC_BUILTIN_VMAXUH: - case ALTIVEC_BUILTIN_VMAXUW: - case ALTIVEC_BUILTIN_VMAXFP: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, MAX_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_eqv. */ - case P8V_BUILTIN_EQV_V16QI: - case P8V_BUILTIN_EQV_V8HI: - case P8V_BUILTIN_EQV_V4SI: - case P8V_BUILTIN_EQV_V4SF: - case P8V_BUILTIN_EQV_V2DF: - case P8V_BUILTIN_EQV_V2DI: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - temp = create_tmp_reg_or_ssa_name (TREE_TYPE (arg1)); - g = gimple_build_assign (temp, BIT_XOR_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - g = gimple_build_assign (lhs, BIT_NOT_EXPR, temp); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vec_rotate_left. */ - case ALTIVEC_BUILTIN_VRLB: - case ALTIVEC_BUILTIN_VRLH: - case ALTIVEC_BUILTIN_VRLW: - case P8V_BUILTIN_VRLD: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, LROTATE_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - /* Flavors of vector shift right algebraic. - vec_sra{b,h,w} -> vsra{b,h,w}. */ - case ALTIVEC_BUILTIN_VSRAB: - case ALTIVEC_BUILTIN_VSRAH: - case ALTIVEC_BUILTIN_VSRAW: - case P8V_BUILTIN_VSRAD: - { - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - tree arg1_type = TREE_TYPE (arg1); - tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); - tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); - location_t loc = gimple_location (stmt); - /* Force arg1 into the range valid matching the arg0 type. */ - /* Build a vector consisting of the max valid bit-size values. */ - int n_elts = VECTOR_CST_NELTS (arg1); - tree element_size = build_int_cst (unsigned_element_type, - 128 / n_elts); - tree_vector_builder elts (unsigned_arg1_type, n_elts, 1); - for (int i = 0; i < n_elts; i++) - elts.safe_push (element_size); - tree modulo_tree = elts.build (); - /* Modulo the provided shift value against that vector. */ - gimple_seq stmts = NULL; - tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, - unsigned_arg1_type, arg1); - tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, - unsigned_arg1_type, unsigned_arg1, - modulo_tree); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - /* And finally, do the shift. */ - g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, new_arg1); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; - } - /* Flavors of vector shift left. - builtin_altivec_vsl{b,h,w} -> vsl{b,h,w}. */ - case ALTIVEC_BUILTIN_VSLB: - case ALTIVEC_BUILTIN_VSLH: - case ALTIVEC_BUILTIN_VSLW: - case P8V_BUILTIN_VSLD: - { - location_t loc; - gimple_seq stmts = NULL; - arg0 = gimple_call_arg (stmt, 0); - tree arg0_type = TREE_TYPE (arg0); - if (INTEGRAL_TYPE_P (TREE_TYPE (arg0_type)) - && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0_type))) - return false; - arg1 = gimple_call_arg (stmt, 1); - tree arg1_type = TREE_TYPE (arg1); - tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); - tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); - loc = gimple_location (stmt); - lhs = gimple_call_lhs (stmt); - /* Force arg1 into the range valid matching the arg0 type. */ - /* Build a vector consisting of the max valid bit-size values. */ - int n_elts = VECTOR_CST_NELTS (arg1); - int tree_size_in_bits = TREE_INT_CST_LOW (size_in_bytes (arg1_type)) - * BITS_PER_UNIT; - tree element_size = build_int_cst (unsigned_element_type, - tree_size_in_bits / n_elts); - tree_vector_builder elts (unsigned_type_for (arg1_type), n_elts, 1); - for (int i = 0; i < n_elts; i++) - elts.safe_push (element_size); - tree modulo_tree = elts.build (); - /* Modulo the provided shift value against that vector. */ - tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, - unsigned_arg1_type, arg1); - tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, - unsigned_arg1_type, unsigned_arg1, - modulo_tree); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - /* And finally, do the shift. */ - g = gimple_build_assign (lhs, LSHIFT_EXPR, arg0, new_arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } - /* Flavors of vector shift right. */ - case ALTIVEC_BUILTIN_VSRB: - case ALTIVEC_BUILTIN_VSRH: - case ALTIVEC_BUILTIN_VSRW: - case P8V_BUILTIN_VSRD: - { - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - tree arg1_type = TREE_TYPE (arg1); - tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); - tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); - location_t loc = gimple_location (stmt); - gimple_seq stmts = NULL; - /* Convert arg0 to unsigned. */ - tree arg0_unsigned - = gimple_build (&stmts, VIEW_CONVERT_EXPR, - unsigned_type_for (TREE_TYPE (arg0)), arg0); - /* Force arg1 into the range valid matching the arg0 type. */ - /* Build a vector consisting of the max valid bit-size values. */ - int n_elts = VECTOR_CST_NELTS (arg1); - tree element_size = build_int_cst (unsigned_element_type, - 128 / n_elts); - tree_vector_builder elts (unsigned_arg1_type, n_elts, 1); - for (int i = 0; i < n_elts; i++) - elts.safe_push (element_size); - tree modulo_tree = elts.build (); - /* Modulo the provided shift value against that vector. */ - tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, - unsigned_arg1_type, arg1); - tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, - unsigned_arg1_type, unsigned_arg1, - modulo_tree); - /* Do the shift. */ - tree res - = gimple_build (&stmts, RSHIFT_EXPR, - TREE_TYPE (arg0_unsigned), arg0_unsigned, new_arg1); - /* Convert result back to the lhs type. */ - res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - update_call_from_tree (gsi, res); - return true; - } - /* Vector loads. */ - case ALTIVEC_BUILTIN_LVX_V16QI: - case ALTIVEC_BUILTIN_LVX_V8HI: - case ALTIVEC_BUILTIN_LVX_V4SI: - case ALTIVEC_BUILTIN_LVX_V4SF: - case ALTIVEC_BUILTIN_LVX_V2DI: - case ALTIVEC_BUILTIN_LVX_V2DF: - case ALTIVEC_BUILTIN_LVX_V1TI: - { - arg0 = gimple_call_arg (stmt, 0); // offset - arg1 = gimple_call_arg (stmt, 1); // address - lhs = gimple_call_lhs (stmt); - location_t loc = gimple_location (stmt); - /* Since arg1 may be cast to a different type, just use ptr_type_node - here instead of trying to enforce TBAA on pointer types. */ - tree arg1_type = ptr_type_node; - tree lhs_type = TREE_TYPE (lhs); - /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create - the tree using the value from arg0. The resulting type will match - the type of arg1. */ - gimple_seq stmts = NULL; - tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0); - tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, - arg1_type, arg1, temp_offset); - /* Mask off any lower bits from the address. */ - tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR, - arg1_type, temp_addr, - build_int_cst (arg1_type, -16)); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - if (!is_gimple_mem_ref_addr (aligned_addr)) - { - tree t = make_ssa_name (TREE_TYPE (aligned_addr)); - gimple *g = gimple_build_assign (t, aligned_addr); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - aligned_addr = t; - } - /* Use the build2 helper to set up the mem_ref. The MEM_REF could also - take an offset, but since we've already incorporated the offset - above, here we just pass in a zero. */ - gimple *g - = gimple_build_assign (lhs, build2 (MEM_REF, lhs_type, aligned_addr, - build_int_cst (arg1_type, 0))); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; - } - /* Vector stores. */ - case ALTIVEC_BUILTIN_STVX_V16QI: - case ALTIVEC_BUILTIN_STVX_V8HI: - case ALTIVEC_BUILTIN_STVX_V4SI: - case ALTIVEC_BUILTIN_STVX_V4SF: - case ALTIVEC_BUILTIN_STVX_V2DI: - case ALTIVEC_BUILTIN_STVX_V2DF: - { - arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */ - arg1 = gimple_call_arg (stmt, 1); /* Offset. */ - tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */ - location_t loc = gimple_location (stmt); - tree arg0_type = TREE_TYPE (arg0); - /* Use ptr_type_node (no TBAA) for the arg2_type. - FIXME: (Richard) "A proper fix would be to transition this type as - seen from the frontend to GIMPLE, for example in a similar way we - do for MEM_REFs by piggy-backing that on an extra argument, a - constant zero pointer of the alias pointer type to use (which would - also serve as a type indicator of the store itself). I'd use a - target specific internal function for this (not sure if we can have - those target specific, but I guess if it's folded away then that's - fine) and get away with the overload set." */ - tree arg2_type = ptr_type_node; - /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create - the tree using the value from arg0. The resulting type will match - the type of arg2. */ - gimple_seq stmts = NULL; - tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1); - tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, - arg2_type, arg2, temp_offset); - /* Mask off any lower bits from the address. */ - tree aligned_addr = gimple_build (&stmts, loc, BIT_AND_EXPR, - arg2_type, temp_addr, - build_int_cst (arg2_type, -16)); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - if (!is_gimple_mem_ref_addr (aligned_addr)) - { - tree t = make_ssa_name (TREE_TYPE (aligned_addr)); - gimple *g = gimple_build_assign (t, aligned_addr); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - aligned_addr = t; - } - /* The desired gimple result should be similar to: - MEM[(__vector floatD.1407 *)_1] = vf1D.2697; */ - gimple *g - = gimple_build_assign (build2 (MEM_REF, arg0_type, aligned_addr, - build_int_cst (arg2_type, 0)), arg0); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; - } - - /* unaligned Vector loads. */ - case VSX_BUILTIN_LXVW4X_V16QI: - case VSX_BUILTIN_LXVW4X_V8HI: - case VSX_BUILTIN_LXVW4X_V4SF: - case VSX_BUILTIN_LXVW4X_V4SI: - case VSX_BUILTIN_LXVD2X_V2DF: - case VSX_BUILTIN_LXVD2X_V2DI: - { - arg0 = gimple_call_arg (stmt, 0); // offset - arg1 = gimple_call_arg (stmt, 1); // address - lhs = gimple_call_lhs (stmt); - location_t loc = gimple_location (stmt); - /* Since arg1 may be cast to a different type, just use ptr_type_node - here instead of trying to enforce TBAA on pointer types. */ - tree arg1_type = ptr_type_node; - tree lhs_type = TREE_TYPE (lhs); - /* In GIMPLE the type of the MEM_REF specifies the alignment. The - required alignment (power) is 4 bytes regardless of data type. */ - tree align_ltype = build_aligned_type (lhs_type, 4); - /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create - the tree using the value from arg0. The resulting type will match - the type of arg1. */ - gimple_seq stmts = NULL; - tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg0); - tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, - arg1_type, arg1, temp_offset); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - if (!is_gimple_mem_ref_addr (temp_addr)) - { - tree t = make_ssa_name (TREE_TYPE (temp_addr)); - gimple *g = gimple_build_assign (t, temp_addr); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - temp_addr = t; - } - /* Use the build2 helper to set up the mem_ref. The MEM_REF could also - take an offset, but since we've already incorporated the offset - above, here we just pass in a zero. */ - gimple *g; - g = gimple_build_assign (lhs, build2 (MEM_REF, align_ltype, temp_addr, - build_int_cst (arg1_type, 0))); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; - } - - /* unaligned Vector stores. */ - case VSX_BUILTIN_STXVW4X_V16QI: - case VSX_BUILTIN_STXVW4X_V8HI: - case VSX_BUILTIN_STXVW4X_V4SF: - case VSX_BUILTIN_STXVW4X_V4SI: - case VSX_BUILTIN_STXVD2X_V2DF: - case VSX_BUILTIN_STXVD2X_V2DI: - { - arg0 = gimple_call_arg (stmt, 0); /* Value to be stored. */ - arg1 = gimple_call_arg (stmt, 1); /* Offset. */ - tree arg2 = gimple_call_arg (stmt, 2); /* Store-to address. */ - location_t loc = gimple_location (stmt); - tree arg0_type = TREE_TYPE (arg0); - /* Use ptr_type_node (no TBAA) for the arg2_type. */ - tree arg2_type = ptr_type_node; - /* In GIMPLE the type of the MEM_REF specifies the alignment. The - required alignment (power) is 4 bytes regardless of data type. */ - tree align_stype = build_aligned_type (arg0_type, 4); - /* POINTER_PLUS_EXPR wants the offset to be of type 'sizetype'. Create - the tree using the value from arg1. */ - gimple_seq stmts = NULL; - tree temp_offset = gimple_convert (&stmts, loc, sizetype, arg1); - tree temp_addr = gimple_build (&stmts, loc, POINTER_PLUS_EXPR, - arg2_type, arg2, temp_offset); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - if (!is_gimple_mem_ref_addr (temp_addr)) - { - tree t = make_ssa_name (TREE_TYPE (temp_addr)); - gimple *g = gimple_build_assign (t, temp_addr); - gsi_insert_before (gsi, g, GSI_SAME_STMT); - temp_addr = t; - } - gimple *g; - g = gimple_build_assign (build2 (MEM_REF, align_stype, temp_addr, - build_int_cst (arg2_type, 0)), arg0); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; - } - - /* Vector Fused multiply-add (fma). */ - case ALTIVEC_BUILTIN_VMADDFP: - case VSX_BUILTIN_XVMADDDP: - case ALTIVEC_BUILTIN_VMLADDUHM: - { - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - tree arg2 = gimple_call_arg (stmt, 2); - lhs = gimple_call_lhs (stmt); - gcall *g = gimple_build_call_internal (IFN_FMA, 3, arg0, arg1, arg2); - gimple_call_set_lhs (g, lhs); - gimple_call_set_nothrow (g, true); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } - - /* Vector compares; EQ, NE, GE, GT, LE. */ - case ALTIVEC_BUILTIN_VCMPEQUB: - case ALTIVEC_BUILTIN_VCMPEQUH: - case ALTIVEC_BUILTIN_VCMPEQUW: - case P8V_BUILTIN_VCMPEQUD: - fold_compare_helper (gsi, EQ_EXPR, stmt); - return true; - - case P9V_BUILTIN_CMPNEB: - case P9V_BUILTIN_CMPNEH: - case P9V_BUILTIN_CMPNEW: - fold_compare_helper (gsi, NE_EXPR, stmt); - return true; - - case VSX_BUILTIN_CMPGE_16QI: - case VSX_BUILTIN_CMPGE_U16QI: - case VSX_BUILTIN_CMPGE_8HI: - case VSX_BUILTIN_CMPGE_U8HI: - case VSX_BUILTIN_CMPGE_4SI: - case VSX_BUILTIN_CMPGE_U4SI: - case VSX_BUILTIN_CMPGE_2DI: - case VSX_BUILTIN_CMPGE_U2DI: - fold_compare_helper (gsi, GE_EXPR, stmt); - return true; - - case ALTIVEC_BUILTIN_VCMPGTSB: - case ALTIVEC_BUILTIN_VCMPGTUB: - case ALTIVEC_BUILTIN_VCMPGTSH: - case ALTIVEC_BUILTIN_VCMPGTUH: - case ALTIVEC_BUILTIN_VCMPGTSW: - case ALTIVEC_BUILTIN_VCMPGTUW: - case P8V_BUILTIN_VCMPGTUD: - case P8V_BUILTIN_VCMPGTSD: - fold_compare_helper (gsi, GT_EXPR, stmt); - return true; - - case VSX_BUILTIN_CMPLE_16QI: - case VSX_BUILTIN_CMPLE_U16QI: - case VSX_BUILTIN_CMPLE_8HI: - case VSX_BUILTIN_CMPLE_U8HI: - case VSX_BUILTIN_CMPLE_4SI: - case VSX_BUILTIN_CMPLE_U4SI: - case VSX_BUILTIN_CMPLE_2DI: - case VSX_BUILTIN_CMPLE_U2DI: - fold_compare_helper (gsi, LE_EXPR, stmt); - return true; - - /* flavors of vec_splat_[us]{8,16,32}. */ - case ALTIVEC_BUILTIN_VSPLTISB: - case ALTIVEC_BUILTIN_VSPLTISH: - case ALTIVEC_BUILTIN_VSPLTISW: - { - arg0 = gimple_call_arg (stmt, 0); - lhs = gimple_call_lhs (stmt); - - /* Only fold the vec_splat_*() if the lower bits of arg 0 is a - 5-bit signed constant in range -16 to +15. */ - if (TREE_CODE (arg0) != INTEGER_CST - || !IN_RANGE (TREE_INT_CST_LOW (arg0), -16, 15)) - return false; - gimple_seq stmts = NULL; - location_t loc = gimple_location (stmt); - tree splat_value = gimple_convert (&stmts, loc, - TREE_TYPE (TREE_TYPE (lhs)), arg0); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - tree splat_tree = build_vector_from_val (TREE_TYPE (lhs), splat_value); - g = gimple_build_assign (lhs, splat_tree); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } - - /* Flavors of vec_splat. */ - /* a = vec_splat (b, 0x3) becomes a = { b[3],b[3],b[3],...}; */ - case ALTIVEC_BUILTIN_VSPLTB: - case ALTIVEC_BUILTIN_VSPLTH: - case ALTIVEC_BUILTIN_VSPLTW: - case VSX_BUILTIN_XXSPLTD_V2DI: - case VSX_BUILTIN_XXSPLTD_V2DF: - { - arg0 = gimple_call_arg (stmt, 0); /* input vector. */ - arg1 = gimple_call_arg (stmt, 1); /* index into arg0. */ - /* Only fold the vec_splat_*() if arg1 is both a constant value and - is a valid index into the arg0 vector. */ - unsigned int n_elts = VECTOR_CST_NELTS (arg0); - if (TREE_CODE (arg1) != INTEGER_CST - || TREE_INT_CST_LOW (arg1) > (n_elts -1)) - return false; - lhs = gimple_call_lhs (stmt); - tree lhs_type = TREE_TYPE (lhs); - tree arg0_type = TREE_TYPE (arg0); - tree splat; - if (TREE_CODE (arg0) == VECTOR_CST) - splat = VECTOR_CST_ELT (arg0, TREE_INT_CST_LOW (arg1)); - else - { - /* Determine (in bits) the length and start location of the - splat value for a call to the tree_vec_extract helper. */ - int splat_elem_size = TREE_INT_CST_LOW (size_in_bytes (arg0_type)) - * BITS_PER_UNIT / n_elts; - int splat_start_bit = TREE_INT_CST_LOW (arg1) * splat_elem_size; - tree len = build_int_cst (bitsizetype, splat_elem_size); - tree start = build_int_cst (bitsizetype, splat_start_bit); - splat = tree_vec_extract (gsi, TREE_TYPE (lhs_type), arg0, - len, start); - } - /* And finally, build the new vector. */ - tree splat_tree = build_vector_from_val (lhs_type, splat); - g = gimple_build_assign (lhs, splat_tree); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } - - /* vec_mergel (integrals). */ - case ALTIVEC_BUILTIN_VMRGLH: - case ALTIVEC_BUILTIN_VMRGLW: - case VSX_BUILTIN_XXMRGLW_4SI: - case ALTIVEC_BUILTIN_VMRGLB: - case VSX_BUILTIN_VEC_MERGEL_V2DI: - case VSX_BUILTIN_XXMRGLW_4SF: - case VSX_BUILTIN_VEC_MERGEL_V2DF: - fold_mergehl_helper (gsi, stmt, 1); - return true; - /* vec_mergeh (integrals). */ - case ALTIVEC_BUILTIN_VMRGHH: - case ALTIVEC_BUILTIN_VMRGHW: - case VSX_BUILTIN_XXMRGHW_4SI: - case ALTIVEC_BUILTIN_VMRGHB: - case VSX_BUILTIN_VEC_MERGEH_V2DI: - case VSX_BUILTIN_XXMRGHW_4SF: - case VSX_BUILTIN_VEC_MERGEH_V2DF: - fold_mergehl_helper (gsi, stmt, 0); - return true; - - /* Flavors of vec_mergee. */ - case P8V_BUILTIN_VMRGEW_V4SI: - case P8V_BUILTIN_VMRGEW_V2DI: - case P8V_BUILTIN_VMRGEW_V4SF: - case P8V_BUILTIN_VMRGEW_V2DF: - fold_mergeeo_helper (gsi, stmt, 0); - return true; - /* Flavors of vec_mergeo. */ - case P8V_BUILTIN_VMRGOW_V4SI: - case P8V_BUILTIN_VMRGOW_V2DI: - case P8V_BUILTIN_VMRGOW_V4SF: - case P8V_BUILTIN_VMRGOW_V2DF: - fold_mergeeo_helper (gsi, stmt, 1); - return true; - - /* d = vec_pack (a, b) */ - case P8V_BUILTIN_VPKUDUM: - case ALTIVEC_BUILTIN_VPKUHUM: - case ALTIVEC_BUILTIN_VPKUWUM: - { - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - gimple *g = gimple_build_assign (lhs, VEC_PACK_TRUNC_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } - - /* d = vec_unpackh (a) */ - /* Note that the UNPACK_{HI,LO}_EXPR used in the gimple_build_assign call - in this code is sensitive to endian-ness, and needs to be inverted to - handle both LE and BE targets. */ - case ALTIVEC_BUILTIN_VUPKHSB: - case ALTIVEC_BUILTIN_VUPKHSH: - case P8V_BUILTIN_VUPKHSW: - { - arg0 = gimple_call_arg (stmt, 0); - lhs = gimple_call_lhs (stmt); - if (BYTES_BIG_ENDIAN) - g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); - else - g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } - /* d = vec_unpackl (a) */ - case ALTIVEC_BUILTIN_VUPKLSB: - case ALTIVEC_BUILTIN_VUPKLSH: - case P8V_BUILTIN_VUPKLSW: - { - arg0 = gimple_call_arg (stmt, 0); - lhs = gimple_call_lhs (stmt); - if (BYTES_BIG_ENDIAN) - g = gimple_build_assign (lhs, VEC_UNPACK_LO_EXPR, arg0); - else - g = gimple_build_assign (lhs, VEC_UNPACK_HI_EXPR, arg0); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; - } - /* There is no gimple type corresponding with pixel, so just return. */ - case ALTIVEC_BUILTIN_VUPKHPX: - case ALTIVEC_BUILTIN_VUPKLPX: - return false; - - /* vec_perm. */ - case ALTIVEC_BUILTIN_VPERM_16QI: - case ALTIVEC_BUILTIN_VPERM_8HI: - case ALTIVEC_BUILTIN_VPERM_4SI: - case ALTIVEC_BUILTIN_VPERM_2DI: - case ALTIVEC_BUILTIN_VPERM_4SF: - case ALTIVEC_BUILTIN_VPERM_2DF: - { - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - tree permute = gimple_call_arg (stmt, 2); - lhs = gimple_call_lhs (stmt); - location_t loc = gimple_location (stmt); - gimple_seq stmts = NULL; - // convert arg0 and arg1 to match the type of the permute - // for the VEC_PERM_EXPR operation. - tree permute_type = (TREE_TYPE (permute)); - tree arg0_ptype = gimple_convert (&stmts, loc, permute_type, arg0); - tree arg1_ptype = gimple_convert (&stmts, loc, permute_type, arg1); - tree lhs_ptype = gimple_build (&stmts, loc, VEC_PERM_EXPR, - permute_type, arg0_ptype, arg1_ptype, - permute); - // Convert the result back to the desired lhs type upon completion. - tree temp = gimple_convert (&stmts, loc, TREE_TYPE (lhs), lhs_ptype); - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - g = gimple_build_assign (lhs, temp); - gimple_set_location (g, loc); - gsi_replace (gsi, g, true); - return true; - } - - default: - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "gimple builtin intrinsic not matched:%d %s %s\n", - fn_code, fn_name1, fn_name2); - break; - } - - return false; -} - -/* Expand an expression EXP that calls a built-in function, - with result going to TARGET if that's convenient - (and in mode MODE if that's convenient). - SUBTARGET may be used as the target for computing one of EXP's operands. - IGNORE is nonzero if the value is to be ignored. */ - -static rtx -rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, - machine_mode mode ATTRIBUTE_UNUSED, - int ignore ATTRIBUTE_UNUSED) -{ - tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - enum rs6000_builtins fcode - = (enum rs6000_builtins)DECL_FUNCTION_CODE (fndecl); - size_t uns_fcode = (size_t)fcode; - const struct builtin_description *d; - size_t i; - rtx ret; - bool success; - HOST_WIDE_INT mask = rs6000_builtin_info[uns_fcode].mask; - bool func_valid_p = ((rs6000_builtin_mask & mask) == mask); - enum insn_code icode = rs6000_builtin_info[uns_fcode].icode; - - /* We have two different modes (KFmode, TFmode) that are the IEEE 128-bit - floating point type, depending on whether long double is the IBM extended - double (KFmode) or long double is IEEE 128-bit (TFmode). It is simpler if - we only define one variant of the built-in function, and switch the code - when defining it, rather than defining two built-ins and using the - overload table in rs6000-c.c to switch between the two. If we don't have - the proper assembler, don't do this switch because CODE_FOR_*kf* and - CODE_FOR_*tf* will be CODE_FOR_nothing. */ - if (FLOAT128_IEEE_P (TFmode)) - switch (icode) - { - default: - break; - - case CODE_FOR_sqrtkf2_odd: icode = CODE_FOR_sqrttf2_odd; break; - case CODE_FOR_trunckfdf2_odd: icode = CODE_FOR_trunctfdf2_odd; break; - case CODE_FOR_addkf3_odd: icode = CODE_FOR_addtf3_odd; break; - case CODE_FOR_subkf3_odd: icode = CODE_FOR_subtf3_odd; break; - case CODE_FOR_mulkf3_odd: icode = CODE_FOR_multf3_odd; break; - case CODE_FOR_divkf3_odd: icode = CODE_FOR_divtf3_odd; break; - case CODE_FOR_fmakf4_odd: icode = CODE_FOR_fmatf4_odd; break; - case CODE_FOR_xsxexpqp_kf: icode = CODE_FOR_xsxexpqp_tf; break; - case CODE_FOR_xsxsigqp_kf: icode = CODE_FOR_xsxsigqp_tf; break; - case CODE_FOR_xststdcnegqp_kf: icode = CODE_FOR_xststdcnegqp_tf; break; - case CODE_FOR_xsiexpqp_kf: icode = CODE_FOR_xsiexpqp_tf; break; - case CODE_FOR_xsiexpqpf_kf: icode = CODE_FOR_xsiexpqpf_tf; break; - case CODE_FOR_xststdcqp_kf: icode = CODE_FOR_xststdcqp_tf; break; - } - - if (TARGET_DEBUG_BUILTIN) - { - const char *name1 = rs6000_builtin_info[uns_fcode].name; - const char *name2 = (icode != CODE_FOR_nothing) - ? get_insn_name ((int) icode) - : "nothing"; - const char *name3; - - switch (rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK) - { - default: name3 = "unknown"; break; - case RS6000_BTC_SPECIAL: name3 = "special"; break; - case RS6000_BTC_UNARY: name3 = "unary"; break; - case RS6000_BTC_BINARY: name3 = "binary"; break; - case RS6000_BTC_TERNARY: name3 = "ternary"; break; - case RS6000_BTC_PREDICATE: name3 = "predicate"; break; - case RS6000_BTC_ABS: name3 = "abs"; break; - case RS6000_BTC_DST: name3 = "dst"; break; - } - - - fprintf (stderr, - "rs6000_expand_builtin, %s (%d), insn = %s (%d), type=%s%s\n", - (name1) ? name1 : "---", fcode, - (name2) ? name2 : "---", (int) icode, - name3, - func_valid_p ? "" : ", not valid"); - } - - if (!func_valid_p) - { - rs6000_invalid_builtin (fcode); - - /* Given it is invalid, just generate a normal call. */ - return expand_call (exp, target, ignore); - } - - switch (fcode) - { - case RS6000_BUILTIN_RECIP: - return rs6000_expand_binop_builtin (CODE_FOR_recipdf3, exp, target); - - case RS6000_BUILTIN_RECIPF: - return rs6000_expand_binop_builtin (CODE_FOR_recipsf3, exp, target); - - case RS6000_BUILTIN_RSQRTF: - return rs6000_expand_unop_builtin (CODE_FOR_rsqrtsf2, exp, target); - - case RS6000_BUILTIN_RSQRT: - return rs6000_expand_unop_builtin (CODE_FOR_rsqrtdf2, exp, target); - - case POWER7_BUILTIN_BPERMD: - return rs6000_expand_binop_builtin (((TARGET_64BIT) - ? CODE_FOR_bpermd_di - : CODE_FOR_bpermd_si), exp, target); - - case RS6000_BUILTIN_GET_TB: - return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_get_timebase, - target); - - case RS6000_BUILTIN_MFTB: - return rs6000_expand_zeroop_builtin (((TARGET_64BIT) - ? CODE_FOR_rs6000_mftb_di - : CODE_FOR_rs6000_mftb_si), - target); - - case RS6000_BUILTIN_MFFS: - return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_mffs, target); - - case RS6000_BUILTIN_MTFSB0: - return rs6000_expand_mtfsb_builtin (CODE_FOR_rs6000_mtfsb0, exp); - - case RS6000_BUILTIN_MTFSB1: - return rs6000_expand_mtfsb_builtin (CODE_FOR_rs6000_mtfsb1, exp); - - case RS6000_BUILTIN_SET_FPSCR_RN: - return rs6000_expand_set_fpscr_rn_builtin (CODE_FOR_rs6000_set_fpscr_rn, - exp); - - case RS6000_BUILTIN_SET_FPSCR_DRN: - return - rs6000_expand_set_fpscr_drn_builtin (CODE_FOR_rs6000_set_fpscr_drn, - exp); - - case RS6000_BUILTIN_MFFSL: - return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_mffsl, target); - - case RS6000_BUILTIN_MTFSF: - return rs6000_expand_mtfsf_builtin (CODE_FOR_rs6000_mtfsf, exp); - - case RS6000_BUILTIN_CPU_INIT: - case RS6000_BUILTIN_CPU_IS: - case RS6000_BUILTIN_CPU_SUPPORTS: - return cpu_expand_builtin (fcode, exp, target); - - case MISC_BUILTIN_SPEC_BARRIER: - { - emit_insn (gen_speculation_barrier ()); - return NULL_RTX; - } - - case ALTIVEC_BUILTIN_MASK_FOR_LOAD: - case ALTIVEC_BUILTIN_MASK_FOR_STORE: - { - int icode2 = (BYTES_BIG_ENDIAN ? (int) CODE_FOR_altivec_lvsr_direct - : (int) CODE_FOR_altivec_lvsl_direct); - machine_mode tmode = insn_data[icode2].operand[0].mode; - machine_mode mode = insn_data[icode2].operand[1].mode; - tree arg; - rtx op, addr, pat; - - gcc_assert (TARGET_ALTIVEC); - - arg = CALL_EXPR_ARG (exp, 0); - gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg))); - op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL); - addr = memory_address (mode, op); - if (fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE) - op = addr; - else - { - /* For the load case need to negate the address. */ - op = gen_reg_rtx (GET_MODE (addr)); - emit_insn (gen_rtx_SET (op, gen_rtx_NEG (GET_MODE (addr), addr))); - } - op = gen_rtx_MEM (mode, op); - - if (target == 0 - || GET_MODE (target) != tmode - || ! (*insn_data[icode2].operand[0].predicate) (target, tmode)) - target = gen_reg_rtx (tmode); - - pat = GEN_FCN (icode2) (target, op); - if (!pat) - return 0; - emit_insn (pat); - - return target; - } - - case ALTIVEC_BUILTIN_VCFUX: - case ALTIVEC_BUILTIN_VCFSX: - case ALTIVEC_BUILTIN_VCTUXS: - case ALTIVEC_BUILTIN_VCTSXS: - /* FIXME: There's got to be a nicer way to handle this case than - constructing a new CALL_EXPR. */ - if (call_expr_nargs (exp) == 1) - { - exp = build_call_nary (TREE_TYPE (exp), CALL_EXPR_FN (exp), - 2, CALL_EXPR_ARG (exp, 0), integer_zero_node); - } - break; - - /* For the pack and unpack int128 routines, fix up the builtin so it - uses the correct IBM128 type. */ - case MISC_BUILTIN_PACK_IF: - if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD) - { - icode = CODE_FOR_packtf; - fcode = MISC_BUILTIN_PACK_TF; - uns_fcode = (size_t)fcode; - } - break; - - case MISC_BUILTIN_UNPACK_IF: - if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD) - { - icode = CODE_FOR_unpacktf; - fcode = MISC_BUILTIN_UNPACK_TF; - uns_fcode = (size_t)fcode; - } - break; - - default: - break; - } - - if (TARGET_ALTIVEC) - { - ret = altivec_expand_builtin (exp, target, &success); - - if (success) - return ret; - } - if (TARGET_HTM) - { - ret = htm_expand_builtin (exp, target, &success); - - if (success) - return ret; - } - - unsigned attr = rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK; - /* RS6000_BTC_SPECIAL represents no-operand operators. */ - gcc_assert (attr == RS6000_BTC_UNARY - || attr == RS6000_BTC_BINARY - || attr == RS6000_BTC_TERNARY - || attr == RS6000_BTC_SPECIAL); - - /* Handle simple unary operations. */ - d = bdesc_1arg; - for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++) - if (d->code == fcode) - return rs6000_expand_unop_builtin (icode, exp, target); - - /* Handle simple binary operations. */ - d = bdesc_2arg; - for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++) - if (d->code == fcode) - return rs6000_expand_binop_builtin (icode, exp, target); - - /* Handle simple ternary operations. */ - d = bdesc_3arg; - for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) - if (d->code == fcode) - return rs6000_expand_ternop_builtin (icode, exp, target); - - /* Handle simple no-argument operations. */ - d = bdesc_0arg; - for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++) - if (d->code == fcode) - return rs6000_expand_zeroop_builtin (icode, target); - - gcc_unreachable (); -} - -/* Create a builtin vector type with a name. Taking care not to give - the canonical type a name. */ - -static tree -rs6000_vector_type (const char *name, tree elt_type, unsigned num_elts) -{ - tree result = build_vector_type (elt_type, num_elts); - - /* Copy so we don't give the canonical type a name. */ - result = build_variant_type_copy (result); - - add_builtin_type (name, result); - - return result; -} - -static void -rs6000_init_builtins (void) -{ - tree tdecl; - tree ftype; - machine_mode mode; - - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_init_builtins%s%s\n", - (TARGET_ALTIVEC) ? ", altivec" : "", - (TARGET_VSX) ? ", vsx" : ""); - - V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 ? "__vector long" - : "__vector long long", - intDI_type_node, 2); - V2DF_type_node = rs6000_vector_type ("__vector double", double_type_node, 2); - V4SI_type_node = rs6000_vector_type ("__vector signed int", - intSI_type_node, 4); - V4SF_type_node = rs6000_vector_type ("__vector float", float_type_node, 4); - V8HI_type_node = rs6000_vector_type ("__vector signed short", - intHI_type_node, 8); - V16QI_type_node = rs6000_vector_type ("__vector signed char", - intQI_type_node, 16); - - unsigned_V16QI_type_node = rs6000_vector_type ("__vector unsigned char", - unsigned_intQI_type_node, 16); - unsigned_V8HI_type_node = rs6000_vector_type ("__vector unsigned short", - unsigned_intHI_type_node, 8); - unsigned_V4SI_type_node = rs6000_vector_type ("__vector unsigned int", - unsigned_intSI_type_node, 4); - unsigned_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 - ? "__vector unsigned long" - : "__vector unsigned long long", - unsigned_intDI_type_node, 2); - - opaque_V4SI_type_node = build_opaque_vector_type (intSI_type_node, 4); - - const_str_type_node - = build_pointer_type (build_qualified_type (char_type_node, - TYPE_QUAL_CONST)); - - /* We use V1TI mode as a special container to hold __int128_t items that - must live in VSX registers. */ - if (intTI_type_node) - { - V1TI_type_node = rs6000_vector_type ("__vector __int128", - intTI_type_node, 1); - unsigned_V1TI_type_node - = rs6000_vector_type ("__vector unsigned __int128", - unsigned_intTI_type_node, 1); - } - - /* The 'vector bool ...' types must be kept distinct from 'vector unsigned ...' - types, especially in C++ land. Similarly, 'vector pixel' is distinct from - 'vector unsigned short'. */ - - bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node); - bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node); - bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node); - bool_long_long_type_node = build_distinct_type_copy (unsigned_intDI_type_node); - pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node); - - long_integer_type_internal_node = long_integer_type_node; - long_unsigned_type_internal_node = long_unsigned_type_node; - long_long_integer_type_internal_node = long_long_integer_type_node; - long_long_unsigned_type_internal_node = long_long_unsigned_type_node; - intQI_type_internal_node = intQI_type_node; - uintQI_type_internal_node = unsigned_intQI_type_node; - intHI_type_internal_node = intHI_type_node; - uintHI_type_internal_node = unsigned_intHI_type_node; - intSI_type_internal_node = intSI_type_node; - uintSI_type_internal_node = unsigned_intSI_type_node; - intDI_type_internal_node = intDI_type_node; - uintDI_type_internal_node = unsigned_intDI_type_node; - intTI_type_internal_node = intTI_type_node; - uintTI_type_internal_node = unsigned_intTI_type_node; - float_type_internal_node = float_type_node; - double_type_internal_node = double_type_node; - long_double_type_internal_node = long_double_type_node; - dfloat64_type_internal_node = dfloat64_type_node; - dfloat128_type_internal_node = dfloat128_type_node; - void_type_internal_node = void_type_node; - - /* 128-bit floating point support. KFmode is IEEE 128-bit floating point. - IFmode is the IBM extended 128-bit format that is a pair of doubles. - TFmode will be either IEEE 128-bit floating point or the IBM double-double - format that uses a pair of doubles, depending on the switches and - defaults. - - If we don't support for either 128-bit IBM double double or IEEE 128-bit - floating point, we need make sure the type is non-zero or else self-test - fails during bootstrap. - - Always create __ibm128 as a separate type, even if the current long double - format is IBM extended double. - - For IEEE 128-bit floating point, always create the type __ieee128. If the - user used -mfloat128, rs6000-c.c will create a define from __float128 to - __ieee128. */ - if (TARGET_FLOAT128_TYPE) - { - if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128) - ibm128_float_type_node = long_double_type_node; - else - { - ibm128_float_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (ibm128_float_type_node) = 128; - SET_TYPE_MODE (ibm128_float_type_node, IFmode); - layout_type (ibm128_float_type_node); - } - - lang_hooks.types.register_builtin_type (ibm128_float_type_node, - "__ibm128"); - - if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128) - ieee128_float_type_node = long_double_type_node; - else - ieee128_float_type_node = float128_type_node; - - lang_hooks.types.register_builtin_type (ieee128_float_type_node, - "__ieee128"); - } - - else - ieee128_float_type_node = ibm128_float_type_node = long_double_type_node; - - /* Initialize the modes for builtin_function_type, mapping a machine mode to - tree type node. */ - builtin_mode_to_type[QImode][0] = integer_type_node; - builtin_mode_to_type[HImode][0] = integer_type_node; - builtin_mode_to_type[SImode][0] = intSI_type_node; - builtin_mode_to_type[SImode][1] = unsigned_intSI_type_node; - builtin_mode_to_type[DImode][0] = intDI_type_node; - builtin_mode_to_type[DImode][1] = unsigned_intDI_type_node; - builtin_mode_to_type[TImode][0] = intTI_type_node; - builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node; - builtin_mode_to_type[SFmode][0] = float_type_node; - builtin_mode_to_type[DFmode][0] = double_type_node; - builtin_mode_to_type[IFmode][0] = ibm128_float_type_node; - builtin_mode_to_type[KFmode][0] = ieee128_float_type_node; - builtin_mode_to_type[TFmode][0] = long_double_type_node; - builtin_mode_to_type[DDmode][0] = dfloat64_type_node; - builtin_mode_to_type[TDmode][0] = dfloat128_type_node; - builtin_mode_to_type[V1TImode][0] = V1TI_type_node; - builtin_mode_to_type[V1TImode][1] = unsigned_V1TI_type_node; - builtin_mode_to_type[V2DImode][0] = V2DI_type_node; - builtin_mode_to_type[V2DImode][1] = unsigned_V2DI_type_node; - builtin_mode_to_type[V2DFmode][0] = V2DF_type_node; - builtin_mode_to_type[V4SImode][0] = V4SI_type_node; - builtin_mode_to_type[V4SImode][1] = unsigned_V4SI_type_node; - builtin_mode_to_type[V4SFmode][0] = V4SF_type_node; - builtin_mode_to_type[V8HImode][0] = V8HI_type_node; - builtin_mode_to_type[V8HImode][1] = unsigned_V8HI_type_node; - builtin_mode_to_type[V16QImode][0] = V16QI_type_node; - builtin_mode_to_type[V16QImode][1] = unsigned_V16QI_type_node; - - tdecl = add_builtin_type ("__bool char", bool_char_type_node); - TYPE_NAME (bool_char_type_node) = tdecl; - - tdecl = add_builtin_type ("__bool short", bool_short_type_node); - TYPE_NAME (bool_short_type_node) = tdecl; - - tdecl = add_builtin_type ("__bool int", bool_int_type_node); - TYPE_NAME (bool_int_type_node) = tdecl; - - tdecl = add_builtin_type ("__pixel", pixel_type_node); - TYPE_NAME (pixel_type_node) = tdecl; - - bool_V16QI_type_node = rs6000_vector_type ("__vector __bool char", - bool_char_type_node, 16); - bool_V8HI_type_node = rs6000_vector_type ("__vector __bool short", - bool_short_type_node, 8); - bool_V4SI_type_node = rs6000_vector_type ("__vector __bool int", - bool_int_type_node, 4); - bool_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 - ? "__vector __bool long" - : "__vector __bool long long", - bool_long_long_type_node, 2); - pixel_V8HI_type_node = rs6000_vector_type ("__vector __pixel", - pixel_type_node, 8); - - /* Create Altivec and VSX builtins on machines with at least the - general purpose extensions (970 and newer) to allow the use of - the target attribute. */ - if (TARGET_EXTRA_BUILTINS) - altivec_init_builtins (); - if (TARGET_HTM) - htm_init_builtins (); - - if (TARGET_EXTRA_BUILTINS) - rs6000_common_init_builtins (); - - ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode, - RS6000_BUILTIN_RECIP, "__builtin_recipdiv"); - def_builtin ("__builtin_recipdiv", ftype, RS6000_BUILTIN_RECIP); - - ftype = builtin_function_type (SFmode, SFmode, SFmode, VOIDmode, - RS6000_BUILTIN_RECIPF, "__builtin_recipdivf"); - def_builtin ("__builtin_recipdivf", ftype, RS6000_BUILTIN_RECIPF); - - ftype = builtin_function_type (DFmode, DFmode, VOIDmode, VOIDmode, - RS6000_BUILTIN_RSQRT, "__builtin_rsqrt"); - def_builtin ("__builtin_rsqrt", ftype, RS6000_BUILTIN_RSQRT); - - ftype = builtin_function_type (SFmode, SFmode, VOIDmode, VOIDmode, - RS6000_BUILTIN_RSQRTF, "__builtin_rsqrtf"); - def_builtin ("__builtin_rsqrtf", ftype, RS6000_BUILTIN_RSQRTF); - - mode = (TARGET_64BIT) ? DImode : SImode; - ftype = builtin_function_type (mode, mode, mode, VOIDmode, - POWER7_BUILTIN_BPERMD, "__builtin_bpermd"); - def_builtin ("__builtin_bpermd", ftype, POWER7_BUILTIN_BPERMD); - - ftype = build_function_type_list (unsigned_intDI_type_node, - NULL_TREE); - def_builtin ("__builtin_ppc_get_timebase", ftype, RS6000_BUILTIN_GET_TB); - - if (TARGET_64BIT) - ftype = build_function_type_list (unsigned_intDI_type_node, - NULL_TREE); - else - ftype = build_function_type_list (unsigned_intSI_type_node, - NULL_TREE); - def_builtin ("__builtin_ppc_mftb", ftype, RS6000_BUILTIN_MFTB); - - ftype = build_function_type_list (double_type_node, NULL_TREE); - def_builtin ("__builtin_mffs", ftype, RS6000_BUILTIN_MFFS); - - ftype = build_function_type_list (double_type_node, NULL_TREE); - def_builtin ("__builtin_mffsl", ftype, RS6000_BUILTIN_MFFSL); - - ftype = build_function_type_list (void_type_node, - intSI_type_node, - NULL_TREE); - def_builtin ("__builtin_mtfsb0", ftype, RS6000_BUILTIN_MTFSB0); - - ftype = build_function_type_list (void_type_node, - intSI_type_node, - NULL_TREE); - def_builtin ("__builtin_mtfsb1", ftype, RS6000_BUILTIN_MTFSB1); - - ftype = build_function_type_list (void_type_node, - intDI_type_node, - NULL_TREE); - def_builtin ("__builtin_set_fpscr_rn", ftype, RS6000_BUILTIN_SET_FPSCR_RN); - - ftype = build_function_type_list (void_type_node, - intDI_type_node, - NULL_TREE); - def_builtin ("__builtin_set_fpscr_drn", ftype, RS6000_BUILTIN_SET_FPSCR_DRN); - - ftype = build_function_type_list (void_type_node, - intSI_type_node, double_type_node, - NULL_TREE); - def_builtin ("__builtin_mtfsf", ftype, RS6000_BUILTIN_MTFSF); - - ftype = build_function_type_list (void_type_node, NULL_TREE); - def_builtin ("__builtin_cpu_init", ftype, RS6000_BUILTIN_CPU_INIT); - def_builtin ("__builtin_ppc_speculation_barrier", ftype, - MISC_BUILTIN_SPEC_BARRIER); - - ftype = build_function_type_list (bool_int_type_node, const_ptr_type_node, - NULL_TREE); - def_builtin ("__builtin_cpu_is", ftype, RS6000_BUILTIN_CPU_IS); - def_builtin ("__builtin_cpu_supports", ftype, RS6000_BUILTIN_CPU_SUPPORTS); - - /* AIX libm provides clog as __clog. */ - if (TARGET_XCOFF && - (tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE) - set_user_assembler_name (tdecl, "__clog"); - -#ifdef SUBTARGET_INIT_BUILTINS - SUBTARGET_INIT_BUILTINS; -#endif -} - -/* Returns the rs6000 builtin decl for CODE. */ - -static tree -rs6000_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) -{ - HOST_WIDE_INT fnmask; - - if (code >= RS6000_BUILTIN_COUNT) - return error_mark_node; - - fnmask = rs6000_builtin_info[code].mask; - if ((fnmask & rs6000_builtin_mask) != fnmask) - { - rs6000_invalid_builtin ((enum rs6000_builtins)code); - return error_mark_node; - } - - return rs6000_builtin_decls[code]; -} - -static void -altivec_init_builtins (void) -{ - const struct builtin_description *d; - size_t i; - tree ftype; - tree decl; - HOST_WIDE_INT builtin_mask = rs6000_builtin_mask; - - tree pvoid_type_node = build_pointer_type (void_type_node); - - tree pcvoid_type_node - = build_pointer_type (build_qualified_type (void_type_node, - TYPE_QUAL_CONST)); - - tree int_ftype_opaque - = build_function_type_list (integer_type_node, - opaque_V4SI_type_node, NULL_TREE); - tree opaque_ftype_opaque - = build_function_type_list (integer_type_node, NULL_TREE); - tree opaque_ftype_opaque_int - = build_function_type_list (opaque_V4SI_type_node, - opaque_V4SI_type_node, integer_type_node, NULL_TREE); - tree opaque_ftype_opaque_opaque_int - = build_function_type_list (opaque_V4SI_type_node, - opaque_V4SI_type_node, opaque_V4SI_type_node, - integer_type_node, NULL_TREE); - tree opaque_ftype_opaque_opaque_opaque - = build_function_type_list (opaque_V4SI_type_node, - opaque_V4SI_type_node, opaque_V4SI_type_node, - opaque_V4SI_type_node, NULL_TREE); - tree opaque_ftype_opaque_opaque - = build_function_type_list (opaque_V4SI_type_node, - opaque_V4SI_type_node, opaque_V4SI_type_node, - NULL_TREE); - tree int_ftype_int_opaque_opaque - = build_function_type_list (integer_type_node, - integer_type_node, opaque_V4SI_type_node, - opaque_V4SI_type_node, NULL_TREE); - tree int_ftype_int_v4si_v4si - = build_function_type_list (integer_type_node, - integer_type_node, V4SI_type_node, - V4SI_type_node, NULL_TREE); - tree int_ftype_int_v2di_v2di - = build_function_type_list (integer_type_node, - integer_type_node, V2DI_type_node, - V2DI_type_node, NULL_TREE); - tree void_ftype_v4si - = build_function_type_list (void_type_node, V4SI_type_node, NULL_TREE); - tree v8hi_ftype_void - = build_function_type_list (V8HI_type_node, NULL_TREE); - tree void_ftype_void - = build_function_type_list (void_type_node, NULL_TREE); - tree void_ftype_int - = build_function_type_list (void_type_node, integer_type_node, NULL_TREE); - - tree opaque_ftype_long_pcvoid - = build_function_type_list (opaque_V4SI_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree v16qi_ftype_long_pcvoid - = build_function_type_list (V16QI_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree v8hi_ftype_long_pcvoid - = build_function_type_list (V8HI_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree v4si_ftype_long_pcvoid - = build_function_type_list (V4SI_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree v4sf_ftype_long_pcvoid - = build_function_type_list (V4SF_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree v2df_ftype_long_pcvoid - = build_function_type_list (V2DF_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree v2di_ftype_long_pcvoid - = build_function_type_list (V2DI_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree v1ti_ftype_long_pcvoid - = build_function_type_list (V1TI_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - - tree void_ftype_opaque_long_pvoid - = build_function_type_list (void_type_node, - opaque_V4SI_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - tree void_ftype_v4si_long_pvoid - = build_function_type_list (void_type_node, - V4SI_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - tree void_ftype_v16qi_long_pvoid - = build_function_type_list (void_type_node, - V16QI_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - - tree void_ftype_v16qi_pvoid_long - = build_function_type_list (void_type_node, - V16QI_type_node, pvoid_type_node, - long_integer_type_node, NULL_TREE); - - tree void_ftype_v8hi_long_pvoid - = build_function_type_list (void_type_node, - V8HI_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - tree void_ftype_v4sf_long_pvoid - = build_function_type_list (void_type_node, - V4SF_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - tree void_ftype_v2df_long_pvoid - = build_function_type_list (void_type_node, - V2DF_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - tree void_ftype_v1ti_long_pvoid - = build_function_type_list (void_type_node, - V1TI_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - tree void_ftype_v2di_long_pvoid - = build_function_type_list (void_type_node, - V2DI_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - tree int_ftype_int_v8hi_v8hi - = build_function_type_list (integer_type_node, - integer_type_node, V8HI_type_node, - V8HI_type_node, NULL_TREE); - tree int_ftype_int_v16qi_v16qi - = build_function_type_list (integer_type_node, - integer_type_node, V16QI_type_node, - V16QI_type_node, NULL_TREE); - tree int_ftype_int_v4sf_v4sf - = build_function_type_list (integer_type_node, - integer_type_node, V4SF_type_node, - V4SF_type_node, NULL_TREE); - tree int_ftype_int_v2df_v2df - = build_function_type_list (integer_type_node, - integer_type_node, V2DF_type_node, - V2DF_type_node, NULL_TREE); - tree v2di_ftype_v2di - = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE); - tree v4si_ftype_v4si - = build_function_type_list (V4SI_type_node, V4SI_type_node, NULL_TREE); - tree v8hi_ftype_v8hi - = build_function_type_list (V8HI_type_node, V8HI_type_node, NULL_TREE); - tree v16qi_ftype_v16qi - = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE); - tree v4sf_ftype_v4sf - = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE); - tree v2df_ftype_v2df - = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE); - tree void_ftype_pcvoid_int_int - = build_function_type_list (void_type_node, - pcvoid_type_node, integer_type_node, - integer_type_node, NULL_TREE); - - def_builtin ("__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR); - def_builtin ("__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR); - def_builtin ("__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL); - def_builtin ("__builtin_altivec_dss", void_ftype_int, ALTIVEC_BUILTIN_DSS); - def_builtin ("__builtin_altivec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSL); - def_builtin ("__builtin_altivec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSR); - def_builtin ("__builtin_altivec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEBX); - def_builtin ("__builtin_altivec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEHX); - def_builtin ("__builtin_altivec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEWX); - def_builtin ("__builtin_altivec_lvxl", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVXL); - def_builtin ("__builtin_altivec_lvxl_v2df", v2df_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVXL_V2DF); - def_builtin ("__builtin_altivec_lvxl_v2di", v2di_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVXL_V2DI); - def_builtin ("__builtin_altivec_lvxl_v4sf", v4sf_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVXL_V4SF); - def_builtin ("__builtin_altivec_lvxl_v4si", v4si_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVXL_V4SI); - def_builtin ("__builtin_altivec_lvxl_v8hi", v8hi_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVXL_V8HI); - def_builtin ("__builtin_altivec_lvxl_v16qi", v16qi_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVXL_V16QI); - def_builtin ("__builtin_altivec_lvx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVX); - def_builtin ("__builtin_altivec_lvx_v1ti", v1ti_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVX_V1TI); - def_builtin ("__builtin_altivec_lvx_v2df", v2df_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVX_V2DF); - def_builtin ("__builtin_altivec_lvx_v2di", v2di_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVX_V2DI); - def_builtin ("__builtin_altivec_lvx_v4sf", v4sf_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVX_V4SF); - def_builtin ("__builtin_altivec_lvx_v4si", v4si_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVX_V4SI); - def_builtin ("__builtin_altivec_lvx_v8hi", v8hi_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVX_V8HI); - def_builtin ("__builtin_altivec_lvx_v16qi", v16qi_ftype_long_pcvoid, - ALTIVEC_BUILTIN_LVX_V16QI); - def_builtin ("__builtin_altivec_stvx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVX); - def_builtin ("__builtin_altivec_stvx_v2df", void_ftype_v2df_long_pvoid, - ALTIVEC_BUILTIN_STVX_V2DF); - def_builtin ("__builtin_altivec_stvx_v2di", void_ftype_v2di_long_pvoid, - ALTIVEC_BUILTIN_STVX_V2DI); - def_builtin ("__builtin_altivec_stvx_v4sf", void_ftype_v4sf_long_pvoid, - ALTIVEC_BUILTIN_STVX_V4SF); - def_builtin ("__builtin_altivec_stvx_v4si", void_ftype_v4si_long_pvoid, - ALTIVEC_BUILTIN_STVX_V4SI); - def_builtin ("__builtin_altivec_stvx_v8hi", void_ftype_v8hi_long_pvoid, - ALTIVEC_BUILTIN_STVX_V8HI); - def_builtin ("__builtin_altivec_stvx_v16qi", void_ftype_v16qi_long_pvoid, - ALTIVEC_BUILTIN_STVX_V16QI); - def_builtin ("__builtin_altivec_stvewx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVEWX); - def_builtin ("__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL); - def_builtin ("__builtin_altivec_stvxl_v2df", void_ftype_v2df_long_pvoid, - ALTIVEC_BUILTIN_STVXL_V2DF); - def_builtin ("__builtin_altivec_stvxl_v2di", void_ftype_v2di_long_pvoid, - ALTIVEC_BUILTIN_STVXL_V2DI); - def_builtin ("__builtin_altivec_stvxl_v4sf", void_ftype_v4sf_long_pvoid, - ALTIVEC_BUILTIN_STVXL_V4SF); - def_builtin ("__builtin_altivec_stvxl_v4si", void_ftype_v4si_long_pvoid, - ALTIVEC_BUILTIN_STVXL_V4SI); - def_builtin ("__builtin_altivec_stvxl_v8hi", void_ftype_v8hi_long_pvoid, - ALTIVEC_BUILTIN_STVXL_V8HI); - def_builtin ("__builtin_altivec_stvxl_v16qi", void_ftype_v16qi_long_pvoid, - ALTIVEC_BUILTIN_STVXL_V16QI); - def_builtin ("__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX); - def_builtin ("__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX); - def_builtin ("__builtin_vec_ld", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LD); - def_builtin ("__builtin_vec_lde", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDE); - def_builtin ("__builtin_vec_ldl", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDL); - def_builtin ("__builtin_vec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSL); - def_builtin ("__builtin_vec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSR); - def_builtin ("__builtin_vec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEBX); - def_builtin ("__builtin_vec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEHX); - def_builtin ("__builtin_vec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEWX); - def_builtin ("__builtin_vec_st", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_ST); - def_builtin ("__builtin_vec_ste", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STE); - def_builtin ("__builtin_vec_stl", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STL); - def_builtin ("__builtin_vec_stvewx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEWX); - def_builtin ("__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX); - def_builtin ("__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX); - - def_builtin ("__builtin_vsx_lxvd2x_v2df", v2df_ftype_long_pcvoid, - VSX_BUILTIN_LXVD2X_V2DF); - def_builtin ("__builtin_vsx_lxvd2x_v2di", v2di_ftype_long_pcvoid, - VSX_BUILTIN_LXVD2X_V2DI); - def_builtin ("__builtin_vsx_lxvw4x_v4sf", v4sf_ftype_long_pcvoid, - VSX_BUILTIN_LXVW4X_V4SF); - def_builtin ("__builtin_vsx_lxvw4x_v4si", v4si_ftype_long_pcvoid, - VSX_BUILTIN_LXVW4X_V4SI); - def_builtin ("__builtin_vsx_lxvw4x_v8hi", v8hi_ftype_long_pcvoid, - VSX_BUILTIN_LXVW4X_V8HI); - def_builtin ("__builtin_vsx_lxvw4x_v16qi", v16qi_ftype_long_pcvoid, - VSX_BUILTIN_LXVW4X_V16QI); - def_builtin ("__builtin_vsx_stxvd2x_v2df", void_ftype_v2df_long_pvoid, - VSX_BUILTIN_STXVD2X_V2DF); - def_builtin ("__builtin_vsx_stxvd2x_v2di", void_ftype_v2di_long_pvoid, - VSX_BUILTIN_STXVD2X_V2DI); - def_builtin ("__builtin_vsx_stxvw4x_v4sf", void_ftype_v4sf_long_pvoid, - VSX_BUILTIN_STXVW4X_V4SF); - def_builtin ("__builtin_vsx_stxvw4x_v4si", void_ftype_v4si_long_pvoid, - VSX_BUILTIN_STXVW4X_V4SI); - def_builtin ("__builtin_vsx_stxvw4x_v8hi", void_ftype_v8hi_long_pvoid, - VSX_BUILTIN_STXVW4X_V8HI); - def_builtin ("__builtin_vsx_stxvw4x_v16qi", void_ftype_v16qi_long_pvoid, - VSX_BUILTIN_STXVW4X_V16QI); - - def_builtin ("__builtin_vsx_ld_elemrev_v2df", v2df_ftype_long_pcvoid, - VSX_BUILTIN_LD_ELEMREV_V2DF); - def_builtin ("__builtin_vsx_ld_elemrev_v2di", v2di_ftype_long_pcvoid, - VSX_BUILTIN_LD_ELEMREV_V2DI); - def_builtin ("__builtin_vsx_ld_elemrev_v4sf", v4sf_ftype_long_pcvoid, - VSX_BUILTIN_LD_ELEMREV_V4SF); - def_builtin ("__builtin_vsx_ld_elemrev_v4si", v4si_ftype_long_pcvoid, - VSX_BUILTIN_LD_ELEMREV_V4SI); - def_builtin ("__builtin_vsx_ld_elemrev_v8hi", v8hi_ftype_long_pcvoid, - VSX_BUILTIN_LD_ELEMREV_V8HI); - def_builtin ("__builtin_vsx_ld_elemrev_v16qi", v16qi_ftype_long_pcvoid, - VSX_BUILTIN_LD_ELEMREV_V16QI); - def_builtin ("__builtin_vsx_st_elemrev_v2df", void_ftype_v2df_long_pvoid, - VSX_BUILTIN_ST_ELEMREV_V2DF); - def_builtin ("__builtin_vsx_st_elemrev_v1ti", void_ftype_v1ti_long_pvoid, - VSX_BUILTIN_ST_ELEMREV_V1TI); - def_builtin ("__builtin_vsx_st_elemrev_v2di", void_ftype_v2di_long_pvoid, - VSX_BUILTIN_ST_ELEMREV_V2DI); - def_builtin ("__builtin_vsx_st_elemrev_v4sf", void_ftype_v4sf_long_pvoid, - VSX_BUILTIN_ST_ELEMREV_V4SF); - def_builtin ("__builtin_vsx_st_elemrev_v4si", void_ftype_v4si_long_pvoid, - VSX_BUILTIN_ST_ELEMREV_V4SI); - def_builtin ("__builtin_vsx_st_elemrev_v8hi", void_ftype_v8hi_long_pvoid, - VSX_BUILTIN_ST_ELEMREV_V8HI); - def_builtin ("__builtin_vsx_st_elemrev_v16qi", void_ftype_v16qi_long_pvoid, - VSX_BUILTIN_ST_ELEMREV_V16QI); - - def_builtin ("__builtin_vec_vsx_ld", opaque_ftype_long_pcvoid, - VSX_BUILTIN_VEC_LD); - def_builtin ("__builtin_vec_vsx_st", void_ftype_opaque_long_pvoid, - VSX_BUILTIN_VEC_ST); - def_builtin ("__builtin_vec_xl", opaque_ftype_long_pcvoid, - VSX_BUILTIN_VEC_XL); - def_builtin ("__builtin_vec_xl_be", opaque_ftype_long_pcvoid, - VSX_BUILTIN_VEC_XL_BE); - def_builtin ("__builtin_vec_xst", void_ftype_opaque_long_pvoid, - VSX_BUILTIN_VEC_XST); - def_builtin ("__builtin_vec_xst_be", void_ftype_opaque_long_pvoid, - VSX_BUILTIN_VEC_XST_BE); - - def_builtin ("__builtin_vec_step", int_ftype_opaque, ALTIVEC_BUILTIN_VEC_STEP); - def_builtin ("__builtin_vec_splats", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_SPLATS); - def_builtin ("__builtin_vec_promote", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_PROMOTE); - - def_builtin ("__builtin_vec_sld", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_SLD); - def_builtin ("__builtin_vec_splat", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_SPLAT); - def_builtin ("__builtin_vec_extract", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_EXTRACT); - def_builtin ("__builtin_vec_insert", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_INSERT); - def_builtin ("__builtin_vec_vspltw", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTW); - def_builtin ("__builtin_vec_vsplth", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTH); - def_builtin ("__builtin_vec_vspltb", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTB); - def_builtin ("__builtin_vec_ctf", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTF); - def_builtin ("__builtin_vec_vcfsx", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFSX); - def_builtin ("__builtin_vec_vcfux", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFUX); - def_builtin ("__builtin_vec_cts", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTS); - def_builtin ("__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU); - - def_builtin ("__builtin_vec_adde", opaque_ftype_opaque_opaque_opaque, - ALTIVEC_BUILTIN_VEC_ADDE); - def_builtin ("__builtin_vec_addec", opaque_ftype_opaque_opaque_opaque, - ALTIVEC_BUILTIN_VEC_ADDEC); - def_builtin ("__builtin_vec_cmpne", opaque_ftype_opaque_opaque, - ALTIVEC_BUILTIN_VEC_CMPNE); - def_builtin ("__builtin_vec_mul", opaque_ftype_opaque_opaque, - ALTIVEC_BUILTIN_VEC_MUL); - def_builtin ("__builtin_vec_sube", opaque_ftype_opaque_opaque_opaque, - ALTIVEC_BUILTIN_VEC_SUBE); - def_builtin ("__builtin_vec_subec", opaque_ftype_opaque_opaque_opaque, - ALTIVEC_BUILTIN_VEC_SUBEC); - - /* Cell builtins. */ - def_builtin ("__builtin_altivec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLX); - def_builtin ("__builtin_altivec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLXL); - def_builtin ("__builtin_altivec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRX); - def_builtin ("__builtin_altivec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVRXL); - - def_builtin ("__builtin_vec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLX); - def_builtin ("__builtin_vec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVLXL); - def_builtin ("__builtin_vec_lvrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRX); - def_builtin ("__builtin_vec_lvrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVRXL); - - def_builtin ("__builtin_altivec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLX); - def_builtin ("__builtin_altivec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVLXL); - def_builtin ("__builtin_altivec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRX); - def_builtin ("__builtin_altivec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVRXL); - - def_builtin ("__builtin_vec_stvlx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLX); - def_builtin ("__builtin_vec_stvlxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVLXL); - def_builtin ("__builtin_vec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRX); - def_builtin ("__builtin_vec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRXL); - - if (TARGET_P9_VECTOR) - { - def_builtin ("__builtin_altivec_stxvl", void_ftype_v16qi_pvoid_long, - P9V_BUILTIN_STXVL); - def_builtin ("__builtin_xst_len_r", void_ftype_v16qi_pvoid_long, - P9V_BUILTIN_XST_LEN_R); - } - - /* Add the DST variants. */ - d = bdesc_dst; - for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++) - { - HOST_WIDE_INT mask = d->mask; - - /* It is expected that these dst built-in functions may have - d->icode equal to CODE_FOR_nothing. */ - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "altivec_init_builtins, skip dst %s\n", - d->name); - continue; - } - def_builtin (d->name, void_ftype_pcvoid_int_int, d->code); - } - - /* Initialize the predicates. */ - d = bdesc_altivec_preds; - for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, d++) - { - machine_mode mode1; - tree type; - HOST_WIDE_INT mask = d->mask; - - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "altivec_init_builtins, skip predicate %s\n", - d->name); - continue; - } - - if (rs6000_overloaded_builtin_p (d->code)) - mode1 = VOIDmode; - else - { - /* Cannot define builtin if the instruction is disabled. */ - gcc_assert (d->icode != CODE_FOR_nothing); - mode1 = insn_data[d->icode].operand[1].mode; - } - - switch (mode1) - { - case E_VOIDmode: - type = int_ftype_int_opaque_opaque; - break; - case E_V2DImode: - type = int_ftype_int_v2di_v2di; - break; - case E_V4SImode: - type = int_ftype_int_v4si_v4si; - break; - case E_V8HImode: - type = int_ftype_int_v8hi_v8hi; - break; - case E_V16QImode: - type = int_ftype_int_v16qi_v16qi; - break; - case E_V4SFmode: - type = int_ftype_int_v4sf_v4sf; - break; - case E_V2DFmode: - type = int_ftype_int_v2df_v2df; - break; - default: - gcc_unreachable (); - } - - def_builtin (d->name, type, d->code); - } - - /* Initialize the abs* operators. */ - d = bdesc_abs; - for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++) - { - machine_mode mode0; - tree type; - HOST_WIDE_INT mask = d->mask; - - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "altivec_init_builtins, skip abs %s\n", - d->name); - continue; - } - - /* Cannot define builtin if the instruction is disabled. */ - gcc_assert (d->icode != CODE_FOR_nothing); - mode0 = insn_data[d->icode].operand[0].mode; - - switch (mode0) - { - case E_V2DImode: - type = v2di_ftype_v2di; - break; - case E_V4SImode: - type = v4si_ftype_v4si; - break; - case E_V8HImode: - type = v8hi_ftype_v8hi; - break; - case E_V16QImode: - type = v16qi_ftype_v16qi; - break; - case E_V4SFmode: - type = v4sf_ftype_v4sf; - break; - case E_V2DFmode: - type = v2df_ftype_v2df; - break; - default: - gcc_unreachable (); - } - - def_builtin (d->name, type, d->code); - } - - /* Initialize target builtin that implements - targetm.vectorize.builtin_mask_for_load. */ - - decl = add_builtin_function ("__builtin_altivec_mask_for_load", - v16qi_ftype_long_pcvoid, - ALTIVEC_BUILTIN_MASK_FOR_LOAD, - BUILT_IN_MD, NULL, NULL_TREE); - TREE_READONLY (decl) = 1; - /* Record the decl. Will be used by rs6000_builtin_mask_for_load. */ - altivec_builtin_mask_for_load = decl; - - /* Access to the vec_init patterns. */ - ftype = build_function_type_list (V4SI_type_node, integer_type_node, - integer_type_node, integer_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_init_v4si", ftype, ALTIVEC_BUILTIN_VEC_INIT_V4SI); - - ftype = build_function_type_list (V8HI_type_node, short_integer_type_node, - short_integer_type_node, - short_integer_type_node, - short_integer_type_node, - short_integer_type_node, - short_integer_type_node, - short_integer_type_node, - short_integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_init_v8hi", ftype, ALTIVEC_BUILTIN_VEC_INIT_V8HI); - - ftype = build_function_type_list (V16QI_type_node, char_type_node, - char_type_node, char_type_node, - char_type_node, char_type_node, - char_type_node, char_type_node, - char_type_node, char_type_node, - char_type_node, char_type_node, - char_type_node, char_type_node, - char_type_node, char_type_node, - char_type_node, NULL_TREE); - def_builtin ("__builtin_vec_init_v16qi", ftype, - ALTIVEC_BUILTIN_VEC_INIT_V16QI); - - ftype = build_function_type_list (V4SF_type_node, float_type_node, - float_type_node, float_type_node, - float_type_node, NULL_TREE); - def_builtin ("__builtin_vec_init_v4sf", ftype, ALTIVEC_BUILTIN_VEC_INIT_V4SF); - - /* VSX builtins. */ - ftype = build_function_type_list (V2DF_type_node, double_type_node, - double_type_node, NULL_TREE); - def_builtin ("__builtin_vec_init_v2df", ftype, VSX_BUILTIN_VEC_INIT_V2DF); - - ftype = build_function_type_list (V2DI_type_node, intDI_type_node, - intDI_type_node, NULL_TREE); - def_builtin ("__builtin_vec_init_v2di", ftype, VSX_BUILTIN_VEC_INIT_V2DI); - - /* Access to the vec_set patterns. */ - ftype = build_function_type_list (V4SI_type_node, V4SI_type_node, - intSI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_set_v4si", ftype, ALTIVEC_BUILTIN_VEC_SET_V4SI); - - ftype = build_function_type_list (V8HI_type_node, V8HI_type_node, - intHI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_set_v8hi", ftype, ALTIVEC_BUILTIN_VEC_SET_V8HI); - - ftype = build_function_type_list (V16QI_type_node, V16QI_type_node, - intQI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_set_v16qi", ftype, ALTIVEC_BUILTIN_VEC_SET_V16QI); - - ftype = build_function_type_list (V4SF_type_node, V4SF_type_node, - float_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_set_v4sf", ftype, ALTIVEC_BUILTIN_VEC_SET_V4SF); - - ftype = build_function_type_list (V2DF_type_node, V2DF_type_node, - double_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_set_v2df", ftype, VSX_BUILTIN_VEC_SET_V2DF); - - ftype = build_function_type_list (V2DI_type_node, V2DI_type_node, - intDI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_set_v2di", ftype, VSX_BUILTIN_VEC_SET_V2DI); - - /* Access to the vec_extract patterns. */ - ftype = build_function_type_list (intSI_type_node, V4SI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_ext_v4si", ftype, ALTIVEC_BUILTIN_VEC_EXT_V4SI); - - ftype = build_function_type_list (intHI_type_node, V8HI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_ext_v8hi", ftype, ALTIVEC_BUILTIN_VEC_EXT_V8HI); - - ftype = build_function_type_list (intQI_type_node, V16QI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_ext_v16qi", ftype, ALTIVEC_BUILTIN_VEC_EXT_V16QI); - - ftype = build_function_type_list (float_type_node, V4SF_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_ext_v4sf", ftype, ALTIVEC_BUILTIN_VEC_EXT_V4SF); - - ftype = build_function_type_list (double_type_node, V2DF_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_ext_v2df", ftype, VSX_BUILTIN_VEC_EXT_V2DF); - - ftype = build_function_type_list (intDI_type_node, V2DI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_ext_v2di", ftype, VSX_BUILTIN_VEC_EXT_V2DI); - - - if (V1TI_type_node) - { - tree v1ti_ftype_long_pcvoid - = build_function_type_list (V1TI_type_node, - long_integer_type_node, pcvoid_type_node, - NULL_TREE); - tree void_ftype_v1ti_long_pvoid - = build_function_type_list (void_type_node, - V1TI_type_node, long_integer_type_node, - pvoid_type_node, NULL_TREE); - def_builtin ("__builtin_vsx_ld_elemrev_v1ti", v1ti_ftype_long_pcvoid, - VSX_BUILTIN_LD_ELEMREV_V1TI); - def_builtin ("__builtin_vsx_lxvd2x_v1ti", v1ti_ftype_long_pcvoid, - VSX_BUILTIN_LXVD2X_V1TI); - def_builtin ("__builtin_vsx_stxvd2x_v1ti", void_ftype_v1ti_long_pvoid, - VSX_BUILTIN_STXVD2X_V1TI); - ftype = build_function_type_list (V1TI_type_node, intTI_type_node, - NULL_TREE, NULL_TREE); - def_builtin ("__builtin_vec_init_v1ti", ftype, VSX_BUILTIN_VEC_INIT_V1TI); - ftype = build_function_type_list (V1TI_type_node, V1TI_type_node, - intTI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_set_v1ti", ftype, VSX_BUILTIN_VEC_SET_V1TI); - ftype = build_function_type_list (intTI_type_node, V1TI_type_node, - integer_type_node, NULL_TREE); - def_builtin ("__builtin_vec_ext_v1ti", ftype, VSX_BUILTIN_VEC_EXT_V1TI); - } - -} - -static void -htm_init_builtins (void) -{ - HOST_WIDE_INT builtin_mask = rs6000_builtin_mask; - const struct builtin_description *d; - size_t i; - - d = bdesc_htm; - for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++) - { - tree op[MAX_HTM_OPERANDS], type; - HOST_WIDE_INT mask = d->mask; - unsigned attr = rs6000_builtin_info[d->code].attr; - bool void_func = (attr & RS6000_BTC_VOID); - int attr_args = (attr & RS6000_BTC_TYPE_MASK); - int nopnds = 0; - tree gpr_type_node; - tree rettype; - tree argtype; - - /* It is expected that these htm built-in functions may have - d->icode equal to CODE_FOR_nothing. */ - - if (TARGET_32BIT && TARGET_POWERPC64) - gpr_type_node = long_long_unsigned_type_node; - else - gpr_type_node = long_unsigned_type_node; - - if (attr & RS6000_BTC_SPR) - { - rettype = gpr_type_node; - argtype = gpr_type_node; - } - else if (d->code == HTM_BUILTIN_TABORTDC - || d->code == HTM_BUILTIN_TABORTDCI) - { - rettype = unsigned_type_node; - argtype = gpr_type_node; - } - else - { - rettype = unsigned_type_node; - argtype = unsigned_type_node; - } - - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "htm_builtin, skip binary %s\n", d->name); - continue; - } - - if (d->name == 0) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "htm_builtin, bdesc_htm[%ld] no name\n", - (long unsigned) i); - continue; - } - - op[nopnds++] = (void_func) ? void_type_node : rettype; - - if (attr_args == RS6000_BTC_UNARY) - op[nopnds++] = argtype; - else if (attr_args == RS6000_BTC_BINARY) - { - op[nopnds++] = argtype; - op[nopnds++] = argtype; - } - else if (attr_args == RS6000_BTC_TERNARY) - { - op[nopnds++] = argtype; - op[nopnds++] = argtype; - op[nopnds++] = argtype; - } - - switch (nopnds) - { - case 1: - type = build_function_type_list (op[0], NULL_TREE); - break; - case 2: - type = build_function_type_list (op[0], op[1], NULL_TREE); - break; - case 3: - type = build_function_type_list (op[0], op[1], op[2], NULL_TREE); - break; - case 4: - type = build_function_type_list (op[0], op[1], op[2], op[3], - NULL_TREE); - break; - default: - gcc_unreachable (); - } - - def_builtin (d->name, type, d->code); - } -} - -/* Hash function for builtin functions with up to 3 arguments and a return - type. */ -hashval_t -builtin_hasher::hash (builtin_hash_struct *bh) -{ - unsigned ret = 0; - int i; - - for (i = 0; i < 4; i++) - { - ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]); - ret = (ret * 2) + bh->uns_p[i]; - } - - return ret; -} - -/* Compare builtin hash entries H1 and H2 for equivalence. */ -bool -builtin_hasher::equal (builtin_hash_struct *p1, builtin_hash_struct *p2) -{ - return ((p1->mode[0] == p2->mode[0]) - && (p1->mode[1] == p2->mode[1]) - && (p1->mode[2] == p2->mode[2]) - && (p1->mode[3] == p2->mode[3]) - && (p1->uns_p[0] == p2->uns_p[0]) - && (p1->uns_p[1] == p2->uns_p[1]) - && (p1->uns_p[2] == p2->uns_p[2]) - && (p1->uns_p[3] == p2->uns_p[3])); -} - -/* Map types for builtin functions with an explicit return type and up to 3 - arguments. Functions with fewer than 3 arguments use VOIDmode as the type - of the argument. */ -static tree -builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0, - machine_mode mode_arg1, machine_mode mode_arg2, - enum rs6000_builtins builtin, const char *name) -{ - struct builtin_hash_struct h; - struct builtin_hash_struct *h2; - int num_args = 3; - int i; - tree ret_type = NULL_TREE; - tree arg_type[3] = { NULL_TREE, NULL_TREE, NULL_TREE }; - - /* Create builtin_hash_table. */ - if (builtin_hash_table == NULL) - builtin_hash_table = hash_table::create_ggc (1500); - - h.type = NULL_TREE; - h.mode[0] = mode_ret; - h.mode[1] = mode_arg0; - h.mode[2] = mode_arg1; - h.mode[3] = mode_arg2; - h.uns_p[0] = 0; - h.uns_p[1] = 0; - h.uns_p[2] = 0; - h.uns_p[3] = 0; - - /* If the builtin is a type that produces unsigned results or takes unsigned - arguments, and it is returned as a decl for the vectorizer (such as - widening multiplies, permute), make sure the arguments and return value - are type correct. */ - switch (builtin) - { - /* unsigned 1 argument functions. */ - case CRYPTO_BUILTIN_VSBOX: - case CRYPTO_BUILTIN_VSBOX_BE: - case P8V_BUILTIN_VGBBD: - case MISC_BUILTIN_CDTBCD: - case MISC_BUILTIN_CBCDTD: - h.uns_p[0] = 1; - h.uns_p[1] = 1; - break; - - /* unsigned 2 argument functions. */ - case ALTIVEC_BUILTIN_VMULEUB: - case ALTIVEC_BUILTIN_VMULEUH: - case P8V_BUILTIN_VMULEUW: - case ALTIVEC_BUILTIN_VMULOUB: - case ALTIVEC_BUILTIN_VMULOUH: - case P8V_BUILTIN_VMULOUW: - case CRYPTO_BUILTIN_VCIPHER: - case CRYPTO_BUILTIN_VCIPHER_BE: - case CRYPTO_BUILTIN_VCIPHERLAST: - case CRYPTO_BUILTIN_VCIPHERLAST_BE: - case CRYPTO_BUILTIN_VNCIPHER: - case CRYPTO_BUILTIN_VNCIPHER_BE: - case CRYPTO_BUILTIN_VNCIPHERLAST: - case CRYPTO_BUILTIN_VNCIPHERLAST_BE: - case CRYPTO_BUILTIN_VPMSUMB: - case CRYPTO_BUILTIN_VPMSUMH: - case CRYPTO_BUILTIN_VPMSUMW: - case CRYPTO_BUILTIN_VPMSUMD: - case CRYPTO_BUILTIN_VPMSUM: - case MISC_BUILTIN_ADDG6S: - case MISC_BUILTIN_DIVWEU: - case MISC_BUILTIN_DIVDEU: - case VSX_BUILTIN_UDIV_V2DI: - case ALTIVEC_BUILTIN_VMAXUB: - case ALTIVEC_BUILTIN_VMINUB: - case ALTIVEC_BUILTIN_VMAXUH: - case ALTIVEC_BUILTIN_VMINUH: - case ALTIVEC_BUILTIN_VMAXUW: - case ALTIVEC_BUILTIN_VMINUW: - case P8V_BUILTIN_VMAXUD: - case P8V_BUILTIN_VMINUD: - h.uns_p[0] = 1; - h.uns_p[1] = 1; - h.uns_p[2] = 1; - break; - - /* unsigned 3 argument functions. */ - case ALTIVEC_BUILTIN_VPERM_16QI_UNS: - case ALTIVEC_BUILTIN_VPERM_8HI_UNS: - case ALTIVEC_BUILTIN_VPERM_4SI_UNS: - case ALTIVEC_BUILTIN_VPERM_2DI_UNS: - case ALTIVEC_BUILTIN_VSEL_16QI_UNS: - case ALTIVEC_BUILTIN_VSEL_8HI_UNS: - case ALTIVEC_BUILTIN_VSEL_4SI_UNS: - case ALTIVEC_BUILTIN_VSEL_2DI_UNS: - case VSX_BUILTIN_VPERM_16QI_UNS: - case VSX_BUILTIN_VPERM_8HI_UNS: - case VSX_BUILTIN_VPERM_4SI_UNS: - case VSX_BUILTIN_VPERM_2DI_UNS: - case VSX_BUILTIN_XXSEL_16QI_UNS: - case VSX_BUILTIN_XXSEL_8HI_UNS: - case VSX_BUILTIN_XXSEL_4SI_UNS: - case VSX_BUILTIN_XXSEL_2DI_UNS: - case CRYPTO_BUILTIN_VPERMXOR: - case CRYPTO_BUILTIN_VPERMXOR_V2DI: - case CRYPTO_BUILTIN_VPERMXOR_V4SI: - case CRYPTO_BUILTIN_VPERMXOR_V8HI: - case CRYPTO_BUILTIN_VPERMXOR_V16QI: - case CRYPTO_BUILTIN_VSHASIGMAW: - case CRYPTO_BUILTIN_VSHASIGMAD: - case CRYPTO_BUILTIN_VSHASIGMA: - h.uns_p[0] = 1; - h.uns_p[1] = 1; - h.uns_p[2] = 1; - h.uns_p[3] = 1; - break; - - /* signed permute functions with unsigned char mask. */ - case ALTIVEC_BUILTIN_VPERM_16QI: - case ALTIVEC_BUILTIN_VPERM_8HI: - case ALTIVEC_BUILTIN_VPERM_4SI: - case ALTIVEC_BUILTIN_VPERM_4SF: - case ALTIVEC_BUILTIN_VPERM_2DI: - case ALTIVEC_BUILTIN_VPERM_2DF: - case VSX_BUILTIN_VPERM_16QI: - case VSX_BUILTIN_VPERM_8HI: - case VSX_BUILTIN_VPERM_4SI: - case VSX_BUILTIN_VPERM_4SF: - case VSX_BUILTIN_VPERM_2DI: - case VSX_BUILTIN_VPERM_2DF: - h.uns_p[3] = 1; - break; - - /* unsigned args, signed return. */ - case VSX_BUILTIN_XVCVUXDSP: - case VSX_BUILTIN_XVCVUXDDP_UNS: - case ALTIVEC_BUILTIN_UNSFLOAT_V4SI_V4SF: - h.uns_p[1] = 1; - break; - - /* signed args, unsigned return. */ - case VSX_BUILTIN_XVCVDPUXDS_UNS: - case ALTIVEC_BUILTIN_FIXUNS_V4SF_V4SI: - case MISC_BUILTIN_UNPACK_TD: - case MISC_BUILTIN_UNPACK_V1TI: - h.uns_p[0] = 1; - break; - - /* unsigned arguments, bool return (compares). */ - case ALTIVEC_BUILTIN_VCMPEQUB: - case ALTIVEC_BUILTIN_VCMPEQUH: - case ALTIVEC_BUILTIN_VCMPEQUW: - case P8V_BUILTIN_VCMPEQUD: - case VSX_BUILTIN_CMPGE_U16QI: - case VSX_BUILTIN_CMPGE_U8HI: - case VSX_BUILTIN_CMPGE_U4SI: - case VSX_BUILTIN_CMPGE_U2DI: - case ALTIVEC_BUILTIN_VCMPGTUB: - case ALTIVEC_BUILTIN_VCMPGTUH: - case ALTIVEC_BUILTIN_VCMPGTUW: - case P8V_BUILTIN_VCMPGTUD: - h.uns_p[1] = 1; - h.uns_p[2] = 1; - break; - - /* unsigned arguments for 128-bit pack instructions. */ - case MISC_BUILTIN_PACK_TD: - case MISC_BUILTIN_PACK_V1TI: - h.uns_p[1] = 1; - h.uns_p[2] = 1; - break; - - /* unsigned second arguments (vector shift right). */ - case ALTIVEC_BUILTIN_VSRB: - case ALTIVEC_BUILTIN_VSRH: - case ALTIVEC_BUILTIN_VSRW: - case P8V_BUILTIN_VSRD: - h.uns_p[2] = 1; - break; - - default: - break; - } - - /* Figure out how many args are present. */ - while (num_args > 0 && h.mode[num_args] == VOIDmode) - num_args--; - - ret_type = builtin_mode_to_type[h.mode[0]][h.uns_p[0]]; - if (!ret_type && h.uns_p[0]) - ret_type = builtin_mode_to_type[h.mode[0]][0]; - - if (!ret_type) - fatal_error (input_location, - "internal error: builtin function %qs had an unexpected " - "return type %qs", name, GET_MODE_NAME (h.mode[0])); - - for (i = 0; i < (int) ARRAY_SIZE (arg_type); i++) - arg_type[i] = NULL_TREE; - - for (i = 0; i < num_args; i++) - { - int m = (int) h.mode[i+1]; - int uns_p = h.uns_p[i+1]; - - arg_type[i] = builtin_mode_to_type[m][uns_p]; - if (!arg_type[i] && uns_p) - arg_type[i] = builtin_mode_to_type[m][0]; - - if (!arg_type[i]) - fatal_error (input_location, - "internal error: builtin function %qs, argument %d " - "had unexpected argument type %qs", name, i, - GET_MODE_NAME (m)); - } - - builtin_hash_struct **found = builtin_hash_table->find_slot (&h, INSERT); - if (*found == NULL) - { - h2 = ggc_alloc (); - *h2 = h; - *found = h2; - - h2->type = build_function_type_list (ret_type, arg_type[0], arg_type[1], - arg_type[2], NULL_TREE); - } - - return (*found)->type; -} - -static void -rs6000_common_init_builtins (void) -{ - const struct builtin_description *d; - size_t i; - - tree opaque_ftype_opaque = NULL_TREE; - tree opaque_ftype_opaque_opaque = NULL_TREE; - tree opaque_ftype_opaque_opaque_opaque = NULL_TREE; - HOST_WIDE_INT builtin_mask = rs6000_builtin_mask; - - /* Create Altivec and VSX builtins on machines with at least the - general purpose extensions (970 and newer) to allow the use of - the target attribute. */ - - if (TARGET_EXTRA_BUILTINS) - builtin_mask |= RS6000_BTM_COMMON; - - /* Add the ternary operators. */ - d = bdesc_3arg; - for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) - { - tree type; - HOST_WIDE_INT mask = d->mask; - - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, skip ternary %s\n", d->name); - continue; - } - - if (rs6000_overloaded_builtin_p (d->code)) - { - if (! (type = opaque_ftype_opaque_opaque_opaque)) - type = opaque_ftype_opaque_opaque_opaque - = build_function_type_list (opaque_V4SI_type_node, - opaque_V4SI_type_node, - opaque_V4SI_type_node, - opaque_V4SI_type_node, - NULL_TREE); - } - else - { - enum insn_code icode = d->icode; - if (d->name == 0) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, bdesc_3arg[%ld] no name\n", - (long unsigned)i); - - continue; - } - - if (icode == CODE_FOR_nothing) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, skip ternary %s (no code)\n", - d->name); - - continue; - } - - type = builtin_function_type (insn_data[icode].operand[0].mode, - insn_data[icode].operand[1].mode, - insn_data[icode].operand[2].mode, - insn_data[icode].operand[3].mode, - d->code, d->name); - } - - def_builtin (d->name, type, d->code); - } - - /* Add the binary operators. */ - d = bdesc_2arg; - for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++) - { - machine_mode mode0, mode1, mode2; - tree type; - HOST_WIDE_INT mask = d->mask; - - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, skip binary %s\n", d->name); - continue; - } - - if (rs6000_overloaded_builtin_p (d->code)) - { - if (! (type = opaque_ftype_opaque_opaque)) - type = opaque_ftype_opaque_opaque - = build_function_type_list (opaque_V4SI_type_node, - opaque_V4SI_type_node, - opaque_V4SI_type_node, - NULL_TREE); - } - else - { - enum insn_code icode = d->icode; - if (d->name == 0) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, bdesc_2arg[%ld] no name\n", - (long unsigned)i); - - continue; - } - - if (icode == CODE_FOR_nothing) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, skip binary %s (no code)\n", - d->name); - - continue; - } - - mode0 = insn_data[icode].operand[0].mode; - mode1 = insn_data[icode].operand[1].mode; - mode2 = insn_data[icode].operand[2].mode; - - type = builtin_function_type (mode0, mode1, mode2, VOIDmode, - d->code, d->name); - } - - def_builtin (d->name, type, d->code); - } - - /* Add the simple unary operators. */ - d = bdesc_1arg; - for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++) - { - machine_mode mode0, mode1; - tree type; - HOST_WIDE_INT mask = d->mask; - - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, skip unary %s\n", d->name); - continue; - } - - if (rs6000_overloaded_builtin_p (d->code)) - { - if (! (type = opaque_ftype_opaque)) - type = opaque_ftype_opaque - = build_function_type_list (opaque_V4SI_type_node, - opaque_V4SI_type_node, - NULL_TREE); - } - else - { - enum insn_code icode = d->icode; - if (d->name == 0) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, bdesc_1arg[%ld] no name\n", - (long unsigned)i); - - continue; - } - - if (icode == CODE_FOR_nothing) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, skip unary %s (no code)\n", - d->name); - - continue; - } - - mode0 = insn_data[icode].operand[0].mode; - mode1 = insn_data[icode].operand[1].mode; - - type = builtin_function_type (mode0, mode1, VOIDmode, VOIDmode, - d->code, d->name); - } - - def_builtin (d->name, type, d->code); - } - - /* Add the simple no-argument operators. */ - d = bdesc_0arg; - for (i = 0; i < ARRAY_SIZE (bdesc_0arg); i++, d++) - { - machine_mode mode0; - tree type; - HOST_WIDE_INT mask = d->mask; - - if ((mask & builtin_mask) != mask) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, skip no-argument %s\n", d->name); - continue; - } - if (rs6000_overloaded_builtin_p (d->code)) - { - if (!opaque_ftype_opaque) - opaque_ftype_opaque - = build_function_type_list (opaque_V4SI_type_node, NULL_TREE); - type = opaque_ftype_opaque; - } - else - { - enum insn_code icode = d->icode; - if (d->name == 0) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "rs6000_builtin, bdesc_0arg[%lu] no name\n", - (long unsigned) i); - continue; - } - if (icode == CODE_FOR_nothing) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, - "rs6000_builtin, skip no-argument %s (no code)\n", - d->name); - continue; - } - mode0 = insn_data[icode].operand[0].mode; - type = builtin_function_type (mode0, VOIDmode, VOIDmode, VOIDmode, - d->code, d->name); - } - def_builtin (d->name, type, d->code); - } -} - -/* Set up AIX/Darwin/64-bit Linux quad floating point routines. */ -static void -init_float128_ibm (machine_mode mode) -{ - if (!TARGET_XL_COMPAT) - { - set_optab_libfunc (add_optab, mode, "__gcc_qadd"); - set_optab_libfunc (sub_optab, mode, "__gcc_qsub"); - set_optab_libfunc (smul_optab, mode, "__gcc_qmul"); - set_optab_libfunc (sdiv_optab, mode, "__gcc_qdiv"); - - if (!TARGET_HARD_FLOAT) - { - set_optab_libfunc (neg_optab, mode, "__gcc_qneg"); - set_optab_libfunc (eq_optab, mode, "__gcc_qeq"); - set_optab_libfunc (ne_optab, mode, "__gcc_qne"); - set_optab_libfunc (gt_optab, mode, "__gcc_qgt"); - set_optab_libfunc (ge_optab, mode, "__gcc_qge"); - set_optab_libfunc (lt_optab, mode, "__gcc_qlt"); - set_optab_libfunc (le_optab, mode, "__gcc_qle"); - set_optab_libfunc (unord_optab, mode, "__gcc_qunord"); - - set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq"); - set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq"); - set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos"); - set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod"); - set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi"); - set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou"); - set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq"); - set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq"); - } - } - else - { - set_optab_libfunc (add_optab, mode, "_xlqadd"); - set_optab_libfunc (sub_optab, mode, "_xlqsub"); - set_optab_libfunc (smul_optab, mode, "_xlqmul"); - set_optab_libfunc (sdiv_optab, mode, "_xlqdiv"); - } - - /* Add various conversions for IFmode to use the traditional TFmode - names. */ - if (mode == IFmode) - { - set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdtf"); - set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddtf"); - set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunctdtf"); - set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunctfsd"); - set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunctfdd"); - set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendtftd"); - - if (TARGET_POWERPC64) - { - set_conv_libfunc (sfix_optab, TImode, mode, "__fixtfti"); - set_conv_libfunc (ufix_optab, TImode, mode, "__fixunstfti"); - set_conv_libfunc (sfloat_optab, mode, TImode, "__floattitf"); - set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntitf"); - } - } -} - -/* Create a decl for either complex long double multiply or complex long double - divide when long double is IEEE 128-bit floating point. We can't use - __multc3 and __divtc3 because the original long double using IBM extended - double used those names. The complex multiply/divide functions are encoded - as builtin functions with a complex result and 4 scalar inputs. */ - -static void -create_complex_muldiv (const char *name, built_in_function fncode, tree fntype) -{ - tree fndecl = add_builtin_function (name, fntype, fncode, BUILT_IN_NORMAL, - name, NULL_TREE); - - set_builtin_decl (fncode, fndecl, true); - - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "create complex %s, fncode: %d\n", name, (int) fncode); - - return; -} - -/* Set up IEEE 128-bit floating point routines. Use different names if the - arguments can be passed in a vector register. The historical PowerPC - implementation of IEEE 128-bit floating point used _q_ for the names, so - continue to use that if we aren't using vector registers to pass IEEE - 128-bit floating point. */ - -static void -init_float128_ieee (machine_mode mode) -{ - if (FLOAT128_VECTOR_P (mode)) - { - static bool complex_muldiv_init_p = false; - - /* Set up to call __mulkc3 and __divkc3 under -mabi=ieeelongdouble. If - we have clone or target attributes, this will be called a second - time. We want to create the built-in function only once. */ - if (mode == TFmode && TARGET_IEEEQUAD && !complex_muldiv_init_p) - { - complex_muldiv_init_p = true; - built_in_function fncode_mul = - (built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + TCmode - - MIN_MODE_COMPLEX_FLOAT); - built_in_function fncode_div = - (built_in_function) (BUILT_IN_COMPLEX_DIV_MIN + TCmode - - MIN_MODE_COMPLEX_FLOAT); - - tree fntype = build_function_type_list (complex_long_double_type_node, - long_double_type_node, - long_double_type_node, - long_double_type_node, - long_double_type_node, - NULL_TREE); - - create_complex_muldiv ("__mulkc3", fncode_mul, fntype); - create_complex_muldiv ("__divkc3", fncode_div, fntype); - } - - set_optab_libfunc (add_optab, mode, "__addkf3"); - set_optab_libfunc (sub_optab, mode, "__subkf3"); - set_optab_libfunc (neg_optab, mode, "__negkf2"); - set_optab_libfunc (smul_optab, mode, "__mulkf3"); - set_optab_libfunc (sdiv_optab, mode, "__divkf3"); - set_optab_libfunc (sqrt_optab, mode, "__sqrtkf2"); - set_optab_libfunc (abs_optab, mode, "__abskf2"); - set_optab_libfunc (powi_optab, mode, "__powikf2"); - - set_optab_libfunc (eq_optab, mode, "__eqkf2"); - set_optab_libfunc (ne_optab, mode, "__nekf2"); - set_optab_libfunc (gt_optab, mode, "__gtkf2"); - set_optab_libfunc (ge_optab, mode, "__gekf2"); - set_optab_libfunc (lt_optab, mode, "__ltkf2"); - set_optab_libfunc (le_optab, mode, "__lekf2"); - set_optab_libfunc (unord_optab, mode, "__unordkf2"); - - set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2"); - set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2"); - set_conv_libfunc (trunc_optab, SFmode, mode, "__trunckfsf2"); - set_conv_libfunc (trunc_optab, DFmode, mode, "__trunckfdf2"); - - set_conv_libfunc (sext_optab, mode, IFmode, "__trunctfkf2"); - if (mode != TFmode && FLOAT128_IBM_P (TFmode)) - set_conv_libfunc (sext_optab, mode, TFmode, "__trunctfkf2"); - - set_conv_libfunc (trunc_optab, IFmode, mode, "__extendkftf2"); - if (mode != TFmode && FLOAT128_IBM_P (TFmode)) - set_conv_libfunc (trunc_optab, TFmode, mode, "__extendkftf2"); - - set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdkf"); - set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddkf"); - set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunctdkf"); - set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunckfsd"); - set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunckfdd"); - set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendkftd"); - - set_conv_libfunc (sfix_optab, SImode, mode, "__fixkfsi"); - set_conv_libfunc (ufix_optab, SImode, mode, "__fixunskfsi"); - set_conv_libfunc (sfix_optab, DImode, mode, "__fixkfdi"); - set_conv_libfunc (ufix_optab, DImode, mode, "__fixunskfdi"); - - set_conv_libfunc (sfloat_optab, mode, SImode, "__floatsikf"); - set_conv_libfunc (ufloat_optab, mode, SImode, "__floatunsikf"); - set_conv_libfunc (sfloat_optab, mode, DImode, "__floatdikf"); - set_conv_libfunc (ufloat_optab, mode, DImode, "__floatundikf"); - - if (TARGET_POWERPC64) - { - set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti"); - set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti"); - set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf"); - set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf"); - } - } - - else - { - set_optab_libfunc (add_optab, mode, "_q_add"); - set_optab_libfunc (sub_optab, mode, "_q_sub"); - set_optab_libfunc (neg_optab, mode, "_q_neg"); - set_optab_libfunc (smul_optab, mode, "_q_mul"); - set_optab_libfunc (sdiv_optab, mode, "_q_div"); - if (TARGET_PPC_GPOPT) - set_optab_libfunc (sqrt_optab, mode, "_q_sqrt"); - - set_optab_libfunc (eq_optab, mode, "_q_feq"); - set_optab_libfunc (ne_optab, mode, "_q_fne"); - set_optab_libfunc (gt_optab, mode, "_q_fgt"); - set_optab_libfunc (ge_optab, mode, "_q_fge"); - set_optab_libfunc (lt_optab, mode, "_q_flt"); - set_optab_libfunc (le_optab, mode, "_q_fle"); - - set_conv_libfunc (sext_optab, mode, SFmode, "_q_stoq"); - set_conv_libfunc (sext_optab, mode, DFmode, "_q_dtoq"); - set_conv_libfunc (trunc_optab, SFmode, mode, "_q_qtos"); - set_conv_libfunc (trunc_optab, DFmode, mode, "_q_qtod"); - set_conv_libfunc (sfix_optab, SImode, mode, "_q_qtoi"); - set_conv_libfunc (ufix_optab, SImode, mode, "_q_qtou"); - set_conv_libfunc (sfloat_optab, mode, SImode, "_q_itoq"); - set_conv_libfunc (ufloat_optab, mode, SImode, "_q_utoq"); - } -} - -static void -rs6000_init_libfuncs (void) -{ - /* __float128 support. */ - if (TARGET_FLOAT128_TYPE) + /* __float128 support. */ + if (TARGET_FLOAT128_TYPE) { init_float128_ibm (IFmode); init_float128_ieee (KFmode); @@ -21067,7 +13165,7 @@ print_operand_address (FILE *file, rtx x) /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ -static bool +bool rs6000_output_addr_const_extra (FILE *file, rtx x) { if (GET_CODE (x) == UNSPEC) @@ -23747,173 +15845,25 @@ get_TOC_alias_set (void) return TOC_alias_set; } -/* Return the internal arg pointer used for function incoming - arguments. When -fsplit-stack, the arg pointer is r12 so we need - to copy it to a pseudo in order for it to be preserved over calls - and suchlike. We'd really like to use a pseudo here for the - internal arg pointer but data-flow analysis is not prepared to - accept pseudos as live at the beginning of a function. */ - -static rtx -rs6000_internal_arg_pointer (void) -{ - if (flag_split_stack - && (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (cfun->decl)) - == NULL)) - - { - if (cfun->machine->split_stack_arg_pointer == NULL_RTX) - { - rtx pat; - - cfun->machine->split_stack_arg_pointer = gen_reg_rtx (Pmode); - REG_POINTER (cfun->machine->split_stack_arg_pointer) = 1; - - /* Put the pseudo initialization right after the note at the - beginning of the function. */ - pat = gen_rtx_SET (cfun->machine->split_stack_arg_pointer, - gen_rtx_REG (Pmode, 12)); - push_topmost_sequence (); - emit_insn_after (pat, get_insns ()); - pop_topmost_sequence (); - } - rtx ret = plus_constant (Pmode, cfun->machine->split_stack_arg_pointer, - FIRST_PARM_OFFSET (current_function_decl)); - return copy_to_reg (ret); - } - return virtual_incoming_args_rtx; -} - -/* We may have to tell the dataflow pass that the split stack prologue - is initializing a register. */ +/* The mode the ABI uses for a word. This is not the same as word_mode + for -m32 -mpowerpc64. This is used to implement various target hooks. */ -static void -rs6000_live_on_entry (bitmap regs) +static scalar_int_mode +rs6000_abi_word_mode (void) { - if (flag_split_stack) - bitmap_set_bit (regs, 12); + return TARGET_32BIT ? SImode : DImode; } - -/* A C compound statement that outputs the assembler code for a thunk - function, used to implement C++ virtual function calls with - multiple inheritance. The thunk acts as a wrapper around a virtual - function, adjusting the implicit object parameter before handing - control off to the real function. - - First, emit code to add the integer DELTA to the location that - contains the incoming first argument. Assume that this argument - contains a pointer, and is the one used to pass the `this' pointer - in C++. This is the incoming argument *before* the function - prologue, e.g. `%o0' on a sparc. The addition must preserve the - values of all other incoming arguments. - - After the addition, emit code to jump to FUNCTION, which is a - `FUNCTION_DECL'. This is a direct pure jump, not a call, and does - not touch the return address. Hence returning from FUNCTION will - return to whoever called the current `thunk'. - - The effect must be as if FUNCTION had been called directly with the - adjusted first argument. This macro is responsible for emitting - all of the code for a thunk function; output_function_prologue() - and output_function_epilogue() are not invoked. - - The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already - been extracted from it.) It might possibly be useful on some - targets, but probably not. - - If you do not define this macro, the target-independent code in the - C++ frontend will generate a less efficient heavyweight thunk that - calls FUNCTION instead of jumping to it. The generic approach does - not support varargs. */ - -static void -rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, - HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, - tree function) +/* Implement the TARGET_OFFLOAD_OPTIONS hook. */ +static char * +rs6000_offload_options (void) { - const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl)); - rtx this_rtx, funexp; - rtx_insn *insn; - - reload_completed = 1; - epilogue_completed = 1; - - /* Mark the end of the (empty) prologue. */ - emit_note (NOTE_INSN_PROLOGUE_END); - - /* Find the "this" pointer. If the function returns a structure, - the structure return pointer is in r3. */ - if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) - this_rtx = gen_rtx_REG (Pmode, 4); + if (TARGET_64BIT) + return xstrdup ("-foffload-abi=lp64"); else - this_rtx = gen_rtx_REG (Pmode, 3); - - /* Apply the constant offset, if required. */ - if (delta) - emit_insn (gen_add3_insn (this_rtx, this_rtx, GEN_INT (delta))); - - /* Apply the offset from the vtable, if required. */ - if (vcall_offset) - { - rtx vcall_offset_rtx = GEN_INT (vcall_offset); - rtx tmp = gen_rtx_REG (Pmode, 12); - - emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx)); - if (((unsigned HOST_WIDE_INT) vcall_offset) + 0x8000 >= 0x10000) - { - emit_insn (gen_add3_insn (tmp, tmp, vcall_offset_rtx)); - emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp)); - } - else - { - rtx loc = gen_rtx_PLUS (Pmode, tmp, vcall_offset_rtx); - - emit_move_insn (tmp, gen_rtx_MEM (Pmode, loc)); - } - emit_insn (gen_add3_insn (this_rtx, this_rtx, tmp)); - } - - /* Generate a tail call to the target function. */ - if (!TREE_USED (function)) - { - assemble_external (function); - TREE_USED (function) = 1; - } - funexp = XEXP (DECL_RTL (function), 0); - funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); - -#if TARGET_MACHO - if (MACHOPIC_INDIRECT) - funexp = machopic_indirect_call_target (funexp); -#endif - - /* gen_sibcall expects reload to convert scratch pseudo to LR so we must - generate sibcall RTL explicitly. */ - insn = emit_call_insn ( - gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (3, - gen_rtx_CALL (VOIDmode, - funexp, const0_rtx), - gen_rtx_USE (VOIDmode, const0_rtx), - simple_return_rtx))); - SIBLING_CALL_P (insn) = 1; - emit_barrier (); - - /* Run just enough of rest_of_compilation to get the insns emitted. - There's not really enough bulk here to make other passes such as - instruction scheduling worth while. */ - insn = get_insns (); - shorten_branches (insn); - assemble_start_function (thunk_fndecl, fnname); - final_start_function (insn, file, 1); - final (insn, file, 1); - final_end_function (); - assemble_end_function (thunk_fndecl, fnname); - - reload_completed = 0; - epilogue_completed = 0; + return xstrdup ("-foffload-abi=ilp32"); } + /* A quick summary of the various types of 'constant-pool tables' under PowerPC: diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000 index c689d51..59a1424 100644 --- a/gcc/config/rs6000/t-rs6000 +++ b/gcc/config/rs6000/t-rs6000 @@ -43,6 +43,10 @@ rs6000-logue.o: $(srcdir)/config/rs6000/rs6000-logue.c $(COMPILE) $< $(POSTCOMPILE) +rs6000-call.o: $(srcdir)/config/rs6000/rs6000-call.c + $(COMPILE) $< + $(POSTCOMPILE) + $(srcdir)/config/rs6000/rs6000-tables.opt: $(srcdir)/config/rs6000/genopt.sh \ $(srcdir)/config/rs6000/rs6000-cpus.def $(SHELL) $(srcdir)/config/rs6000/genopt.sh $(srcdir)/config/rs6000 > \ -- cgit v1.1 From db67ea0f935148714d465defe743533715b735a4 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Fri, 19 Jul 2019 20:10:33 +0000 Subject: [Darwin] More specs TLC. This strips out a few driver specs that are only specifying a default state. Also warn on an option now ignored, and add some comments to the driver specs section. 2019-07-19 Iain Sandoe * config/darwin.h (DRIVER_SELF_SPECS): Ignore X and Mach specs which refer to default conditions. Warn for the 'y' spec which is ignored by current linkers. From-SVN: r273608 --- gcc/ChangeLog | 6 ++++++ gcc/config/darwin.h | 28 ++++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a9c2450..f37e270 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-19 Iain Sandoe + + * config/darwin.h (DRIVER_SELF_SPECS): Ignore X and Mach specs which + refer to default conditions. Warn for the 'y' spec which is ignored + by current linkers. + 2019-07-19 Bill Seurer * config/rs6000/rs6000.c (builtin_description, cpu_is_info, diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index e17bc64..ed87984 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -118,13 +118,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* True if pragma ms_struct is in effect. */ extern GTY(()) int darwin_ms_struct; -#define DRIVER_SELF_SPECS \ - "%{gfull:-g -fno-eliminate-unused-debug-symbols} % Date: Fri, 19 Jul 2019 22:14:56 +0000 Subject: rs6000-call.c (HAVE_AS_GNU_ATTRIBUTE): define value as in rs6000.c. 2019-07-17 Bill Seurer * config/rs6000/rs6000-call.c (HAVE_AS_GNU_ATTRIBUTE): define value as in rs6000.c. From-SVN: r273610 --- gcc/ChangeLog | 5 +++++ gcc/config/rs6000/rs6000-call.c | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f37e270..92e5b2e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-17 Bill Seurer + + * config/rs6000/rs6000-call.c (HAVE_AS_GNU_ATTRIBUTE): define value + as in rs6000.c. + 2019-07-19 Iain Sandoe * config/darwin.h (DRIVER_SELF_SPECS): Ignore X and Mach specs which diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index ff48ff1..cefb737 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -80,6 +80,12 @@ #define TARGET_PROFILE_KERNEL 0 #endif +#ifdef HAVE_AS_GNU_ATTRIBUTE +# ifndef HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE +# define HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE 0 +# endif +#endif + struct builtin_description { const HOST_WIDE_INT mask; -- cgit v1.1 From aa4d56e2ce1d89599654d33051486cb58aadbc2e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 19 Jul 2019 23:10:55 +0000 Subject: compiler: don't export bodies for functions marked "go:noinline" The current Mark_inline_candidates helper looks only at budget when deciding to mark a function or method as inline (with the proviso that IR constructs not yet supported by the inliner are given artificially high cost). This patch changes the helper to also look at whether a function has the "go:noinline" pragma; if it does have the pragma there is no point putting it into the export data (it will just make the export data bigger). Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/186923 From-SVN: r273611 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/gogo.cc | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index ccc1a24..2c53602 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -4df7c8d7af894ee93f50c3a50debdcf4e369a2c6 +e242929304e7a524ced56dc94605bbf6d83e6489 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index abd8686..30523f7 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -5109,6 +5109,8 @@ int Mark_inline_candidates::function(Named_object* no) { Function* func = no->func_value(); + if ((func->pragmas() & GOPRAGMA_NOINLINE) != 0) + return TRAVERSE_CONTINUE; int budget = budget_heuristic; Inline_within_budget iwb(&budget); func->block()->traverse(&iwb); @@ -5138,6 +5140,8 @@ Mark_inline_candidates::type(Type* t) Named_object* no = *p; go_assert(no->is_function()); Function *func = no->func_value(); + if ((func->pragmas() & GOPRAGMA_NOINLINE) != 0) + continue; int budget = budget_heuristic; Inline_within_budget iwb(&budget); func->block()->traverse(&iwb); -- cgit v1.1 From 05584e7c94f71ae287e2b9f148c0a1c93aff6b55 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 20 Jul 2019 00:16:21 +0000 Subject: Daily bump. From-SVN: r273615 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 0d6cbf1..5030968 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190719 +20190720 -- cgit v1.1 From b6339213ff68ac5a87b7fdda878f26b52d801b76 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 20 Jul 2019 08:38:59 +0200 Subject: omp-low.c (lower_rec_input_clauses): Don't force simd arrays for lastprivate non-addressable iterator of a... * omp-low.c (lower_rec_input_clauses): Don't force simd arrays for lastprivate non-addressable iterator of a collapse(1) simd. * gcc.dg/vect/vect-simd-16.c: New test. From-SVN: r273620 --- gcc/ChangeLog | 5 +++ gcc/omp-low.c | 5 ++- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/vect/vect-simd-16.c | 61 ++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/vect/vect-simd-16.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92e5b2e..40f6db5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-20 Jakub Jelinek + + * omp-low.c (lower_rec_input_clauses): Don't force simd arrays for + lastprivate non-addressable iterator of a collapse(1) simd. + 2019-07-17 Bill Seurer * config/rs6000/rs6000-call.c (HAVE_AS_GNU_ATTRIBUTE): define value diff --git a/gcc/omp-low.c b/gcc/omp-low.c index a18f24c..03df07b 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -5097,7 +5097,10 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, { tree y = lang_hooks.decls.omp_clause_dtor (c, new_var); if ((TREE_ADDRESSABLE (new_var) || nx || y - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE + || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE + && (gimple_omp_for_collapse (ctx->stmt) != 1 + || (gimple_omp_for_index (ctx->stmt, 0) + != new_var))) || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_ || omp_is_reference (var)) && lower_rec_simd_input_clauses (new_var, ctx, &sctx, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ce8e3c7..a7c9426 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-20 Jakub Jelinek + + * gcc.dg/vect/vect-simd-16.c: New test. + 2019-07-19 Jeff Law * gcc.dg/tree-ssa/ssa-dse-37.c: New test. diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-16.c b/gcc/testsuite/gcc.dg/vect/vect-simd-16.c new file mode 100644 index 0000000..ee4459a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-16.c @@ -0,0 +1,61 @@ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 3 "vect" { target i?86-*-* x86_64-*-* } } } */ + +#include "tree-vect.h" + +__attribute__((noipa)) int +foo (int *a) +{ + int i; + #pragma omp simd lastprivate (i) + for (i = 0; i < 64; i++) + a[i] = i; + return i; +} + +__attribute__((noipa)) void +bar (int *a) +{ + int i; + #pragma omp simd private (i) + for (i = 0; i < 64; i++) + a[i] = i + 1; +} + +__attribute__((noipa)) int +baz (int *a) +{ + int i; + #pragma omp simd linear (i) + for (i = 0; i < 64; i++) + a[i] = i + 2; + return i; +} + +int +main () +{ + int i; + int a[64]; + check_vect (); + if (foo (a) != 64) + abort (); + for (i = 0; i < 64; ++i) + if (a[i] != i) + abort (); + else + a[i] = -8; + bar (a); + for (i = 0; i < 64; ++i) + if (a[i] != i + 1) + abort (); + else + a[i] = -8; + if (baz (a) != 64) + abort (); + for (i = 0; i < 64; ++i) + if (a[i] != i + 2) + abort (); + return 0; +} -- cgit v1.1 From 554a530ff81870098572832eed8ca00b3593bb41 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 20 Jul 2019 13:21:42 +0200 Subject: tree.def (OMP_LOOP): New tree code. * tree.def (OMP_LOOP): New tree code. * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_BIND. (enum omp_clause_bind_kind): New enum. (struct tree_omp_clause): Add subcode.bind_kind. * tree.h (OMP_LOOP_CHECK): Rename to ... (OMP_LOOPING_CHECK): ... this. (OMP_FOR_BODY, OMP_FOR_CLAUSES, OMP_FOR_INIT, OMP_FOR_COND, OMP_FOR_INCR, OMP_FOR_PRE_BODY, OMP_FOR_ORIG_DECLS): Use OMP_LOOPING_CHECK instead of OMP_LOOP_CHECK. (OMP_CLAUSE_BIND_KIND): Define. * tree.c (omp_clause_num_ops, omp_clause_code_name): Add bind clause entries. (walk_tree_1): Handle OMP_CLAUSE_BIND. * tree-pretty-print.c (dump_omp_clause): Likewise. (dump_generic_node): Handle OMP_LOOP. * gimplify.c (enum omp_region_type): Add ORT_IMPLICIT_TARGET. (in_omp_construct): New variable. (is_gimple_stmt): Handle OMP_LOOP. (gimplify_scan_omp_clauses): For lastprivate don't set check_non_private if code == OMP_LOOP. For reduction clause on OMP_LOOP combined with parallel or teams propagate as shared on the combined construct. Handle OMP_CLAUSE_BIND. (gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_BIND. (gimplify_omp_for): Pass OMP_LOOP instead of OMP_{FOR,DISTRIBUTE} for constructs from a loop construct to gimplify_scan_omp_clauses. Don't predetermine iterator linear on OMP_SIMD from loop construct. (replace_reduction_placeholders, gimplify_omp_loop): New functions. (gimplify_omp_workshare): Use ORT_IMPLICIT_TARGET instead of trying to match the implicit ORT_TARGET construct around whole body. Temporarily clear in_omp_construct when processing body. (gimplify_expr): Handle OMP_LOOP. For OMP_MASTER, OMP_TASKGROUP etc. temporarily set in_omp_construct when processing body. (gimplify_body): Create ORT_IMPLICIT_TARGET instead of ORT_TARGET. * omp-low.c (struct omp_context): Add loop_p. (build_outer_var_ref): Treat ctx->loop_p similarly to simd construct in that the original var might be private. (scan_sharing_clauses): Handle OMP_CLAUSE_BIND. (check_omp_nesting_restrictions): Adjust nesting restrictions for addition of loop construct. (scan_omp_1_stmt): Allow setjmp inside of loop construct. gcc/c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_LOOP. (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_BIND. * c-pragma.c (omp_pragmas_simd): Add PRAGMA_OMP_LOOP entry. * c-common.h (enum c_omp_clause_split): Add C_OMP_CLAUSE_SPLIT_LOOP. * c-omp.c (c_omp_split_clauses): Add support for 4 new combined constructs with the loop construct. gcc/c/ * c-parser.c (c_parser_omp_clause_name): Handle bind clause. (c_parser_omp_clause_bind): New function. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_BIND. (OMP_LOOP_CLAUSE_MASK): Define. (c_parser_omp_loop): New function. (c_parser_omp_parallel, c_parser_omp_teams): Handle parsing of loop combined with parallel or teams. (c_parser_omp_construct): Handle PRAGMA_OMP_LOOP. * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_BIND. gcc/cp/ * cp-tree.h (OMP_FOR_GIMPLIFYING_P): Use OMP_LOOPING_CHECK instead of OMP_LOOP_CHECK. * parser.c (cp_parser_omp_clause_name): Handle bind clause. (cp_parser_omp_clause_bind): New function. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_BIND. (OMP_LOOP_CLAUSE_MASK): Define. (cp_parser_omp_loop): New function. (cp_parser_omp_parallel, cp_parser_omp_teams): Handle parsing of loop combined with parallel or teams. (cp_parser_omp_construct): Handle PRAGMA_OMP_LOOP. (cp_parser_pragma): Likewise. * pt.c (tsubst_expr): Handle OMP_LOOP. * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_BIND. gcc/testsuite/ * c-c++-common/gomp/cancel-1.c: Adjust expected diagnostic wording. * c-c++-common/gomp/clauses-1.c (foo, baz, bar): Add order(concurrent) clause where allowed. Add combined constructs with loop with all possible clauses. (qux): New function. * c-c++-common/gomp/loop-1.c: New test. * c-c++-common/gomp/loop-2.c: New test. * c-c++-common/gomp/loop-3.c: New test. * c-c++-common/gomp/loop-4.c: New test. * c-c++-common/gomp/loop-5.c: New test. * c-c++-common/gomp/order-3.c: Adjust expected diagnostic wording. * c-c++-common/gomp/simd-setjmp-1.c: New test. * c-c++-common/gomp/teams-2.c: Adjust expected diagnostic wording. libgomp/ * testsuite/libgomp.c-c++-common/loop-1.c: New test. From-SVN: r273621 --- gcc/ChangeLog | 41 ++++ gcc/c-family/ChangeLog | 9 + gcc/c-family/c-common.h | 3 +- gcc/c-family/c-omp.c | 56 +++-- gcc/c-family/c-pragma.c | 1 + gcc/c-family/c-pragma.h | 2 + gcc/c/ChangeLog | 12 + gcc/c/c-parser.c | 143 ++++++++++- gcc/c/c-typeck.c | 1 + gcc/cp/ChangeLog | 16 ++ gcc/cp/cp-tree.h | 2 +- gcc/cp/parser.c | 165 ++++++++++++- gcc/cp/pt.c | 1 + gcc/cp/semantics.c | 1 + gcc/gimplify.c | 312 ++++++++++++++++++++++-- gcc/omp-low.c | 92 ++++--- gcc/testsuite/ChangeLog | 14 ++ gcc/testsuite/c-c++-common/gomp/cancel-1.c | 16 +- gcc/testsuite/c-c++-common/gomp/clauses-1.c | 133 ++++++++-- gcc/testsuite/c-c++-common/gomp/loop-1.c | 271 ++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/loop-2.c | 294 ++++++++++++++++++++++ gcc/testsuite/c-c++-common/gomp/loop-3.c | 145 +++++++++++ gcc/testsuite/c-c++-common/gomp/loop-4.c | 46 ++++ gcc/testsuite/c-c++-common/gomp/loop-5.c | 56 +++++ gcc/testsuite/c-c++-common/gomp/order-3.c | 48 ++-- gcc/testsuite/c-c++-common/gomp/simd-setjmp-1.c | 68 ++++++ gcc/testsuite/c-c++-common/gomp/teams-2.c | 44 ++-- gcc/tree-core.h | 10 + gcc/tree-pretty-print.c | 23 ++ gcc/tree.c | 3 + gcc/tree.def | 4 + gcc/tree.h | 19 +- 32 files changed, 1889 insertions(+), 162 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/loop-1.c create mode 100644 gcc/testsuite/c-c++-common/gomp/loop-2.c create mode 100644 gcc/testsuite/c-c++-common/gomp/loop-3.c create mode 100644 gcc/testsuite/c-c++-common/gomp/loop-4.c create mode 100644 gcc/testsuite/c-c++-common/gomp/loop-5.c create mode 100644 gcc/testsuite/c-c++-common/gomp/simd-setjmp-1.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 40f6db5..537799e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,46 @@ 2019-07-20 Jakub Jelinek + * tree.def (OMP_LOOP): New tree code. + * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_BIND. + (enum omp_clause_bind_kind): New enum. + (struct tree_omp_clause): Add subcode.bind_kind. + * tree.h (OMP_LOOP_CHECK): Rename to ... + (OMP_LOOPING_CHECK): ... this. + (OMP_FOR_BODY, OMP_FOR_CLAUSES, OMP_FOR_INIT, OMP_FOR_COND, + OMP_FOR_INCR, OMP_FOR_PRE_BODY, OMP_FOR_ORIG_DECLS): Use + OMP_LOOPING_CHECK instead of OMP_LOOP_CHECK. + (OMP_CLAUSE_BIND_KIND): Define. + * tree.c (omp_clause_num_ops, omp_clause_code_name): Add + bind clause entries. + (walk_tree_1): Handle OMP_CLAUSE_BIND. + * tree-pretty-print.c (dump_omp_clause): Likewise. + (dump_generic_node): Handle OMP_LOOP. + * gimplify.c (enum omp_region_type): Add ORT_IMPLICIT_TARGET. + (in_omp_construct): New variable. + (is_gimple_stmt): Handle OMP_LOOP. + (gimplify_scan_omp_clauses): For lastprivate don't set + check_non_private if code == OMP_LOOP. For reduction clause + on OMP_LOOP combined with parallel or teams propagate as shared + on the combined construct. Handle OMP_CLAUSE_BIND. + (gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_BIND. + (gimplify_omp_for): Pass OMP_LOOP instead of OMP_{FOR,DISTRIBUTE} + for constructs from a loop construct to gimplify_scan_omp_clauses. + Don't predetermine iterator linear on OMP_SIMD from loop construct. + (replace_reduction_placeholders, gimplify_omp_loop): New functions. + (gimplify_omp_workshare): Use ORT_IMPLICIT_TARGET instead of trying + to match the implicit ORT_TARGET construct around whole body. + Temporarily clear in_omp_construct when processing body. + (gimplify_expr): Handle OMP_LOOP. For OMP_MASTER, OMP_TASKGROUP + etc. temporarily set in_omp_construct when processing body. + (gimplify_body): Create ORT_IMPLICIT_TARGET instead of ORT_TARGET. + * omp-low.c (struct omp_context): Add loop_p. + (build_outer_var_ref): Treat ctx->loop_p similarly to simd construct + in that the original var might be private. + (scan_sharing_clauses): Handle OMP_CLAUSE_BIND. + (check_omp_nesting_restrictions): Adjust nesting restrictions for + addition of loop construct. + (scan_omp_1_stmt): Allow setjmp inside of loop construct. + * omp-low.c (lower_rec_input_clauses): Don't force simd arrays for lastprivate non-addressable iterator of a collapse(1) simd. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d360759..e645254 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2019-07-20 Jakub Jelinek + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_LOOP. + (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_BIND. + * c-pragma.c (omp_pragmas_simd): Add PRAGMA_OMP_LOOP entry. + * c-common.h (enum c_omp_clause_split): Add C_OMP_CLAUSE_SPLIT_LOOP. + * c-omp.c (c_omp_split_clauses): Add support for 4 new combined + constructs with the loop construct. + 2019-07-13 Jakub Jelinek PR c/91149 diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 5ac6e5e..117d729 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1148,7 +1148,8 @@ enum c_omp_clause_split C_OMP_CLAUSE_SPLIT_SIMD, C_OMP_CLAUSE_SPLIT_COUNT, C_OMP_CLAUSE_SPLIT_SECTIONS = C_OMP_CLAUSE_SPLIT_FOR, - C_OMP_CLAUSE_SPLIT_TASKLOOP = C_OMP_CLAUSE_SPLIT_FOR + C_OMP_CLAUSE_SPLIT_TASKLOOP = C_OMP_CLAUSE_SPLIT_FOR, + C_OMP_CLAUSE_SPLIT_LOOP = C_OMP_CLAUSE_SPLIT_FOR }; enum c_omp_region_type diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index dc59bd2..10f7c4e 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -1263,7 +1263,7 @@ c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses, } /* This function attempts to split or duplicate clauses for OpenMP - combined/composite constructs. Right now there are 26 different + combined/composite constructs. Right now there are 30 different constructs. CODE is the innermost construct in the combined construct, and MASK allows to determine which constructs are combined together, as every construct has at least one clause that no other construct @@ -1278,6 +1278,7 @@ c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses, #pragma omp master taskloop simd #pragma omp parallel for #pragma omp parallel for simd + #pragma omp parallel loop #pragma omp parallel master #pragma omp parallel master taskloop #pragma omp parallel master taskloop simd @@ -1285,17 +1286,20 @@ c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses, #pragma omp target parallel #pragma omp target parallel for #pragma omp target parallel for simd + #pragma omp target parallel loop #pragma omp target teams #pragma omp target teams distribute #pragma omp target teams distribute parallel for #pragma omp target teams distribute parallel for simd #pragma omp target teams distribute simd + #pragma omp target teams loop #pragma omp target simd #pragma omp taskloop simd #pragma omp teams distribute #pragma omp teams distribute parallel for #pragma omp teams distribute parallel for simd - #pragma omp teams distribute simd */ + #pragma omp teams distribute simd + #pragma omp teams loop */ void c_omp_split_clauses (location_t loc, enum tree_code code, @@ -1375,7 +1379,11 @@ c_omp_split_clauses (location_t loc, enum tree_code code, case OMP_CLAUSE_PRIORITY: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break; - /* Duplicate this to all of taskloop, distribute, for and simd. */ + case OMP_CLAUSE_BIND: + s = C_OMP_CLAUSE_SPLIT_LOOP; + break; + /* Duplicate this to all of taskloop, distribute, for, simd and + loop. */ case OMP_CLAUSE_COLLAPSE: if (code == OMP_SIMD) { @@ -1418,6 +1426,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) s = C_OMP_CLAUSE_SPLIT_TASKLOOP; + else if (code == OMP_LOOP) + s = C_OMP_CLAUSE_SPLIT_LOOP; else s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; @@ -1435,12 +1445,13 @@ c_omp_split_clauses (location_t loc, enum tree_code code, case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break; case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break; + case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break; default: gcc_unreachable (); } break; /* Firstprivate clause is supported on all constructs but - simd and master. Put it on the outermost of those and duplicate on - teams and parallel. */ + simd, master and loop. Put it on the outermost of those and + duplicate on teams and parallel. */ case OMP_CLAUSE_FIRSTPRIVATE: if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) @@ -1486,7 +1497,7 @@ c_omp_split_clauses (location_t loc, enum tree_code code, s = C_OMP_CLAUSE_SPLIT_TASKLOOP; else /* This must be - #pragma omp parallel{, for{, simd}, sections} + #pragma omp parallel{, for{, simd}, sections,loop} or #pragma omp target parallel. */ s = C_OMP_CLAUSE_SPLIT_PARALLEL; @@ -1495,10 +1506,11 @@ c_omp_split_clauses (location_t loc, enum tree_code code, != 0) { /* This must be one of - #pragma omp {,target }teams distribute + #pragma omp {,target }teams {distribute,loop} #pragma omp target teams #pragma omp {,target }teams distribute simd. */ gcc_assert (code == OMP_DISTRIBUTE + || code == OMP_LOOP || code == OMP_TEAMS || code == OMP_SIMD); s = C_OMP_CLAUSE_SPLIT_TEAMS; @@ -1526,9 +1538,9 @@ c_omp_split_clauses (location_t loc, enum tree_code code, s = C_OMP_CLAUSE_SPLIT_FOR; } break; - /* Lastprivate is allowed on distribute, for, sections, taskloop and - simd. In parallel {for{, simd},sections} we actually want to put - it on parallel rather than for or sections. */ + /* Lastprivate is allowed on distribute, for, sections, taskloop, loop + and simd. In parallel {for{, simd},sections} we actually want to + put it on parallel rather than for or sections. */ case OMP_CLAUSE_LASTPRIVATE: if (code == OMP_DISTRIBUTE) { @@ -1560,6 +1572,11 @@ c_omp_split_clauses (location_t loc, enum tree_code code, s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break; } + if (code == OMP_LOOP) + { + s = C_OMP_CLAUSE_SPLIT_LOOP; + break; + } gcc_assert (code == OMP_SIMD); if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) { @@ -1632,7 +1649,7 @@ c_omp_split_clauses (location_t loc, enum tree_code code, } s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; - /* order clauses are allowed on for and simd. */ + /* order clauses are allowed on for, simd and loop. */ case OMP_CLAUSE_ORDER: if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) { @@ -1647,22 +1664,24 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else s = C_OMP_CLAUSE_SPLIT_FOR; } + else if (code == OMP_LOOP) + s = C_OMP_CLAUSE_SPLIT_LOOP; else s = C_OMP_CLAUSE_SPLIT_SIMD; break; - /* Reduction is allowed on simd, for, parallel, sections, taskloop - and teams. Duplicate it on all of them, but omit on for or + /* Reduction is allowed on simd, for, parallel, sections, taskloop, + teams and loop. Duplicate it on all of them, but omit on for or sections if parallel is present (unless inscan, in that case - omit on parallel). If taskloop is combined with + omit on parallel). If taskloop or loop is combined with parallel, omit it on parallel. */ case OMP_CLAUSE_REDUCTION: if (OMP_CLAUSE_REDUCTION_TASK (clauses)) { - if (code == OMP_SIMD /* || code == OMP_LOOP */) + if (code == OMP_SIMD || code == OMP_LOOP) { error_at (OMP_CLAUSE_LOCATION (clauses), "invalid % reduction modifier on construct " - "combined with %" /* or % */); + "combined with % or %"); OMP_CLAUSE_REDUCTION_TASK (clauses) = 0; } else if (code != OMP_SECTIONS @@ -1739,6 +1758,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, s = C_OMP_CLAUSE_SPLIT_PARALLEL; else if (code == OMP_TASKLOOP) s = C_OMP_CLAUSE_SPLIT_TASKLOOP; + else if (code == OMP_LOOP) + s = C_OMP_CLAUSE_SPLIT_LOOP; else if (code == OMP_SIMD) { if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) @@ -1930,7 +1951,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE); if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0 - && code != OMP_SECTIONS) + && code != OMP_SECTIONS + && code != OMP_LOOP) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE); if (code != OMP_SIMD) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE); diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 9af713d..9fee84b 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1318,6 +1318,7 @@ static const struct omp_pragma_def omp_pragmas_simd[] = { { "declare", PRAGMA_OMP_DECLARE }, { "distribute", PRAGMA_OMP_DISTRIBUTE }, { "for", PRAGMA_OMP_FOR }, + { "loop", PRAGMA_OMP_LOOP }, { "ordered", PRAGMA_OMP_ORDERED }, { "parallel", PRAGMA_OMP_PARALLEL }, { "scan", PRAGMA_OMP_SCAN }, diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 4239ada..e8a509f 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -52,6 +52,7 @@ enum pragma_kind { PRAGMA_OMP_END_DECLARE_TARGET, PRAGMA_OMP_FLUSH, PRAGMA_OMP_FOR, + PRAGMA_OMP_LOOP, PRAGMA_OMP_MASTER, PRAGMA_OMP_ORDERED, PRAGMA_OMP_PARALLEL, @@ -84,6 +85,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_NONE = 0, PRAGMA_OMP_CLAUSE_ALIGNED, + PRAGMA_OMP_CLAUSE_BIND, PRAGMA_OMP_CLAUSE_COLLAPSE, PRAGMA_OMP_CLAUSE_COPYIN, PRAGMA_OMP_CLAUSE_COPYPRIVATE, diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index ee0c559..a75f0d8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,15 @@ +2019-07-20 Jakub Jelinek + + * c-parser.c (c_parser_omp_clause_name): Handle bind clause. + (c_parser_omp_clause_bind): New function. + (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_BIND. + (OMP_LOOP_CLAUSE_MASK): Define. + (c_parser_omp_loop): New function. + (c_parser_omp_parallel, c_parser_omp_teams): Handle parsing of + loop combined with parallel or teams. + (c_parser_omp_construct): Handle PRAGMA_OMP_LOOP. + * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_BIND. + 2019-07-18 Richard Sandiford PR c/53633 diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 1f83c24..6721049 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -11688,6 +11688,10 @@ c_parser_omp_clause_name (c_parser *parser) else if (!strcmp ("async", p)) result = PRAGMA_OACC_CLAUSE_ASYNC; break; + case 'b': + if (!strcmp ("bind", p)) + result = PRAGMA_OMP_CLAUSE_BIND; + break; case 'c': if (!strcmp ("collapse", p)) result = PRAGMA_OMP_CLAUSE_COLLAPSE; @@ -13507,6 +13511,45 @@ c_parser_omp_clause_order (c_parser *parser, tree list) } +/* OpenMP 5.0: + bind ( teams | parallel | thread ) */ + +static tree +c_parser_omp_clause_bind (c_parser *parser, tree list) +{ + location_t loc = c_parser_peek_token (parser)->location; + tree c; + const char *p; + enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + if (!c_parser_next_token_is (parser, CPP_NAME)) + { + invalid: + c_parser_error (parser, + "expected %, % or %"); + parens.skip_until_found_close (parser); + return list; + } + p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "teams") == 0) + kind = OMP_CLAUSE_BIND_TEAMS; + else if (strcmp (p, "parallel") == 0) + kind = OMP_CLAUSE_BIND_PARALLEL; + else if (strcmp (p, "thread") != 0) + goto invalid; + c_parser_consume_token (parser); + parens.skip_until_found_close (parser); + /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */ + c = build_omp_clause (loc, OMP_CLAUSE_BIND); + OMP_CLAUSE_BIND_KIND (c) = kind; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + + /* OpenMP 2.5: ordered @@ -15066,6 +15109,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, switch (c_kind) { + case PRAGMA_OMP_CLAUSE_BIND: + clauses = c_parser_omp_clause_bind (parser, clauses); + c_name = "bind"; + break; case PRAGMA_OMP_CLAUSE_COLLAPSE: clauses = c_parser_omp_clause_collapse (parser, clauses); c_name = "collapse"; @@ -17248,6 +17295,46 @@ omp_split_clauses (location_t loc, enum tree_code code, cclauses[i] = c_finish_omp_clauses (cclauses[i], C_ORT_OMP); } +/* OpenMP 5.0: + #pragma omp loop loop-clause[optseq] new-line + for-loop + + LOC is the location of the #pragma token. +*/ + +#define OMP_LOOP_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) + +static tree +c_parser_omp_loop (location_t loc, c_parser *parser, + char *p_name, omp_clause_mask mask, tree *cclauses, + bool *if_p) +{ + tree block, clauses, ret; + + strcat (p_name, " loop"); + mask |= OMP_LOOP_CLAUSE_MASK; + + clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); + if (cclauses) + { + omp_split_clauses (loc, OMP_LOOP, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP]; + } + + block = c_begin_compound_stmt (true); + ret = c_parser_omp_for_loop (loc, parser, OMP_LOOP, clauses, cclauses, if_p); + block = c_end_compound_stmt (loc, block, true); + add_stmt (block); + + return ret; +} + /* OpenMP 4.0: #pragma omp simd simd-clause[optseq] new-line for-loop @@ -17713,10 +17800,10 @@ c_parser_omp_parallel (location_t loc, c_parser *parser, c_parser_skip_to_pragma_eol (parser); return NULL_TREE; } - else if (cclauses == NULL && c_parser_next_token_is (parser, CPP_NAME)) + else if (c_parser_next_token_is (parser, CPP_NAME)) { const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - if (strcmp (p, "master") == 0) + if (cclauses == NULL && strcmp (p, "master") == 0) { tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; cclauses = cclauses_buf; @@ -17736,12 +17823,34 @@ c_parser_omp_parallel (location_t loc, c_parser *parser, return ret; return stmt; } + else if (strcmp (p, "loop") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + c_parser_consume_token (parser); + if (!flag_openmp) /* flag_openmp_simd */ + return c_parser_omp_loop (loc, parser, p_name, mask, cclauses, + if_p); + block = c_begin_omp_parallel (); + tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, + if_p); + stmt + = c_finish_omp_parallel (loc, + cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], + block); + if (ret == NULL_TREE) + return ret; + OMP_PARALLEL_COMBINED (stmt) = 1; + return stmt; + } else if (!flag_openmp) /* flag_openmp_simd */ { c_parser_skip_to_pragma_eol (parser, false); return NULL_TREE; } - else if (strcmp (p, "sections") == 0) + else if (cclauses == NULL && strcmp (p, "sections") == 0) { tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; cclauses = cclauses_buf; @@ -18121,6 +18230,30 @@ c_parser_omp_teams (location_t loc, c_parser *parser, SET_EXPR_LOCATION (ret, loc); return add_stmt (ret); } + else if (strcmp (p, "loop") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + c_parser_consume_token (parser); + if (!flag_openmp) /* flag_openmp_simd */ + return c_parser_omp_loop (loc, parser, p_name, mask, cclauses, + if_p); + block = c_begin_omp_parallel (); + ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p); + block = c_end_compound_stmt (loc, block, true); + if (ret == NULL) + return ret; + clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + ret = make_node (OMP_TEAMS); + TREE_TYPE (ret) = void_type_node; + OMP_TEAMS_CLAUSES (ret) = clauses; + OMP_TEAMS_BODY (ret) = block; + OMP_TEAMS_COMBINED (ret) = 1; + SET_EXPR_LOCATION (ret, loc); + return add_stmt (ret); + } } if (!flag_openmp) /* flag_openmp_simd */ { @@ -19670,6 +19803,10 @@ c_parser_omp_construct (c_parser *parser, bool *if_p) strcpy (p_name, "#pragma omp"); stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p); break; + case PRAGMA_OMP_LOOP: + strcpy (p_name, "#pragma omp"); + stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p); + break; case PRAGMA_OMP_MASTER: strcpy (p_name, "#pragma omp"); stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index e4ce03d..9a1a910 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -14674,6 +14674,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_SIMD: case OMP_CLAUSE_HINT: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_BIND: case OMP_CLAUSE_NUM_GANGS: case OMP_CLAUSE_NUM_WORKERS: case OMP_CLAUSE_VECTOR_LENGTH: diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c1fc980..c776243 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2019-07-20 Jakub Jelinek + + * cp-tree.h (OMP_FOR_GIMPLIFYING_P): Use OMP_LOOPING_CHECK + instead of OMP_LOOP_CHECK. + * parser.c (cp_parser_omp_clause_name): Handle bind clause. + (cp_parser_omp_clause_bind): New function. + (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_BIND. + (OMP_LOOP_CLAUSE_MASK): Define. + (cp_parser_omp_loop): New function. + (cp_parser_omp_parallel, cp_parser_omp_teams): Handle parsing of + loop combined with parallel or teams. + (cp_parser_omp_construct): Handle PRAGMA_OMP_LOOP. + (cp_parser_pragma): Likewise. + * pt.c (tsubst_expr): Handle OMP_LOOP. + * semantics.c (finish_omp_clauses): Handle OMP_CLAUSE_BIND. + 2019-07-19 Jason Merrill PR c++/90101 - dependent class non-type parameter. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 970296d..6068745 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4923,7 +4923,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* Used while gimplifying continue statements bound to OMP_FOR nodes. */ #define OMP_FOR_GIMPLIFYING_P(NODE) \ - (TREE_LANG_FLAG_0 (OMP_LOOP_CHECK (NODE))) + (TREE_LANG_FLAG_0 (OMP_LOOPING_CHECK (NODE))) /* A language-specific token attached to the OpenMP data clauses to hold code (or code fragments) related to ctors, dtors, and op=. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1a5da1d..5c379aa 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -32409,6 +32409,10 @@ cp_parser_omp_clause_name (cp_parser *parser) else if (!strcmp ("async", p)) result = PRAGMA_OACC_CLAUSE_ASYNC; break; + case 'b': + if (!strcmp ("bind", p)) + result = PRAGMA_OMP_CLAUSE_BIND; + break; case 'c': if (!strcmp ("collapse", p)) result = PRAGMA_OMP_CLAUSE_COLLAPSE; @@ -33945,6 +33949,56 @@ cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location) return list; } +/* OpenMP 5.0: + bind ( teams | parallel | thread ) */ + +static tree +cp_parser_omp_clause_bind (cp_parser *parser, tree list, + location_t location) +{ + tree c; + const char *p; + enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + invalid: + cp_parser_error (parser, + "expected %, % or %"); + goto out_err; + } + else + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + p = IDENTIFIER_POINTER (id); + } + if (strcmp (p, "teams") == 0) + kind = OMP_CLAUSE_BIND_TEAMS; + else if (strcmp (p, "parallel") == 0) + kind = OMP_CLAUSE_BIND_PARALLEL; + else if (strcmp (p, "thread") != 0) + goto invalid; + cp_lexer_consume_token (parser->lexer); + if (!parens.require_close (parser)) + goto out_err; + + /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind", location); */ + c = build_omp_clause (location, OMP_CLAUSE_BIND); + OMP_CLAUSE_BIND_KIND (c) = kind; + OMP_CLAUSE_CHAIN (c) = list; + return c; + + out_err: + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; +} + /* OpenMP 2.5: ordered @@ -35462,6 +35516,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, switch (c_kind) { + case PRAGMA_OMP_CLAUSE_BIND: + clauses = cp_parser_omp_clause_bind (parser, clauses, + token->location); + c_name = "bind"; + break; case PRAGMA_OMP_CLAUSE_COLLAPSE: clauses = cp_parser_omp_clause_collapse (parser, clauses, token->location); @@ -37578,6 +37637,50 @@ cp_omp_split_clauses (location_t loc, enum tree_code code, cclauses[i] = finish_omp_clauses (cclauses[i], C_ORT_OMP); } +/* OpenMP 5.0: + #pragma omp loop loop-clause[optseq] new-line + for-loop */ + +#define OMP_LOOP_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER)) + +static tree +cp_parser_omp_loop (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses, + bool *if_p) +{ + tree clauses, sb, ret; + unsigned int save; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + strcat (p_name, " loop"); + mask |= OMP_LOOP_CLAUSE_MASK; + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_LOOP, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP]; + } + + keep_next_level (true); + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + + ret = cp_parser_omp_for_loop (parser, OMP_LOOP, clauses, cclauses, if_p); + + cp_parser_end_omp_structured_block (parser, save); + add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret)); + + return ret; +} + /* OpenMP 4.0: #pragma omp simd simd-clause[optseq] new-line for-loop */ @@ -38038,11 +38141,11 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, cp_parser_skip_to_pragma_eol (parser, pragma_tok); return NULL_TREE; } - else if (cclauses == NULL && cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; const char *p = IDENTIFIER_POINTER (id); - if (strcmp (p, "master") == 0) + if (cclauses == NULL && strcmp (p, "master") == 0) { tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; cclauses = cclauses_buf; @@ -38060,12 +38163,34 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, return ret; return stmt; } + else if (strcmp (p, "loop") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + if (!flag_openmp) /* flag_openmp_simd */ + return cp_parser_omp_loop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + block = begin_omp_parallel (); + save = cp_parser_begin_omp_structured_block (parser); + tree ret = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + cp_parser_end_omp_structured_block (parser, save); + stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], + block); + if (ret == NULL_TREE) + return ret; + OMP_PARALLEL_COMBINED (stmt) = 1; + return stmt; + } else if (!flag_openmp) /* flag_openmp_simd */ { cp_parser_skip_to_pragma_eol (parser, pragma_tok); return NULL_TREE; } - else if (strcmp (p, "sections") == 0) + else if (cclauses == NULL && strcmp (p, "sections") == 0) { tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; cclauses = cclauses_buf; @@ -38460,6 +38585,34 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok, SET_EXPR_LOCATION (ret, loc); return add_stmt (ret); } + else if (strcmp (p, "loop") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + if (!flag_openmp) /* flag_openmp_simd */ + return cp_parser_omp_loop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + keep_next_level (true); + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + ret = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + ret = make_node (OMP_TEAMS); + TREE_TYPE (ret) = void_type_node; + OMP_TEAMS_CLAUSES (ret) = clauses; + OMP_TEAMS_BODY (ret) = body; + OMP_TEAMS_COMBINED (ret) = 1; + SET_EXPR_LOCATION (ret, loc); + return add_stmt (ret); + } } if (!flag_openmp) /* flag_openmp_simd */ { @@ -40716,6 +40869,11 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL, if_p); break; + case PRAGMA_OMP_LOOP: + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, NULL, + if_p); + break; case PRAGMA_OMP_MASTER: strcpy (p_name, "#pragma omp"); stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL, @@ -41352,6 +41510,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_CRITICAL: case PRAGMA_OMP_DISTRIBUTE: case PRAGMA_OMP_FOR: + case PRAGMA_OMP_LOOP: case PRAGMA_OMP_MASTER: case PRAGMA_OMP_PARALLEL: case PRAGMA_OMP_SECTIONS: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e433413..b6eda7e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17553,6 +17553,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, break; case OMP_FOR: + case OMP_LOOP: case OMP_SIMD: case OMP_DISTRIBUTE: case OMP_TASKLOOP: diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1a21705..269092d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7550,6 +7550,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: case OMP_CLAUSE_DEFAULTMAP: + case OMP_CLAUSE_BIND: case OMP_CLAUSE_AUTO: case OMP_CLAUSE_INDEPENDENT: case OMP_CLAUSE_SEQ: diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 66df5c5..723897f 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -154,6 +154,7 @@ enum omp_region_type /* Data region with offloading. */ ORT_TARGET = 0x80, ORT_COMBINED_TARGET = ORT_TARGET | 1, + ORT_IMPLICIT_TARGET = ORT_TARGET | 2, /* OpenACC variants. */ ORT_ACC = 0x100, /* A generic OpenACC region. */ @@ -228,6 +229,7 @@ struct gimplify_omp_ctx static struct gimplify_ctx *gimplify_ctxp; static struct gimplify_omp_ctx *gimplify_omp_ctxp; +static bool in_omp_construct; /* Forward declaration. */ static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool); @@ -5533,6 +5535,7 @@ is_gimple_stmt (tree t) case OMP_FOR: case OMP_SIMD: case OMP_DISTRIBUTE: + case OMP_LOOP: case OACC_LOOP: case OMP_SCAN: case OMP_SECTIONS: @@ -8185,7 +8188,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, break; } flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT; - check_non_private = "lastprivate"; + if (code != OMP_LOOP) + check_non_private = "lastprivate"; decl = OMP_CLAUSE_DECL (c); if (error_operand_p (decl)) goto do_add; @@ -9142,15 +9146,20 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, " or private in outer context", DECL_NAME (decl)); } do_notice: - if (((region_type & ORT_TASKLOOP) == ORT_TASKLOOP - || (region_type == ORT_WORKSHARE - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - && OMP_CLAUSE_REDUCTION_INSCAN (c))) + if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) && outer_ctx - && outer_ctx->region_type == ORT_COMBINED_PARALLEL - && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)) + && ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP + || (region_type == ORT_WORKSHARE + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && (OMP_CLAUSE_REDUCTION_INSCAN (c) + || code == OMP_LOOP))) + && (outer_ctx->region_type == ORT_COMBINED_PARALLEL + || (code == OMP_LOOP + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && ((outer_ctx->region_type & ORT_COMBINED_TEAMS) + == ORT_COMBINED_TEAMS)))) { splay_tree_node on = splay_tree_lookup (outer_ctx->variables, @@ -9274,6 +9283,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_THREADS: case OMP_CLAUSE_SIMD: + case OMP_CLAUSE_BIND: case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: break; @@ -10239,6 +10249,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_HINT: case OMP_CLAUSE_DEFAULTMAP: case OMP_CLAUSE_ORDER: + case OMP_CLAUSE_BIND: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_IS_DEVICE_PTR: case OMP_CLAUSE_ASYNC: @@ -10764,9 +10775,12 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) } } + bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND) + != NULL_TREE); if (TREE_CODE (for_stmt) != OMP_TASKLOOP) gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort, - TREE_CODE (for_stmt)); + loop_p && TREE_CODE (for_stmt) != OMP_SIMD + ? OMP_LOOP : TREE_CODE (for_stmt)); if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE) gimplify_omp_ctxp->distribute = true; @@ -10997,7 +11011,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL; } } - else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1) + else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1 && !loop_p) { c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR); OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1; @@ -11740,6 +11754,259 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) return GS_ALL_DONE; } +/* Helper for gimplify_omp_loop, called through walk_tree. */ + +static tree +replace_reduction_placeholders (tree *tp, int *walk_subtrees, void *data) +{ + if (DECL_P (*tp)) + { + tree *d = (tree *) data; + if (*tp == OMP_CLAUSE_REDUCTION_PLACEHOLDER (d[0])) + { + *tp = OMP_CLAUSE_REDUCTION_PLACEHOLDER (d[1]); + *walk_subtrees = 0; + } + else if (*tp == OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (d[0])) + { + *tp = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (d[1]); + *walk_subtrees = 0; + } + } + return NULL_TREE; +} + +/* Gimplify the gross structure of an OMP_LOOP statement. */ + +static enum gimplify_status +gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p) +{ + tree for_stmt = *expr_p; + tree clauses = OMP_FOR_CLAUSES (for_stmt); + struct gimplify_omp_ctx *octx = gimplify_omp_ctxp; + enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD; + int i; + + /* If order is not present, the behavior is as if order(concurrent) + appeared. */ + tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER); + if (order == NULL_TREE) + { + order = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_ORDER); + OMP_CLAUSE_CHAIN (order) = clauses; + OMP_FOR_CLAUSES (for_stmt) = clauses = order; + } + + tree bind = omp_find_clause (clauses, OMP_CLAUSE_BIND); + if (bind == NULL_TREE) + { + if (!flag_openmp) /* flag_openmp_simd */ + ; + else if (octx && (octx->region_type & ORT_TEAMS) != 0) + kind = OMP_CLAUSE_BIND_TEAMS; + else if (octx && (octx->region_type & ORT_PARALLEL) != 0) + kind = OMP_CLAUSE_BIND_PARALLEL; + else + { + for (; octx; octx = octx->outer_context) + { + if ((octx->region_type & ORT_ACC) != 0 + || octx->region_type == ORT_NONE + || octx->region_type == ORT_IMPLICIT_TARGET) + continue; + break; + } + if (octx == NULL && !in_omp_construct) + error_at (EXPR_LOCATION (for_stmt), + "% clause not specified on a % " + "construct not nested inside another OpenMP construct"); + } + bind = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_BIND); + OMP_CLAUSE_CHAIN (bind) = clauses; + OMP_CLAUSE_BIND_KIND (bind) = kind; + OMP_FOR_CLAUSES (for_stmt) = bind; + } + else + switch (OMP_CLAUSE_BIND_KIND (bind)) + { + case OMP_CLAUSE_BIND_THREAD: + break; + case OMP_CLAUSE_BIND_PARALLEL: + if (!flag_openmp) /* flag_openmp_simd */ + { + OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD; + break; + } + for (; octx; octx = octx->outer_context) + if (octx->region_type == ORT_SIMD + && omp_find_clause (octx->clauses, OMP_CLAUSE_BIND) == NULL_TREE) + { + error_at (EXPR_LOCATION (for_stmt), + "% on a % construct nested " + "inside % construct"); + OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD; + break; + } + kind = OMP_CLAUSE_BIND_PARALLEL; + break; + case OMP_CLAUSE_BIND_TEAMS: + if (!flag_openmp) /* flag_openmp_simd */ + { + OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD; + break; + } + if ((octx + && octx->region_type != ORT_IMPLICIT_TARGET + && octx->region_type != ORT_NONE + && (octx->region_type & ORT_TEAMS) == 0) + || in_omp_construct) + { + error_at (EXPR_LOCATION (for_stmt), + "% on a % region not strictly " + "nested inside of a % region"); + OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD; + break; + } + kind = OMP_CLAUSE_BIND_TEAMS; + break; + default: + gcc_unreachable (); + } + + for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; ) + switch (OMP_CLAUSE_CODE (*pc)) + { + case OMP_CLAUSE_REDUCTION: + if (OMP_CLAUSE_REDUCTION_INSCAN (*pc)) + { + error_at (OMP_CLAUSE_LOCATION (*pc), + "% % clause on " + "%qs construct", "loop"); + OMP_CLAUSE_REDUCTION_INSCAN (*pc) = 0; + } + if (OMP_CLAUSE_REDUCTION_TASK (*pc)) + { + error_at (OMP_CLAUSE_LOCATION (*pc), + "invalid % reduction modifier on construct " + "other than %, % or %"); + OMP_CLAUSE_REDUCTION_TASK (*pc) = 0; + } + pc = &OMP_CLAUSE_CHAIN (*pc); + break; + case OMP_CLAUSE_LASTPRIVATE: + for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++) + { + tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i); + gcc_assert (TREE_CODE (t) == MODIFY_EXPR); + if (OMP_CLAUSE_DECL (*pc) == TREE_OPERAND (t, 0)) + break; + if (OMP_FOR_ORIG_DECLS (for_stmt) + && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), + i)) == TREE_LIST + && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), + i))) + { + tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i); + if (OMP_CLAUSE_DECL (*pc) == TREE_PURPOSE (orig)) + break; + } + } + if (i == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))) + { + error_at (OMP_CLAUSE_LOCATION (*pc), + "% clause on a % construct refers " + "to a variable %qD which is not the loop iterator", + OMP_CLAUSE_DECL (*pc)); + *pc = OMP_CLAUSE_CHAIN (*pc); + break; + } + pc = &OMP_CLAUSE_CHAIN (*pc); + break; + default: + pc = &OMP_CLAUSE_CHAIN (*pc); + break; + } + + TREE_SET_CODE (for_stmt, OMP_SIMD); + + int last; + switch (kind) + { + case OMP_CLAUSE_BIND_THREAD: last = 0; break; + case OMP_CLAUSE_BIND_PARALLEL: last = 1; break; + case OMP_CLAUSE_BIND_TEAMS: last = 2; break; + } + for (int pass = 1; pass <= last; pass++) + { + if (pass == 2) + { + tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); + append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind)); + *expr_p = make_node (OMP_PARALLEL); + TREE_TYPE (*expr_p) = void_type_node; + OMP_PARALLEL_BODY (*expr_p) = bind; + OMP_PARALLEL_COMBINED (*expr_p) = 1; + SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (for_stmt)); + } + tree t = make_node (pass == 2 ? OMP_DISTRIBUTE : OMP_FOR); + tree *pc = &OMP_FOR_CLAUSES (t); + TREE_TYPE (t) = void_type_node; + OMP_FOR_BODY (t) = *expr_p; + SET_EXPR_LOCATION (t, EXPR_LOCATION (for_stmt)); + for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c)) + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_BIND: + case OMP_CLAUSE_ORDER: + case OMP_CLAUSE_COLLAPSE: + *pc = copy_node (c); + pc = &OMP_CLAUSE_CHAIN (*pc); + break; + case OMP_CLAUSE_PRIVATE: + /* Only needed on innermost. */ + break; + case OMP_CLAUSE_LASTPRIVATE: + *pc = copy_node (c); + OMP_CLAUSE_LASTPRIVATE_STMT (*pc) = NULL_TREE; + TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c)); + pc = &OMP_CLAUSE_CHAIN (*pc); + break; + case OMP_CLAUSE_REDUCTION: + *pc = copy_node (c); + OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c)); + TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c)); + OMP_CLAUSE_REDUCTION_INIT (*pc) + = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c)); + OMP_CLAUSE_REDUCTION_MERGE (*pc) + = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c)); + if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)) + { + OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc) + = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)); + if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)) + OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc) + = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)); + tree nc = *pc; + tree data[2] = { c, nc }; + walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (nc), + replace_reduction_placeholders, + data); + walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (nc), + replace_reduction_placeholders, + data); + } + pc = &OMP_CLAUSE_CHAIN (*pc); + break; + default: + gcc_unreachable (); + } + *pc = NULL_TREE; + *expr_p = t; + } + return gimplify_omp_for (expr_p, pre_p); +} + + /* Helper function of optimize_target_teams, find OMP_TEAMS inside of OMP_TARGET's body. */ @@ -11974,10 +12241,7 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) case OMP_TEAMS: ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS; if (gimplify_omp_ctxp == NULL - || (gimplify_omp_ctxp->region_type == ORT_TARGET - && gimplify_omp_ctxp->outer_context == NULL - && lookup_attribute ("omp declare target", - DECL_ATTRIBUTES (current_function_decl)))) + || gimplify_omp_ctxp->region_type == ORT_IMPLICIT_TARGET) ort = (enum omp_region_type) (ort | ORT_HOST_TEAMS); break; case OACC_HOST_DATA: @@ -11986,6 +12250,10 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) default: gcc_unreachable (); } + + bool save_in_omp_construct = in_omp_construct; + if ((ort & ORT_ACC) == 0) + in_omp_construct = false; gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort, TREE_CODE (expr)); if (TREE_CODE (expr) == OMP_TARGET) @@ -12027,6 +12295,7 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p) gimplify_and_add (OMP_BODY (expr), &body); gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr), TREE_CODE (expr)); + in_omp_construct = save_in_omp_construct; switch (TREE_CODE (expr)) { @@ -13266,6 +13535,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_omp_for (expr_p, pre_p); break; + case OMP_LOOP: + ret = gimplify_omp_loop (expr_p, pre_p); + break; + case OACC_CACHE: gimplify_oacc_cache (expr_p, pre_p); ret = GS_ALL_DONE; @@ -13307,8 +13580,11 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { gimple_seq body = NULL; gimple *g; + bool saved_in_omp_construct = in_omp_construct; + in_omp_construct = true; gimplify_and_add (OMP_BODY (*expr_p), &body); + in_omp_construct = saved_in_omp_construct; switch (TREE_CODE (*expr_p)) { case OMP_SECTION: @@ -13351,10 +13627,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gimple_seq body = NULL; tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p); + bool saved_in_omp_construct = in_omp_construct; gimplify_scan_omp_clauses (pclauses, pre_p, ORT_TASKGROUP, OMP_TASKGROUP); gimplify_adjust_omp_clauses (pre_p, NULL, pclauses, OMP_TASKGROUP); + + in_omp_construct = true; gimplify_and_add (OMP_BODY (*expr_p), &body); + in_omp_construct = saved_in_omp_construct; gimple_seq cleanup = NULL; tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END); gimple *g = gimple_build_call (fn, 0); @@ -13977,7 +14257,7 @@ gimplify_body (tree fndecl, bool do_parms) { gcc_assert (gimplify_omp_ctxp == NULL); if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl))) - gimplify_omp_ctxp = new_omp_context (ORT_TARGET); + gimplify_omp_ctxp = new_omp_context (ORT_IMPLICIT_TARGET); } /* Unshare most shared trees in the body and in that of any nested functions. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 03df07b..d8756c0 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -153,6 +153,9 @@ struct omp_context /* True if there is order(concurrent) clause on the construct. */ bool order_concurrent; + + /* True if there is bind clause on the construct (i.e. a loop construct). */ + bool loop_p; }; static splay_tree all_contexts; @@ -581,6 +584,7 @@ build_outer_var_ref (tree var, omp_context *ctx, } else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) + || ctx->loop_p || (code == OMP_CLAUSE_PRIVATE && (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR || gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS @@ -1397,6 +1401,10 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) ctx->order_concurrent = true; break; + case OMP_CLAUSE_BIND: + ctx->loop_p = true; + break; + case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_COLLAPSE: @@ -1603,6 +1611,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE_NOGROUP: case OMP_CLAUSE_DEFAULTMAP: case OMP_CLAUSE_ORDER: + case OMP_CLAUSE_BIND: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_NONTEMPORAL: case OMP_CLAUSE_ASYNC: @@ -2675,7 +2684,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR) ctx = ctx->outer; if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD + && !ctx->loop_p) { c = NULL_TREE; if (ctx->order_concurrent @@ -2684,8 +2694,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)) { error_at (gimple_location (stmt), - "OpenMP constructs other than % or" - " % may not be nested inside a region with" + "OpenMP constructs other than %, %" + " or % may not be nested inside a region with" " the % clause"); return false; } @@ -2714,23 +2724,28 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE || gimple_code (stmt) == GIMPLE_OMP_SCAN) return true; + else if (gimple_code (stmt) == GIMPLE_OMP_FOR + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) + return true; error_at (gimple_location (stmt), - "OpenMP constructs other than %<#pragma omp ordered simd%>" - " or %<#pragma omp atomic%> may not be nested inside" - " % region"); + "OpenMP constructs other than " + "%, %, % or % may " + "not be nested inside % region"); return false; } else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS) { if ((gimple_code (stmt) != GIMPLE_OMP_FOR - || ((gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_DISTRIBUTE) - && (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_GRID_LOOP))) + || (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_DISTRIBUTE + && gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_GRID_LOOP + && omp_find_clause (gimple_omp_for_clauses (stmt), + OMP_CLAUSE_BIND) == NULL_TREE)) && gimple_code (stmt) != GIMPLE_OMP_PARALLEL) { error_at (gimple_location (stmt), - "only % or % regions are " - "allowed to be strictly nested inside % " - "region"); + "only %, % or % " + "regions are allowed to be strictly nested inside " + "% region"); return false; } } @@ -2740,10 +2755,15 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) || gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_SIMD) && gimple_code (stmt) != GIMPLE_OMP_SCAN) { - error_at (gimple_location (stmt), - "OpenMP constructs other than % or" - " % may not be nested inside a region with" - " the % clause"); + if (ctx->loop_p) + error_at (gimple_location (stmt), + "OpenMP constructs other than %, % or " + "% may not be nested inside a % region"); + else + error_at (gimple_location (stmt), + "OpenMP constructs other than %, % or " + "% may not be nested inside a region with " + "the % clause"); return false; } } @@ -2766,6 +2786,11 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) /* We split taskloop into task and nested taskloop in it. */ if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP) return true; + /* For now, hope this will change and loop bind(parallel) will not + be allowed in lots of contexts. */ + if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR + && omp_find_clause (gimple_omp_for_clauses (stmt), OMP_CLAUSE_BIND)) + return true; if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP) { bool ok = false; @@ -2816,8 +2841,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) const char *construct = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) == BUILT_IN_GOMP_CANCEL) - ? "#pragma omp cancel" - : "#pragma omp cancellation point"; + ? "cancel" + : "cancellation point"; if (ctx == NULL) { error_at (gimple_location (stmt), "orphaned %qs construct", @@ -2830,7 +2855,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) { case 1: if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL) - bad = "#pragma omp parallel"; + bad = "parallel"; else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) == BUILT_IN_GOMP_CANCEL && !integer_zerop (gimple_call_arg (stmt, 1))) @@ -2840,7 +2865,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) case 2: if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR) - bad = "#pragma omp for"; + bad = "for"; else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) == BUILT_IN_GOMP_CANCEL && !integer_zerop (gimple_call_arg (stmt, 1))) @@ -2849,12 +2874,12 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt), OMP_CLAUSE_NOWAIT)) warning_at (gimple_location (stmt), 0, - "%<#pragma omp cancel for%> inside " + "% inside " "% for construct"); if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt), OMP_CLAUSE_ORDERED)) warning_at (gimple_location (stmt), 0, - "%<#pragma omp cancel for%> inside " + "% inside " "% for construct"); } kind = "for"; @@ -2862,7 +2887,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) case 4: if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION) - bad = "#pragma omp sections"; + bad = "sections"; else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) == BUILT_IN_GOMP_CANCEL && !integer_zerop (gimple_call_arg (stmt, 1))) @@ -2874,7 +2899,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) (ctx->stmt), OMP_CLAUSE_NOWAIT)) warning_at (gimple_location (stmt), 0, - "%<#pragma omp cancel sections%> inside " + "% inside " "% sections construct"); } else @@ -2887,7 +2912,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) (ctx->outer->stmt), OMP_CLAUSE_NOWAIT)) warning_at (gimple_location (stmt), 0, - "%<#pragma omp cancel sections%> inside " + "% inside " "% sections construct"); } } @@ -2898,7 +2923,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) && (!is_taskloop_ctx (ctx) || ctx->outer == NULL || !is_task_ctx (ctx->outer))) - bad = "#pragma omp task"; + bad = "task"; else { for (omp_context *octx = ctx->outer; @@ -2976,14 +3001,14 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) return true; error_at (gimple_location (stmt), "barrier region may not be closely nested inside " - "of work-sharing, %, %, " - "%, explicit % or % " - "region"); + "of work-sharing, %, %, " + "%, %, explicit % or " + "% region"); return false; } error_at (gimple_location (stmt), "work-sharing region may not be closely nested inside " - "of work-sharing, %, %, " + "of work-sharing, %, %, %, " "%, explicit % or % region"); return false; case GIMPLE_OMP_PARALLEL: @@ -3012,8 +3037,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) case GIMPLE_OMP_TASK: error_at (gimple_location (stmt), "% region may not be closely nested inside " - "of work-sharing, explicit % or % " - "region"); + "of work-sharing, %, explicit % or " + "% region"); return false; case GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TEAMS: @@ -3497,11 +3522,12 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD - && setjmp_or_longjmp_p (fndecl)) + && setjmp_or_longjmp_p (fndecl) + && !ctx->loop_p) { remove = true; error_at (gimple_location (stmt), - "setjmp/longjmp inside simd construct"); + "setjmp/longjmp inside % construct"); } else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (fndecl)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a7c9426..adefdb9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,19 @@ 2019-07-20 Jakub Jelinek + * c-c++-common/gomp/cancel-1.c: Adjust expected diagnostic wording. + * c-c++-common/gomp/clauses-1.c (foo, baz, bar): Add order(concurrent) + clause where allowed. Add combined constructs with loop with all + possible clauses. + (qux): New function. + * c-c++-common/gomp/loop-1.c: New test. + * c-c++-common/gomp/loop-2.c: New test. + * c-c++-common/gomp/loop-3.c: New test. + * c-c++-common/gomp/loop-4.c: New test. + * c-c++-common/gomp/loop-5.c: New test. + * c-c++-common/gomp/order-3.c: Adjust expected diagnostic wording. + * c-c++-common/gomp/simd-setjmp-1.c: New test. + * c-c++-common/gomp/teams-2.c: Adjust expected diagnostic wording. + * gcc.dg/vect/vect-simd-16.c: New test. 2019-07-19 Jeff Law diff --git a/gcc/testsuite/c-c++-common/gomp/cancel-1.c b/gcc/testsuite/c-c++-common/gomp/cancel-1.c index 03aedeb..5255dd3 100644 --- a/gcc/testsuite/c-c++-common/gomp/cancel-1.c +++ b/gcc/testsuite/c-c++-common/gomp/cancel-1.c @@ -336,14 +336,14 @@ f2 (void) } #pragma omp target teams { - #pragma omp cancel parallel /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ - #pragma omp cancel for /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ - #pragma omp cancel sections /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ - #pragma omp cancel taskgroup /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ - #pragma omp cancellation point parallel /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ - #pragma omp cancellation point for /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ - #pragma omp cancellation point sections /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ - #pragma omp cancellation point taskgroup /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */ + #pragma omp cancel parallel /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ + #pragma omp cancel for /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ + #pragma omp cancel sections /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ + #pragma omp cancel taskgroup /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point parallel /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point for /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point sections /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ + #pragma omp cancellation point taskgroup /* { dg-error "only .distribute., .parallel. or .loop. regions are allowed to be strictly nested" } */ } #pragma omp target teams distribute for (i = 0; i < 10; i++) diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-1.c b/gcc/testsuite/c-c++-common/gomp/clauses-1.c index 652270c..be42797 100644 --- a/gcc/testsuite/c-c++-common/gomp/clauses-1.c +++ b/gcc/testsuite/c-c++-common/gomp/clauses-1.c @@ -14,22 +14,32 @@ foo (int d, int m, int i1, int i2, int p, int *idp, int s, #pragma omp distribute parallel for \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) + lastprivate (l) schedule(static, 4) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp distribute parallel for simd \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ lastprivate (l) schedule(static, 4) nontemporal(ntm) \ - safelen(8) simdlen(4) aligned(q: 32) + safelen(8) simdlen(4) aligned(q: 32) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp distribute simd \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ - safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) + safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; } + +void +qux (int p) +{ + #pragma omp loop bind(teams) order(concurrent) \ + private (p) lastprivate (l) collapse(1) reduction(+:r) + for (l = 0; l < 64; ++l) + ll++; +} #pragma omp end declare target void @@ -39,21 +49,26 @@ baz (int d, int m, int i1, int i2, int p, int *idp, int s, #pragma omp distribute parallel for \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) copyin(t) + lastprivate (l) schedule(static, 4) copyin(t) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp distribute parallel for simd \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ lastprivate (l) schedule(static, 4) nontemporal(ntm) \ - safelen(8) simdlen(4) aligned(q: 32) copyin(t) + safelen(8) simdlen(4) aligned(q: 32) copyin(t) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp distribute simd \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ - safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) + safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; + #pragma omp loop bind(parallel) order(concurrent) \ + private (p) lastprivate (l) collapse(1) reduction(+:r) + for (l = 0; l < 64; ++l) + ll++; } void @@ -62,7 +77,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, { #pragma omp for simd \ private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait \ - safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) + safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp parallel for \ @@ -70,10 +85,15 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1) for (int i = 0; i < 64; i++) ll++; + #pragma omp parallel for \ + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \ + lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) order(concurrent) + for (int i = 0; i < 64; i++) + ll++; #pragma omp parallel for simd \ private (p) firstprivate (f) if (i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \ lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) \ - safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) + safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp parallel sections \ @@ -96,11 +116,17 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, lastprivate (l) linear (ll:1) ordered schedule(static, 4) collapse(1) nowait depend(inout: dd[0]) for (int i = 0; i < 64; i++) ll++; + #pragma omp target parallel for \ + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ + lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) nowait depend(inout: dd[0]) order(concurrent) + for (int i = 0; i < 64; i++) + ll++; #pragma omp target parallel for simd \ device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) \ - safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) + safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp target teams \ @@ -118,7 +144,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ collapse(1) dist_schedule(static, 16) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) nowait depend(inout: dd[0]) + lastprivate (l) schedule(static, 4) nowait depend(inout: dd[0]) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp target teams distribute parallel for simd \ @@ -126,39 +152,42 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ collapse(1) dist_schedule(static, 16) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) \ + lastprivate (l) schedule(static, 4) order(concurrent) \ safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) for (int i = 0; i < 64; i++) ll++; #pragma omp target teams distribute simd \ device(d) map (tofrom: m) if (i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ - collapse(1) dist_schedule(static, 16) \ + collapse(1) dist_schedule(static, 16) order(concurrent) \ safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp target simd \ device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ safelen(8) simdlen(4) lastprivate (l) linear(ll: 1) aligned(q: 32) reduction(+:r) \ - nowait depend(inout: dd[0]) nontemporal(ntm) if(simd:i3) + nowait depend(inout: dd[0]) nontemporal(ntm) if(simd:i3) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp taskgroup task_reduction(+:r2) #pragma omp taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp taskgroup task_reduction(+:r) #pragma omp taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(i1) final(fi) mergeable nogroup priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) in_reduction(+:r) nontemporal(ntm) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) in_reduction(+:r) nontemporal(ntm) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp taskwait #pragma omp taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) if(taskloop: i1) final(fi) priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(+:r) if (simd: i3) nontemporal(ntm) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(+:r) if (simd: i3) nontemporal(ntm) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp target nowait depend(inout: dd[0]) @@ -172,7 +201,7 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ collapse(1) dist_schedule(static, 16) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) + lastprivate (l) schedule(static, 4) order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp target @@ -180,20 +209,20 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ collapse(1) dist_schedule(static, 16) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) \ + lastprivate (l) schedule(static, 4) order(concurrent) \ safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp target #pragma omp teams distribute simd \ private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ - collapse(1) dist_schedule(static, 16) \ + collapse(1) dist_schedule(static, 16) order(concurrent) \ safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp teams distribute parallel for \ private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ - collapse(1) dist_schedule(static, 16) \ + collapse(1) dist_schedule(static, 16) order(concurrent) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ lastprivate (l) schedule(static, 4) copyin(t) for (int i = 0; i < 64; i++) @@ -202,13 +231,13 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ collapse(1) dist_schedule(static, 16) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) \ + lastprivate (l) schedule(static, 4) order(concurrent) \ safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) copyin(t) for (int i = 0; i < 64; i++) ll++; #pragma omp teams distribute simd \ private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ - collapse(1) dist_schedule(static, 16) \ + collapse(1) dist_schedule(static, 16) order(concurrent) \ safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; @@ -225,7 +254,8 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, #pragma omp taskgroup task_reduction (+:r2) #pragma omp master taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp parallel master taskloop \ @@ -235,7 +265,8 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, ll++; #pragma omp parallel master taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp taskgroup task_reduction (+:r2) @@ -247,7 +278,8 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, #pragma omp taskgroup task_reduction (+:r2) #pragma omp master taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; #pragma omp parallel master taskloop \ @@ -257,7 +289,56 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, ll++; #pragma omp parallel master taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) num_threads (nth) proc_bind(spread) copyin(t) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) num_threads (nth) proc_bind(spread) copyin(t) \ + order(concurrent) for (int i = 0; i < 64; i++) ll++; + #pragma omp loop bind(thread) order(concurrent) \ + private (p) lastprivate (l) collapse(1) reduction(+:r) + for (l = 0; l < 64; ++l) + ll++; + #pragma omp parallel loop \ + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \ + lastprivate (l) collapse(1) bind(parallel) order(concurrent) + for (l = 0; l < 64; l++) + ll++; + #pragma omp parallel loop \ + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \ + lastprivate (l) collapse(1) + for (l = 0; l < 64; l++) + ll++; + #pragma omp teams loop \ + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ + collapse(1) lastprivate (l) bind(teams) + for (l = 0; l < 64; ++l) + ; + #pragma omp teams loop \ + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ + collapse(1) lastprivate (l) order(concurrent) + for (l = 0; l < 64; ++l) + ; + #pragma omp target parallel loop \ + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ + nowait depend(inout: dd[0]) lastprivate (l) bind(parallel) order(concurrent) collapse(1) + for (l = 0; l < 64; ++l) + ; + #pragma omp target parallel loop \ + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ + nowait depend(inout: dd[0]) lastprivate (l) order(concurrent) collapse(1) + for (l = 0; l < 64; ++l) + ; + #pragma omp target teams loop \ + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) \ + lastprivate (l) bind(teams) collapse(1) + for (l = 0; l < 64; ++l) + ; + #pragma omp target teams loop \ + device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ + shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) nowait depend(inout: dd[0]) \ + lastprivate (l) order(concurrent) collapse(1) + for (l = 0; l < 64; ++l) + ; } diff --git a/gcc/testsuite/c-c++-common/gomp/loop-1.c b/gcc/testsuite/c-c++-common/gomp/loop-1.c new file mode 100644 index 0000000..d2f943a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-1.c @@ -0,0 +1,271 @@ +void foo (void); +int v; +#ifdef __cplusplus +extern "C" { +#endif +int omp_get_thread_num (void); +int omp_get_num_threads (void); +int omp_target_is_present (const void *, int); +int omp_get_cancellation (void); +#ifdef __cplusplus +} +#endif + +void +f1 (int *a) +{ + int i; + #pragma omp simd order(concurrent) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp loop + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } +} + +void +f2 (int *a) +{ + int i; + #pragma omp for simd order(concurrent) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp loop + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } +} + +void +f3 (int *a) +{ + int i; + #pragma omp for order(concurrent) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp loop + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } +} + +void +f4 (int *a) +{ + int i; + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + #pragma omp parallel + foo (); + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp simd + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + int j; + #pragma omp loop + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + foo (); + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + foo (); + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + v++; + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + #pragma omp atomic read + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + { + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" "" { target c } } */ + } + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop order(concurrent) bind(parallel) + for (i = 0; i < 64; i++) + a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ +} + +void +f5 (int *a) +{ + int i; + #pragma omp parallel + { + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp parallel + foo (); + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + int j; + #pragma omp simd + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + int j; + #pragma omp loop + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + foo (); + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + foo (); + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + v++; + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp atomic read + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" "" { target c } } */ + } + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + } +} + +void +f6 (int *a) +{ + int i; + #pragma omp master + { + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp parallel + foo (); + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + int j; + #pragma omp simd + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + int j; + #pragma omp loop + for (j = 0; j < 64; j++) + a[64 * i + j] = i + j; + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + foo (); + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + foo (); + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + v++; + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp atomic read + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" } */ + } + #pragma omp loop + for (i = 0; i < 64; i++) + { + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' region" "" { target c } } */ + } + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_get_thread_num (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_thread_num\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_get_num_threads (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_num_threads\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_target_is_present (a + i, 0); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_target_is_present\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] += omp_get_cancellation (); /* { dg-error "OpenMP runtime API call '\[^\n\r]*omp_get_cancellation\[^\n\r]*' in a region with 'order\\(concurrent\\)' clause" } */ + } +} + diff --git a/gcc/testsuite/c-c++-common/gomp/loop-2.c b/gcc/testsuite/c-c++-common/gomp/loop-2.c new file mode 100644 index 0000000..ce9b6c9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-2.c @@ -0,0 +1,294 @@ +#ifdef __cplusplus +extern "C" { +#endif +int omp_get_thread_num (void); +#ifdef __cplusplus +} +#endif + +void +f0 (int *a) +{ + int i; + #pragma omp loop bind(teams) order(concurrent) + for (i = 0; i < 64; i++) + a[i] = i; +} + +void +f1 (int *a) +{ + int i; + #pragma omp teams + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp teams + { + #pragma omp loop bind(teams) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp teams + { + #pragma omp loop bind(parallel) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp teams + { + #pragma omp loop lastprivate (i) bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } +} + +void +f2 (int *a) +{ + int i; + #pragma omp loop bind(parallel) order(concurrent) + for (i = 0; i < 64; i++) + a[i] = i; + #pragma omp parallel + { + #pragma omp loop private (i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp parallel + { + #pragma omp loop lastprivate (i) bind(parallel) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp parallel + { + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp taskgroup + { + #pragma omp loop bind(parallel) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp teams + { + int j; + #pragma omp distribute + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(parallel) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + } + #pragma omp target + { + #pragma omp loop bind(parallel) + for (i = 0; i < 64; i++) + a[i] = i; + } +} + +void +f3 (int *a) +{ + int i, j; + #pragma omp loop order ( concurrent )bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + #pragma omp parallel num_threads (4) + { + int j = omp_get_thread_num (); + #pragma omp loop private (i) bind(thread) + for (i = 0; i < 64; i++) + a[j * 64 + i] = i; + } + #pragma omp critical + { + #pragma omp loop lastprivate (i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp critical + { + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp master + { + #pragma omp loop private (i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp master + { + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp sections + { + #pragma omp loop private (i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp sections + { + #pragma omp loop bind(thread) lastprivate(i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp single + { + #pragma omp loop private (i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp single + { + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp task + { + #pragma omp loop private (i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp task + { + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp taskgroup + { + #pragma omp loop private (i) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp taskgroup + { + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp teams + { + #pragma omp distribute + for (j = 0; j < 64; ++j) + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + } + #pragma omp for + for (j = 0; j < 64; ++j) + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp parallel + #pragma omp loop + for (j = 0; j < 64; ++j) + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp loop bind(thread) + for (j = 0; j < 64; ++j) + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp loop bind(parallel) + for (j = 0; j < 64; ++j) + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp for ordered + for (j = 0; j < 64; ++j) + { + #pragma omp ordered + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp ordered threads + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp simd + for (j = 0; j < 64; ++j) + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp taskloop + for (j = 0; j < 64; ++j) + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp target + { + #pragma omp loop + for (i = 0; i < 64; i++) + a[i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } +} + +void +f4 (int *a) +{ + int i; + #pragma omp ordered + { + #pragma omp loop private (i) + for (i = 0; i < 64; i++) + a[i] = i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + a[i] = i; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/loop-3.c b/gcc/testsuite/c-c++-common/gomp/loop-3.c new file mode 100644 index 0000000..186b8cc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-3.c @@ -0,0 +1,145 @@ +#ifdef __cplusplus +extern "C" { +#endif +int omp_get_thread_num (void); +#ifdef __cplusplus +} +#endif + +void +f1 (int *a) +{ + int i; + #pragma omp loop /* { dg-error "'bind' clause not specified on a 'loop' construct not nested inside another OpenMP construct" } */ + for (i = 0; i < 64; i++) + a[i] = i; +} + +void +f2 (int *a) +{ + int i, j; + #pragma omp parallel num_threads (4) + { + int j = omp_get_thread_num (); + #pragma omp loop private (i) bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[j * 64 + i] = i; + } + #pragma omp critical + { + #pragma omp loop lastprivate (i) bind(teams)/* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp master + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp sections + { + #pragma omp loop bind(teams) lastprivate(i) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp single + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp task + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp taskgroup + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[i] = i; + } + #pragma omp teams + { + #pragma omp distribute + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + } + #pragma omp for + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp parallel + #pragma omp loop + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp loop bind(thread) + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp loop bind(parallel) + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp for ordered + for (j = 0; j < 64; ++j) + { + #pragma omp ordered threads + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp simd + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp taskloop + for (j = 0; j < 64; ++j) + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } + #pragma omp target + { + #pragma omp loop bind(teams) /* { dg-error "'bind\\(teams\\)' on a 'loop' region not strictly nested inside of a 'teams' region" } */ + for (i = 0; i < 64; i++) + a[i] = i; + } +} + +void +f3 (int *a) +{ + int i, j; + #pragma omp simd + for (j = 0; j < 64; j++) + { + #pragma omp loop bind(parallel) /* { dg-error "'bind\\(parallel\\)' on a 'loop' construct nested inside 'simd' construct" } */ + for (i = 0; i < 64; i++) + a[64 * j + i] = i; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/loop-4.c b/gcc/testsuite/c-c++-common/gomp/loop-4.c new file mode 100644 index 0000000..b77f8c9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-4.c @@ -0,0 +1,46 @@ +int r, l; + +void +f1 (int *a) +{ + int i; + #pragma omp master + { + #pragma omp loop bind /* { dg-error "expected" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind ) /* { dg-error "expected" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind ( /* { dg-error "expected" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind () /* { dg-error "expected" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind ( foobar ) /* { dg-error "expected" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind (default) /* { dg-error "expected" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind (parallel /* { dg-error "expected" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + } +} + +void +f2 (int *a) +{ + int i; + #pragma omp loop bind(parallel) reduction(task, +: r) /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind(thread) reduction(inscan, +: r) /* { dg-error "'inscan' 'reduction' clause on 'loop' construct" } */ + for (i = 0; i < 64; ++i) + a[i] = i; + #pragma omp loop bind(parallel) lastprivate (l) /* { dg-error "'lastprivate' clause on a 'loop' construct refers to a variable 'l' which is not the loop iterator" } */ + for (i = 0; i < 64; ++i) + l = i; +} diff --git a/gcc/testsuite/c-c++-common/gomp/loop-5.c b/gcc/testsuite/c-c++-common/gomp/loop-5.c new file mode 100644 index 0000000..b9b2ad9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/loop-5.c @@ -0,0 +1,56 @@ +__attribute__((noipa)) int +foo (int *a, int *r3) +{ + int r = 0, r2[2] = { 0, 0 }, i; + #pragma omp parallel loop default (none) reduction (+:r, r2[:2], r3[:2]) shared (a) lastprivate (i) + for (i = 0; i < 1024; i++) + { + r += a[i]; + r2[0] += a[i]; + r3[1] += a[i]; + }; + return r + r2[0] + r3[1] + i; +} + +__attribute__((noipa)) int +bar (int *a, int *r3) +{ + int r = 0, r2[2] = { 0, 0 }, i; + #pragma omp target parallel loop default (none) reduction (+:r, r2[0:2], r3[0:2]) shared (a) lastprivate (i) + for (i = 0; i < 1024; i++) + { + r += a[i]; + r2[1] += a[i]; + r3[0] += a[i]; + } + return r + r2[1] + r3[0] + i; +} + +__attribute__((noipa)) int +baz (int *a, int *r3) +{ + int r = 0, r2[2] = { 0, 0 }, i; + #pragma omp teams loop default (none) reduction (+:r, r2[0:2], r3[1:1]) shared (a) lastprivate (i) + for (i = 0; i < 1024; i++) + { + r += a[i]; + r2[0] += a[i]; + r3[1] += a[i]; + } + return r + r2[0] + r3[1] + i; +} + +__attribute__((noipa)) int +qux (int *a, int *r3) +{ + int r = 0, r2[2] = { 0, 0 }, i; + #pragma omp target teams loop default (none) reduction (+:r, r2[1:1], r3[0:2]) shared (a) lastprivate (i) + for (i = 0; i < 1024; i++) + { + r += a[i]; + r2[1] += a[i]; + r3[0] += a[i] - 1; + r3[1] += a[i]; + } + return r + r2[1] + r3[0] + r3[1] + i; +} diff --git a/gcc/testsuite/c-c++-common/gomp/order-3.c b/gcc/testsuite/c-c++-common/gomp/order-3.c index 225d0cc..2d51bf3 100644 --- a/gcc/testsuite/c-c++-common/gomp/order-3.c +++ b/gcc/testsuite/c-c++-common/gomp/order-3.c @@ -18,46 +18,46 @@ f1 (int *a) #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp parallel /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + #pragma omp parallel /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */ foo (); } #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) { int j; - #pragma omp simd /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + #pragma omp simd for (j = 0; j < 64; j++) a[64 * i + j] = i + j; } #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp critical /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + #pragma omp critical /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */ foo (); } #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ foo (); } #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ v++; } #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) { #pragma omp atomic read - a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ } #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ - v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ } #pragma omp simd order(concurrent) for (i = 0; i < 64; i++) @@ -80,46 +80,46 @@ f2 (int *a) #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp parallel /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + #pragma omp parallel /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */ foo (); } #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) { int j; - #pragma omp simd /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + #pragma omp simd for (j = 0; j < 64; j++) a[64 * i + j] = i + j; } #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp critical /* { dg-error "OpenMP constructs other than '#pragma omp ordered simd' or '#pragma omp atomic' may not be nested inside 'simd' region" } */ + #pragma omp critical /* { dg-error "OpenMP constructs other than 'ordered simd', 'simd', 'loop' or 'atomic' may not be nested inside 'simd' region" } */ foo (); } #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ foo (); } #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ v++; } #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) { #pragma omp atomic read - a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ } #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ - v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ } #pragma omp for simd order(concurrent) for (i = 0; i < 64; i++) @@ -156,44 +156,44 @@ f3 (int *a) #pragma omp for order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp critical /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ foo (); } #pragma omp for order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp ordered simd /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ foo (); } #pragma omp for order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp atomic /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ v++; } #pragma omp for order(concurrent) for (i = 0; i < 64; i++) { #pragma omp atomic read - a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + a[i] = v; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ } #pragma omp for order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ - v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ + #pragma omp atomic write /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ + v = a[i]; /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" "" { target c } } */ } #pragma omp for order(concurrent) for (i = 0; i < 64; i++) { - #pragma omp task /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp task /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ a[i]++; } #pragma omp for order(concurrent) for (i = 0; i < 64; i++) { int j; - #pragma omp taskloop /* { dg-error "OpenMP constructs other than 'parallel' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ + #pragma omp taskloop /* { dg-error "OpenMP constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a region with the 'order\\(concurrent\\)' clause" } */ for (j = 0; j < 64; j++) a[64 * i + j] = i + j; } diff --git a/gcc/testsuite/c-c++-common/gomp/simd-setjmp-1.c b/gcc/testsuite/c-c++-common/gomp/simd-setjmp-1.c new file mode 100644 index 0000000..453e001 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/simd-setjmp-1.c @@ -0,0 +1,68 @@ +typedef long int jmp_buf[8]; +extern +#ifdef __cplusplus +"C" +#endif +int setjmp (jmp_buf); + +void +foo (void) +{ + int i; + #pragma omp simd + for (i = 0; i < 64; i++) + { + jmp_buf buf; + setjmp (buf); /* { dg-error "setjmp/longjmp inside 'simd' construct" } */ + } +} + +void +bar (void) +{ + int i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + { + jmp_buf buf; + setjmp (buf); + } +} + +#ifdef __cplusplus +struct S +{ + static int setjmp (jmp_buf); +}; + +namespace N +{ + int setjmp (jmp_buf); +} + +void +baz (void) +{ + int i; + #pragma omp simd + for (i = 0; i < 64; i++) + { + jmp_buf buf; + S::setjmp (buf); + N::setjmp (buf); + } +} + +void +qux (void) +{ + int i; + #pragma omp loop bind(thread) + for (i = 0; i < 64; i++) + { + jmp_buf buf; + S::setjmp (buf); + N::setjmp (buf); + } +} +#endif diff --git a/gcc/testsuite/c-c++-common/gomp/teams-2.c b/gcc/testsuite/c-c++-common/gomp/teams-2.c index 011c284..85a5be7 100644 --- a/gcc/testsuite/c-c++-common/gomp/teams-2.c +++ b/gcc/testsuite/c-c++-common/gomp/teams-2.c @@ -10,7 +10,7 @@ foo (void) } #pragma omp teams { - #pragma omp teams /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp teams /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; } #pragma omp target @@ -72,48 +72,48 @@ bar (void) #pragma omp teams { int x, y, v = 4; - #pragma omp target /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp target /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp target data map (to: v) /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp target data map (to: v) /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp for /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp for /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ for (int i = 0; i < 64; ++i) ; - #pragma omp simd /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp simd /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ for (int i = 0; i < 64; ++i) ; - #pragma omp for simd /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp for simd /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ for (int i = 0; i < 64; ++i) ; - #pragma omp single /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp single /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp master /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp master /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp sections /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp sections /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ { x = 1; #pragma omp section y = 2; } - #pragma omp critical /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp critical /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp target enter data map (to: v) /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ - #pragma omp target exit data map (from: v) /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ - #pragma omp cancel parallel /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ - #pragma omp cancellation point parallel /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ - #pragma omp barrier /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ - #pragma omp ordered /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp target enter data map (to: v) /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp target exit data map (from: v) /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp cancel parallel /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp cancellation point parallel /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp barrier /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp ordered /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp task /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp task /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp taskloop /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp taskloop /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ for (int i = 0; i < 64; ++i) ; - #pragma omp atomic /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp atomic /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ v++; - #pragma omp taskgroup /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp taskgroup /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ ; - #pragma omp taskwait /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ - #pragma omp taskyield /* { dg-error "only 'distribute' or 'parallel' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp taskwait /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ + #pragma omp taskyield /* { dg-error "only 'distribute', 'parallel' or 'loop' regions are allowed to be strictly nested inside 'teams' region" } */ } } diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 8ac07e8..fa37a0d 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -451,6 +451,9 @@ enum omp_clause_code { /* OpenMP clause: order (concurrent). */ OMP_CLAUSE_ORDER, + /* OpenMP clause: bind (binding). */ + OMP_CLAUSE_BIND, + /* Internally used only clause, holding SIMD uid. */ OMP_CLAUSE__SIMDUID_, @@ -539,6 +542,12 @@ enum omp_clause_defaultmap_kind { OMP_CLAUSE_DEFAULTMAP_MASK = 7 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1) }; +enum omp_clause_bind_kind { + OMP_CLAUSE_BIND_TEAMS, + OMP_CLAUSE_BIND_PARALLEL, + OMP_CLAUSE_BIND_THREAD +}; + /* memory-order-clause on OpenMP atomic/flush constructs or argument of atomic_default_mem_order clause. */ enum omp_memory_order { @@ -1531,6 +1540,7 @@ struct GTY(()) tree_omp_clause { enum omp_clause_linear_kind linear_kind; enum tree_code if_modifier; enum omp_clause_defaultmap_kind defaultmap_kind; + enum omp_clause_bind_kind bind_kind; /* The dimension a OMP_CLAUSE__GRIDDIM_ clause of a gridified target construct describes. */ unsigned int dimension; diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index a75f97a..9bea132 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -1044,6 +1044,25 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) pp_string (pp, "order(concurrent)"); break; + case OMP_CLAUSE_BIND: + pp_string (pp, "bind("); + switch (OMP_CLAUSE_BIND_KIND (clause)) + { + case OMP_CLAUSE_BIND_TEAMS: + pp_string (pp, "teams"); + break; + case OMP_CLAUSE_BIND_PARALLEL: + pp_string (pp, "parallel"); + break; + case OMP_CLAUSE_BIND_THREAD: + pp_string (pp, "thread"); + break; + default: + gcc_unreachable (); + } + pp_right_paren (pp); + break; + case OMP_CLAUSE__SIMDUID_: pp_string (pp, "_simduid_("); dump_generic_node (pp, OMP_CLAUSE__SIMDUID__DECL (clause), @@ -3261,6 +3280,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, pp_string (pp, "#pragma omp taskloop"); goto dump_omp_loop; + case OMP_LOOP: + pp_string (pp, "#pragma omp loop"); + goto dump_omp_loop; + case OACC_LOOP: pp_string (pp, "#pragma acc loop"); goto dump_omp_loop; diff --git a/gcc/tree.c b/gcc/tree.c index 751370b..8cf75f2 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -344,6 +344,7 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_HINT */ 0, /* OMP_CLAUSE_DEFAULTMAP */ 0, /* OMP_CLAUSE_ORDER */ + 0, /* OMP_CLAUSE_BIND */ 1, /* OMP_CLAUSE__SIMDUID_ */ 0, /* OMP_CLAUSE__SIMT_ */ 0, /* OMP_CLAUSE_INDEPENDENT */ @@ -426,6 +427,7 @@ const char * const omp_clause_code_name[] = "hint", "defaultmap", "order", + "bind", "_simduid_", "_simt_", "independent", @@ -12343,6 +12345,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, case OMP_CLAUSE_SIMD: case OMP_CLAUSE_DEFAULTMAP: case OMP_CLAUSE_ORDER: + case OMP_CLAUSE_BIND: case OMP_CLAUSE_AUTO: case OMP_CLAUSE_SEQ: case OMP_CLAUSE_TILE: diff --git a/gcc/tree.def b/gcc/tree.def index d2e6938..4a22d94 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -1153,6 +1153,10 @@ DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 7) Operands like for OMP_FOR. */ DEFTREECODE (OMP_TASKLOOP, "omp_taskloop", tcc_statement, 7) +/* OpenMP - #pragma omp loop [clause1 ... clauseN] + Operands like for OMP_FOR. */ +DEFTREECODE (OMP_LOOP, "omp_loop", tcc_statement, 7) + /* OpenMP - #pragma acc loop [clause1 ... clauseN] Operands like for OMP_FOR. */ DEFTREECODE (OACC_LOOP, "oacc_loop", tcc_statement, 7) diff --git a/gcc/tree.h b/gcc/tree.h index 992abd1..99d021e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1387,14 +1387,14 @@ class auto_suppress_location_wrappers #define OMP_TASKREG_BODY(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 0) #define OMP_TASKREG_CLAUSES(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 1) -#define OMP_LOOP_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_FOR, OACC_LOOP) -#define OMP_FOR_BODY(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 0) -#define OMP_FOR_CLAUSES(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 1) -#define OMP_FOR_INIT(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 2) -#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 3) -#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 4) -#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 5) -#define OMP_FOR_ORIG_DECLS(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 6) +#define OMP_LOOPING_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_FOR, OACC_LOOP) +#define OMP_FOR_BODY(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 0) +#define OMP_FOR_CLAUSES(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 1) +#define OMP_FOR_INIT(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 2) +#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 3) +#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 4) +#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 5) +#define OMP_FOR_ORIG_DECLS(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 6) #define OMP_SECTIONS_BODY(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0) #define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1) @@ -1742,6 +1742,9 @@ class auto_suppress_location_wrappers (OMP_CLAUSE_DEFAULTMAP_KIND (NODE) \ = (enum omp_clause_defaultmap_kind) (CATEGORY | BEHAVIOR)) +#define OMP_CLAUSE_BIND_KIND(NODE) \ + (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_BIND)->omp_clause.subcode.bind_kind) + #define OMP_CLAUSE_TILE_LIST(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_TILE), 0) #define OMP_CLAUSE_TILE_ITERVAR(NODE) \ -- cgit v1.1 From 1ab1f3502038323f6f5cd8c16c0ac1b1416e3545 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 20 Jul 2019 09:48:38 -0400 Subject: Reduce memory consumption for push/pop_access_scope. I was seeing memory consumption issues on the concepts-cxx2a branch. push_scope was, surprisingly, at the top of -fmem-report, and push_access_scope was pretty high. Fixing them was pretty simple. * name-lookup.c (leave_scope): Do add class levels other than previous_class_level to free_binding_level. (invalidate_class_lookup_cache): Move from class.c, add to free_binding_level. * pt.c (saved_access_scope): Change from list to vec. From-SVN: r273622 --- gcc/cp/ChangeLog | 9 +++++++++ gcc/cp/class.c | 10 ---------- gcc/cp/name-lookup.c | 14 +++++++++++++- gcc/cp/pt.c | 10 +++------- 4 files changed, 25 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c776243..0c6a7de 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2019-07-20 Jason Merrill + + Reduce memory consumption for push/pop_access_scope. + * name-lookup.c (leave_scope): Do add class levels other than + previous_class_level to free_binding_level. + (invalidate_class_lookup_cache): Move from class.c, add to + free_binding_level. + * pt.c (saved_access_scope): Change from list to vec. + 2019-07-20 Jakub Jelinek * cp-tree.h (OMP_FOR_GIMPLIFYING_P): Use OMP_LOOPING_CHECK diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f77b7f4..b61152c 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -7588,16 +7588,6 @@ pushclass (tree type) restore_class_cache (); } -/* When we exit a toplevel class scope, we save its binding level so - that we can restore it quickly. Here, we've entered some other - class, so we must invalidate our cache. */ - -void -invalidate_class_lookup_cache (void) -{ - previous_class_level = NULL; -} - /* Get out of the current class scope. If we were in a class scope previously, that is the one popped to. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index ad86629..9f27822 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3392,7 +3392,7 @@ leave_scope (void) namespace. For classes, we cache some binding levels. For other scopes, we just make the structure available for reuse. */ if (scope->kind != sk_namespace - && scope->kind != sk_class) + && scope != previous_class_level) { scope->level_chain = free_binding_level; gcc_assert (!ENABLE_SCOPE_CHECKING @@ -3420,6 +3420,18 @@ leave_scope (void) return current_binding_level; } +/* When we exit a toplevel class scope, we save its binding level so + that we can restore it quickly. Here, we've entered some other + class, so we must invalidate our cache. */ + +void +invalidate_class_lookup_cache (void) +{ + previous_class_level->level_chain = free_binding_level; + free_binding_level = previous_class_level; + previous_class_level = NULL; +} + static void resume_scope (cp_binding_level* b) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b6eda7e..deaac57 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -67,7 +67,7 @@ static vec inline_parm_levels; static GTY(()) struct tinst_level *current_tinst_level; -static GTY(()) tree saved_access_scope; +static GTY(()) vec *saved_access_scope; /* Live only within one (recursive) call to tsubst_expr. We use this to pass the statement expression node from the STMT_EXPR @@ -247,8 +247,7 @@ push_access_scope (tree t) if (TREE_CODE (t) == FUNCTION_DECL) { - saved_access_scope = tree_cons - (NULL_TREE, current_function_decl, saved_access_scope); + vec_safe_push (saved_access_scope, current_function_decl); current_function_decl = t; } } @@ -260,10 +259,7 @@ static void pop_access_scope (tree t) { if (TREE_CODE (t) == FUNCTION_DECL) - { - current_function_decl = TREE_VALUE (saved_access_scope); - saved_access_scope = TREE_CHAIN (saved_access_scope); - } + current_function_decl = saved_access_scope->pop(); if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t)) pop_nested_class (); -- cgit v1.1 From 2dc1070584c5d700ab878fa13a18e2e25f0380c8 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 20 Jul 2019 10:43:49 -0400 Subject: Fix ICE on class template argument deduction with inherited ctor. In general, when we see a dependent using-declaration we don't know whether it names a function or not, so it doesn't get an OVERLOAD unless we see overloads of the same name in the current class. In the case of an inherited constructor we could figure that out from the name, but it's simpler to handle USING_DECL properly. * cp-tree.h (ovl_iterator::using_p): A USING_DECL by itself was also introduced by a using-declaration. From-SVN: r273623 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/cp-tree.h | 3 ++- gcc/testsuite/g++.dg/cpp1z/class-deduction67.C | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction67.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0c6a7de..d645cde 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2019-07-20 Jason Merrill + * cp-tree.h (ovl_iterator::using_p): A USING_DECL by itself was also + introduced by a using-declaration. + +2019-07-20 Jason Merrill + Reduce memory consumption for push/pop_access_scope. * name-lookup.c (leave_scope): Do add class levels other than previous_class_level to free_binding_level. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 6068745..688924c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -774,7 +774,8 @@ class ovl_iterator /* Whether this overload was introduced by a using decl. */ bool using_p () const { - return TREE_CODE (ovl) == OVERLOAD && OVL_USING_P (ovl); + return (TREE_CODE (ovl) == USING_DECL + || (TREE_CODE (ovl) == OVERLOAD && OVL_USING_P (ovl))); } bool hidden_p () const { diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction67.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction67.C new file mode 100644 index 0000000..4624794 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction67.C @@ -0,0 +1,21 @@ +// Deduction from inherited constructors isn't supported yet, but we shouldn't +// crash. It may well be supported in C++23. + +//{ dg-do compile { target c++17 } } + +template struct A +{ + A(T); +}; + +template struct B: A +{ + using A::A; +}; + +int main() +{ + B b = 42; // { dg-line init } + // { dg-prune-output "no matching function" } + // { dg-error "class template argument deduction" "" { target *-*-* } init } +} -- cgit v1.1 From 7604f4351a2c08ea9340bd124570d2c4bb11d3cd Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Sat, 20 Jul 2019 16:47:25 +0000 Subject: pa.h (hppa_profile_hook): Delete declaration. * config/pa/pa.h (hppa_profile_hook): Delete declaration. * config/pa/pa-protos.h (hppa_profile_hook): Add declaration. From-SVN: r273628 --- gcc/ChangeLog | 5 +++++ gcc/config/pa/pa-protos.h | 1 + gcc/config/pa/pa.h | 1 - 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 537799e..8adea2d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-20 John David Anglin + + * config/pa/pa.h (hppa_profile_hook): Delete declaration. + * config/pa/pa-protos.h (hppa_profile_hook): Add declaration. + 2019-07-20 Jakub Jelinek * tree.def (OMP_LOOP): New tree code. diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index a62eeb7..6e9e7a7 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -109,6 +109,7 @@ extern void pa_hpux_asm_output_external (FILE *, tree, const char *); extern HOST_WIDE_INT pa_initial_elimination_offset (int, int); extern HOST_WIDE_INT pa_function_arg_size (machine_mode, const_tree); extern void pa_output_function_label (FILE *); +extern void hppa_profile_hook (int); extern const int pa_magic_milli[]; diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 561efa5..f38a6dc 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -666,7 +666,6 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; }; (*targetm.asm_out.internal_label) (FILE, FUNC_BEGIN_PROLOG_LABEL, LABEL) #define PROFILE_HOOK(label_no) hppa_profile_hook (label_no) -void hppa_profile_hook (int label_no); /* The profile counter if emitted must come before the prologue. */ #define PROFILE_BEFORE_PROLOGUE 1 -- cgit v1.1 From 4b3df2657401475f94a7fc60e4e7f8ed6bbe2610 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 20 Jul 2019 19:13:00 +0200 Subject: re PR target/91204 (ICE in expand_expr_real_2, at expr.c:9215 with -O3) PR target/91204 * optabs.c (expand_unop): As fallback, expand ~op0 as op0 ^ -1. * gcc.c-torture/compile/pr91204.c: New test. From-SVN: r273629 --- gcc/ChangeLog | 5 +++++ gcc/optabs.c | 11 +++++++++++ gcc/testsuite/ChangeLog | 3 +++ gcc/testsuite/gcc.c-torture/compile/pr91204.c | 11 +++++++++++ 4 files changed, 30 insertions(+) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr91204.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8adea2d..535636b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-20 Jakub Jelinek + + PR target/91204 + * optabs.c (expand_unop): As fallback, expand ~op0 as op0 ^ -1. + 2019-07-20 John David Anglin * config/pa/pa.h (hppa_profile_hook): Delete declaration. diff --git a/gcc/optabs.c b/gcc/optabs.c index 4b39ff6..06bcaab 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -2972,6 +2972,17 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, return target; } + /* Emit ~op0 as op0 ^ -1. */ + if (unoptab == one_cmpl_optab + && (SCALAR_INT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + && optab_handler (xor_optab, mode) != CODE_FOR_nothing) + { + temp = expand_binop (mode, xor_optab, op0, CONSTM1_RTX (mode), + target, unsignedp, OPTAB_DIRECT); + if (temp) + return temp; + } + if (optab_to_code (unoptab) == NEG) { /* Try negating floating point values by flipping the sign bit. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index adefdb9..cd553db 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2019-07-20 Jakub Jelinek + PR target/91204 + * gcc.c-torture/compile/pr91204.c: New test. + * c-c++-common/gomp/cancel-1.c: Adjust expected diagnostic wording. * c-c++-common/gomp/clauses-1.c (foo, baz, bar): Add order(concurrent) clause where allowed. Add combined constructs with loop with all diff --git a/gcc/testsuite/gcc.c-torture/compile/pr91204.c b/gcc/testsuite/gcc.c-torture/compile/pr91204.c new file mode 100644 index 0000000..dc26732 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr91204.c @@ -0,0 +1,11 @@ +/* PR target/91204 */ + +int a, b, c[64]; + +void +foo (void) +{ + int i; + for (i = 2; i < 64; i++) + c[i] &= b ^ c[i] ^ c[i - 2]; +} -- cgit v1.1 From 5744faa9851c86d018f32de7363b1064d5348d26 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sat, 20 Jul 2019 19:28:37 +0200 Subject: rs6000: New predicate any_memory_operand The new predicate accepts both memory_operand and volatile_mem_operand. * config/rs6000/predicates.md (volatile_mem_operand): Modernize syntax. (any_memory_operand): New predicate. (reg_or_mem_operand): Use it. From-SVN: r273630 --- gcc/ChangeLog | 6 ++++++ gcc/config/rs6000/predicates.md | 16 ++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 535636b..58220e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-20 Segher Boessenkool + + * config/rs6000/predicates.md (volatile_mem_operand): Modernize syntax. + (any_memory_operand): New predicate. + (reg_or_mem_operand): Use it. + 2019-07-20 Jakub Jelinek PR target/91204 diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 5f687ea..13c7c02 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -703,12 +703,17 @@ ;; memory references. So this function allows us to recognize volatile ;; references where it's safe. (define_predicate "volatile_mem_operand" - (and (and (match_code "mem") - (match_test "MEM_VOLATILE_P (op)")) + (and (match_code "mem") + (match_test "MEM_VOLATILE_P (op)") (if_then_else (match_test "reload_completed") (match_operand 0 "memory_operand") (match_test "memory_address_p (mode, XEXP (op, 0))")))) +;; Return 1 if the operand is a volatile or non-volatile memory operand. +(define_predicate "any_memory_operand" + (ior (match_operand 0 "memory_operand") + (match_operand 0 "volatile_mem_operand"))) + ;; Return 1 if the operand is an offsettable memory operand. (define_predicate "offsettable_mem_operand" (and (match_operand 0 "memory_operand") @@ -891,11 +896,10 @@ ;; Return 1 if the operand is a general non-special register or memory operand. (define_predicate "reg_or_mem_operand" - (ior (match_operand 0 "memory_operand") + (ior (match_operand 0 "gpc_reg_operand") + (match_operand 0 "any_memory_operand") (and (match_code "mem") - (match_test "macho_lo_sum_memory_operand (op, mode)")) - (match_operand 0 "volatile_mem_operand") - (match_operand 0 "gpc_reg_operand"))) + (match_test "macho_lo_sum_memory_operand (op, mode)")))) ;; Return 1 if the operand is CONST_DOUBLE 0, register or memory operand. (define_predicate "zero_reg_mem_operand" -- cgit v1.1 From 45986ed939d2187a03b6f55721e51e363968f5be Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sat, 20 Jul 2019 19:34:06 +0200 Subject: rs6000: Make lwa_operand use any_memory_operand Testcase from comex, see https://lwn.net/Articles/793932/ . * config/rs6000/predicates.md (lwa_operand): Allow volatile memory. gcc/testsuite/ * gcc.target/powerpc/volatile-mem.c: New testcase. From-SVN: r273631 --- gcc/ChangeLog | 4 ++++ gcc/config/rs6000/predicates.md | 2 +- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.target/powerpc/volatile-mem.c | 16 ++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/volatile-mem.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 58220e6..459c869 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2019-07-20 Segher Boessenkool + * config/rs6000/predicates.md (lwa_operand): Allow volatile memory. + +2019-07-20 Segher Boessenkool + * config/rs6000/predicates.md (volatile_mem_operand): Modernize syntax. (any_memory_operand): New predicate. (reg_or_mem_operand): Use it. diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 13c7c02..23d626b 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -929,7 +929,7 @@ if (gpc_reg_operand (inner, mode)) return true; - if (!memory_operand (inner, mode)) + if (!any_memory_operand (inner, mode)) return false; addr = XEXP (inner, 0); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cd553db..fc9b4c8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-20 Segher Boessenkool + + * gcc.target/powerpc/volatile-mem.c: New testcase. + 2019-07-20 Jakub Jelinek PR target/91204 diff --git a/gcc/testsuite/gcc.target/powerpc/volatile-mem.c b/gcc/testsuite/gcc.target/powerpc/volatile-mem.c new file mode 100644 index 0000000..c8a7444 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/volatile-mem.c @@ -0,0 +1,16 @@ +/* { dg-options "-O2 -std=c11" } */ +/* { dg-require-effective-target lp64 } */ + +/* This tests if the instructions used for C atomic are optimised properly + as atomic by the target code, too. */ + +#include + +int load(_Atomic int *ptr) +{ + return atomic_load_explicit(ptr, memory_order_relaxed); +} + +/* There should be only two machine instructions, an lwa and a blr: */ +/* { dg-final { scan-assembler-times {(?n)^\s+[a-z]} 2 } } */ +/* { dg-final { scan-assembler-times {\mlwa\M} 1 } } */ -- cgit v1.1 From 4f5ddf27080251b223106346c95b3edf0fee2c52 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sat, 20 Jul 2019 19:35:04 +0200 Subject: rs6000: Make input_operand use any_memory_operand * config/rs6000/predicates.md (input_operand): Allow volatile memory. From-SVN: r273632 --- gcc/ChangeLog | 4 ++++ gcc/config/rs6000/predicates.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 459c869..33a50fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2019-07-20 Segher Boessenkool + * config/rs6000/predicates.md (input_operand): Allow volatile memory. + +2019-07-20 Segher Boessenkool + * config/rs6000/predicates.md (lwa_operand): Allow volatile memory. 2019-07-20 Segher Boessenkool diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 23d626b..7c451df 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -1031,7 +1031,7 @@ const_double,const_wide_int,const_vector,const_int") { /* Memory is always valid. */ - if (memory_operand (op, mode)) + if (any_memory_operand (op, mode)) return 1; /* For floating-point, easy constants are valid. */ -- cgit v1.1 From 925763576e83e69d25edc890bc6e62fa5f99d466 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Sat, 20 Jul 2019 19:37:07 +0200 Subject: rs6000: Make offsettable_mem_operand use any_memory_operand * config/rs6000/predicates.md (offsettable_mem_operand): Allow volatile memory. From-SVN: r273633 --- gcc/ChangeLog | 5 +++++ gcc/config/rs6000/predicates.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 33a50fa..3caaafe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2019-07-20 Segher Boessenkool + * config/rs6000/predicates.md (offsettable_mem_operand): Allow volatile + memory. + +2019-07-20 Segher Boessenkool + * config/rs6000/predicates.md (input_operand): Allow volatile memory. 2019-07-20 Segher Boessenkool diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 7c451df..5a2d2d3 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -716,7 +716,7 @@ ;; Return 1 if the operand is an offsettable memory operand. (define_predicate "offsettable_mem_operand" - (and (match_operand 0 "memory_operand") + (and (match_operand 0 "any_memory_operand") (match_test "offsettable_nonstrict_memref_p (op)"))) ;; Return 1 if the operand is a simple offsettable memory operand -- cgit v1.1 From 037455d49c2c19521bf60253c098d0e1e48d68fa Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 21 Jul 2019 00:16:16 +0000 Subject: Daily bump. From-SVN: r273640 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5030968..6d7642c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190720 +20190721 -- cgit v1.1 From c37b0163fe5307ab508489926114de9cf7e240c1 Mon Sep 17 00:00:00 2001 From: Thomas Koenig Date: Sun, 21 Jul 2019 15:55:49 +0000 Subject: re PR libfortran/91030 (Poor performance of I/O -fconvert=big-endian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2019-07-21 Thomas König PR libfortran/91030 * gfortran.texi (GFORTRAN_FORMATTED_BUFFER_SIZE): Document (GFORTRAN_UNFORMATTED_BUFFER_SIZE): Likewise. 2019-07-21 Thomas König PR libfortran/91030 * io/unix.c (BUFFER_SIZE): Delete. (BUFFER_FORMATTED_SIZE_DEFAULT): New variable. (BUFFER_UNFORMATTED_SIZE_DEFAULT): New variable. (unix_stream): Add buffer_size. (buf_read): Use s->buffer_size instead of BUFFER_SIZE. (buf_write): Likewise. (buf_init): Add argument unformatted. Handle block sizes for unformatted vs. formatted, using defaults if provided. (fd_to_stream): Add argument unformatted in call to buf_init. * libgfortran.h (options_t): Add buffer_size_formatted and buffer_size_unformatted. * runtime/environ.c (variable_table): Add GFORTRAN_UNFORMATTED_BUFFER_SIZE and GFORTRAN_FORMATTED_BUFFER_SIZE. From-SVN: r273643 --- gcc/fortran/ChangeLog | 6 ++++++ gcc/fortran/gfortran.texi | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'gcc') diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 342aaa5..c4c35ad 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2019-07-21 Thomas König + + PR libfortran/91030 + * gfortran.texi (GFORTRAN_FORMATTED_BUFFER_SIZE): Document + (GFORTRAN_UNFORMATTED_BUFFER_SIZE): Likewise. + 2019-07-16 Harald Anlauf PR fortran/90903 diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 4f65450..16be9e0 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -611,6 +611,8 @@ Malformed environment variables are silently ignored. * GFORTRAN_LIST_SEPARATOR:: Separator for list output * GFORTRAN_CONVERT_UNIT:: Set endianness for unformatted I/O * GFORTRAN_ERROR_BACKTRACE:: Show backtrace on run-time errors +* GFORTRAN_FORMATTED_BUFFER_SIZE:: Buffer size for formatted files. +* GFORTRAN_UNFORMATTED_BUFFER_SIZE:: Buffer size for unformatted files. @end menu @node TMPDIR @@ -782,6 +784,20 @@ the backtracing, set the variable to @samp{n}, @samp{N}, @samp{0}. Default is to print a backtrace unless the @option{-fno-backtrace} compile option was used. +@node GFORTRAN_FORMATTED_BUFFER_SIZE +@section @env{GFORTRAN_FORMATTED_BUFFER_SIZE}---Set buffer size for formatted I/O + +The @env{GFORTRAN_FORMATTED_BUFFER_SIZE} environment variable +specifies buffer size in bytes to be used for formatted output. +The default value is 8192. + +@node GFORTRAN_UNFORMATTED_BUFFER_SIZE +@section @env{GFORTRAN_UNFORMATTED_BUFFER_SIZE}---Set buffer size for unformatted I/O + +The @env{GFORTRAN_UNFORMATTED_BUFFER_SIZE} environment variable +specifies buffer size in bytes to be used for unformatted output. +The default value is 131072. + @c ===================================================================== @c PART II: LANGUAGE REFERENCE @c ===================================================================== -- cgit v1.1 From 48df93911ab1b71a533934419c320fe9102b5ec1 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Sun, 21 Jul 2019 20:15:00 +0000 Subject: [PPC] Fix bootstrap for non-SVR4 targets. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The recent change to move code into the new rs6000-call.c file is missing a default value for the TARGET_NO_PROTOTYPE value (which only affects targets that don’t include svr4.h). Fixed by moving the fallback setting from rs6000.c (which has no uses now) to rs6000-call.c. 2019-07-21 Iain Sandoe * config/rs6000/rs6000.c (TARGET_NO_PROTOTYPE): Move from here... * config/rs6000/rs6000-call.c: ... to here. From-SVN: r273646 --- gcc/ChangeLog | 5 +++++ gcc/config/rs6000/rs6000-call.c | 4 ++++ gcc/config/rs6000/rs6000.c | 4 ---- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3caaafe..7f070e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-21 Iain Sandoe + + * config/rs6000/rs6000.c (TARGET_NO_PROTOTYPE): Move from here... + * config/rs6000/rs6000-call.c: ... to here. + 2019-07-20 Segher Boessenkool * config/rs6000/predicates.md (offsettable_mem_operand): Allow volatile diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index cefb737..2ef8c7f 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -86,6 +86,10 @@ # endif #endif +#ifndef TARGET_NO_PROTOTYPE +#define TARGET_NO_PROTOTYPE 0 +#endif + struct builtin_description { const HOST_WIDE_INT mask; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index dbb6a0f..edd8f2b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -84,10 +84,6 @@ /* This file should be included last. */ #include "target-def.h" -#ifndef TARGET_NO_PROTOTYPE -#define TARGET_NO_PROTOTYPE 0 -#endif - /* Set -mabi=ieeelongdouble on some old targets. In the future, power server systems will also set long double to be IEEE 128-bit. AIX and Darwin explicitly redefine TARGET_IEEEQUAD and TARGET_IEEEQUAD_DEFAULT to 0, so -- cgit v1.1 From 2e92185a033ec94d3dbaf22577110883db1474a1 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 21 Jul 2019 20:58:54 +0000 Subject: or1k: Fix code quality for volatile memory loads Volatile memory does not match the memory_operand predicate. This causes extra extend/mask instructions instructions when reading from volatile memory. On OpenRISC loading volatile memory can be treated the same as regular memory loads which supports combined sign/zero extends. Fixing this eliminates the need for extra extend/mask instructions. This also adds a test provided by Richard Selvaggi which uncovered the issue while we were looking into another issue. gcc/ChangeLog: PR target/90363 * config/or1k/or1k.md (zero_extendsi2): Update predicate. (extendsi2): Update predicate. * gcc/config/or1k/predicates.md (volatile_mem_operand): New. (reg_or_mem_operand): New. gcc/testsuite/ChangeLog: PR target/90363 * gcc.target/or1k/swap-1.c: New test. * gcc.target/or1k/swap-2.c: New test. From-SVN: r273647 --- gcc/ChangeLog | 8 ++++++++ gcc/config/or1k/or1k.md | 6 +++--- gcc/config/or1k/predicates.md | 18 ++++++++++++++++++ gcc/testsuite/ChangeLog | 6 ++++++ 4 files changed, 35 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f070e8..59e11bc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-22 Stafford Horne + + PR target/90363 + * config/or1k/or1k.md (zero_extendsi2): Update predicate. + (extendsi2): Update predicate. + * gcc/config/or1k/predicates.md (volatile_mem_operand): New. + (reg_or_mem_operand): New. + 2019-07-21 Iain Sandoe * config/rs6000/rs6000.c (TARGET_NO_PROTOTYPE): Move from here... diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md index 2dad51c..757d899 100644 --- a/gcc/config/or1k/or1k.md +++ b/gcc/config/or1k/or1k.md @@ -328,11 +328,11 @@ ;; Sign Extending ;; ------------------------------------------------------------------------- -;; Zero extension can always be done with AND and an extending load. +;; Zero extension can always be done with AND or an extending load. (define_insn "zero_extendsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:I12 1 "nonimmediate_operand" "r,m")))] + (zero_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))] "" "@ l.andi\t%0, %1, @@ -344,7 +344,7 @@ (define_insn "extendsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") - (sign_extend:SI (match_operand:I12 1 "nonimmediate_operand" "r,m")))] + (sign_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))] "TARGET_SEXT" "@ l.exts\t%0, %1 diff --git a/gcc/config/or1k/predicates.md b/gcc/config/or1k/predicates.md index 879236b..dad1c5d 100644 --- a/gcc/config/or1k/predicates.md +++ b/gcc/config/or1k/predicates.md @@ -82,3 +82,21 @@ (define_predicate "equality_comparison_operator" (match_code "ne,eq")) + +;; Borrowed from rs6000 +;; Return true if the operand is in volatile memory. Note that during the +;; RTL generation phase, memory_operand does not return TRUE for volatile +;; memory references. So this function allows us to recognize volatile +;; references where it's safe. +(define_predicate "volatile_mem_operand" + (and (match_code "mem") + (match_test "MEM_VOLATILE_P (op)") + (if_then_else (match_test "reload_completed") + (match_operand 0 "memory_operand") + (match_test "memory_address_p (mode, XEXP (op, 0))")))) + +;; Return true if the operand is a register or memory; including volatile +;; memory. +(define_predicate "reg_or_mem_operand" + (ior (match_operand 0 "nonimmediate_operand") + (match_operand 0 "volatile_mem_operand"))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fc9b4c8..95e73d9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-22 Stafford Horne + + PR target/90363 + * gcc.target/or1k/swap-1.c: New test. + * gcc.target/or1k/swap-2.c: New test. + 2019-07-20 Segher Boessenkool * gcc.target/powerpc/volatile-mem.c: New testcase. -- cgit v1.1 From 9c0dba7c451ddd232dc3ba8a5ebc797762c74736 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 21 Jul 2019 20:59:50 +0000 Subject: or1k: Fix issues with msoft-div Fixes bad assembly logic with software divide as reported by Richard Selvaggi. Also, add a basic test to verify the soft math works when enabled. gcc/testsuite/ChangeLog: PR target/90362 * gcc.target/or1k/div-mul-3.c: New test. libgcc/ChangeLog: PR target/90362 * config/or1k/lib1funcs.S (__udivsi3): Change l.sfeqi to l.sfeq and l.sfltsi to l.sflts equivalents as the immediate instructions are not available on every processor. Change a l.bnf to l.bf to fix logic issue. From-SVN: r273648 --- gcc/testsuite/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 95e73d9..846d201 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2019-07-22 Stafford Horne + PR target/90362 + * gcc.target/or1k/div-mul-3.c: New test. + +2019-07-22 Stafford Horne + PR target/90363 * gcc.target/or1k/swap-1.c: New test. * gcc.target/or1k/swap-2.c: New test. -- cgit v1.1 From 1e2e81c1a36a51f4660d30a0278366a8a0727a9d Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 21 Jul 2019 21:00:47 +0000 Subject: or1k: Add mrori option, fix option docs gcc/ChangeLog: * config.gcc (or1k*-*-*): Add mrori and mror to validation. * doc/invoke.texi (OpenRISC Options): Add mrori option, rewrite all documenation to be more clear. * config/or1k/elf.opt (mboard=, mnewlib): Rewrite documentation to be more clear. * config/or1k/or1k.opt (mrori): New option. (mhard-div, msoft-div, mhard-mul, msoft-mul, mcmov, mror, msext, msfimm, mshftimm): Rewrite documentation to be more clear. * config/or1k/or1k.md (insn_support): Add ror and rori. (enabled): Add conditions for ror and rori. (rotrsi3): Replace condition for shftimm with ror and rori. gcc/testsuite/ChangeLog: * gcc.target/or1k/ror-4.c: New file. * gcc.target/or1k/shftimm-1.c: Update test from rotate to shift as the shftimm option no longer controls rotate. From-SVN: r273649 --- gcc/ChangeLog | 14 ++++++++ gcc/config.gcc | 1 + gcc/config/or1k/elf.opt | 6 ++-- gcc/config/or1k/or1k.md | 14 +++++--- gcc/config/or1k/or1k.opt | 56 ++++++++++++++++++------------- gcc/config/or1k/predicates.md | 7 ++++ gcc/doc/invoke.texi | 56 +++++++++++++++++-------------- gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.target/or1k/shftimm-1.c | 8 ++--- 9 files changed, 107 insertions(+), 61 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 59e11bc..dafbb24 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2019-07-22 Stafford Horne + * config.gcc (or1k*-*-*): Add mrori and mror to validation. + * doc/invoke.texi (OpenRISC Options): Add mrori option, rewrite all + documenation to be more clear. + * config/or1k/elf.opt (mboard=, mnewlib): Rewrite documentation to be + more clear. + * config/or1k/or1k.opt (mrori): New option. + (mhard-div, msoft-div, mhard-mul, msoft-mul, mcmov, mror, msext, + msfimm, mshftimm): Rewrite documentation to be more clear. + * config/or1k/or1k.md (insn_support): Add ror and rori. + (enabled): Add conditions for ror and rori. + (rotrsi3): Replace condition for shftimm with ror and rori. + +2019-07-22 Stafford Horne + PR target/90363 * config/or1k/or1k.md (zero_extendsi2): Update predicate. (extendsi2): Update predicate. diff --git a/gcc/config.gcc b/gcc/config.gcc index 446a852..6679a3a 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2578,6 +2578,7 @@ or1k*-*-*) for or1k_multilib in ${or1k_multilibs}; do case ${or1k_multilib} in mcmov | msext | msfimm | \ + mror | mrori | \ mhard-div | mhard-mul | \ msoft-div | msoft-mul ) TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${or1k_multilib}" diff --git a/gcc/config/or1k/elf.opt b/gcc/config/or1k/elf.opt index 641b6dd..2d4d187 100644 --- a/gcc/config/or1k/elf.opt +++ b/gcc/config/or1k/elf.opt @@ -25,9 +25,9 @@ mboard= Target RejectNegative Joined -Configure board specific runtime. +Configure the newlib board specific runtime. The default is or1ksim. mnewlib Target RejectNegative -For compatibility, it's always newlib for elf now. - +This option is ignored; it is provided for compatibility purposes only. This +used to select linker and preprocessor options for use with newlib. diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md index 757d899..0faa0fa 100644 --- a/gcc/config/or1k/or1k.md +++ b/gcc/config/or1k/or1k.md @@ -63,7 +63,7 @@ "alu,st,ld,control,multi" (const_string "alu")) -(define_attr "insn_support" "class1,sext,sfimm,shftimm" (const_string "class1")) +(define_attr "insn_support" "class1,sext,sfimm,shftimm,ror,rori" (const_string "class1")) (define_attr "enabled" "" (cond [(eq_attr "insn_support" "class1") (const_int 1) @@ -72,7 +72,11 @@ (and (eq_attr "insn_support" "sfimm") (ne (symbol_ref "TARGET_SFIMM") (const_int 0))) (const_int 1) (and (eq_attr "insn_support" "shftimm") - (ne (symbol_ref "TARGET_SHFTIMM") (const_int 0))) (const_int 1)] + (ne (symbol_ref "TARGET_SHFTIMM") (const_int 0))) (const_int 1) + (and (eq_attr "insn_support" "ror") + (ne (symbol_ref "TARGET_ROR") (const_int 0))) (const_int 1) + (and (eq_attr "insn_support" "rori") + (ne (symbol_ref "TARGET_RORI") (const_int 0))) (const_int 1)] (const_int 0))) ;; Describe a user's asm statement. @@ -178,12 +182,12 @@ (define_insn "rotrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") - (match_operand:SI 2 "reg_or_u6_operand" "r,n")))] - "TARGET_ROR" + (match_operand:SI 2 "ror_reg_or_u6_operand" "r,n")))] + "TARGET_ROR || TARGET_RORI" "@ l.ror\t%0, %1, %2 l.rori\t%0, %1, %2" - [(set_attr "insn_support" "*,shftimm")]) + [(set_attr "insn_support" "ror,rori")]) (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") diff --git a/gcc/config/or1k/or1k.opt b/gcc/config/or1k/or1k.opt index 7bdbd84..c2f64c5 100644 --- a/gcc/config/or1k/or1k.opt +++ b/gcc/config/or1k/or1k.opt @@ -21,47 +21,55 @@ ; See the GCC internals manual (options.texi) for a description of ; this file's format. -; Please try to keep this file in ASCII collating order. - mhard-div Target RejectNegative InverseMask(SOFT_DIV) -Use hardware divide instructions, use -msoft-div for emulation. +Enable generation of hardware divide (l.div, l.divu) instructions. This is the +default; use -msoft-div to override. + +msoft-div +Target RejectNegative Mask(SOFT_DIV) +Enable generation of binaries which use functions from libgcc to perform divide +operations. The default is -mhard-div. mhard-mul Target RejectNegative InverseMask(SOFT_MUL). -Use hardware multiply instructions, use -msoft-mul for emulation. +Enable generation of hardware multiply instructions (l.mul, l.muli) instructions. +This is the default; use -msoft-mul to override. + +msoft-mul +Target RejectNegative Mask(SOFT_MUL). +Enable generation of binaries which use functions from libgcc to perform +multiply operations. The default is -mhard-mul. mcmov Target RejectNegative Mask(CMOV) -Allows generation of binaries which use the l.cmov instruction. If your target -does not support this the compiler will generate the equivalent using set and -branch. +Enable generation of conditional move (l.cmov) instructions. By default the +equivalent will be generated using using set and branch. mror Target RejectNegative Mask(ROR) -Allows generation of binaries which use the l.rori instructions. +Enable generation of rotate right (l.ror) instructions. By default functions +from libgcc are used to perform rotate right operations. + +mrori +Target RejectNegative Mask(RORI) +Enable generation of rotate right with immediate (l.rori) instructions. By +default functions from libgcc are used to perform rotate right with immediate +operations. msext Target RejectNegative Mask(SEXT) -Allows generation of binaries which use sign-extension instructions. If your -target does not support this the compiler will use memory loads to perform sign -extension. +Enable generation of sign extension (l.ext*) instructions. By default memory +loads are used to perform sign extension. msfimm Target RejectNegative Mask(SFIMM) -Allows generation of binaries which use l.sf*i instructions. If your target -does not support this the compiler will generate instructions to store the -immediate to a register first. +Enable generation of compare and set flag with immediate (l.sf*i) instructions. +By default extra instructions will be generated to store the immediate to a +register first. mshftimm Target RejectNegative Mask(SHFTIMM) -Allows generation of binaries which support shifts and rotate instructions -supporting immediate arguments, for example l.rori. - -msoft-div -Target RejectNegative Mask(SOFT_DIV) -Use divide emulation. - -msoft-mul -Target RejectNegative Mask(SOFT_MUL). -Use multiply emulation. +Enable generation of shift with immediate (l.srai, l.srli, l.slli) instructions. +By default extra instructions will be generated to store the immediate to a +register first. diff --git a/gcc/config/or1k/predicates.md b/gcc/config/or1k/predicates.md index dad1c5d..5e97bf4 100644 --- a/gcc/config/or1k/predicates.md +++ b/gcc/config/or1k/predicates.md @@ -53,6 +53,13 @@ (match_test "INTVAL (op) >= -32768 && INTVAL (op) <= 32767") (match_operand 0 "register_operand"))) +(define_predicate "ror_reg_or_u6_operand" + (if_then_else (match_code "const_int") + (and (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 0x3f") + (match_test "TARGET_RORI")) + (and (match_operand 0 "register_operand") + (match_test "TARGET_ROR")))) + (define_predicate "call_insn_operand" (ior (match_code "symbol_ref") (match_operand 0 "register_operand"))) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b887f5f..1703a0a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1034,7 +1034,7 @@ Objective-C and Objective-C++ Dialects}. @emph{OpenRISC Options} @gccoptlist{-mboard=@var{name} -mnewlib -mhard-mul -mhard-div @gol -msoft-mul -msoft-div @gol --mcmov -mror -msext -msfimm -mshftimm} +-mcmov -mror -mrori -msext -msfimm -mshftimm} @emph{PDP-11 Options} @gccoptlist{-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol @@ -23649,50 +23649,56 @@ newlib board library linking. The default is @code{or1ksim}. @item -mnewlib @opindex mnewlib -For compatibility, it's always newlib for elf now. +This option is ignored; it is for compatibility purposes only. This used to +select linker and preprocessor options for use with newlib. -@item -mhard-div +@item -msoft-div +@itemx -mhard-div +@opindex msoft-div @opindex mhard-div -Generate code for hardware which supports divide instructions. This is the -default. +Select software or hardware divide (@code{l.div}, @code{l.divu}) instructions. +This default is hardware divide. -@item -mhard-mul +@item -msoft-mul +@itemx -mhard-mul +@opindex msoft-mul @opindex mhard-mul -Generate code for hardware which supports multiply instructions. This is the -default. +Select software or hardware multiply (@code{l.mul}, @code{l.muli}) instructions. +This default is hardware multiply. @item -mcmov @opindex mcmov -Generate code for hardware which supports the conditional move (@code{l.cmov}) -instruction. +Enable generation of conditional move (@code{l.cmov}) instructions. By +default the equivalent will be generated using using set and branch. @item -mror @opindex mror -Generate code for hardware which supports rotate right instructions. +Enable generation of rotate right (@code{l.ror}) instructions. By default +functions from @file{libgcc} are used to perform rotate right operations. + +@item -mrori +@opindex mrori +Enable generation of rotate right with immediate (@code{l.rori}) instructions. +By default functions from @file{libgcc} are used to perform rotate right with +immediate operations. @item -msext @opindex msext -Generate code for hardware which supports sign-extension instructions. +Enable generation of sign extension (@code{l.ext*}) instructions. By default +memory loads are used to perform sign extension. @item -msfimm @opindex msfimm -Generate code for hardware which supports set flag immediate (@code{l.sf*i}) -instructions. +Enable generation of compare and set flag with immediate (@code{l.sf*i}) +instructions. By default extra instructions will be generated to store the +immediate to a register first. @item -mshftimm @opindex mshftimm -Generate code for hardware which supports shift immediate related instructions -(i.e. @code{l.srai}, @code{l.srli}, @code{l.slli}, @code{1.rori}). Note, to -enable generation of the @code{l.rori} instruction the @option{-mror} flag must -also be specified. +Enable generation of shift with immediate (@code{l.srai}, @code{l.srli}, +@code{l.slli}) instructions. By default extra instructions will be generated +to store the immediate to a register first. -@item -msoft-div -@opindex msoft-div -Generate code for hardware which requires divide instruction emulation. - -@item -msoft-mul -@opindex msoft-mul -Generate code for hardware which requires multiply instruction emulation. @end table diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 846d201..234bc10 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2019-07-22 Stafford Horne + * gcc.target/or1k/ror-4.c: New file. + * gcc.target/or1k/shftimm-1.c: Update test from rotate to shift + as the shftimm option no longer controls rotate. + +2019-07-22 Stafford Horne + PR target/90362 * gcc.target/or1k/div-mul-3.c: New test. diff --git a/gcc/testsuite/gcc.target/or1k/shftimm-1.c b/gcc/testsuite/gcc.target/or1k/shftimm-1.c index be8d9e8..3a8dc06 100644 --- a/gcc/testsuite/gcc.target/or1k/shftimm-1.c +++ b/gcc/testsuite/gcc.target/or1k/shftimm-1.c @@ -1,8 +1,8 @@ /* { dg-do compile } */ -/* { dg-options "-mror -mshftimm -O2" } */ +/* { dg-options "-mshftimm -O2" } */ -unsigned int rotate6 (unsigned int a) { - return ( a >> 6 ) | ( a << ( 32 - 6 ) ); +unsigned int shift6 (unsigned int a) { + return a << 6; } -/* { dg-final { scan-assembler "l.rori" } } */ +/* { dg-final { scan-assembler "l.slli" } } */ -- cgit v1.1 From 44080af98edf7d8a59a94dd803f60cf0505fba34 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 21 Jul 2019 21:01:59 +0000 Subject: or1k: Initial support for FPU This adds support for OpenRISC hardware floating point instructions. This is enabled with the -mhard-float option. Double-prevision floating point operations work using register pairing as specified in: https://openrisc.io/proposals/orfpx64a32. This has just been added in the OpenRISC architecture specification 1.3. This is enabled with the -mdouble-float option. Not all architectures support unordered comparisons so an option, -munordered-float is added. Currently OpenRISC does not support sf/df or df/sf conversions, but this has also just been added in architecture specification 1.3. gcc/ChangeLog: * config.gcc (or1k*-*-*): Add mhard-float, mdouble-float, msoft-float and munordered-float validations. * config/or1k/constraints.md (d): New register constraint. * config/or1k/predicates.md (fp_comparison_operator): New. * config/or1k/or1k.c (or1k_print_operand): Add support for printing 'd' operands. (or1k_expand_compare): Normalize unordered comparisons. * config/or1k/or1k.h (reg_class): Define DOUBLE_REGS. (REG_CLASS_NAMES): Add "DOUBLE_REGS". (REG_CLASS_CONTENTS): Add contents for DOUBLE_REGS. * config/or1k/or1k.md (type): Add fpu. (fpu): New instruction reservation. (F, f, fr, fi, FI, FOP, fop): New. (3): New ALU instruction definition. (float2): New conversion instruction definition. (fix_trunc2): New conversion instruction definition. (fpcmpcc): New code iterator. (*sf_fp_insn): New instruction definition. (cstore4): New expand definition. (cbranch4): New expand definition. * config/or1k/or1k.opt (msoft-float, mhard-float, mdouble-float, munordered-float): New options. * doc/invoke.texi: Document msoft-float, mhard-float, mdouble-float and munordered-float. From-SVN: r273650 --- gcc/ChangeLog | 27 ++++++++++ gcc/config.gcc | 1 + gcc/config/or1k/constraints.md | 4 ++ gcc/config/or1k/or1k.c | 38 +++++++++++++- gcc/config/or1k/or1k.h | 3 ++ gcc/config/or1k/or1k.md | 111 ++++++++++++++++++++++++++++++++++++++++- gcc/config/or1k/or1k.opt | 22 ++++++++ gcc/config/or1k/predicates.md | 5 ++ gcc/doc/invoke.texi | 21 ++++++++ 9 files changed, 228 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dafbb24..224b785 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,32 @@ 2019-07-22 Stafford Horne + * config.gcc (or1k*-*-*): Add mhard-float, mdouble-float, msoft-float + and munordered-float validations. + * config/or1k/constraints.md (d): New register constraint. + * config/or1k/predicates.md (fp_comparison_operator): New. + * config/or1k/or1k.c (or1k_print_operand): Add support for printing 'd' + operands. + (or1k_expand_compare): Normalize unordered comparisons. + * config/or1k/or1k.h (reg_class): Define DOUBLE_REGS. + (REG_CLASS_NAMES): Add "DOUBLE_REGS". + (REG_CLASS_CONTENTS): Add contents for DOUBLE_REGS. + * config/or1k/or1k.md (type): Add fpu. + (fpu): New instruction reservation. + (F, f, fr, fi, FI, FOP, fop): New. + (3): New ALU instruction definition. + (float2): New conversion instruction definition. + (fix_trunc2): New conversion instruction definition. + (fpcmpcc): New code iterator. + (*sf_fp_insn): New instruction definition. + (cstore4): New expand definition. + (cbranch4): New expand definition. + * config/or1k/or1k.opt (msoft-float, mhard-float, mdouble-float, + munordered-float): New options. + * doc/invoke.texi: Document msoft-float, mhard-float, mdouble-float and + munordered-float. + +2019-07-22 Stafford Horne + * config.gcc (or1k*-*-*): Add mrori and mror to validation. * doc/invoke.texi (OpenRISC Options): Add mrori option, rewrite all documenation to be more clear. diff --git a/gcc/config.gcc b/gcc/config.gcc index 6679a3a..58262e5 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2579,6 +2579,7 @@ or1k*-*-*) case ${or1k_multilib} in mcmov | msext | msfimm | \ mror | mrori | \ + mhard-float | mdouble-float | munordered-float | msoft-float | \ mhard-div | mhard-mul | \ msoft-div | msoft-mul ) TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${or1k_multilib}" diff --git a/gcc/config/or1k/constraints.md b/gcc/config/or1k/constraints.md index 93da8c0..8cac7eb 100644 --- a/gcc/config/or1k/constraints.md +++ b/gcc/config/or1k/constraints.md @@ -24,6 +24,7 @@ ; We use: ; c - sibcall registers +; d - double pair base registers (excludes r0, r30 and r31 which overflow) ; I - constant signed 16-bit ; K - constant unsigned 16-bit ; M - constant signed 16-bit shifted left 16-bits (l.movhi) @@ -32,6 +33,9 @@ (define_register_constraint "c" "SIBCALL_REGS" "Registers which can hold a sibling call address") +(define_register_constraint "d" "DOUBLE_REGS" + "Registers which can be used for double reg pairs.") + ;; Immediates (define_constraint "I" "A signed 16-bit immediate in the range -32768 to 32767." diff --git a/gcc/config/or1k/or1k.c b/gcc/config/or1k/or1k.c index 54c9e80..1eea84f 100644 --- a/gcc/config/or1k/or1k.c +++ b/gcc/config/or1k/or1k.c @@ -1226,6 +1226,19 @@ or1k_print_operand (FILE *file, rtx x, int code) output_operand_lossage ("invalid %%H value"); break; + case 'd': + if (REG_P (x)) + { + if (GET_MODE (x) == DFmode || GET_MODE (x) == DImode) + fprintf (file, "%s,%s", reg_names[REGNO (operand)], + reg_names[REGNO (operand) + 1]); + else + fprintf (file, "%s", reg_names[REGNO (operand)]); + } + else + output_operand_lossage ("invalid %%d value"); + break; + case 'h': print_reloc (file, x, 0, RKIND_HI); break; @@ -1435,21 +1448,42 @@ void or1k_expand_compare (rtx *operands) { rtx sr_f = gen_rtx_REG (BImode, SR_F_REGNUM); + rtx_code cmp_code = GET_CODE (operands[0]); + bool flag_check_ne = true; /* The RTL may receive an immediate in argument 1 of the compare, this is not supported unless we have l.sf*i instructions, force them into registers. */ if (!TARGET_SFIMM) XEXP (operands[0], 1) = force_reg (SImode, XEXP (operands[0], 1)); + /* Normalize comparison operators to ones OpenRISC support. */ + switch (cmp_code) + { + case LTGT: + cmp_code = UNEQ; + flag_check_ne = false; + break; + + case ORDERED: + cmp_code = UNORDERED; + flag_check_ne = false; + break; + + default: + break; + } + /* Emit the given comparison into the Flag bit. */ PUT_MODE (operands[0], BImode); + PUT_CODE (operands[0], cmp_code); emit_insn (gen_rtx_SET (sr_f, operands[0])); /* Adjust the operands for use in the caller. */ - operands[0] = gen_rtx_NE (VOIDmode, sr_f, const0_rtx); + operands[0] = flag_check_ne ? gen_rtx_NE (VOIDmode, sr_f, const0_rtx) + : gen_rtx_EQ (VOIDmode, sr_f, const0_rtx); operands[1] = sr_f; operands[2] = const0_rtx; -} + } /* Expand the patterns "call", "sibcall", "call_value" and "sibcall_value". Expands a function call where argument RETVAL is an optional RTX providing diff --git a/gcc/config/or1k/or1k.h b/gcc/config/or1k/or1k.h index 6dda230..2b29e62 100644 --- a/gcc/config/or1k/or1k.h +++ b/gcc/config/or1k/or1k.h @@ -189,6 +189,7 @@ enum reg_class { NO_REGS, SIBCALL_REGS, + DOUBLE_REGS, GENERAL_REGS, FLAG_REGS, ALL_REGS, @@ -200,6 +201,7 @@ enum reg_class #define REG_CLASS_NAMES { \ "NO_REGS", \ "SIBCALL_REGS", \ + "DOUBLE_REGS", \ "GENERAL_REGS", \ "FLAG_REGS", \ "ALL_REGS" } @@ -212,6 +214,7 @@ enum reg_class #define REG_CLASS_CONTENTS \ { { 0x00000000, 0x00000000 }, \ { SIBCALL_REGS_MASK, 0 }, \ + { 0x7f7ffffe, 0x00000000 }, \ { 0xffffffff, 0x00000003 }, \ { 0x00000000, 0x00000004 }, \ { 0xffffffff, 0x00000007 } \ diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md index 0faa0fa..cee11d0 100644 --- a/gcc/config/or1k/or1k.md +++ b/gcc/config/or1k/or1k.md @@ -60,7 +60,7 @@ (define_attr "length" "" (const_int 4)) (define_attr "type" - "alu,st,ld,control,multi" + "alu,st,ld,control,multi,fpu" (const_string "alu")) (define_attr "insn_support" "class1,sext,sfimm,shftimm,ror,rori" (const_string "class1")) @@ -97,6 +97,10 @@ (define_insn_reservation "control" 1 (eq_attr "type" "control") "cpu") +(define_insn_reservation "fpu" 2 + (eq_attr "type" "fpu") + "cpu") + ; Define delay slots for any branch (define_delay (eq_attr "type" "control") @@ -160,6 +164,47 @@ "l.sub\t%0, %r1, %2") ;; ------------------------------------------------------------------------- +;; Floating Point Arithmetic instructions +;; ------------------------------------------------------------------------- + +;; Mode iterator for single/double float +(define_mode_iterator F [(SF "TARGET_HARD_FLOAT") + (DF "TARGET_DOUBLE_FLOAT")]) +(define_mode_attr f [(SF "s") (DF "d")]) +(define_mode_attr fr [(SF "r") (DF "d")]) +(define_mode_attr fi [(SF "si") (DF "di")]) +(define_mode_attr FI [(SF "SI") (DF "DI")]) + +;; Basic arithmetic instructions +(define_code_iterator FOP [plus minus mult div]) +(define_code_attr fop [(plus "add") (minus "sub") (mult "mul") (div "div")]) + +(define_insn "3" + [(set (match_operand:F 0 "register_operand" "=") + (FOP:F (match_operand:F 1 "register_operand" "") + (match_operand:F 2 "register_operand" "")))] + "TARGET_HARD_FLOAT" + "lf..\t%d0, %d1, %d2" + [(set_attr "type" "fpu")]) + +;; Basic float<->int conversion +(define_insn "float2" + [(set (match_operand:F 0 "register_operand" "=") + (float:F + (match_operand: 1 "register_operand" "")))] + "TARGET_HARD_FLOAT" + "lf.itof.\t%d0, %d1" + [(set_attr "type" "fpu")]) + +(define_insn "fix_trunc2" + [(set (match_operand: 0 "register_operand" "=") + (fix: + (match_operand:F 1 "register_operand" "")))] + "TARGET_HARD_FLOAT" + "lf.ftoi.\t%d0, %d1" + [(set_attr "type" "fpu")]) + +;; ------------------------------------------------------------------------- ;; Logical operators ;; ------------------------------------------------------------------------- @@ -380,7 +425,7 @@ (define_code_iterator intcmpcc [ne eq lt ltu gt gtu ge le geu leu]) (define_code_attr insn [(ne "ne") (eq "eq") (lt "lts") (ltu "ltu") (gt "gts") (gtu "gtu") (ge "ges") (le "les") - (geu "geu") (leu "leu") ]) + (geu "geu") (leu "leu")]) (define_insn "*sf_insn" [(set (reg:BI SR_F_REGNUM) @@ -392,6 +437,36 @@ l.sfi\t%r0, %1" [(set_attr "insn_support" "*,sfimm")]) +;; Support FP comparisons too + +;; The OpenRISC FPU supports these comparisons: +;; +;; lf.sfeq.{d,s} - equality, r r, double or single precision +;; lf.sfge.{d,s} - greater than or equal, r r, double or single precision +;; lf.sfgt.{d,s} - greater than, r r, double or single precision +;; lf.sfle.{d,s} - less than or equal, r r, double or single precision +;; lf.sflt.{d,s} - less than, r r, double or single precision +;; lf.sfne.{d,s} - not equal, r r, double or single precision +;; +;; Double precision is only supported on some hardware. Only register/register +;; comparisons are supported. All comparisons are signed. + +(define_code_iterator fpcmpcc [ne eq lt gt ge le uneq unle unlt ungt unge + unordered]) +(define_code_attr fpcmpinsn [(ne "ne") (eq "eq") (lt "lt") (gt "gt") (ge "ge") + (le "le") (uneq "ueq") (unle "ule") (unlt "ult") + (ungt "ugt") (unge "uge") (unordered "un")]) + + +(define_insn "*sf_fp_insn" + [(set (reg:BI SR_F_REGNUM) + (fpcmpcc:BI (match_operand:F 0 "register_operand" "") + (match_operand:F 1 "register_operand" "")))] + "TARGET_HARD_FLOAT" + "lf.sf.\t%d0, %d1" + [(set_attr "type" "fpu")]) + + ;; ------------------------------------------------------------------------- ;; Conditional Store instructions ;; ------------------------------------------------------------------------- @@ -412,6 +487,23 @@ DONE; }) +;; Support FP cstores too +(define_expand "cstore4" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:F + (match_operator 1 "fp_comparison_operator" + [(match_operand:F 2 "register_operand" "") + (match_operand:F 3 "register_operand" "")]) + (match_dup 0) + (const_int 0)))] + "TARGET_HARD_FLOAT" +{ + or1k_expand_compare (operands + 1); + PUT_MODE (operands[1], SImode); + emit_insn (gen_rtx_SET (operands[0], operands[1])); + DONE; +}) + ;; Being able to "copy" SR_F to a general register is helpful for ;; the atomic insns, wherein the usual usage is to test the success ;; of the compare-and-swap. Representing the operation in this way, @@ -505,6 +597,21 @@ or1k_expand_compare (operands); }) +;; Support FP branching + +(define_expand "cbranch4" + [(set (pc) + (if_then_else + (match_operator 0 "fp_comparison_operator" + [(match_operand:F 1 "register_operand" "") + (match_operand:F 2 "register_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_HARD_FLOAT" +{ + or1k_expand_compare (operands); +}) + (define_insn "*cbranch" [(set (pc) (if_then_else diff --git a/gcc/config/or1k/or1k.opt b/gcc/config/or1k/or1k.opt index c2f64c5..15085fa 100644 --- a/gcc/config/or1k/or1k.opt +++ b/gcc/config/or1k/or1k.opt @@ -41,6 +41,28 @@ Target RejectNegative Mask(SOFT_MUL). Enable generation of binaries which use functions from libgcc to perform multiply operations. The default is -mhard-mul. +msoft-float +Target RejectNegative InverseMask(HARD_FLOAT) +Enable generation of binaries which use functions from libgcc to perform +floating point operations. This is the default; use -mhard-float to override. + +mhard-float +Target RejectNegative Mask(HARD_FLOAT) +Enable generation of hardware floating point instructions. The default is +-msoft-float. + +mdouble-float +Target Mask(DOUBLE_FLOAT) +When -mhard-float is selected, enables generation of double-precision floating +point instructions. By default functions from libgcc are used to perform +double-precision floating point operations. + +munordered-float +Target RejectNegative Mask(FP_UNORDERED) +When -mhard-float is selected, enables generation of unordered floating point +compare and set flag (lf.sfun*) instructions. By default functions from libgcc +are used to perform unordered floating point compare and set flag operations. + mcmov Target RejectNegative Mask(CMOV) Enable generation of conditional move (l.cmov) instructions. By default the diff --git a/gcc/config/or1k/predicates.md b/gcc/config/or1k/predicates.md index 5e97bf4..3aa6ca3 100644 --- a/gcc/config/or1k/predicates.md +++ b/gcc/config/or1k/predicates.md @@ -90,6 +90,11 @@ (define_predicate "equality_comparison_operator" (match_code "ne,eq")) +(define_predicate "fp_comparison_operator" + (if_then_else (match_test "TARGET_FP_UNORDERED") + (match_operand 0 "comparison_operator") + (match_operand 0 "ordered_comparison_operator"))) + ;; Borrowed from rs6000 ;; Return true if the operand is in volatile memory. Note that during the ;; RTL generation phase, memory_operand does not return TRUE for volatile diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1703a0a..7bac080 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1034,6 +1034,7 @@ Objective-C and Objective-C++ Dialects}. @emph{OpenRISC Options} @gccoptlist{-mboard=@var{name} -mnewlib -mhard-mul -mhard-div @gol -msoft-mul -msoft-div @gol +-msoft-float -mhard-float -mdouble-float -munordered-float @gol -mcmov -mror -mrori -msext -msfimm -mshftimm} @emph{PDP-11 Options} @@ -23666,6 +23667,26 @@ This default is hardware divide. Select software or hardware multiply (@code{l.mul}, @code{l.muli}) instructions. This default is hardware multiply. +@item -msoft-float +@itemx -mhard-float +@opindex msoft-float +@opindex mhard-float +Select software or hardware for floating point operations. +The default is software. + +@item -mdouble-float +@opindex mdouble-float +When @option{-mhard-float} is selected, enables generation of double-precision +floating point instructions. By default functions from @file{libgcc} are used +to perform double-precision floating point operations. + +@item -munordered-float +@opindex munordered-float +When @option{-mhard-float} is selected, enables generation of unordered +floating point compare and set flag (@code{lf.sfun*}) instructions. By default +functions from @file{libgcc} are used to perform unordered floating point +compare and set flag operations. + @item -mcmov @opindex mcmov Enable generation of conditional move (@code{l.cmov}) instructions. By -- cgit v1.1 From 575ce8934206f6884fe009916551ee221931565c Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 21 Jul 2019 21:02:54 +0000 Subject: or1k: only force reg for immediates The force_reg in or1k_expand_compare is hard coded for SImode, which is fine as this used to only be used on SI expands. However, with FP support this will cause issues. In general we should only force the right hand operand to a register if its an immediate. This patch adds an condition to check for that. gcc/ChangeLog: * config/or1k/or1k.c (or1k_expand_compare): Check for int before force_reg. From-SVN: r273651 --- gcc/ChangeLog | 5 +++++ gcc/config/or1k/or1k.c | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 224b785..711a31e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2019-07-22 Stafford Horne + * config/or1k/or1k.c (or1k_expand_compare): Check for int before + force_reg. + +2019-07-22 Stafford Horne + * config.gcc (or1k*-*-*): Add mhard-float, mdouble-float, msoft-float and munordered-float validations. * config/or1k/constraints.md (d): New register constraint. diff --git a/gcc/config/or1k/or1k.c b/gcc/config/or1k/or1k.c index 1eea84f..f8eed4a 100644 --- a/gcc/config/or1k/or1k.c +++ b/gcc/config/or1k/or1k.c @@ -1448,13 +1448,15 @@ void or1k_expand_compare (rtx *operands) { rtx sr_f = gen_rtx_REG (BImode, SR_F_REGNUM); + rtx righthand_op = XEXP (operands[0], 1); rtx_code cmp_code = GET_CODE (operands[0]); bool flag_check_ne = true; - /* The RTL may receive an immediate in argument 1 of the compare, this is not - supported unless we have l.sf*i instructions, force them into registers. */ - if (!TARGET_SFIMM) - XEXP (operands[0], 1) = force_reg (SImode, XEXP (operands[0], 1)); + /* Integer RTL may receive an immediate in argument 1 of the compare, this is + not supported unless we have l.sf*i instructions, force them into + registers. */ + if (!TARGET_SFIMM && CONST_INT_P (righthand_op)) + XEXP (operands[0], 1) = force_reg (SImode, righthand_op); /* Normalize comparison operators to ones OpenRISC support. */ switch (cmp_code) -- cgit v1.1 From 33c43069281380cfc02f130cc10e28830ba8a711 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Sun, 21 Jul 2019 21:20:27 +0000 Subject: re PR c++/67853 (decltype of parenthesized xvalue does not correctly yield rvalue-reference) PR c++/67853 * g++.dg/cpp0x/decltype72.C: New test. From-SVN: r273652 --- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/cpp0x/decltype72.C | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype72.C (limited to 'gcc') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 234bc10..12774c0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-21 Marek Polacek + + PR c++/67853 + * g++.dg/cpp0x/decltype72.C: New test. + 2019-07-22 Stafford Horne * gcc.target/or1k/ror-4.c: New file. diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype72.C b/gcc/testsuite/g++.dg/cpp0x/decltype72.C new file mode 100644 index 0000000..071e0e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype72.C @@ -0,0 +1,19 @@ +// PR c++/67853 +// { dg-do compile { target c++11 } } + +template +struct is_same +{ + static const bool value = false; +}; + +template +struct is_same +{ + static const bool value = true; +}; + +struct Member {}; +struct A { Member x; }; +A MakeA(); +static_assert(is_same::value, ""); -- cgit v1.1 From 9e23d3bb28fc1efe3ed4eea47922291ad1311264 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 22 Jul 2019 00:16:23 +0000 Subject: Daily bump. From-SVN: r273656 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 6d7642c..924bff9 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190721 +20190722 -- cgit v1.1 From 4be6c9b9a2085b32be37df4216c37b395c7bd1a2 Mon Sep 17 00:00:00 2001 From: Claudiu Zissulescu Date: Mon, 22 Jul 2019 09:06:37 +0200 Subject: [ARC] Fix emitting TLS symbols. When storing a TLS symbol to memory, always use an intermediate register to load it. gcc/ xxxx-xx-xx Claudiu Zissulescu * config/arc/arc.c (prepare_move_operands): Always use an intermediate register when storing a TLS symbols. gcc/ xxxx-xx-xx Claudiu Zissulescu * gcc/testsuite/gcc.target/arc/tls-2.c: New test. * gcc/testsuite/gcc.target/arc/tls-3.c: Likewise. From-SVN: r273657 --- gcc/ChangeLog | 5 +++++ gcc/config/arc/arc.c | 2 +- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/arc/tls-2.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/arc/tls-3.c | 19 +++++++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/arc/tls-2.c create mode 100644 gcc/testsuite/gcc.target/arc/tls-3.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 711a31e..078a7d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Claudiu Zissulescu + + * config/arc/arc.c (prepare_move_operands): Always use an + intermediate register when storing a TLS symbols. + 2019-07-22 Stafford Horne * config/or1k/or1k.c (or1k_expand_compare): Check for int before diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 5decf91..71e6576 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -8959,7 +8959,7 @@ prepare_move_operands (rtx *operands, machine_mode mode) if (GET_CODE (operands[1]) == SYMBOL_REF) { enum tls_model model = SYMBOL_REF_TLS_MODEL (operands[1]); - if (MEM_P (operands[0]) && flag_pic) + if (MEM_P (operands[0])) operands[1] = force_reg (mode, operands[1]); else if (model) operands[1] = arc_legitimize_tls_address (operands[1], model); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 12774c0..31a9d33 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Claudiu Zissulescu + + * gcc.target/arc/tls-2.c: New test. + * gcc.target/arc/tls-3.c: Likewise. + 2019-07-21 Marek Polacek PR c++/67853 diff --git a/gcc/testsuite/gcc.target/arc/tls-2.c b/gcc/testsuite/gcc.target/arc/tls-2.c new file mode 100644 index 0000000..3cec309 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tls-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls } */ +/* { dg-skip-if "" { arc*-*-elf* } } */ +/* { dg-options "-O2" } */ + +typedef int type_a; +__thread int b; +int c; + +extern int bar (char *, int, int *, int, int *, char, type_a, int *, int *); +int foo (int *f, char buffer, type_a buflen, int *g) +{ + bar("", c, (int *)foo, 1, (int *)f, buffer, buflen, (int *)g, &b); +} diff --git a/gcc/testsuite/gcc.target/arc/tls-3.c b/gcc/testsuite/gcc.target/arc/tls-3.c new file mode 100644 index 0000000..e78b5a2 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tls-3.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls } */ +/* { dg-skip-if "" { arc*-*-elf* } } */ +/* { dg-options "-Os -fPIC" } */ + + +typedef struct +{ + int(a); + char b[]; +} type_c; + + +extern int bar (char *, int, char *); +static _Thread_local type_c d; +int foo(void) +{ + bar(d.b, 0, d.b); +} -- cgit v1.1 From 2df89b66f1b397c9eacd2078eb6a9b52c2c4853f Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 22 Jul 2019 09:34:10 +0200 Subject: Make a warning for -Werror=wrong-language (PR driver/91172). 2019-07-22 Martin Liska PR driver/91172 * opts-common.c (decode_cmdline_option): Decode argument of -Werror and check it for a wrong language. * opts-global.c (complain_wrong_lang): Remove such case. 2019-07-22 Martin Liska PR driver/91172 * gcc.dg/pr91172.c: New test. From-SVN: r273660 --- gcc/ChangeLog | 7 +++++++ gcc/opts-common.c | 20 +++++++++++++++++++- gcc/opts-global.c | 6 +++++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/pr91172.c | 3 +++ 5 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr91172.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 078a7d7..ae03a33 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Martin Liska + + PR driver/91172 + * opts-common.c (decode_cmdline_option): Decode + argument of -Werror and check it for a wrong language. + * opts-global.c (complain_wrong_lang): Remove such case. + 2019-07-22 Claudiu Zissulescu * config/arc/arc.c (prepare_move_operands): Always use an diff --git a/gcc/opts-common.c b/gcc/opts-common.c index 660dfe6..e3f9c54 100644 --- a/gcc/opts-common.c +++ b/gcc/opts-common.c @@ -537,7 +537,8 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, extra_args = 0; - opt_index = find_opt (argv[0] + 1, lang_mask); + const char *opt_value = argv[0] + 1; + opt_index = find_opt (opt_value, lang_mask); i = 0; while (opt_index == OPT_SPECIAL_unknown && i < ARRAY_SIZE (option_map)) @@ -745,6 +746,23 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, /* Check if this is a switch for a different front end. */ if (!option_ok_for_language (option, lang_mask)) errors |= CL_ERR_WRONG_LANG; + else if (strcmp (option->opt_text, "-Werror=") == 0 + && strchr (opt_value, ',') == NULL) + { + /* Verify that -Werror argument is a valid warning + for a language. */ + char *werror_arg = xstrdup (opt_value + 6); + werror_arg[0] = 'W'; + + size_t warning_index = find_opt (werror_arg, lang_mask); + if (warning_index != OPT_SPECIAL_unknown) + { + const struct cl_option *warning_option + = &cl_options[warning_index]; + if (!option_ok_for_language (warning_option, lang_mask)) + errors |= CL_ERR_WRONG_LANG; + } + } /* Convert the argument to lowercase if appropriate. */ if (arg && option->cl_tolower) diff --git a/gcc/opts-global.c b/gcc/opts-global.c index bf4db77..7c5bd16 100644 --- a/gcc/opts-global.c +++ b/gcc/opts-global.c @@ -103,10 +103,14 @@ complain_wrong_lang (const struct cl_decoded_option *decoded, text, bad_lang); else if (lang_mask == CL_DRIVER) gcc_unreachable (); - else + else if (ok_langs[0] != '\0') /* Eventually this should become a hard error IMO. */ warning (0, "command-line option %qs is valid for %s but not for %s", text, ok_langs, bad_lang); + else + /* Happens for -Werror=warning_name. */ + warning (0, "%<-Werror=%> argument %qs is not valid for %s", + text, bad_lang); free (ok_langs); free (bad_lang); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31a9d33..7332696 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Martin Liska + + PR driver/91172 + * gcc.dg/pr91172.c: New test. + 2019-07-22 Claudiu Zissulescu * gcc.target/arc/tls-2.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr91172.c b/gcc/testsuite/gcc.dg/pr91172.c new file mode 100644 index 0000000..a38a058 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr91172.c @@ -0,0 +1,3 @@ +/* { dg-do compile } */ +/* { dg-options "-Werror=target-lifetime" } */ +/* { dg-warning "'-Werror\=' argument '-Werror=target-lifetime' is not valid for C" "" { target *-*-* } 0 } */ -- cgit v1.1 From d1caf05a899bb57d1a96acd4869890991dedca20 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 22 Jul 2019 09:34:32 +0200 Subject: Simplify LTO section format. 2019-07-22 Martin Liska * lto-section-in.c (lto_get_section_data): Use new function get_compression. * lto-streamer-out.c (produce_lto_section): Use set_compression to encode compression algorithm. * lto-streamer.h (struct lto_section): Do not use bitfields in the format. From-SVN: r273661 --- gcc/ChangeLog | 9 +++++++++ gcc/lto-section-in.c | 3 ++- gcc/lto-streamer-out.c | 3 ++- gcc/lto-streamer.h | 19 ++++++++++++++++--- 4 files changed, 29 insertions(+), 5 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ae03a33..528432f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,14 @@ 2019-07-22 Martin Liska + * lto-section-in.c (lto_get_section_data): + Use new function get_compression. + * lto-streamer-out.c (produce_lto_section): Use + set_compression to encode compression algorithm. + * lto-streamer.h (struct lto_section): Do not + use bitfields in the format. + +2019-07-22 Martin Liska + PR driver/91172 * opts-common.c (decode_cmdline_option): Decode argument of -Werror and check it for a wrong language. diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c index 4c28701..0bdcf62 100644 --- a/gcc/lto-section-in.c +++ b/gcc/lto-section-in.c @@ -161,7 +161,8 @@ lto_get_section_data (struct lto_file_decl_data *file_data, stream = lto_start_uncompression (lto_append_data, &buffer); lto_uncompress_block (stream, data, *len); - lto_end_uncompression (stream, file_data->lto_section_header.compression); + lto_end_uncompression (stream, + file_data->lto_section_header.get_compression ()); *len = buffer.length - header_length; data = buffer.data + header_length; diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 35dcae4..e0881cf5 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -2403,7 +2403,8 @@ produce_lto_section () bool slim_object = flag_generate_lto && !flag_fat_lto_objects; lto_section s - = { LTO_major_version, LTO_minor_version, slim_object, compression, 0 }; + = { LTO_major_version, LTO_minor_version, slim_object, 0 }; + s.set_compression (compression); lto_write_data (&s, sizeof s); lto_end_section (); destroy_output_block (ob); diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 3c35d8a..bf755a6 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -394,9 +394,22 @@ struct lto_section { int16_t major_version; int16_t minor_version; - unsigned char slim_object: 1; - lto_compression compression: 4; - int32_t reserved0: 27; + unsigned char slim_object; + + /* Flags is a private field that is not defined publicly. */ + uint16_t flags; + + /* Set compression to FLAGS. */ + inline void set_compression (lto_compression c) + { + flags = c; + } + + /* Get compression from FLAGS. */ + inline lto_compression get_compression () + { + return (lto_compression) flags; + } }; STATIC_ASSERT (sizeof (lto_section) == 8); -- cgit v1.1 From a861990d21a7f495695597e75509a834d44fdb2d Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 22 Jul 2019 09:34:47 +0200 Subject: Do not emit __gnu_lto_v1 symbol. 2019-07-22 Martin Liska * config/avr/avr.c (avr_asm_output_aligned_decl_common): Update comment. * toplev.c (compile_file): Do not emit __gnu_lto_v1 symbol. 2019-07-22 Martin Liska * config/pa/stublib.c: Remove stub symbol __gnu_lto_v1. * config/pa/t-stublib: Likewise. 2019-07-22 Martin Liska * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): Do not search for gnu_lto_v1, but search for first '\0'. From-SVN: r273662 --- gcc/ChangeLog | 6 ++++++ gcc/config/avr/avr.c | 2 +- gcc/toplev.c | 21 --------------------- 3 files changed, 7 insertions(+), 22 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 528432f..05d8efa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-07-22 Martin Liska + * config/avr/avr.c (avr_asm_output_aligned_decl_common): Update + comment. + * toplev.c (compile_file): Do not emit __gnu_lto_v1 symbol. + +2019-07-22 Martin Liska + * lto-section-in.c (lto_get_section_data): Use new function get_compression. * lto-streamer-out.c (produce_lto_section): Use diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index b97faaf..760e937 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -10163,7 +10163,7 @@ avr_asm_output_aligned_decl_common (FILE * stream, return; } - /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c. + /* __gnu_lto_slim is just a marker for the linker injected by toplev.c. There is no need to trigger __do_clear_bss code for them. */ if (!STR_PREFIX_P (name, "__gnu_lto")) diff --git a/gcc/toplev.c b/gcc/toplev.c index 2567fe2..56ef63e 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -543,27 +543,6 @@ compile_file (void) process_pending_assemble_externals (); } - /* Emit LTO marker if LTO info has been previously emitted. This is - used by collect2 to determine whether an object file contains IL. - We used to emit an undefined reference here, but this produces - link errors if an object file with IL is stored into a shared - library without invoking lto1. */ - if (flag_generate_lto || flag_generate_offload) - { -#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON - ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE, - "__gnu_lto_v1", - HOST_WIDE_INT_1U, 8); -#elif defined ASM_OUTPUT_ALIGNED_COMMON - ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_v1", - HOST_WIDE_INT_1U, 8); -#else - ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_v1", - HOST_WIDE_INT_1U, - HOST_WIDE_INT_1U); -#endif - } - /* Let linker plugin know that this is a slim object and must be LTOed even when user did not ask for it. */ if (flag_generate_lto && !flag_fat_lto_objects) -- cgit v1.1 From ff8f129bc2f57fdfc80f56d73b84a80948d11d84 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 22 Jul 2019 08:07:29 +0000 Subject: x86/AVX512: improve generated code for bit-wise negation of vectors of integers NOT on vectors of integers does not require loading a constant vector of all ones into a register - VPTERNLOG can be used here (and could/should be further used to carry out other binary and ternary logical operations which don't have a special purpose instruction). gcc/ 2019-07-22 Jan Beulich * config/i386/sse.md (ternlogsuffix): New. (one_cmpl2): Don't force CONSTM1_RTX into a register when AVX512F is in use. (one_cmpl2): New. From-SVN: r273663 --- gcc/ChangeLog | 7 +++++++ gcc/config/i386/sse.md | 22 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 05d8efa..3e861ef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Jan Beulich + + * config/i386/sse.md (ternlogsuffix): New. + (one_cmpl2): Don't force CONSTM1_RTX into a register when + AVX512F is in use. + (one_cmpl2): New. + 2019-07-22 Martin Liska * config/avr/avr.c (avr_asm_output_aligned_decl_common): Update diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 12d6dc0..8abd161 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -853,6 +853,13 @@ (V4SF "k") (V2DF "q") (SF "k") (DF "q")]) +;; Mapping of vector modes to VPTERNLOG suffix +(define_mode_attr ternlogsuffix + [(V8DI "q") (V4DI "q") (V2DI "q") + (V16SI "d") (V8SI "d") (V4SI "d") + (V32HI "d") (V16HI "d") (V8HI "d") + (V64QI "d") (V32QI "d") (V16QI "d")]) + ;; Number of scalar elements in each vector type (define_mode_attr ssescalarnum [(V64QI "64") (V16SI "16") (V8DI "8") @@ -12723,9 +12730,22 @@ (match_dup 2)))] "TARGET_SSE" { - operands[2] = force_reg (mode, CONSTM1_RTX (mode)); + if (!TARGET_AVX512F) + operands[2] = force_reg (mode, CONSTM1_RTX (mode)); + else + operands[2] = CONSTM1_RTX (mode); }) +(define_insn "one_cmpl2" + [(set (match_operand:VI 0 "register_operand" "=v") + (xor:VI (match_operand:VI 1 "nonimmediate_operand" "vm") + (match_operand:VI 2 "vector_all_ones_operand" "BC")))] + "TARGET_AVX512F" + "vpternlog\t{$0x55, %1, %0, %0|%0, %0, %1, 0x55}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "")]) + (define_expand "_andnot3" [(set (match_operand:VI_AVX2 0 "register_operand") (and:VI_AVX2 -- cgit v1.1 From 8801ca5c28c3a9e9f36fa39a6a4455b48c8221fa Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 22 Jul 2019 11:18:55 +0000 Subject: re PR tree-optimization/91221 (ICE in get_int_cst_ext_nunits, at tree.c:1299 since r273548) 2019-07-22 Richard Biener PR tree-optimization/91221 * tree-ssa-sccvn.c (vn_reference_lookup_3): Appropriately restrict partial-def handling of empty constructors and memset to refs with known offset. * g++.dg/pr91221.C: New testcase. From-SVN: r273667 --- gcc/ChangeLog | 7 +++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/pr91221.C | 13 +++++++++++++ gcc/tree-ssa-sccvn.c | 6 ++++-- 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr91221.C (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3e861ef..e58dfe1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Richard Biener + + PR tree-optimization/91221 + * tree-ssa-sccvn.c (vn_reference_lookup_3): Appropriately + restrict partial-def handling of empty constructors and + memset to refs with known offset. + 2019-07-22 Jan Beulich * config/i386/sse.md (ternlogsuffix): New. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7332696..e063774 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Richard Biener + + PR tree-optimization/91221 + * g++.dg/pr91221.C: New testcase. + 2019-07-22 Martin Liska PR driver/91172 diff --git a/gcc/testsuite/g++.dg/pr91221.C b/gcc/testsuite/g++.dg/pr91221.C new file mode 100644 index 0000000..3036f1b --- /dev/null +++ b/gcc/testsuite/g++.dg/pr91221.C @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-options "-O2 -fno-ipa-pure-const -fpack-struct -Wno-address-of-packed-member" } + +void printf(...); +struct A { + A() : bar_(), dbar_() { + for (int i;; i++) + printf(i, bar_[i]); + } + int bar_[5]; + double dbar_[5]; +}; +void fn1() { A a; } diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 5b0460d..cab2460 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2455,7 +2455,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, (vuse, vr->set, vr->type, vr->operands, val); } /* For now handle clearing memory with partial defs. */ - else if (integer_zerop (gimple_call_arg (def_stmt, 1)) + else if (known_eq (ref->size, maxsize) + && integer_zerop (gimple_call_arg (def_stmt, 1)) && tree_to_poly_int64 (len).is_constant (&leni) && offset.is_constant (&offseti) && offset2.is_constant (&offset2i) @@ -2503,7 +2504,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, return vn_reference_lookup_or_insert_for_pieces (vuse, vr->set, vr->type, vr->operands, val); } - else if (maxsize.is_constant (&maxsizei) + else if (known_eq (ref->size, maxsize) + && maxsize.is_constant (&maxsizei) && maxsizei % BITS_PER_UNIT == 0 && offset.is_constant (&offseti) && offseti % BITS_PER_UNIT == 0 -- cgit v1.1 From c961d8205b749d6df462202efd09efa6bf01442d Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:56:26 +0000 Subject: [Ada] Fix internal error on array slice in loop and Loop_Invariant This fixes an internal error caused by the presence of an Itype in a wrong scope. This Itype is created for an array slice present in the condition of a while loop whose body also contains a pragma Loop_Invariant, initially in the correct scope but then relocated into a function created for the pragma. 2019-07-22 Eric Botcazou gcc/ada/ * exp_attr.adb (Expand_Loop_Entry_Attribute): Copy the condition of a while loop instead of simply relocating it. gcc/testsuite/ * gnat.dg/loop_invariant1.adb, gnat.dg/loop_invariant1.ads: New testcase. From-SVN: r273668 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/exp_attr.adb | 7 +++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/loop_invariant1.adb | 15 +++++++++++++++ gcc/testsuite/gnat.dg/loop_invariant1.ads | 7 +++++++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/loop_invariant1.adb create mode 100644 gcc/testsuite/gnat.dg/loop_invariant1.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ff3582f..38cc4b8 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Eric Botcazou + + * exp_attr.adb (Expand_Loop_Entry_Attribute): Copy the condition + of a while loop instead of simply relocating it. + 2019-07-18 Arnaud Charlet * Makefile.rtl, expect.c, env.c, aux-io.c, mkdir.c, initialize.c, diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index ac99ec1..90ca8ff 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -1384,6 +1384,8 @@ package body Exp_Attr is Stmts : List_Id; begin + Func_Id := Make_Temporary (Loc, 'F'); + -- Wrap the condition of the while loop in a Boolean function. -- This avoids the duplication of the same code which may lead -- to gigi issues with respect to multiple declaration of the @@ -1403,7 +1405,9 @@ package body Exp_Attr is Append_To (Stmts, Make_Simple_Return_Statement (Loc, - Expression => Relocate_Node (Condition (Scheme)))); + Expression => + New_Copy_Tree (Condition (Scheme), + New_Scope => Func_Id))); -- Generate: -- function Fnn return Boolean is @@ -1411,7 +1415,6 @@ package body Exp_Attr is -- -- end Fnn; - Func_Id := Make_Temporary (Loc, 'F'); Func_Decl := Make_Subprogram_Body (Loc, Specification => diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e063774..e9c2b5e3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Eric Botcazou + + * gnat.dg/loop_invariant1.adb, gnat.dg/loop_invariant1.ads: New + testcase. + 2019-07-22 Richard Biener PR tree-optimization/91221 diff --git a/gcc/testsuite/gnat.dg/loop_invariant1.adb b/gcc/testsuite/gnat.dg/loop_invariant1.adb new file mode 100644 index 0000000..a5c9476 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_invariant1.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +package body Loop_Invariant1 is + + procedure Proc (A : Arr; N : Integer) is + I : Integer := A'First; + begin + while i <= A'Last and then A(A'First .. A'Last) /= A loop + pragma Loop_Invariant (N = N'Loop_Entry); + i := i + 1; + end loop; + end; + +end Loop_Invariant1; diff --git a/gcc/testsuite/gnat.dg/loop_invariant1.ads b/gcc/testsuite/gnat.dg/loop_invariant1.ads new file mode 100644 index 0000000..5c19a92 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_invariant1.ads @@ -0,0 +1,7 @@ +package Loop_Invariant1 is + + type Arr is array (Natural range <>) of Integer; + + procedure Proc (A : Arr; N : Integer); + +end Loop_Invariant1; -- cgit v1.1 From 0af66bdce078d022e19dae1c83dfa06f7f622648 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 22 Jul 2019 13:56:31 +0000 Subject: [Ada] Spurious warning about a useless assignment This patch removes a spurious warning about a useless assignment, when a composite object is the target of an assignment and is an actual for an out parameter in a subsewuent call, and there is an intervening use of the object as the prefix of a selected component in an intervening operation. 2019-07-22 Ed Schonberg gcc/ada/ * sem_res.adb (Resolve_Selected_Component): If the prefix has a deferred reference, generate the correct reference now, to indicate that the previous assignment is used. This prevents spurious warnings on useless assignments when compiling with all warnings enabled. when there is a subsequent call in the same stqtement list, in which the prefix of the selected component is the actual for an out parameter. gcc/testsuite/ * gnat.dg/warn22.adb: New testcase. From-SVN: r273669 --- gcc/ada/ChangeLog | 10 ++++++++++ gcc/ada/sem_res.adb | 17 +++++++++++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/warn22.adb | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/warn22.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 38cc4b8..c42164b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-07-22 Ed Schonberg + + * sem_res.adb (Resolve_Selected_Component): If the prefix has a + deferred reference, generate the correct reference now, to + indicate that the previous assignment is used. This prevents + spurious warnings on useless assignments when compiling with all + warnings enabled. when there is a subsequent call in the same + stqtement list, in which the prefix of the selected component is + the actual for an out parameter. + 2019-07-22 Eric Botcazou * exp_attr.adb (Expand_Loop_Entry_Attribute): Copy the condition diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 4ca74f8..fd4fedc 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -10625,8 +10625,25 @@ package body Sem_Res is if Is_Access_Type (Etype (P)) then T := Designated_Type (Etype (P)); Check_Fully_Declared_Prefix (T, P); + else T := Etype (P); + + -- If the prefix is an entity it may have a deferred reference set + -- during analysis of the selected component. After resolution we + -- can transform it into a proper reference. This prevents spurious + -- warnings on useless assignments when the same selected component + -- is the actual for an out parameter in a subsequent call. + + if Is_Entity_Name (P) + and then Has_Deferred_Reference (Entity (P)) + then + if May_Be_Lvalue (N) then + Generate_Reference (Entity (P), P, 'm'); + else + Generate_Reference (Entity (P), P, 'r'); + end if; + end if; end if; -- Set flag for expander if discriminant check required on a component diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e9c2b5e3..f8372ba 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Ed Schonberg + + * gnat.dg/warn22.adb: New testcase. + 2019-07-22 Eric Botcazou * gnat.dg/loop_invariant1.adb, gnat.dg/loop_invariant1.ads: New diff --git a/gcc/testsuite/gnat.dg/warn22.adb b/gcc/testsuite/gnat.dg/warn22.adb new file mode 100644 index 0000000..0a1692f --- /dev/null +++ b/gcc/testsuite/gnat.dg/warn22.adb @@ -0,0 +1,34 @@ +-- { dg-do compile } +-- { dg-options "-gnatwa" } + +with Ada.Text_IO; + +procedure Warn22 +is + type X is + record + Str : String (1 .. 3); + end record; + + type T is + record + Value : X; + end record; + + procedure Consume_Data (Item : out T) is + begin + Item := (Value => (Str => "Bar")); + end Consume_Data; + + Baz : T; +begin + + Baz := (Value => (Str => "Foo")); + + Ada.Text_IO.Put_Line (Baz.Value.Str); + + Consume_Data (Baz); + + Ada.Text_IO.Put_Line (Baz.Value.Str); + +end Warn22; -- cgit v1.1 From 2fdc20b65c2f3409591aeea810001a29ff1d6739 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Mon, 22 Jul 2019 13:56:36 +0000 Subject: [Ada] Crash in C++ constructor without external and link name The compiler blows up processing the declaration of a tagged type variable that has a C++ constructor without external or link name. After this patch the frontend reports an error. 2019-07-22 Javier Miranda gcc/ada/ * freeze.adb (Freeze_Subprogram): Check that C++ constructors must have external or link name. gcc/testsuite/ * gnat.dg/cpp_constructor2.adb: New testcase. From-SVN: r273670 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/freeze.adb | 15 +++++++++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/cpp_constructor2.adb | 19 +++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/cpp_constructor2.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c42164b..5cb3ab4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Javier Miranda + + * freeze.adb (Freeze_Subprogram): Check that C++ constructors + must have external or link name. + 2019-07-22 Ed Schonberg * sem_res.adb (Resolve_Selected_Component): If the prefix has a diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index b29ff67..728eaf2 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -62,6 +62,7 @@ with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; with Snames; use Snames; with Stand; use Stand; +with Stringt; use Stringt; with Targparm; use Targparm; with Tbuild; use Tbuild; with Ttypes; use Ttypes; @@ -8766,6 +8767,20 @@ package body Freeze is Set_Is_Pure (E, False); end if; + -- For C++ constructors check that their external name has been given + -- (either in pragma CPP_Constructor or in a pragma import). + + if Is_Constructor (E) + and then + (No (Interface_Name (E)) + or else String_Equal + (L => Strval (Interface_Name (E)), + R => Strval (Get_Default_External_Name (E)))) + then + Error_Msg_N + ("'C++ constructor must have external name or link name", E); + end if; + -- We also reset the Pure indication on a subprogram with an Address -- parameter, because the parameter may be used as a pointer and the -- referenced data may change even if the address value does not. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f8372ba..2fa30eb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Javier Miranda + + * gnat.dg/cpp_constructor2.adb: New testcase. + 2019-07-22 Ed Schonberg * gnat.dg/warn22.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/cpp_constructor2.adb b/gcc/testsuite/gnat.dg/cpp_constructor2.adb new file mode 100644 index 0000000..3b245b0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/cpp_constructor2.adb @@ -0,0 +1,19 @@ +-- { dg-do compile } + +procedure CPP_Constructor2 is + + package P is + type X is tagged limited record + A, B, C, D : Integer; + end record; + pragma Import (Cpp, X); + + procedure F1 (V : X); + pragma Import (Cpp, F1); + + function F2 return X; -- { dg-error "C\\+\\+ constructor must have external name or link name" } + pragma Cpp_Constructor (F2); + end P; +begin + null; +end CPP_Constructor2; -- cgit v1.1 From 4123b473427ca6854f874c77f5ce78c7e8c133a7 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 22 Jul 2019 13:56:40 +0000 Subject: [Ada] Incorrect values in conversion from fixed-point subtype with 'Small This patch fixes incorrect computations involving a fixed-point subtype whose parent type has an aspect specification for 'Small. Executing the following: gnatmake -q conv ./conv must yield: 9000.000000 9.00000000000000E+03 9000.000000 9.00000000000000E+03 9.00000000000000E+03 9.00000000000000E+03 9.00000000000000E+03 9.00000000000000E+03 ---- with Text_IO; use Text_IO; procedure Conv is V_P : constant := 10.0 ** (-6); M_V : constant := 9000.0; N_V : constant := -9000.0; type V_T is delta V_P range N_V .. M_V with Small => V_P; subtype S_T is V_T range 0.0 .. M_V; function Convert (Input : in S_T) return Long_Float is begin Put_Line (Input'Img); Put_Line (Long_Float'Image (Long_Float (Input))); return Long_Float (Input); end Convert; begin declare Var_S : constant S_T := S_T'Last; Output : constant Long_Float := Convert (Var_S); begin Put_Line (Long_Float'Image (Convert (Var_S))); Put_Line (Long_Float'Image (Long_Float (Var_S))); Put_Line (Output'Img); end; Put_Line (Long_Float'Image (Long_Float (S_T'Last))); end Conv; 2019-07-22 Ed Schonberg gcc/ada/ * freeze.adb (Freeze_Fixed_Point_Type): When freezing a fixed-point subtype, check whether the parent type declarastion includes an aspect specification for the 'Small type attribute, and inherit the specified value. From-SVN: r273671 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/freeze.adb | 11 +++++++++++ 2 files changed, 18 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 5cb3ab4..5113e77 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Ed Schonberg + + * freeze.adb (Freeze_Fixed_Point_Type): When freezing a + fixed-point subtype, check whether the parent type declarastion + includes an aspect specification for the 'Small type attribute, + and inherit the specified value. + 2019-07-22 Javier Miranda * freeze.adb (Freeze_Subprogram): Check that C++ constructors diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 728eaf2..00d20e9 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -8003,6 +8003,7 @@ package body Freeze is Brng : constant Node_Id := Scalar_Range (Btyp); BLo : constant Node_Id := Low_Bound (Brng); BHi : constant Node_Id := High_Bound (Brng); + Par : constant Entity_Id := First_Subtype (Typ); Small : constant Ureal := Small_Value (Typ); Loval : Ureal; Hival : Ureal; @@ -8055,6 +8056,16 @@ package body Freeze is end if; end if; + -- The 'small attribute may have been specified with an aspect, + -- in which case it is processed after a subtype declaration, so + -- inherit now the specified value. + + if Typ /= Par + and then Present (Find_Aspect (Par, Aspect_Small)) + then + Set_Small_Value (Typ, Small_Value (Par)); + end if; + -- Immediate return if the range is already analyzed. This means that -- the range is already set, and does not need to be computed by this -- routine. -- cgit v1.1 From 1a79e03b8012d5094e5bd432df59abeca5c2fe18 Mon Sep 17 00:00:00 2001 From: Nicolas Roche Date: Mon, 22 Jul 2019 13:56:45 +0000 Subject: [Ada] Ensure Ctrl-C is not emited on terminated processes Due to the reuse policy of PID on Windows. Sending a Ctrl-C to a dead process might result in a Ctrl-C sent to the wrong process. The check is also implemented on Unix platforms and avoid unecessary waits. 2019-07-22 Nicolas Roche gcc/ada/ * terminals.c (__gnat_tty_waitpid): Support both blocking and not blocking mode. * libgnat/g-exptty.ads (Is_Process_Running): New function. * libgnat/g-exptty.adb (Close): Don't try to interrupt/terminate a process if it is already dead. From-SVN: r273672 --- gcc/ada/ChangeLog | 8 +++++++ gcc/ada/libgnat/g-exptty.adb | 51 +++++++++++++++++++++++++++++++++++--------- gcc/ada/libgnat/g-exptty.ads | 14 ++++++++++-- gcc/ada/terminals.c | 45 +++++++++++++++++++++++++++----------- 4 files changed, 93 insertions(+), 25 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 5113e77..ec1b81a 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-22 Nicolas Roche + + * terminals.c (__gnat_tty_waitpid): Support both blocking and + not blocking mode. + * libgnat/g-exptty.ads (Is_Process_Running): New function. + * libgnat/g-exptty.adb (Close): Don't try to interrupt/terminate + a process if it is already dead. + 2019-07-22 Ed Schonberg * freeze.adb (Freeze_Fixed_Point_Type): When freezing a diff --git a/gcc/ada/libgnat/g-exptty.adb b/gcc/ada/libgnat/g-exptty.adb index 1a977b5..728c5c6 100644 --- a/gcc/ada/libgnat/g-exptty.adb +++ b/gcc/ada/libgnat/g-exptty.adb @@ -38,6 +38,28 @@ package body GNAT.Expect.TTY is On_Windows : constant Boolean := Directory_Separator = '\'; -- True when on Windows + function Waitpid (Process : System.Address; Blocking : Integer) + return Integer; + pragma Import (C, Waitpid, "__gnat_tty_waitpid"); + -- Wait for a specific process id, and return its exit code + + ------------------------ + -- Is_Process_Running -- + ------------------------ + + function Is_Process_Running + (Descriptor : in out TTY_Process_Descriptor) + return Boolean + is + begin + if Descriptor.Process = System.Null_Address then + return False; + end if; + + Descriptor.Exit_Status := Waitpid (Descriptor.Process, Blocking => 0); + return Descriptor.Exit_Status = Still_Active; + end Is_Process_Running; + ----------- -- Close -- ----------- @@ -49,10 +71,6 @@ package body GNAT.Expect.TTY is procedure Terminate_Process (Process : System.Address); pragma Import (C, Terminate_Process, "__gnat_terminate_process"); - function Waitpid (Process : System.Address) return Integer; - pragma Import (C, Waitpid, "__gnat_tty_waitpid"); - -- Wait for a specific process id, and return its exit code - procedure Free_Process (Process : System.Address); pragma Import (C, Free_Process, "__gnat_free_process"); @@ -63,7 +81,7 @@ package body GNAT.Expect.TTY is -- If we haven't already closed the process if Descriptor.Process = System.Null_Address then - Status := -1; + Status := Descriptor.Exit_Status; else -- Send a Ctrl-C to the process first. This way, if the launched @@ -75,9 +93,6 @@ package body GNAT.Expect.TTY is -- signal, so this needs to be done while the file descriptors are -- still open (it used to be after the closes and that was wrong). - Interrupt (Descriptor); - delay (0.05); - if Descriptor.Input_Fd /= Invalid_FD then Close (Descriptor.Input_Fd); end if; @@ -92,8 +107,23 @@ package body GNAT.Expect.TTY is Close (Descriptor.Output_Fd); end if; - Terminate_Process (Descriptor.Process); - Status := Waitpid (Descriptor.Process); + if Descriptor.Exit_Status = Still_Active then + Status := Waitpid (Descriptor.Process, Blocking => 0); + + if Status = Still_Active then + -- In theory the process might hav died since the check. In + -- practice the following calls should not cause any issue. + Interrupt (Descriptor); + delay (0.05); + Terminate_Process (Descriptor.Process); + Status := Waitpid (Descriptor.Process, Blocking => 1); + Descriptor.Exit_Status := Status; + end if; + else + -- If Exit_Status is not STILL_ACTIVE just retrieve the saved + -- exit status + Status := Descriptor.Exit_Status; + end if; if not On_Windows then Close_TTY (Descriptor.Process); @@ -258,6 +288,7 @@ package body GNAT.Expect.TTY is pragma Import (C, Internal, "__gnat_setup_communication"); begin + Pid.Exit_Status := Still_Active; if Internal (Pid.Process'Address) /= 0 then raise Invalid_Process with "cannot setup communication."; end if; diff --git a/gcc/ada/libgnat/g-exptty.ads b/gcc/ada/libgnat/g-exptty.ads index 3a90d8d..57aa8d7 100644 --- a/gcc/ada/libgnat/g-exptty.ads +++ b/gcc/ada/libgnat/g-exptty.ads @@ -92,6 +92,11 @@ package GNAT.Expect.TTY is Columns : Natural); -- Sets up the size of the terminal as reported to the spawned process + function Is_Process_Running + (Descriptor : in out TTY_Process_Descriptor) + return Boolean; + -- Return True is the process is still alive + private -- All declarations in the private part must be fully commented ??? @@ -129,9 +134,14 @@ private Cmd : String; Args : System.Address); + Still_Active : constant Integer := -1; + type TTY_Process_Descriptor is new Process_Descriptor with record - Process : System.Address; -- Underlying structure used in C - Use_Pipes : Boolean := True; + Process : System.Address; + -- Underlying structure used in C + Exit_Status : Integer := Still_Active; + -- Hold the exit status of the process. + Use_Pipes : Boolean := True; end record; end GNAT.Expect.TTY; diff --git a/gcc/ada/terminals.c b/gcc/ada/terminals.c index 23f9dfd..320ad28 100644 --- a/gcc/ada/terminals.c +++ b/gcc/ada/terminals.c @@ -108,7 +108,7 @@ __gnat_tty_supported (void) } int -__gnat_tty_waitpid (void *desc ATTRIBUTE_UNUSED) +__gnat_tty_waitpid (void *desc ATTRIBUTE_UNUSED, int blocking) { return 1; } @@ -152,6 +152,7 @@ __gnat_setup_winsize (void *desc ATTRIBUTE_UNUSED, #include #include +#include #define MAXPATHLEN 1024 @@ -1014,20 +1015,28 @@ __gnat_terminate_pid (int pid) the Win32 API instead of the C one. */ int -__gnat_tty_waitpid (struct TTY_Process* p) +__gnat_tty_waitpid (struct TTY_Process* p, int blocking) { DWORD exitcode; - DWORD res; - HANDLE proc_hand = p->procinfo.hProcess; + HANDLE hprocess = p->procinfo.hProcess; - res = WaitForSingleObject (proc_hand, 0); - GetExitCodeProcess (proc_hand, &exitcode); + if (blocking) { + /* Wait is needed on Windows only in blocking mode. */ + WaitForSingleObject (hprocess, 0); + } - CloseHandle (p->procinfo.hThread); - CloseHandle (p->procinfo.hProcess); + GetExitCodeProcess (hprocess, &exitcode); - /* No need to close the handles: they were closed on the ada side */ + if (exitcode == STILL_ACTIVE) { + /* If process is still active return -1. */ + exitcode = -1; + } else { + /* Process is dead, so handle to process and main thread can be closed. */ + CloseHandle (p->procinfo.hThread); + CloseHandle (hprocess); + } + /* No need to close the handles: they were closed on the ada side */ return (int) exitcode; } @@ -1556,11 +1565,21 @@ __gnat_terminate_pid (int pid) * exit status of the child process */ int -__gnat_tty_waitpid (pty_desc *desc) +__gnat_tty_waitpid (pty_desc *desc, int blocking) { - int status = 0; - waitpid (desc->child_pid, &status, 0); - return WEXITSTATUS (status); + int status = -1; + int options = 0; + + if (blocking) { + options = 0; + } else { + options = WNOHANG; + } + waitpid (desc->child_pid, &status, options); + if WIFEXITED (status) { + status = WEXITSTATUS (status); + } + return status; } /* __gnat_tty_supported - Are tty supported ? -- cgit v1.1 From f3d2fbfdb83bcc60d72824daf7a470c0e5398854 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:56:50 +0000 Subject: [Ada] Fix spurious loop warning for function with Out parameter The compiler gives a spurious warning about a possible infinite while loop whose condition contains a call to a function that takes an Out or In/Out parameter and whose actual is a variable that is not modified in the loop, because it still thinks that functions can only have In parameters. 2019-07-22 Eric Botcazou gcc/ada/ * sem_warn.adb (Find_Var): Bail out for a function call with an Out or In/Out parameter. gcc/testsuite/ * gnat.dg/warn23.adb: New testcase. From-SVN: r273673 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_warn.adb | 5 +++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/warn23.adb | 17 +++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/warn23.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ec1b81a..6fc9d1c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Eric Botcazou + + * sem_warn.adb (Find_Var): Bail out for a function call with an + Out or In/Out parameter. + 2019-07-22 Nicolas Roche * terminals.c (__gnat_tty_waitpid): Support both blocking and diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb index 16a772a..0e1e292 100644 --- a/gcc/ada/sem_warn.adb +++ b/gcc/ada/sem_warn.adb @@ -333,6 +333,11 @@ package body Sem_Warn is elsif Has_Warnings_Off (Entity (Name (N))) then return; + + -- Forget it if the parameter is not In + + elsif Has_Out_Or_In_Out_Parameter (Entity (Name (N))) then + return; end if; -- OK, see if we have one argument diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2fa30eb..c542c62 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Eric Botcazou + + * gnat.dg/warn23.adb: New testcase. + 2019-07-22 Javier Miranda * gnat.dg/cpp_constructor2.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/warn23.adb b/gcc/testsuite/gnat.dg/warn23.adb new file mode 100644 index 0000000..63d0557 --- /dev/null +++ b/gcc/testsuite/gnat.dg/warn23.adb @@ -0,0 +1,17 @@ +-- { dg-do compile } + +procedure Warn23 is + + type Enum_Type is (A, B, C); + + function Poll (E : out Enum_Type) return Boolean + with Convention => Ada, + Import => True; + + E : Enum_Type; + +begin + while Poll (E) loop + null; + end loop; +end; -- cgit v1.1 From 52860cc145a7075a9f30840703f96b242cd0150f Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:56:55 +0000 Subject: [Ada] Fix wrong assumption on bounds in GNAT.Encode_String This fixes a couple of oversights in the GNAT.Encode_String package, whose effect is to assume that all the strings have a lower bound of 1. 2019-07-22 Eric Botcazou gcc/ada/ * libgnat/g-encstr.adb (Encode_Wide_String): Fix oversight. (Encode_Wide_Wide_String): Likewise. gcc/testsuite/ * gnat.dg/encode_string1.adb, gnat.dg/encode_string1_pkg.adb, gnat.dg/encode_string1_pkg.ads: New testcase. From-SVN: r273674 --- gcc/ada/ChangeLog | 5 +++ gcc/ada/libgnat/g-encstr.adb | 8 ++--- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gnat.dg/encode_string1.adb | 48 ++++++++++++++++++++++++++++ gcc/testsuite/gnat.dg/encode_string1_pkg.adb | 15 +++++++++ gcc/testsuite/gnat.dg/encode_string1_pkg.ads | 6 ++++ 6 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/encode_string1.adb create mode 100644 gcc/testsuite/gnat.dg/encode_string1_pkg.adb create mode 100644 gcc/testsuite/gnat.dg/encode_string1_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6fc9d1c..cf8b171 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-22 Eric Botcazou + * libgnat/g-encstr.adb (Encode_Wide_String): Fix oversight. + (Encode_Wide_Wide_String): Likewise. + +2019-07-22 Eric Botcazou + * sem_warn.adb (Find_Var): Bail out for a function call with an Out or In/Out parameter. diff --git a/gcc/ada/libgnat/g-encstr.adb b/gcc/ada/libgnat/g-encstr.adb index 81a73fd..b115c8a 100644 --- a/gcc/ada/libgnat/g-encstr.adb +++ b/gcc/ada/libgnat/g-encstr.adb @@ -79,12 +79,12 @@ package body GNAT.Encode_String is Ptr : Natural; begin - Ptr := S'First; + Ptr := Result'First; for J in S'Range loop Encode_Wide_Character (S (J), Result, Ptr); end loop; - Length := Ptr - S'First; + Length := Ptr - Result'First; end Encode_Wide_String; ----------------------------- @@ -108,12 +108,12 @@ package body GNAT.Encode_String is Ptr : Natural; begin - Ptr := S'First; + Ptr := Result'First; for J in S'Range loop Encode_Wide_Wide_Character (S (J), Result, Ptr); end loop; - Length := Ptr - S'First; + Length := Ptr - Result'First; end Encode_Wide_Wide_String; --------------------------- diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c542c62..6dbdc43 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2019-07-22 Eric Botcazou + * gnat.dg/encode_string1.adb, gnat.dg/encode_string1_pkg.adb, + gnat.dg/encode_string1_pkg.ads: New testcase. + +2019-07-22 Eric Botcazou + * gnat.dg/warn23.adb: New testcase. 2019-07-22 Javier Miranda diff --git a/gcc/testsuite/gnat.dg/encode_string1.adb b/gcc/testsuite/gnat.dg/encode_string1.adb new file mode 100644 index 0000000..f1144ba --- /dev/null +++ b/gcc/testsuite/gnat.dg/encode_string1.adb @@ -0,0 +1,48 @@ +-- { dg-do run } + +with Ada.Text_IO; use Ada.Text_IO; +with Encode_String1_Pkg; +with GNAT.Encode_String; +with System.WCh_Con; use System.WCh_Con; + +procedure Encode_String1 is + High_WS : constant Wide_String (1000 .. 1009) := (others => '1'); + High_WWS : constant Wide_Wide_String (1000 .. 1009) := (others => '2'); + Low_WS : constant Wide_String (3 .. 12) := (others => '3'); + Low_WWS : constant Wide_Wide_String (3 .. 12) := (others => '4'); + + procedure Test_Method (Method : WC_Encoding_Method); + -- Test Wide_String and Wide_Wide_String encodings using method Method to + -- encode them. + + ----------------- + -- Test_Method -- + ----------------- + + procedure Test_Method (Method : WC_Encoding_Method) is + package Encoder is new GNAT.Encode_String (Method); + + procedure WS_Tester is new Encode_String1_Pkg + (C => Wide_Character, + S => Wide_String, + Encode => Encoder.Encode_Wide_String); + + procedure WWS_Tester is new Encode_String1_Pkg + (C => Wide_Wide_Character, + S => Wide_Wide_String, + Encode => Encoder.Encode_Wide_Wide_String); + begin + WS_Tester (High_WS); + WS_Tester (Low_WS); + + WWS_Tester (High_WWS); + WWS_Tester (Low_WWS); + end Test_Method; + +-- Start of processing for Main + +begin + for Method in WC_Encoding_Method'Range loop + Test_Method (Method); + end loop; +end; diff --git a/gcc/testsuite/gnat.dg/encode_string1_pkg.adb b/gcc/testsuite/gnat.dg/encode_string1_pkg.adb new file mode 100644 index 0000000..fa969a0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/encode_string1_pkg.adb @@ -0,0 +1,15 @@ +with Ada.Exceptions; use Ada.Exceptions; +with Ada.Text_IO; use Ada.Text_IO; + +procedure Encode_String1_Pkg (Val : S) is +begin + declare + Result : constant String := Encode (Val); + begin + Put_Line (Result); + end; + +exception + when Ex : others => + Put_Line ("ERROR: Unexpected exception " & Exception_Name (Ex)); +end; diff --git a/gcc/testsuite/gnat.dg/encode_string1_pkg.ads b/gcc/testsuite/gnat.dg/encode_string1_pkg.ads new file mode 100644 index 0000000..ba2d675 --- /dev/null +++ b/gcc/testsuite/gnat.dg/encode_string1_pkg.ads @@ -0,0 +1,6 @@ +generic + type C is private; + type S is array (Positive range <>) of C; + with function Encode (Val : S) return String; + +procedure Encode_String1_Pkg (Val : S); -- cgit v1.1 From 7ddc639b7717278075ab1989568d1769ccc040e1 Mon Sep 17 00:00:00 2001 From: Nicolas Roche Date: Mon, 22 Jul 2019 13:56:59 +0000 Subject: [Ada] Ensure meaningless digits in a string are discarded 2019-07-22 Nicolas Roche gcc/ada/ * libgnat/s-valrea.adb (Scan_Real): Ignore non significative digits to avoid converging to infinity in some cases. gcc/testsuite/ * gnat.dg/float_value1.adb: New testcase. From-SVN: r273675 --- gcc/ada/ChangeLog | 5 ++ gcc/ada/libgnat/s-valrea.adb | 98 ++++++++++++++++------------------ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/float_value1.adb | 46 ++++++++++++++++ 4 files changed, 101 insertions(+), 52 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/float_value1.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cf8b171..276fdba 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Nicolas Roche + + * libgnat/s-valrea.adb (Scan_Real): Ignore non significative + digits to avoid converging to infinity in some cases. + 2019-07-22 Eric Botcazou * libgnat/g-encstr.adb (Encode_Wide_String): Fix oversight. diff --git a/gcc/ada/libgnat/s-valrea.adb b/gcc/ada/libgnat/s-valrea.adb index 9039f99..99c7360 100644 --- a/gcc/ada/libgnat/s-valrea.adb +++ b/gcc/ada/libgnat/s-valrea.adb @@ -71,16 +71,13 @@ package body System.Val_Real is After_Point : Natural := 0; -- Set to 1 after the point - Num_Saved_Zeroes : Natural := 0; - -- This counts zeroes after the decimal point. A non-zero value means - -- that this number of previously scanned digits are zero. If the end - -- of the number is reached, these zeroes are simply discarded, which - -- ensures that trailing zeroes after the point never affect the value - -- (which might otherwise happen as a result of rounding). With this - -- processing in place, we can ensure that, for example, we get the - -- same exact result from 1.0E+49 and 1.0000000E+49. This is not - -- necessarily required in a case like this where the result is not - -- a machine number, but it is certainly a desirable behavior. + Precision_Limit : constant Long_Long_Float := + 2.0 ** (Long_Long_Float'Machine_Mantissa - 1); + -- This is an upper bound for the number of bits used to represent the + -- mantissa. Beyond that number, any digits parsed by Scanf are useless. + -- Thus, only the scale should be updated. This ensures that infinity is + -- not reached by the temporary Uval, which could lead to erroneous + -- rounding (for example: 0.4444444... or 1E-n). procedure Scanf; -- Scans integer literal value starting at current character position. @@ -96,56 +93,50 @@ package body System.Val_Real is ----------- procedure Scanf is - Digit : Natural; - + Digit : Natural; + Uval_Tmp : Long_Long_Float; + Precision_Limit_Reached : Boolean := False; begin loop Digit := Character'Pos (Str (P)) - Character'Pos ('0'); - P := P + 1; - - -- Save up trailing zeroes after the decimal point - - if Digit = 0 and then After_Point = 1 then - Num_Saved_Zeroes := Num_Saved_Zeroes + 1; - - -- Here for a non-zero digit - - else - -- First deal with any previously saved zeroes - - if Num_Saved_Zeroes /= 0 then - while Num_Saved_Zeroes > Maxpow loop - Uval := Uval * Powten (Maxpow); - Num_Saved_Zeroes := Num_Saved_Zeroes - Maxpow; - Scale := Scale - Maxpow; - end loop; - Uval := Uval * Powten (Num_Saved_Zeroes); - Scale := Scale - Num_Saved_Zeroes; + if not Precision_Limit_Reached then + -- Compute potential new value + Uval_Tmp := Uval * 10.0 + Long_Long_Float (Digit); - Num_Saved_Zeroes := 0; + if Uval_Tmp > Precision_Limit then + Precision_Limit_Reached := True; end if; + end if; - -- Accumulate new digit - - Uval := Uval * 10.0 + Long_Long_Float (Digit); + if Precision_Limit_Reached then + -- If beyond the precision of the mantissa then just ignore the + -- digit, to avoid rounding issues. + if After_Point = 0 then + Scale := Scale + 1; + end if; + else + Uval := Uval_Tmp; Scale := Scale - After_Point; end if; - -- Done if end of input field + -- Check next character + P := P + 1; if P > Max then + -- Done if end of input field return; - -- Check next character - elsif Str (P) not in Digs then + -- If next character is not a digit, check if this is an + -- underscore. If this is not the case, then return. if Str (P) = '_' then Scan_Underscore (Str, P, Ptr, Max, False); else return; end if; end if; + end loop; end Scanf; @@ -198,7 +189,8 @@ package body System.Val_Real is Base_Char : constant Character := Str (P); Digit : Natural; Fdigit : Long_Long_Float; - + Uval_Tmp : Long_Long_Float; + Precision_Limit_Reached : Boolean := False; begin -- Set bad base if out of range, and use safe base of 16.0, -- to guard against division by zero in the loop below. @@ -243,22 +235,24 @@ package body System.Val_Real is Bad_Value (Str); end if; - -- Save up trailing zeroes after the decimal point + if not Precision_Limit_Reached then + -- Compute potential new value + Uval_Tmp := Uval * Base + Long_Long_Float (Digit); - if Digit = 0 and then After_Point = 1 then - Num_Saved_Zeroes := Num_Saved_Zeroes + 1; + if Uval_Tmp > Precision_Limit then + Precision_Limit_Reached := True; + end if; + end if; - -- Here for a non-zero digit + if Precision_Limit_Reached then + -- If beyond precision of the mantissa then just update + -- the scale and discard remaining digits. - else - -- First deal with any previously saved zeroes - - if Num_Saved_Zeroes /= 0 then - Uval := Uval * Base ** Num_Saved_Zeroes; - Scale := Scale - Num_Saved_Zeroes; - Num_Saved_Zeroes := 0; + if After_Point = 0 then + Scale := Scale + 1; end if; + else -- Now accumulate the new digit Fdigit := Long_Long_Float (Digit); @@ -267,7 +261,7 @@ package body System.Val_Real is Bad_Base := True; else Scale := Scale - After_Point; - Uval := Uval * Base + Fdigit; + Uval := Uval_Tmp; end if; end if; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6dbdc43..d49f018 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Nicolas Roche + + * gnat.dg/float_value1.adb: New testcase. + 2019-07-22 Eric Botcazou * gnat.dg/encode_string1.adb, gnat.dg/encode_string1_pkg.adb, diff --git a/gcc/testsuite/gnat.dg/float_value1.adb b/gcc/testsuite/gnat.dg/float_value1.adb new file mode 100644 index 0000000..8e36767 --- /dev/null +++ b/gcc/testsuite/gnat.dg/float_value1.adb @@ -0,0 +1,46 @@ +-- { dg-do run } + +with Ada.Strings.Fixed; use Ada.Strings.Fixed; + +procedure Float_Value1 is + Str1 : String := "0." & 50000 * "4"; + Str2 : String := "1." & 5000 * "4"; + Str3 : String := "16#0." & 500000 * "4" & "#"; + Str4 : String := "1" & (5000 * "0") & "E-5000"; + Str5 : String := "1" & "." & 50000 * "0" & "1"; + Str6 : String := 50000 * "0" & "." & 50000 * "2" & "1"; + Str7 : String := "1" & (5000 * "0") & "1" & "E-5000"; + Str8 : String := "16#1" & "." & 50000 * "0" & "1#"; + + procedure Test (Msg, Str, Expected : String) is + Number : Long_Long_Float; + begin + Number := Long_Long_Float'Value (Str); + if Number'Img /= Expected then + raise Program_Error; + end if; + end Test; + +begin + Test ("0.4444...[50000 times] ", Str1, " 4.44444444444444444E-01"); + Test ("1.4...[5000 times] ", Str2, " 1.44444444444444444E+00"); + Test ("16#0.[50000 '4']# ", Str3, " 2.66666666666666667E-01"); + Test ("1[5000 zeros]E-5000 ", Str4, " 1.00000000000000000E+00"); + Test ("1.[50000zeros]1 ", Str5, " 1.00000000000000000E+00"); + Test ("[50000zeros].[50000 '2']1", Str6, " 2.22222222222222222E-01"); + Test ("1[50000zeros]1.E-5000 ", Str7, " 1.00000000000000000E+01"); + Test ("16#1.[50000zeros]1# ", Str8, " 1.00000000000000000E+00"); + + -- Check that number of trailing zero after point does not change + -- the value + + for J in 1 .. 10000 loop + declare + Str : String := "0.1" & J * "0"; + begin + if Long_Long_Float'Value (Str) /= 0.1 then + raise Program_Error; + end if; + end; + end loop; +end Float_Value1; -- cgit v1.1 From fd90c808628cead705bb4521d9b8beea0edcf2bf Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:57:04 +0000 Subject: [Ada] Fix missing Constraint_Error for Enum_Val attribute This fixes an old issue involving the Enum_Val attribute: it does not always raise a Constraint_Error exception when the specified value is not valid for the enumeration type (instead a modulo computation is applied to the value). 2019-07-22 Eric Botcazou gcc/ada/ * exp_attr.adb (Expand_N_Attribute_Reference) : Set No_Truncation on the N_Unchecked_Type_Conversion built around the argument passed to the attribute. gcc/testsuite/ * gnat.dg/enum_val1.adb: New testcase. From-SVN: r273676 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/exp_attr.adb | 7 +++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/enum_val1.adb | 22 ++++++++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/enum_val1.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 276fdba..85a0a26 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Eric Botcazou + + * exp_attr.adb (Expand_N_Attribute_Reference) + : Set No_Truncation on the + N_Unchecked_Type_Conversion built around the argument passed to + the attribute. + 2019-07-22 Nicolas Roche * libgnat/s-valrea.adb (Scan_Real): Ignore non significative diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 90ca8ff..2748c51 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -3282,6 +3282,13 @@ package body Exp_Attr is Expr := Unchecked_Convert_To (Ptyp, First (Exprs)); + -- Ensure that the expression is not truncated since the "bad" bits + -- are desired. + + if Nkind (Expr) = N_Unchecked_Type_Conversion then + Set_No_Truncation (Expr); + end if; + Insert_Action (N, Make_Raise_Constraint_Error (Loc, Condition => diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d49f018..da0bf2a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Eric Botcazou + + * gnat.dg/enum_val1.adb: New testcase. + 2019-07-22 Nicolas Roche * gnat.dg/float_value1.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/enum_val1.adb b/gcc/testsuite/gnat.dg/enum_val1.adb new file mode 100644 index 0000000..4550c11 --- /dev/null +++ b/gcc/testsuite/gnat.dg/enum_val1.adb @@ -0,0 +1,22 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Enum_Val1 is + type Enum is (Two, Four); + for Enum use (2, 4); + + Count : Natural := 0; + +begin + for I in 10 .. 11 loop + begin + Put (Integer'Image (I) & ": "); + Put_Line (Enum'Image (Enum'Enum_Val (I))); + exception + when Constraint_Error => + Count := Count + 1; + end; + end loop; + if Count /= 2 then + raise Program_Error; + end if; +end; -- cgit v1.1 From e7f4682af254be73f91ddbb543bc0bc3fcd27659 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:57:09 +0000 Subject: [Ada] Internal error on iterator for limited private discriminated type This patch further extends the short-circuit, aka optimization, present in the Check_Constrained_Object procedure used for renaming declarations to all limited types, so as to prevent type mismatches downstream in more cases. 2019-07-22 Eric Botcazou gcc/ada/ * sem_ch8.adb (Check_Constrained_Object): Further extend the special optimization to all limited types. gcc/testsuite/ * gnat.dg/iter5.adb, gnat.dg/iter5_pkg.ads: New testcase. From-SVN: r273677 --- gcc/ada/ChangeLog | 5 ++ gcc/ada/sem_ch8.adb | 10 +-- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/iter5.adb | 10 +++ gcc/testsuite/gnat.dg/iter5_pkg.ads | 127 ++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/iter5.adb create mode 100644 gcc/testsuite/gnat.dg/iter5_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 85a0a26..0081c3e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-22 Eric Botcazou + * sem_ch8.adb (Check_Constrained_Object): Further extend the + special optimization to all limited types. + +2019-07-22 Eric Botcazou + * exp_attr.adb (Expand_N_Attribute_Reference) : Set No_Truncation on the N_Unchecked_Type_Conversion built around the argument passed to diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index c9d6151..9caddcc 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -809,18 +809,12 @@ package body Sem_Ch8 is -- in particular with record types with an access discriminant -- that are used in iterators. This is an optimization, but it -- also prevents typing anomalies when the prefix is further - -- expanded. This also applies to limited types with access - -- discriminants. + -- expanded. -- Note that we cannot just use the Is_Limited_Record flag because -- it does not apply to records with limited components, for which -- this syntactic flag is not set, but whose size is also fixed. - elsif (Is_Record_Type (Typ) and then Is_Limited_Type (Typ)) - or else - (Ekind (Typ) = E_Limited_Private_Type - and then Has_Discriminants (Typ) - and then Is_Access_Type (Etype (First_Discriminant (Typ)))) - then + elsif Is_Limited_Type (Typ) then null; else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index da0bf2a..94fc579 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-22 Eric Botcazou + * gnat.dg/iter5.adb, gnat.dg/iter5_pkg.ads: New testcase. + +2019-07-22 Eric Botcazou + * gnat.dg/enum_val1.adb: New testcase. 2019-07-22 Nicolas Roche diff --git a/gcc/testsuite/gnat.dg/iter5.adb b/gcc/testsuite/gnat.dg/iter5.adb new file mode 100644 index 0000000..b17b435 --- /dev/null +++ b/gcc/testsuite/gnat.dg/iter5.adb @@ -0,0 +1,10 @@ +-- { dg-do compile } + +with Iter5_Pkg; + +procedure Iter5 is +begin + for The_Filename of Iter5_Pkg.Iterator_For ("C:\Program_Files") loop + null; + end loop; +end Iter5; diff --git a/gcc/testsuite/gnat.dg/iter5_pkg.ads b/gcc/testsuite/gnat.dg/iter5_pkg.ads new file mode 100644 index 0000000..0449f3b --- /dev/null +++ b/gcc/testsuite/gnat.dg/iter5_pkg.ads @@ -0,0 +1,127 @@ +with Ada.Calendar; +with Ada.Directories; + +with Ada.Iterator_Interfaces; + +package Iter5_Pkg is + + subtype Size is Ada.Directories.File_Size; + + type Folder is new String; + + function Folder_Separator return Character; + + function "+" (Directory : String) return Folder; + + function "+" (Left, Right : String) return Folder; + + function "+" (Left : Folder; + Right : String) return Folder; + + function Composure (Directory : Folder; + Filename : String; + Extension : String) return String; + + function Composure (Directory : String; + Filename : String; + Extension : String) return String; + -- no exception + + function Base_Name_Of (Name : String) return String + renames Ada.Directories.Base_Name; + + function Extension_Of (Name : String) return String + renames Ada.Directories.Extension; + + function Containing_Directory_Of (Name : String) return String + renames Ada.Directories.Containing_Directory; + + function Exists (Name : String) return Boolean; + -- no exception + + function Size_Of (Name : String) return Size renames Ada.Directories.Size; + + function Directory_Exists (Name : String) return Boolean; + -- no exception + + function Modification_Time_Of (Name : String) return Ada.Calendar.Time + renames Ada.Directories.Modification_Time; + + function Is_Newer (The_Name : String; + Than_Name : String) return Boolean; + + procedure Delete (Name : String); + -- no exception if no existance + + procedure Create_Directory (Path : String); + -- creates the whole directory path + + procedure Delete_Directory (Name : String); -- including contents + -- no exception if no existance + + procedure Rename (Old_Name : String; + New_Name : String) renames Ada.Directories.Rename; + + procedure Copy (Source_Name : String; + Target_Name : String; + Form : String := "") + renames Ada.Directories.Copy_File; + + function Is_Leaf_Directory (Directory : String) return Boolean; + + procedure Iterate_Over_Leaf_Directories (From_Directory : String; + Iterator : access procedure + (Leaf_Directory : String)); + + function Found_Directory (Simple_Name : String; + In_Directory : String) return String; + + Not_Found : exception; + + Name_Error : exception renames Ada.Directories.Name_Error; + Use_Error : exception renames Ada.Directories.Use_Error; + + ------------------------ + -- File Iterator Loop -- + ------------------------ + -- Example: + -- for The_Filename of Iter5_Pkg.Iterator_For ("C:\Program_Files") loop + -- Log.Write (The_Filename); + -- end loop; + + type Item (Name_Length : Natural) is limited private; + + function Iterator_For (Name : String) return Item; + +private + type Cursor; + + function Has_More (Data : Cursor) return Boolean; + + package List_Iterator_Interfaces is + new Ada.Iterator_Interfaces (Cursor, Has_More); + + function Iterate (The_Item : Item) + return List_Iterator_Interfaces.Forward_Iterator'class; + + type Cursor_Data is record + Has_More : Boolean := False; + Position : Ada.Directories.Search_Type; + end record; + + type Cursor is access all Cursor_Data; + + function Constant_Reference (The_Item : aliased Item; + Unused_Index : Cursor) return String; + + type Item (Name_Length : Natural) is tagged limited record + Name : String(1..Name_Length); + Actual : Ada.Directories.Directory_Entry_Type; + Data : aliased Cursor_Data; + end record + with + Constant_Indexing => Constant_Reference, + Default_Iterator => Iterate, + Iterator_Element => String; + +end Iter5_Pkg; -- cgit v1.1 From 2418e23139edd33f1cab2158b46ac9bbd81b8bd7 Mon Sep 17 00:00:00 2001 From: Gary Dismukes Date: Mon, 22 Jul 2019 13:57:13 +0000 Subject: [Ada] Premature finalization of controlled temporaries in case expressions The compiler was generating finalization of temporary objects used in evaluating case expressions for controlled types in cases where the case statement created by Expand_N_Expression_With_Actions is rewritten as an if statement. This is fixed by inheriting the From_Condition_Expression flag from the rewritten case statement. The test below must generate the following output when executed: $ main Xs(1): 1 ---- package Test is type E is (E1, E2); procedure Test (A : in E); end Test; ---- with Ada.Text_IO; with Ada.Finalization; package body Test is type T is new Ada.Finalization.Controlled with record N : Natural := 0; end record; overriding procedure Finalize (X : in out T) is begin X.N := 42; end Finalize; type T_Array is array (Positive range <>) of T; function Make_T (N : Natural) return T is begin return (Ada.Finalization.Controlled with N => N); end Make_T; X1 : constant T := Make_T (1); X2 : constant T := Make_T (2); procedure Test (A : in E) is Xs : constant T_Array := (case A is when E1 => (1 => X1), when E2 => (1 => X2)); begin Ada.Text_IO.Put_Line ("Xs(1):" & Natural'Image (Xs (1).N)); end Test; end Test; ---- with Test; procedure Main is begin Test.Test (Test.E1); end Main; 2019-07-22 Gary Dismukes gcc/ada/ * exp_ch5.adb (Expand_N_Case_Statement): In the case where a case statement is rewritten as an equivalent if statement, inherit the From_Condition_Expression flag from the case statement. From-SVN: r273678 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/exp_ch5.adb | 23 ++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0081c3e..e9a4cbd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Gary Dismukes + + * exp_ch5.adb (Expand_N_Case_Statement): In the case where a + case statement is rewritten as an equivalent if statement, + inherit the From_Condition_Expression flag from the case + statement. + 2019-07-22 Eric Botcazou * sem_ch8.adb (Check_Constrained_Object): Further extend the diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 18e9708..682c855 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -2856,13 +2856,14 @@ package body Exp_Ch5 is ----------------------------- procedure Expand_N_Case_Statement (N : Node_Id) is - Loc : constant Source_Ptr := Sloc (N); - Expr : constant Node_Id := Expression (N); - Alt : Node_Id; - Len : Nat; - Cond : Node_Id; - Choice : Node_Id; - Chlist : List_Id; + Loc : constant Source_Ptr := Sloc (N); + Expr : constant Node_Id := Expression (N); + From_Cond_Expr : constant Boolean := From_Conditional_Expression (N); + Alt : Node_Id; + Len : Nat; + Cond : Node_Id; + Choice : Node_Id; + Chlist : List_Id; begin -- Check for the situation where we know at compile time which branch @@ -3073,7 +3074,15 @@ package body Exp_Ch5 is Condition => Cond, Then_Statements => Then_Stms, Else_Statements => Else_Stms)); + + -- The rewritten if statement needs to inherit whether the + -- case statement was expanded from a conditional expression, + -- for proper handling of nested controlled objects. + + Set_From_Conditional_Expression (N, From_Cond_Expr); + Analyze (N); + return; end if; end if; -- cgit v1.1 From 2c26d262eb40998040308a57d420849fd764ef53 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:57:18 +0000 Subject: [Ada] Further fix non-stored discriminant in aggregate for GNATprove GNATprove expects discriminants appearing in aggregates and their types to be resolved to stored discriminants. This extends the machinery that makes sure this is the case for default initialization expressions so as to also handle component associations in these expressions. 2019-07-22 Eric Botcazou gcc/ada/ * sem_aggr.adb (Rewrite_Bound): Be prepared for discriminals too. (Rewrite_Range;): Minor tweak. (Resolve_Record_Aggregate): For a component with default initialization whose expression is an array aggregate, also rewrite the bounds of the component associations, if any. From-SVN: r273679 --- gcc/ada/ChangeLog | 9 +++++++++ gcc/ada/sem_aggr.adb | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 11 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e9a4cbd..202dfc7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2019-07-22 Eric Botcazou + + * sem_aggr.adb (Rewrite_Bound): Be prepared for discriminals + too. + (Rewrite_Range;): Minor tweak. + (Resolve_Record_Aggregate): For a component with default + initialization whose expression is an array aggregate, also + rewrite the bounds of the component associations, if any. + 2019-07-22 Gary Dismukes * exp_ch5.adb (Expand_N_Case_Statement): In the case where a diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index 2143cc4..7aacc5f 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -4264,8 +4264,15 @@ package body Sem_Aggr is Expr_Disc : Node_Id) is begin - if Nkind (Bound) = N_Identifier - and then Entity (Bound) = Disc + if Nkind (Bound) /= N_Identifier then + return; + end if; + + -- We expect either the discriminant or the discriminal + + if Entity (Bound) = Disc + or else (Ekind (Entity (Bound)) = E_In_Parameter + and then Discriminal_Link (Entity (Bound)) = Disc) then Rewrite (Bound, New_Copy_Tree (Expr_Disc)); end if; @@ -4280,9 +4287,7 @@ package body Sem_Aggr is -- Start of processing for Rewrite_Range begin - if Has_Discriminants (Root_Type) - and then Nkind (Rge) = N_Range - then + if Has_Discriminants (Root_Type) and then Nkind (Rge) = N_Range then Low := Low_Bound (Rge); High := High_Bound (Rge); @@ -4903,7 +4908,9 @@ package body Sem_Aggr is -- Root record type whose discriminants may be used as -- bounds in range nodes. - Index : Node_Id; + Assoc : Node_Id; + Choice : Node_Id; + Index : Node_Id; begin -- Rewrite the range nodes occurring in the indexes @@ -4919,12 +4926,26 @@ package body Sem_Aggr is end loop; -- Rewrite the range nodes occurring as aggregate - -- bounds. + -- bounds and component associations. - if Nkind (Expr) = N_Aggregate - and then Present (Aggregate_Bounds (Expr)) - then - Rewrite_Range (Rec_Typ, Aggregate_Bounds (Expr)); + if Nkind (Expr) = N_Aggregate then + if Present (Aggregate_Bounds (Expr)) then + Rewrite_Range (Rec_Typ, Aggregate_Bounds (Expr)); + end if; + + if Present (Component_Associations (Expr)) then + Assoc := First (Component_Associations (Expr)); + while Present (Assoc) loop + Choice := First (Choices (Assoc)); + while Present (Choice) loop + Rewrite_Range (Rec_Typ, Choice); + + Next (Choice); + end loop; + + Next (Assoc); + end loop; + end if; end if; end; end if; -- cgit v1.1 From a517030d8b76ae338c7e33253fcd0177979dde2b Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 22 Jul 2019 13:57:22 +0000 Subject: [Ada] Type inconsistency in floating_point type declarations This patch fixes an inconsistency in the typing of the bounds of a floting point type declaration, when some bound is given by a dtatic constant of an explicit type, instead of a real literal, Previous to this patch the bound of the type retained the given type, leading to spurious errors in Codepeer. 2019-07-22 Ed Schonberg gcc/ada/ * sem_ch3.adb (Convert_Bound): Subsidiary of Floating_Point_Type_Declaration, to handle properly range specifications with bounds that may include static constants of a given type rather than real literals. From-SVN: r273680 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch3.adb | 48 +++++++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 19 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 202dfc7..2d0beb3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Ed Schonberg + + * sem_ch3.adb (Convert_Bound): Subsidiary of + Floating_Point_Type_Declaration, to handle properly range + specifications with bounds that may include static constants of + a given type rather than real literals. + 2019-07-22 Eric Botcazou * sem_aggr.adb (Rewrite_Bound): Be prepared for discriminals diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index ae0a7bf..5bee503 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -17827,12 +17827,16 @@ package body Sem_Ch3 is Digs_Val : Uint; Base_Typ : Entity_Id; Implicit_Base : Entity_Id; - Bound : Node_Id; function Can_Derive_From (E : Entity_Id) return Boolean; -- Find if given digits value, and possibly a specified range, allows -- derivation from specified type + procedure Convert_Bound (B : Node_Id); + -- If specified, the bounds must be static but may be of different + -- types. They must be converted into machine numbers of the base type, + -- in accordance with RM 4.9(38). + function Find_Base_Type return Entity_Id; -- Find a predefined base type that Def can derive from, or generate -- an error and substitute Long_Long_Float if none exists. @@ -17870,6 +17874,28 @@ package body Sem_Ch3 is return True; end Can_Derive_From; + ------------------- + -- Convert_Bound -- + -------------------- + + procedure Convert_Bound (B : Node_Id) is + begin + -- If the bound is not a literal it can only be static if it is + -- a static constant, possibly of a specified type. + + if Is_Entity_Name (B) + and then Ekind (Entity (B)) = E_Constant + then + Rewrite (B, Constant_Value (Entity (B))); + end if; + + if Nkind (B) = N_Real_Literal then + Set_Realval (B, Machine (Base_Typ, Realval (B), Round, B)); + Set_Is_Machine_Number (B); + Set_Etype (B, Base_Typ); + end if; + end Convert_Bound; + -------------------- -- Find_Base_Type -- -------------------- @@ -17967,24 +17993,8 @@ package body Sem_Ch3 is Set_Scalar_Range (T, Real_Range_Specification (Def)); Set_Is_Constrained (T); - -- The bounds of this range must be converted to machine numbers - -- in accordance with RM 4.9(38). - - Bound := Type_Low_Bound (T); - - if Nkind (Bound) = N_Real_Literal then - Set_Realval - (Bound, Machine (Base_Typ, Realval (Bound), Round, Bound)); - Set_Is_Machine_Number (Bound); - end if; - - Bound := Type_High_Bound (T); - - if Nkind (Bound) = N_Real_Literal then - Set_Realval - (Bound, Machine (Base_Typ, Realval (Bound), Round, Bound)); - Set_Is_Machine_Number (Bound); - end if; + Convert_Bound (Type_Low_Bound (T)); + Convert_Bound (Type_High_Bound (T)); else Set_Scalar_Range (T, Scalar_Range (Base_Typ)); -- cgit v1.1 From 78e92e11d4a96e0cd2ee9d9b1af9382133cd11b5 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:57:26 +0000 Subject: [Ada] Spurious error on private subtype of derived access type This patch fixes a spurious type error on a dynamic predicate on a subtype of a private type whose full view is a derived access type. Prior to it, the base type of the subtype would appear to be the parent type of the derived type instead of the derived type itself, leading to problems downstream. The following package must now compile quietly: with S; package T is type B_Pointer is private; Null_B_Pointer : constant B_Pointer; function OK (B : B_Pointer) return Boolean is (B /= Null_B_Pointer); subtype Valid_B_Pointer is B_Pointer with Dynamic_Predicate => OK (Valid_B_Pointer); private type B_Pointer is new S.A_Pointer; Null_B_Pointer : constant B_Pointer := B_Pointer (S.Null_A_Pointer); end; package S is type A_Type is new Integer; type A_Pointer is access A_Type; Null_A_Pointer : constant A_Pointer := null; end; Moreover, it also plugs a loophole in the compiler whereby an instantiation of a generic with a formal subprogram declaration nested in an enclosing generic package would be done even if there was a mismatch between an original and a derived types involved in the instantiation. The compiler must now gives the following error: p.adb:11:43: no visible subprogram matches the specification for "Action" on with Q; with R; with G; procedure P is package My_G is new G (Q.T); procedure Proc (Value : R.T) is null; procedure Iter is new My_G.Iteration_G (Proc); begin null; end; with R; package Q is type T is new R.T; end Q; package R is type T is private; private type T is access Integer; end R; generic type Value_T is private; package G is generic with procedure Action (Value : Value_T); procedure Iteration_G; end G; package body G is procedure Iteration_G is null; end G; 2019-07-22 Eric Botcazou gcc/ada/ * sem_ch3.adb (Complete_Private_Subtype): Rework the setting of the Etype of the full view for full base types that cannot contain any discriminant. Remove code and comment about it in the main path. From-SVN: r273681 --- gcc/ada/ChangeLog | 7 ++++ gcc/ada/sem_ch3.adb | 118 +++++++++++++++++++++++++++------------------------- 2 files changed, 68 insertions(+), 57 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2d0beb3..f715f71 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Eric Botcazou + + * sem_ch3.adb (Complete_Private_Subtype): Rework the setting of + the Etype of the full view for full base types that cannot + contain any discriminant. Remove code and comment about it in + the main path. + 2019-07-22 Ed Schonberg * sem_ch3.adb (Convert_Bound): Subsidiary of diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 5bee503..a6df5e4 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -12351,48 +12351,73 @@ package body Sem_Ch3 is -- Next_Entity field of full to ensure that the calls to Copy_Node do -- not corrupt the entity chain. - -- Note that the type of the full view is the same entity as the type - -- of the partial view. In this fashion, the subtype has access to the - -- correct view of the parent. - -- The list below included access types, but this leads to several - -- regressions. How should the base type of the full view be - -- set consistently for subtypes completed by access types? - Save_Next_Entity := Next_Entity (Full); Save_Homonym := Homonym (Priv); - case Ekind (Full_Base) is - when Class_Wide_Kind - | Private_Kind - | Protected_Kind - | Task_Kind - | E_Record_Subtype - | E_Record_Type - => - Copy_Node (Priv, Full); + if Ekind (Full_Base) in Private_Kind + or else Ekind (Full_Base) in Protected_Kind + or else Ekind (Full_Base) in Record_Kind + or else Ekind (Full_Base) in Task_Kind + then + Copy_Node (Priv, Full); - Set_Has_Discriminants - (Full, Has_Discriminants (Full_Base)); - Set_Has_Unknown_Discriminants - (Full, Has_Unknown_Discriminants (Full_Base)); - Set_First_Entity (Full, First_Entity (Full_Base)); - Set_Last_Entity (Full, Last_Entity (Full_Base)); + -- Note that the Etype of the full view is the same as the Etype of + -- the partial view. In this fashion, the subtype has access to the + -- correct view of the parent. - -- If the underlying base type is constrained, we know that the - -- full view of the subtype is constrained as well (the converse - -- is not necessarily true). + Set_Has_Discriminants (Full, Has_Discriminants (Full_Base)); + Set_Has_Unknown_Discriminants + (Full, Has_Unknown_Discriminants (Full_Base)); + Set_First_Entity (Full, First_Entity (Full_Base)); + Set_Last_Entity (Full, Last_Entity (Full_Base)); - if Is_Constrained (Full_Base) then - Set_Is_Constrained (Full); - end if; + -- If the underlying base type is constrained, we know that the + -- full view of the subtype is constrained as well (the converse + -- is not necessarily true). - when others => - Copy_Node (Full_Base, Full); + if Is_Constrained (Full_Base) then + Set_Is_Constrained (Full); + end if; - Set_Chars (Full, Chars (Priv)); - Conditional_Delay (Full, Priv); - Set_Sloc (Full, Sloc (Priv)); - end case; + else + Copy_Node (Full_Base, Full); + + -- The following subtlety with the Etype of the full view needs to be + -- taken into account here. One could think that it must naturally be + -- set to the base type of the full base: + + -- Set_Etype (Full, Base_Type (Full_Base)); + + -- so that the full view becomes a subtype of the full base when the + -- latter is a base type, which must for example happen when the full + -- base is declared as derived type. That's also correct if the full + -- base is declared as an array type, or a floating-point type, or a + -- fixed-point type, or a signed integer type, as these declarations + -- create an implicit base type and a first subtype so the Etype of + -- the full views must be the implicit base type. But that's wrong + -- if the full base is declared as an access type, or an enumeration + -- type, or a modular integer type, as these declarations directly + -- create a base type, i.e. with Etype pointing to itself. Moreover + -- the full base being declared in the private part, i.e. when the + -- views are swapped, the end result is that the Etype of the full + -- base is set to its private view in this case and that we need to + -- propagate this setting to the full view in order for the subtype + -- to be compatible with the base type. + + if Is_Base_Type (Full_Base) + and then (Is_Derived_Type (Full_Base) + or else Ekind (Full_Base) in Array_Kind + or else Ekind (Full_Base) in Fixed_Point_Kind + or else Ekind (Full_Base) in Float_Kind + or else Ekind (Full_Base) in Signed_Integer_Kind) + then + Set_Etype (Full, Full_Base); + end if; + + Set_Chars (Full, Chars (Priv)); + Set_Sloc (Full, Sloc (Priv)); + Conditional_Delay (Full, Priv); + end if; Link_Entities (Full, Save_Next_Entity); Set_Homonym (Full, Save_Homonym); @@ -12400,35 +12425,14 @@ package body Sem_Ch3 is -- Set common attributes for all subtypes: kind, convention, etc. - Set_Ekind (Full, Subtype_Kind (Ekind (Full_Base))); - Set_Convention (Full, Convention (Full_Base)); - - -- The Etype of the full view is inconsistent. Gigi needs to see the - -- structural full view, which is what the current scheme gives: the - -- Etype of the full view is the etype of the full base. However, if the - -- full base is a derived type, the full view then looks like a subtype - -- of the parent, not a subtype of the full base. If instead we write: - - -- Set_Etype (Full, Full_Base); - - -- then we get inconsistencies in the front-end (confusion between - -- views). Several outstanding bugs are related to this ??? - + Set_Ekind (Full, Subtype_Kind (Ekind (Full_Base))); + Set_Convention (Full, Convention (Full_Base)); Set_Is_First_Subtype (Full, False); Set_Scope (Full, Scope (Priv)); Set_Size_Info (Full, Full_Base); Set_RM_Size (Full, RM_Size (Full_Base)); Set_Is_Itype (Full); - -- For the unusual case of a type with unknown discriminants whose - -- completion is an array, use the proper full base. - - if Is_Array_Type (Full_Base) - and then Has_Unknown_Discriminants (Priv) - then - Set_Etype (Full, Full_Base); - end if; - -- A subtype of a private-type-without-discriminants, whose full-view -- has discriminants with default expressions, is not constrained. -- cgit v1.1 From ff9d220ede29dc7d0d40933733180f12cba54f17 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:57:31 +0000 Subject: [Ada] Remove obsolete Is_For_Access_Subtype machinery This change removes the Is_For_Access_Subtype machinery from the compiler. This machinery was devised a long time ago to deal with a peculiarity of the freezing for access-to-record subtypes but has been degenerate for quite some time now and does not seem to serve any useful purpose at this point. Morever it has an annoying side effect whereby it causes Underlying_Type to return the (unconstrained) base record type when invoked on the designated record subtype, which is very problematic for GNATprove. There should be no functional changes. 2019-07-22 Eric Botcazou gcc/ada/ * einfo.ads (Is_For_Access_Subtype): Delete. (Set_Is_For_Access_Subtype): Likewise. * einfo.adb (Is_For_Access_Subtype): Likewise. (Set_Is_For_Access_Subtype): Likewise. (Write_Entity_Flags): Do not write Is_For_Access_Subtype. * exp_ch4.adb (Expand_N_Selected_Component): Do not deal with it. * exp_spark.adb (Expand_SPARK_N_Selected_Component): Likewise. * sem_ch4.adb (Analyze_Explicit_Dereference): Likewise. * sem_ch3.adb (Build_Discriminated_Subtype): Do not build a special private subtype for access-to-record subtypes. From-SVN: r273682 --- gcc/ada/ChangeLog | 14 ++++++++++++++ gcc/ada/einfo.adb | 14 -------------- gcc/ada/einfo.ads | 11 ----------- gcc/ada/exp_ch4.adb | 6 ------ gcc/ada/exp_spark.adb | 6 ------ gcc/ada/sem_ch3.adb | 13 +++---------- gcc/ada/sem_ch4.adb | 13 ++----------- 7 files changed, 19 insertions(+), 58 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f715f71..ace56e3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,19 @@ 2019-07-22 Eric Botcazou + * einfo.ads (Is_For_Access_Subtype): Delete. + (Set_Is_For_Access_Subtype): Likewise. + * einfo.adb (Is_For_Access_Subtype): Likewise. + (Set_Is_For_Access_Subtype): Likewise. + (Write_Entity_Flags): Do not write Is_For_Access_Subtype. + * exp_ch4.adb (Expand_N_Selected_Component): Do not deal with + it. + * exp_spark.adb (Expand_SPARK_N_Selected_Component): Likewise. + * sem_ch4.adb (Analyze_Explicit_Dereference): Likewise. + * sem_ch3.adb (Build_Discriminated_Subtype): Do not build a + special private subtype for access-to-record subtypes. + +2019-07-22 Eric Botcazou + * sem_ch3.adb (Complete_Private_Subtype): Rework the setting of the Etype of the full view for full base types that cannot contain any discriminant. Remove code and comment about it in diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb index 5fba0fa..8ff9ec6 100644 --- a/gcc/ada/einfo.adb +++ b/gcc/ada/einfo.adb @@ -421,7 +421,6 @@ package body Einfo is -- Never_Set_In_Source Flag115 -- Is_Visible_Lib_Unit Flag116 -- Is_Unchecked_Union Flag117 - -- Is_For_Access_Subtype Flag118 -- Has_Convention_Pragma Flag119 -- Has_Primitive_Operations Flag120 @@ -2303,12 +2302,6 @@ package body Einfo is return Flag70 (Id); end Is_First_Subtype; - function Is_For_Access_Subtype (Id : E) return B is - begin - pragma Assert (Ekind_In (Id, E_Record_Subtype, E_Private_Subtype)); - return Flag118 (Id); - end Is_For_Access_Subtype; - function Is_Formal_Subprogram (Id : E) return B is begin return Flag111 (Id); @@ -5526,12 +5519,6 @@ package body Einfo is Set_Flag70 (Id, V); end Set_Is_First_Subtype; - procedure Set_Is_For_Access_Subtype (Id : E; V : B := True) is - begin - pragma Assert (Ekind_In (Id, E_Record_Subtype, E_Private_Subtype)); - Set_Flag118 (Id, V); - end Set_Is_For_Access_Subtype; - procedure Set_Is_Formal_Subprogram (Id : E; V : B := True) is begin Set_Flag111 (Id, V); @@ -9826,7 +9813,6 @@ package body Einfo is W ("Is_Exported", Flag99 (Id)); W ("Is_Finalized_Transient", Flag252 (Id)); W ("Is_First_Subtype", Flag70 (Id)); - W ("Is_For_Access_Subtype", Flag118 (Id)); W ("Is_Formal_Subprogram", Flag111 (Id)); W ("Is_Frozen", Flag4 (Id)); W ("Is_Generic_Actual_Subprogram", Flag274 (Id)); diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index f69a94a..78208a1 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -2608,12 +2608,6 @@ package Einfo is -- Is_Formal_Subprogram (Flag111) -- Defined in all entities. Set for generic formal subprograms. --- Is_For_Access_Subtype (Flag118) --- Defined in E_Private_Subtype and E_Record_Subtype entities. Means the --- sole purpose of the type is to be designated by an Access_Subtype and --- hence should not be expanded into components because the type may not --- have been found or frozen yet. - -- Is_Frozen (Flag4) -- Defined in all type and subtype entities. Set if type or subtype has -- been frozen. @@ -6458,7 +6452,6 @@ package Einfo is -- Stored_Constraint (Elist23) -- Has_Completion (Flag26) -- Is_Controlled_Active (Flag42) (base type only) - -- Is_For_Access_Subtype (Flag118) (subtype only) -- (plus type attributes) -- E_Procedure @@ -7311,7 +7304,6 @@ package Einfo is function Is_Exported (Id : E) return B; function Is_Finalized_Transient (Id : E) return B; function Is_First_Subtype (Id : E) return B; - function Is_For_Access_Subtype (Id : E) return B; function Is_Frozen (Id : E) return B; function Is_Generic_Instance (Id : E) return B; function Is_Hidden (Id : E) return B; @@ -8012,7 +8004,6 @@ package Einfo is procedure Set_Is_Exported (Id : E; V : B := True); procedure Set_Is_Finalized_Transient (Id : E; V : B := True); procedure Set_Is_First_Subtype (Id : E; V : B := True); - procedure Set_Is_For_Access_Subtype (Id : E; V : B := True); procedure Set_Is_Formal_Subprogram (Id : E; V : B := True); procedure Set_Is_Frozen (Id : E; V : B := True); procedure Set_Is_Generic_Actual_Subprogram (Id : E; V : B := True); @@ -8859,7 +8850,6 @@ package Einfo is pragma Inline (Is_First_Subtype); pragma Inline (Is_Fixed_Point_Type); pragma Inline (Is_Floating_Point_Type); - pragma Inline (Is_For_Access_Subtype); pragma Inline (Is_Formal); pragma Inline (Is_Formal_Object); pragma Inline (Is_Formal_Subprogram); @@ -9376,7 +9366,6 @@ package Einfo is pragma Inline (Set_Is_Exported); pragma Inline (Set_Is_Finalized_Transient); pragma Inline (Set_Is_First_Subtype); - pragma Inline (Set_Is_For_Access_Subtype); pragma Inline (Set_Is_Formal_Subprogram); pragma Inline (Set_Is_Frozen); pragma Inline (Set_Is_Generic_Actual_Subprogram); diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7a1e0b8..7ea96de 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -10330,12 +10330,6 @@ package body Exp_Ch4 is Insert_Explicit_Dereference (P); Analyze_And_Resolve (P, Designated_Type (Ptyp)); - if Ekind (Etype (P)) = E_Private_Subtype - and then Is_For_Access_Subtype (Etype (P)) - then - Set_Etype (P, Base_Type (Etype (P))); - end if; - Ptyp := Etype (P); end if; diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb index 58f9243..63f2dad 100644 --- a/gcc/ada/exp_spark.adb +++ b/gcc/ada/exp_spark.adb @@ -522,12 +522,6 @@ package body Exp_SPARK is Insert_Explicit_Dereference (Pref); Analyze_And_Resolve (Pref, Designated_Type (Typ)); - - if Ekind (Etype (Pref)) = E_Private_Subtype - and then Is_For_Access_Subtype (Etype (Pref)) - then - Set_Etype (Pref, Base_Type (Etype (Pref))); - end if; end if; end Expand_SPARK_N_Selected_Component; diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index a6df5e4..d8cd348 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -221,9 +221,7 @@ package body Sem_Ch3 is -- T has discriminants but there are no discriminant constraints). The -- Related_Nod is the same as Decl_Node in Create_Constrained_Components. -- The For_Access says whether or not this subtype is really constraining - -- an access type. That is its sole purpose is the designated type of an - -- access type -- in which case a Private_Subtype Is_For_Access_Subtype - -- is built to avoid freezing T when the access subtype is frozen. + -- an access type. function Build_Scalar_Bound (Bound : Node_Id; @@ -10236,12 +10234,7 @@ package body Sem_Ch3 is begin if Ekind (T) = E_Record_Type then - if For_Access then - Set_Ekind (Def_Id, E_Private_Subtype); - Set_Is_For_Access_Subtype (Def_Id, True); - else - Set_Ekind (Def_Id, E_Record_Subtype); - end if; + Set_Ekind (Def_Id, E_Record_Subtype); -- Inherit preelaboration flag from base, for types for which it -- may have been set: records, private types, protected types. @@ -10372,7 +10365,7 @@ package body Sem_Ch3 is then Create_Constrained_Components (Def_Id, Related_Nod, T, Elist); - elsif not For_Access then + else Set_Cloned_Subtype (Def_Id, T); end if; end if; diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 2b0a8ed..f7b99d4 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -2101,21 +2101,12 @@ package body Sem_Ch4 is if not Is_Overloaded (P) then if Is_Access_Type (Etype (P)) then - -- Set the Etype. We need to go through Is_For_Access_Subtypes to - -- avoid other problems caused by the Private_Subtype and it is - -- safe to go to the Base_Type because this is the same as - -- converting the access value to its Base_Type. + -- Set the Etype declare - DT : Entity_Id := Designated_Type (Etype (P)); + DT : constant Entity_Id := Designated_Type (Etype (P)); begin - if Ekind (DT) = E_Private_Subtype - and then Is_For_Access_Subtype (DT) - then - DT := Base_Type (DT); - end if; - -- An explicit dereference is a legal occurrence of an -- incomplete type imported through a limited_with clause, if -- the full view is visible, or if we are within an instance -- cgit v1.1 From 116992570783944a12e64e63db9f5a2445e10016 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:57:37 +0000 Subject: [Ada] Fix spurious visibility error for tagged type with inlining This fixes a spurious visibility error for the very peculiar case where an operator that operates on the class-wide type of a tagged type is declared in a package, the operator is renamed in another package where a subtype of the tagged type is declared, and both packages end up in the transititive closure of a unit compiled with optimization and inter-inlining (-gnatn). 2019-07-22 Eric Botcazou gcc/ada/ * sem_ch8.adb (End_Use_Type): Reset the In_Use flag on the class-wide type if the type is tagged. (Use_One_Type): Add commentary on the handling of the class-wide type. gcc/testsuite/ * gnat.dg/inline17.adb, gnat.dg/inline17_pkg1.adb, gnat.dg/inline17_pkg1.ads, gnat.dg/inline17_pkg2.ads, gnat.dg/inline17_pkg3.adb, gnat.dg/inline17_pkg3.ads: New testcase. From-SVN: r273683 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch8.adb | 12 +++++++++++- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/gnat.dg/inline17.adb | 10 ++++++++++ gcc/testsuite/gnat.dg/inline17_pkg1.adb | 15 +++++++++++++++ gcc/testsuite/gnat.dg/inline17_pkg1.ads | 7 +++++++ gcc/testsuite/gnat.dg/inline17_pkg2.ads | 10 ++++++++++ gcc/testsuite/gnat.dg/inline17_pkg3.adb | 14 ++++++++++++++ gcc/testsuite/gnat.dg/inline17_pkg3.ads | 16 ++++++++++++++++ 9 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gnat.dg/inline17.adb create mode 100644 gcc/testsuite/gnat.dg/inline17_pkg1.adb create mode 100644 gcc/testsuite/gnat.dg/inline17_pkg1.ads create mode 100644 gcc/testsuite/gnat.dg/inline17_pkg2.ads create mode 100644 gcc/testsuite/gnat.dg/inline17_pkg3.adb create mode 100644 gcc/testsuite/gnat.dg/inline17_pkg3.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ace56e3..06e6421 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,12 @@ 2019-07-22 Eric Botcazou + * sem_ch8.adb (End_Use_Type): Reset the In_Use flag on the + class-wide type if the type is tagged. + (Use_One_Type): Add commentary on the handling of the class-wide + type. + +2019-07-22 Eric Botcazou + * einfo.ads (Is_For_Access_Subtype): Delete. (Set_Is_For_Access_Subtype): Likewise. * einfo.adb (Is_For_Access_Subtype): Likewise. diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 9caddcc..7185c40 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -4836,6 +4836,13 @@ package body Sem_Ch8 is Set_In_Use (Base_Type (T), False); Set_Current_Use_Clause (T, Empty); Set_Current_Use_Clause (Base_Type (T), Empty); + + -- See Use_One_Type for the rationale. This is a bit on the naive + -- side, but should be good enough in practice. + + if Is_Tagged_Type (T) then + Set_In_Use (Class_Wide_Type (T), False); + end if; end if; end if; @@ -9985,7 +9992,10 @@ package body Sem_Ch8 is Set_In_Use (T); -- If T is tagged, primitive operators on class-wide operands are - -- also available. + -- also deemed available. Note that this is really necessary only + -- in semantics-only mode, because the primitive operators are not + -- fully constructed in this mode, but we do it in all modes for the + -- sake of uniformity, as this should not matter in practice. if Is_Tagged_Type (T) then Set_In_Use (Class_Wide_Type (T)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 94fc579..0f8b798 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2019-07-22 Eric Botcazou + * gnat.dg/inline17.adb, gnat.dg/inline17_pkg1.adb, + gnat.dg/inline17_pkg1.ads, gnat.dg/inline17_pkg2.ads, + gnat.dg/inline17_pkg3.adb, gnat.dg/inline17_pkg3.ads: New + testcase. + +2019-07-22 Eric Botcazou + * gnat.dg/iter5.adb, gnat.dg/iter5_pkg.ads: New testcase. 2019-07-22 Eric Botcazou diff --git a/gcc/testsuite/gnat.dg/inline17.adb b/gcc/testsuite/gnat.dg/inline17.adb new file mode 100644 index 0000000..bb6e5c2 --- /dev/null +++ b/gcc/testsuite/gnat.dg/inline17.adb @@ -0,0 +1,10 @@ +-- { dg-do compile } +-- { dg-options "-O -gnatn" } +with Inline17_Pkg1; use Inline17_Pkg1; +with Inline17_Pkg2; use Inline17_Pkg2; + +procedure Inline17 is + use type SQL_Field; +begin + Test; +end; diff --git a/gcc/testsuite/gnat.dg/inline17_pkg1.adb b/gcc/testsuite/gnat.dg/inline17_pkg1.adb new file mode 100644 index 0000000..80febe8 --- /dev/null +++ b/gcc/testsuite/gnat.dg/inline17_pkg1.adb @@ -0,0 +1,15 @@ +with Inline17_Pkg2; use Inline17_Pkg2; + +package body Inline17_Pkg1 is + + procedure Test is + begin + null; + end; + + function Get (Field : SQL_Field) return Integer is + begin + return +Field; + end; + +end Inline17_Pkg1; diff --git a/gcc/testsuite/gnat.dg/inline17_pkg1.ads b/gcc/testsuite/gnat.dg/inline17_pkg1.ads new file mode 100644 index 0000000..78f26b1 --- /dev/null +++ b/gcc/testsuite/gnat.dg/inline17_pkg1.ads @@ -0,0 +1,7 @@ + +package Inline17_Pkg1 is + + procedure Test; + pragma Inline (Test); + +end Inline17_Pkg1; diff --git a/gcc/testsuite/gnat.dg/inline17_pkg2.ads b/gcc/testsuite/gnat.dg/inline17_pkg2.ads new file mode 100644 index 0000000..bf89d55 --- /dev/null +++ b/gcc/testsuite/gnat.dg/inline17_pkg2.ads @@ -0,0 +1,10 @@ +with Inline17_Pkg3; use Inline17_Pkg3; + +package Inline17_Pkg2 is + + subtype SQL_Field is Inline17_Pkg3.SQL_Field; + + function "+" (Field : SQL_Field'Class) return Integer renames + Inline17_Pkg3."+"; + +end Inline17_Pkg2; diff --git a/gcc/testsuite/gnat.dg/inline17_pkg3.adb b/gcc/testsuite/gnat.dg/inline17_pkg3.adb new file mode 100644 index 0000000..411a509 --- /dev/null +++ b/gcc/testsuite/gnat.dg/inline17_pkg3.adb @@ -0,0 +1,14 @@ + +package body Inline17_Pkg3 is + + function "+" (Field : SQL_Field'Class) return Integer is + begin + return 0; + end; + + function Unchecked_Get (Self : Ref) return Integer is + begin + return Self.Data; + end; + +end Inline17_Pkg3; diff --git a/gcc/testsuite/gnat.dg/inline17_pkg3.ads b/gcc/testsuite/gnat.dg/inline17_pkg3.ads new file mode 100644 index 0000000..6f0c5a8 --- /dev/null +++ b/gcc/testsuite/gnat.dg/inline17_pkg3.ads @@ -0,0 +1,16 @@ + +package Inline17_Pkg3 is + + type SQL_Field is tagged null record; + + function "+" (Field : SQL_Field'Class) return Integer; + + type Ref is record + Data : Integer; + end record; + + function Unchecked_Get (Self : Ref) return Integer with Inline_Always; + + function Get (Self : Ref) return Integer is (Unchecked_Get (Self)); + +end Inline17_Pkg3; -- cgit v1.1 From 5dcbefb1c407fcb949597c4257726bfbc8760cfb Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Mon, 22 Jul 2019 13:57:42 +0000 Subject: [Ada] Issue warning or error message on ignored typing constraint GNAT ignores the discriminant constraint on a component when it applies to the type of the record being analyzed. Now issue a warning on Ada code when ignoring this constraint, or an error on SPARK code. 2019-07-22 Yannick Moy gcc/ada/ * sem_ch3.adb (Constrain_Access): Issue a message about ignored constraint. gcc/testsuite/ * gnat.dg/warn24.adb: New testcase. From-SVN: r273684 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sem_ch3.adb | 4 ++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/warn24.adb | 15 +++++++++++++++ 4 files changed, 28 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/warn24.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 06e6421..f47d247 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Yannick Moy + + * sem_ch3.adb (Constrain_Access): Issue a message about ignored + constraint. + 2019-07-22 Eric Botcazou * sem_ch8.adb (End_Use_Type): Reset the In_Use flag on the diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index d8cd348..645a024 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -12970,6 +12970,10 @@ package body Sem_Ch3 is if Desig_Type = Current_Scope and then No (Def_Id) then + Error_Msg_Warn := SPARK_Mode /= On; + Error_Msg_N ("< + + * gnat.dg/warn24.adb: New testcase. + 2019-07-22 Eric Botcazou * gnat.dg/inline17.adb, gnat.dg/inline17_pkg1.adb, diff --git a/gcc/testsuite/gnat.dg/warn24.adb b/gcc/testsuite/gnat.dg/warn24.adb new file mode 100644 index 0000000..e7c9f8a --- /dev/null +++ b/gcc/testsuite/gnat.dg/warn24.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } + +procedure Warn24 is + type List_D (D : Boolean); + + type List_Acc is access List_D; + + type List_D (D : Boolean) is record + Next : List_Acc (D); -- { dg-warning "constraint is ignored on component that is access to current record" } + end record; + + X : List_D (True); +begin + X.Next := new List_D (False); +end Warn24; -- cgit v1.1 From 22862ba6d688c95d9f9577746d212183a11c44da Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Mon, 22 Jul 2019 13:57:46 +0000 Subject: [Ada] Usage of signed type in array bounds in CCG 2019-07-22 Javier Miranda gcc/ada/ * exp_ch4.adb (Size_In_Storage_Elements): Improve the expansion to handle array indexes that are modular type. (Expand_N_Allocator): For 32-bit targets improve the generation of the runtime check associated with large arrays supporting arrays initialized with a qualified expression. * libgnat/s-imenne.adb (Image_Enumeration_8, Image_Enumeration_16, Image_Enumeration_32): Define the index of Index_Table with range Natural'First .. Names'Length since in the worst case all the literals of the enumeration type would be single letter literals and the Table built by the frontend would have as many components as the length of the names string. As a result of this enhancement, the internal tables declared using Index_Table have a length closer to the real needs, thus avoiding the declaration of large arrays on 32-bit CCG targets. From-SVN: r273685 --- gcc/ada/ChangeLog | 17 +++++ gcc/ada/exp_ch4.adb | 167 ++++++++++++++++++++++++++++++++++++++----- gcc/ada/libgnat/s-imenne.adb | 9 ++- 3 files changed, 173 insertions(+), 20 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f47d247..ac990be 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,20 @@ +2019-07-22 Javier Miranda + + * exp_ch4.adb (Size_In_Storage_Elements): Improve the expansion + to handle array indexes that are modular type. + (Expand_N_Allocator): For 32-bit targets improve the generation + of the runtime check associated with large arrays supporting + arrays initialized with a qualified expression. + * libgnat/s-imenne.adb (Image_Enumeration_8, + Image_Enumeration_16, Image_Enumeration_32): Define the index of + Index_Table with range Natural'First .. Names'Length since in + the worst case all the literals of the enumeration type would be + single letter literals and the Table built by the frontend would + have as many components as the length of the names string. As a + result of this enhancement, the internal tables declared using + Index_Table have a length closer to the real needs, thus + avoiding the declaration of large arrays on 32-bit CCG targets. + 2019-07-22 Yannick Moy * sem_ch3.adb (Constrain_Access): Issue a message about ignored diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7ea96de..117d6d6 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4249,9 +4249,12 @@ package body Exp_Ch4 is function Size_In_Storage_Elements (E : Entity_Id) return Node_Id; -- Given a constrained array type E, returns a node representing the - -- code to compute the size in storage elements for the given type. - -- This is done without using the attribute (which malfunctions for - -- large sizes ???) + -- code to compute a close approximation of the size in storage elements + -- for the given type; for indexes that are modular types we compute + -- 'Last - First (instead of 'Length) because for large arrays computing + -- 'Last -'First + 1 causes overflow. This is done without using the + -- attribute 'Size_In_Storage_Elements (which malfunctions for large + -- sizes ???) ------------------------- -- Rewrite_Coextension -- @@ -4310,17 +4313,77 @@ package body Exp_Ch4 is -- just a fraction of a storage element??? declare + Idx : Node_Id := First_Index (E); Len : Node_Id; Res : Node_Id; pragma Warnings (Off, Res); begin for J in 1 .. Number_Dimensions (E) loop - Len := - Make_Attribute_Reference (Loc, - Prefix => New_Occurrence_Of (E, Loc), - Attribute_Name => Name_Length, - Expressions => New_List (Make_Integer_Literal (Loc, J))); + + if not Is_Modular_Integer_Type (Etype (Idx)) then + Len := + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (E, Loc), + Attribute_Name => Name_Length, + Expressions => New_List + (Make_Integer_Literal (Loc, J))); + + -- For indexes that are modular types we cannot generate code + -- to compute 'Length since for large arrays 'Last -'First + 1 + -- causes overflow; therefore we compute 'Last - 'First (which + -- is not the exact number of components but it is valid for + -- the purpose of this runtime check on 32-bit targets) + + else + declare + Len_Minus_1_Expr : Node_Id; + Test_Gt : Node_Id; + + begin + Test_Gt := + Make_Op_Gt (Loc, + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (E, Loc), + Attribute_Name => Name_Last, + Expressions => + New_List (Make_Integer_Literal (Loc, J))), + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (E, Loc), + Attribute_Name => Name_First, + Expressions => + New_List (Make_Integer_Literal (Loc, J)))); + + Len_Minus_1_Expr := + Convert_To (Standard_Unsigned, + Make_Op_Subtract (Loc, + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (E, Loc), + Attribute_Name => Name_Last, + Expressions => + New_List + (Make_Integer_Literal (Loc, J))), + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (E, Loc), + Attribute_Name => Name_First, + Expressions => + New_List + (Make_Integer_Literal (Loc, J))))); + + -- Handle superflat arrays, i.e. arrays with such bounds + -- as 4 .. 2, to insure that the result is correct. + + -- Generate: + -- (if X'Last > X'First then X'Last - X'First else 0) + + Len := + Make_If_Expression (Loc, + Expressions => New_List ( + Test_Gt, + Len_Minus_1_Expr, + Make_Integer_Literal (Loc, Uint_0))); + end; + end if; if J = 1 then Res := Len; @@ -4331,6 +4394,8 @@ package body Exp_Ch4 is Left_Opnd => Res, Right_Opnd => Len); end if; + + Next_Index (Idx); end loop; return @@ -4573,15 +4638,83 @@ package body Exp_Ch4 is -- apply the check for constrained arrays, and manually compute the -- value of the attribute ??? - if Is_Array_Type (Etyp) and then Is_Constrained (Etyp) then - Insert_Action (N, - Make_Raise_Storage_Error (Loc, - Condition => - Make_Op_Gt (Loc, - Left_Opnd => Size_In_Storage_Elements (Etyp), - Right_Opnd => - Make_Integer_Literal (Loc, Uint_7 * (Uint_2 ** 29))), - Reason => SE_Object_Too_Large)); + -- The check on No_Initialization is used here to prevent generating + -- this runtime check twice when the allocator is locally replaced by + -- the expander by another one. + + if Is_Array_Type (Etyp) and then not No_Initialization (N) then + declare + Cond : Node_Id; + Ins_Nod : Node_Id := N; + Siz_Typ : Entity_Id := Etyp; + Expr : Node_Id; + + begin + -- For unconstrained array types initialized with a qualified + -- expression we use its type to perform this check + + if not Is_Constrained (Etyp) + and then not No_Initialization (N) + and then Nkind (Expression (N)) = N_Qualified_Expression + then + Expr := Expression (Expression (N)); + Siz_Typ := Etype (Expression (Expression (N))); + + -- If the qualified expression has been moved to an internal + -- temporary (to remove side effects) then we must insert + -- the runtime check before its declaration to ensure that + -- the check is performed before the execution of the code + -- computing the qualified expression. + + if Nkind (Expr) = N_Identifier + and then Is_Internal_Name (Chars (Expr)) + and then + Nkind (Parent (Entity (Expr))) = N_Object_Declaration + then + Ins_Nod := Parent (Entity (Expr)); + else + Ins_Nod := Expr; + end if; + end if; + + if Is_Constrained (Siz_Typ) + and then Ekind (Siz_Typ) /= E_String_Literal_Subtype + then + -- For CCG targets the largest array may have up to 2**31-1 + -- components (i.e. 2 Gigabytes if each array component is + -- 1-byte). This insures that fat pointer fields do not + -- overflow, since they are 32-bit integer types, and also + -- insures that 'Length can be computed at run time. + + if Modify_Tree_For_C then + Cond := + Make_Op_Gt (Loc, + Left_Opnd => Size_In_Storage_Elements (Siz_Typ), + Right_Opnd => Make_Integer_Literal (Loc, + Uint_2 ** 31 - Uint_1)); + + -- For native targets the largest object is 3.5 gigabytes + + else + Cond := + Make_Op_Gt (Loc, + Left_Opnd => Size_In_Storage_Elements (Siz_Typ), + Right_Opnd => Make_Integer_Literal (Loc, + Uint_7 * (Uint_2 ** 29))); + end if; + + Insert_Action (Ins_Nod, + Make_Raise_Storage_Error (Loc, + Condition => Cond, + Reason => SE_Object_Too_Large)); + + if Entity (Cond) = Standard_True then + Error_Msg_N + ("object too large: Storage_Error will be raised at " + & "run time??", N); + end if; + end if; + end; end if; end if; diff --git a/gcc/ada/libgnat/s-imenne.adb b/gcc/ada/libgnat/s-imenne.adb index 2ea9fc7..30df1a4 100644 --- a/gcc/ada/libgnat/s-imenne.adb +++ b/gcc/ada/libgnat/s-imenne.adb @@ -49,7 +49,8 @@ package body System.Img_Enum_New is pragma Assert (S'First = 1); type Natural_8 is range 0 .. 2 ** 7 - 1; - type Index_Table is array (Natural) of Natural_8; + subtype Index is Natural range Natural'First .. Names'Length; + type Index_Table is array (Index) of Natural_8; type Index_Table_Ptr is access Index_Table; function To_Index_Table_Ptr is @@ -79,7 +80,8 @@ package body System.Img_Enum_New is pragma Assert (S'First = 1); type Natural_16 is range 0 .. 2 ** 15 - 1; - type Index_Table is array (Natural) of Natural_16; + subtype Index is Natural range Natural'First .. Names'Length; + type Index_Table is array (Index) of Natural_16; type Index_Table_Ptr is access Index_Table; function To_Index_Table_Ptr is @@ -109,7 +111,8 @@ package body System.Img_Enum_New is pragma Assert (S'First = 1); type Natural_32 is range 0 .. 2 ** 31 - 1; - type Index_Table is array (Natural) of Natural_32; + subtype Index is Natural range Natural'First .. Names'Length; + type Index_Table is array (Index) of Natural_32; type Index_Table_Ptr is access Index_Table; function To_Index_Table_Ptr is -- cgit v1.1 From 8c029ee8cf5d14e8c0dc0a74d9a5278c3aee49e9 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 22 Jul 2019 13:57:51 +0000 Subject: [Ada] Misleading warning on variable not assigned This patch removes a warning on a referenced entity with no explicit prior assignment, if the type of the entity has Preelaborable_Initialixation, such as Exception_Occurrence. 2019-07-22 Ed Schonberg gcc/ada/ * sem_warn.adb (Check_References): Do not emit s warning on a referenced entity with no explicit assignment if the type of the entity has Preelaborable_Initialixation, such as Exception_Occurrence. gcc/testsuite/ * gnat.dg/warn25.adb: New testcase. From-SVN: r273686 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_warn.adb | 8 ++++++-- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/warn25.adb | 23 +++++++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/warn25.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ac990be..12ea5ad 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Ed Schonberg + + * sem_warn.adb (Check_References): Do not emit s warning on a + referenced entity with no explicit assignment if the type of the + entity has Preelaborable_Initialixation, such as + Exception_Occurrence. + 2019-07-22 Javier Miranda * exp_ch4.adb (Size_In_Storage_Elements): Improve the expansion diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb index 0e1e292..ab85162 100644 --- a/gcc/ada/sem_warn.adb +++ b/gcc/ada/sem_warn.adb @@ -1413,9 +1413,13 @@ package body Sem_Warn is goto Continue; end if; - -- Check for unset reference + -- Check for unset reference. If type of object has + -- preelaborable initialization, warning is misleading. - if Warn_On_No_Value_Assigned and then Present (UR) then + if Warn_On_No_Value_Assigned + and then Present (UR) + and then not Known_To_Have_Preelab_Init (Etype (E1)) + then -- For other than access type, go back to original node to -- deal with case where original unset reference has been diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 079f6e9..c9679c7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Ed Schonberg + + * gnat.dg/warn25.adb: New testcase. + 2019-07-22 Yannick Moy * gnat.dg/warn24.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/warn25.adb b/gcc/testsuite/gnat.dg/warn25.adb new file mode 100644 index 0000000..e784870 --- /dev/null +++ b/gcc/testsuite/gnat.dg/warn25.adb @@ -0,0 +1,23 @@ +-- { dg-do compile } +-- { dg-options "-gnatwa" } + +with Ada.Exceptions; +procedure Warn25 is + CASA_Unavailable : Ada.Exceptions.Exception_Occurrence; + use Ada.Exceptions; +begin + while True loop + declare + begin + if Exception_Identity (CASA_Unavailable) = Null_Id then + exit; + end if; + exception + when E : others => + Save_Occurrence (Source => E, Target => CASA_Unavailable); + end; + end loop; + if Exception_Identity (CASA_Unavailable) /= Null_Id then + Reraise_Occurrence (CASA_Unavailable); + end if; +end; -- cgit v1.1 From ca305a848c4f1cc493e61083a14b77df226ac8af Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 22 Jul 2019 13:57:55 +0000 Subject: [Ada] Optimization loses exception in improper use of 'Value This patch prevents an improper removal of an evaluation of attribute 'Value on an illegal input that will raise Constraint_Error, when a subsequent use of this evaluation might be optimized away by the back-end. 2019-07-22 Ed Schonberg gcc/ada/ * libgnat/s-valboo.ads, libgnat/s-valcha.ads, libgnat/s-valdec.ads, libgnat/s-valenu.ads, libgnat/s-valint.ads, libgnat/s-vallld.ads, libgnat/s-vallli.ads, libgnat/s-valllu.ads, libgnat/s-valrea.ads, libgnat/s-valuns.ads, libgnat/s-valwch.ads: Change categorization of packages that implement attribute 'Value from Pure to Preelaborate, to prevent undesirable optimizations when the evaluation of the attribute raises Constraint_Error, but subsequent use of the result of this evsaluation is removed by a subsequent optimization. gcc/testsuite/ * gnat.dg/opt80.adb: New testcase. From-SVN: r273687 --- gcc/ada/ChangeLog | 13 +++++++++++++ gcc/ada/libgnat/s-valboo.ads | 2 +- gcc/ada/libgnat/s-valcha.ads | 2 +- gcc/ada/libgnat/s-valdec.ads | 2 +- gcc/ada/libgnat/s-valenu.ads | 2 +- gcc/ada/libgnat/s-valint.ads | 2 +- gcc/ada/libgnat/s-vallld.ads | 2 +- gcc/ada/libgnat/s-vallli.ads | 2 +- gcc/ada/libgnat/s-valllu.ads | 2 +- gcc/ada/libgnat/s-valrea.ads | 2 +- gcc/ada/libgnat/s-valuns.ads | 2 +- gcc/ada/libgnat/s-valwch.ads | 2 +- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/opt80.adb | 15 +++++++++++++++ 14 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/opt80.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 12ea5ad..30b798c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,18 @@ 2019-07-22 Ed Schonberg + * libgnat/s-valboo.ads, libgnat/s-valcha.ads, + libgnat/s-valdec.ads, libgnat/s-valenu.ads, + libgnat/s-valint.ads, libgnat/s-vallld.ads, + libgnat/s-vallli.ads, libgnat/s-valllu.ads, + libgnat/s-valrea.ads, libgnat/s-valuns.ads, + libgnat/s-valwch.ads: Change categorization of packages that + implement attribute 'Value from Pure to Preelaborate, to prevent + undesirable optimizations when the evaluation of the attribute + raises Constraint_Error, but subsequent use of the result of + this evsaluation is removed by a subsequent optimization. + +2019-07-22 Ed Schonberg + * sem_warn.adb (Check_References): Do not emit s warning on a referenced entity with no explicit assignment if the type of the entity has Preelaborable_Initialixation, such as diff --git a/gcc/ada/libgnat/s-valboo.ads b/gcc/ada/libgnat/s-valboo.ads index bed1ae3..f900621 100644 --- a/gcc/ada/libgnat/s-valboo.ads +++ b/gcc/ada/libgnat/s-valboo.ads @@ -30,7 +30,7 @@ ------------------------------------------------------------------------------ package System.Val_Bool is - pragma Pure; + pragma Preelaborate; function Value_Boolean (Str : String) return Boolean; -- Computes Boolean'Value (Str) diff --git a/gcc/ada/libgnat/s-valcha.ads b/gcc/ada/libgnat/s-valcha.ads index 0d3edfc..b9d5373 100644 --- a/gcc/ada/libgnat/s-valcha.ads +++ b/gcc/ada/libgnat/s-valcha.ads @@ -30,7 +30,7 @@ ------------------------------------------------------------------------------ package System.Val_Char is - pragma Pure; + pragma Preelaborate; function Value_Character (Str : String) return Character; -- Computes Character'Value (Str) diff --git a/gcc/ada/libgnat/s-valdec.ads b/gcc/ada/libgnat/s-valdec.ads index 9d47333..ec10490 100644 --- a/gcc/ada/libgnat/s-valdec.ads +++ b/gcc/ada/libgnat/s-valdec.ads @@ -34,7 +34,7 @@ -- Decimal_IO, and the Value attribute for such decimal types. package System.Val_Dec is - pragma Pure; + pragma Preelaborate; function Scan_Decimal (Str : String; diff --git a/gcc/ada/libgnat/s-valenu.ads b/gcc/ada/libgnat/s-valenu.ads index 343acf3..e2a3a15 100644 --- a/gcc/ada/libgnat/s-valenu.ads +++ b/gcc/ada/libgnat/s-valenu.ads @@ -34,7 +34,7 @@ -- details of the format of constructed image tables. package System.Val_Enum is - pragma Pure; + pragma Preelaborate; function Value_Enumeration_8 (Names : String; diff --git a/gcc/ada/libgnat/s-valint.ads b/gcc/ada/libgnat/s-valint.ads index b4be1e4..d9f15ed 100644 --- a/gcc/ada/libgnat/s-valint.ads +++ b/gcc/ada/libgnat/s-valint.ads @@ -33,7 +33,7 @@ -- in Text_IO.Integer_IO, and the Value attribute. package System.Val_Int is - pragma Pure; + pragma Preelaborate; function Scan_Integer (Str : String; diff --git a/gcc/ada/libgnat/s-vallld.ads b/gcc/ada/libgnat/s-vallld.ads index 1ff561e..17db078 100644 --- a/gcc/ada/libgnat/s-vallld.ads +++ b/gcc/ada/libgnat/s-vallld.ads @@ -34,7 +34,7 @@ -- Decimal_IO, and the Value attribute for such decimal types. package System.Val_LLD is - pragma Pure; + pragma Preelaborate; function Scan_Long_Long_Decimal (Str : String; diff --git a/gcc/ada/libgnat/s-vallli.ads b/gcc/ada/libgnat/s-vallli.ads index 2f510ca..ee75bdc 100644 --- a/gcc/ada/libgnat/s-vallli.ads +++ b/gcc/ada/libgnat/s-vallli.ads @@ -33,7 +33,7 @@ -- values for use in Text_IO.Integer_IO, and the Value attribute. package System.Val_LLI is - pragma Pure; + pragma Preelaborate; function Scan_Long_Long_Integer (Str : String; diff --git a/gcc/ada/libgnat/s-valllu.ads b/gcc/ada/libgnat/s-valllu.ads index c518492..ddb8414 100644 --- a/gcc/ada/libgnat/s-valllu.ads +++ b/gcc/ada/libgnat/s-valllu.ads @@ -35,7 +35,7 @@ with System.Unsigned_Types; package System.Val_LLU is - pragma Pure; + pragma Preelaborate; function Scan_Raw_Long_Long_Unsigned (Str : String; diff --git a/gcc/ada/libgnat/s-valrea.ads b/gcc/ada/libgnat/s-valrea.ads index 49607ed..b59f345 100644 --- a/gcc/ada/libgnat/s-valrea.ads +++ b/gcc/ada/libgnat/s-valrea.ads @@ -30,7 +30,7 @@ ------------------------------------------------------------------------------ package System.Val_Real is - pragma Pure; + pragma Preelaborate; function Scan_Real (Str : String; diff --git a/gcc/ada/libgnat/s-valuns.ads b/gcc/ada/libgnat/s-valuns.ads index 741ae6f..7d261b1 100644 --- a/gcc/ada/libgnat/s-valuns.ads +++ b/gcc/ada/libgnat/s-valuns.ads @@ -35,7 +35,7 @@ with System.Unsigned_Types; package System.Val_Uns is - pragma Pure; + pragma Preelaborate; function Scan_Raw_Unsigned (Str : String; diff --git a/gcc/ada/libgnat/s-valwch.ads b/gcc/ada/libgnat/s-valwch.ads index 5a72295..5179517 100644 --- a/gcc/ada/libgnat/s-valwch.ads +++ b/gcc/ada/libgnat/s-valwch.ads @@ -34,7 +34,7 @@ with System.WCh_Con; package System.Val_WChar is - pragma Pure; + pragma Preelaborate; function Value_Wide_Character (Str : String; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c9679c7..acc6063 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2019-07-22 Ed Schonberg + * gnat.dg/opt80.adb: New testcase. + +2019-07-22 Ed Schonberg + * gnat.dg/warn25.adb: New testcase. 2019-07-22 Yannick Moy diff --git a/gcc/testsuite/gnat.dg/opt80.adb b/gcc/testsuite/gnat.dg/opt80.adb new file mode 100644 index 0000000..39c6cef --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt80.adb @@ -0,0 +1,15 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Opt80 is + Item : Integer; +begin + Item := Integer'Value ("zzz"); + Put_Line (Boolean'Image (Item'Valid)); + raise Program_Error; +exception + when Constraint_Error => + null; +end; -- cgit v1.1 From 75f6bfcefdb62b6267a10ceb6097c18f5e0973f6 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:58:00 +0000 Subject: [Ada] Beef up comment in exp_attr.adb 2019-07-22 Eric Botcazou gcc/ada/ * exp_attr.adb (Expand_Loop_Entry_Attribute): Beef up comment. From-SVN: r273688 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/exp_attr.adb | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 30b798c..f85dfc4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Eric Botcazou + + * exp_attr.adb (Expand_Loop_Entry_Attribute): Beef up comment. + 2019-07-22 Ed Schonberg * libgnat/s-valboo.ads, libgnat/s-valcha.ads, diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 2748c51..60102a9 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -1390,8 +1390,9 @@ package body Exp_Attr is -- This avoids the duplication of the same code which may lead -- to gigi issues with respect to multiple declaration of the -- same entity in the presence of side effects or checks. Note - -- that the condition actions must also be relocated to the - -- wrapping function. + -- that the condition actions must also be relocated into the + -- wrapping function because they may contain itypes, e.g. in + -- the case of a comparison involving slices. -- Generate: -- -- cgit v1.1 From 2f8313ce5a14700907822a4f8c0dc18649276136 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:58:04 +0000 Subject: [Ada] Small enhancement to the -gnatD/-gnatG output for fixed-point types This is a small enhancement to the -gnatD/-gnatG output: the base type of fixed-point types, which is usually an itype, used to be printed as ??? in this case. It is now printed in a similar fashion as the first subtype. For the following package: package P is type D is delta 128.0 / (2 ** 15) range 0.0 .. 256.0; end P; the -gnatD/-gnatG must now be: Source recreated from tree for P (spec) --------------------------------------- p_E : short_integer := 0; package p is type p__d is delta [1.0/256.0] range 0.0 .. 256.0; [type p__TdB is delta [1.0/256.0] range -[2147483648.0*2**(-8)] .. [2147483647.0*2**(-8)]] freeze p__TdB [] end p; 2019-07-22 Eric Botcazou gcc/ada/ * sprint.adb (Sprint_Node_Actual) : Swap a couple of spaces. (Write_Itype): Minor consistency fixes throughout. Add support for printing ordinary and decimal fixed-point types and subtypes. From-SVN: r273689 --- gcc/ada/ChangeLog | 8 +++++ gcc/ada/sprint.adb | 91 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 32 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f85dfc4..4b817ce 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,13 @@ 2019-07-22 Eric Botcazou + * sprint.adb (Sprint_Node_Actual) + : Swap a couple of spaces. + (Write_Itype): Minor consistency fixes throughout. Add support + for printing ordinary and decimal fixed-point types and + subtypes. + +2019-07-22 Eric Botcazou + * exp_attr.adb (Expand_Loop_Entry_Attribute): Beef up comment. 2019-07-22 Ed Schonberg diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb index c17cf57..8a8139d 100644 --- a/gcc/ada/sprint.adb +++ b/gcc/ada/sprint.adb @@ -1483,9 +1483,9 @@ package body Sprint is end; when N_Decimal_Fixed_Point_Definition => - Write_Str_With_Col_Check_Sloc (" delta "); + Write_Str_With_Col_Check_Sloc ("delta "); Sprint_Node (Delta_Expression (Node)); - Write_Str_With_Col_Check ("digits "); + Write_Str_With_Col_Check (" digits "); Sprint_Node (Digits_Expression (Node)); Sprint_Opt_Node (Real_Range_Specification (Node)); @@ -4187,9 +4187,7 @@ package body Sprint is declare B : constant Node_Id := Etype (Typ); - X : Node_Id; P : constant Node_Id := Parent (Typ); - S : constant Saved_Output_Buffer := Save_Output_Buffer; -- Save current output buffer @@ -4197,6 +4195,8 @@ package body Sprint is -- Save sloc of related node, so it is not modified when -- printing with -gnatD. + X : Node_Id; + begin -- Write indentation at start of line @@ -4324,8 +4324,8 @@ package body Sprint is declare L : constant Node_Id := Type_Low_Bound (Typ); H : constant Node_Id := Type_High_Bound (Typ); - LE : Node_Id; - HE : Node_Id; + BL : Node_Id; + BH : Node_Id; begin -- B can either be a scalar type, in which case the @@ -4335,29 +4335,29 @@ package body Sprint is -- constraint. if Is_Scalar_Type (B) then - LE := Type_Low_Bound (B); - HE := Type_High_Bound (B); + BL := Type_Low_Bound (B); + BH := Type_High_Bound (B); else - LE := Empty; - HE := Empty; + BL := Empty; + BH := Empty; end if; - if No (LE) + if No (BL) or else (True and then Nkind (L) = N_Integer_Literal and then Nkind (H) = N_Integer_Literal - and then Nkind (LE) = N_Integer_Literal - and then Nkind (HE) = N_Integer_Literal - and then UI_Eq (Intval (L), Intval (LE)) - and then UI_Eq (Intval (H), Intval (HE))) + and then Nkind (BL) = N_Integer_Literal + and then Nkind (BH) = N_Integer_Literal + and then UI_Eq (Intval (L), Intval (BL)) + and then UI_Eq (Intval (H), Intval (BH))) then null; else Write_Str (" range "); - Sprint_Node (Type_Low_Bound (Typ)); + Sprint_Node (L); Write_Str (" .. "); - Sprint_Node (Type_High_Bound (Typ)); + Sprint_Node (H); end if; end; @@ -4368,7 +4368,7 @@ package body Sprint is Write_Str ("mod "); Write_Uint_With_Col_Check (Modulus (Typ), Auto); - -- Floating point types and subtypes + -- Floating-point types and subtypes when E_Floating_Point_Subtype | E_Floating_Point_Type @@ -4379,9 +4379,9 @@ package body Sprint is Write_Str ("new "); end if; - Write_Id (Etype (Typ)); + Write_Id (B); - if Digits_Value (Typ) /= Digits_Value (Etype (Typ)) then + if Digits_Value (Typ) /= Digits_Value (B) then Write_Str (" digits "); Write_Uint_With_Col_Check (Digits_Value (Typ), Decimal); @@ -4392,27 +4392,54 @@ package body Sprint is declare L : constant Node_Id := Type_Low_Bound (Typ); H : constant Node_Id := Type_High_Bound (Typ); - LE : constant Node_Id := Type_Low_Bound (B); - HE : constant Node_Id := Type_High_Bound (B); + BL : constant Node_Id := Type_Low_Bound (B); + BH : constant Node_Id := Type_High_Bound (B); begin - if Nkind (L) = N_Real_Literal + if True + and then Nkind (L) = N_Real_Literal and then Nkind (H) = N_Real_Literal - and then Nkind (LE) = N_Real_Literal - and then Nkind (HE) = N_Real_Literal - and then UR_Eq (Realval (L), Realval (LE)) - and then UR_Eq (Realval (H), Realval (HE)) + and then Nkind (BL) = N_Real_Literal + and then Nkind (BH) = N_Real_Literal + and then UR_Eq (Realval (L), Realval (BL)) + and then UR_Eq (Realval (H), Realval (BH)) then null; else Write_Str (" range "); - Sprint_Node (Type_Low_Bound (Typ)); + Sprint_Node (L); Write_Str (" .. "); - Sprint_Node (Type_High_Bound (Typ)); + Sprint_Node (H); end if; end; + -- Ordinary fixed-point types and subtypes + + when E_Ordinary_Fixed_Point_Subtype + | E_Ordinary_Fixed_Point_Type + => + Write_Header (Ekind (Typ) = E_Ordinary_Fixed_Point_Type); + + Write_Str ("delta "); + Write_Ureal_With_Col_Check_Sloc (Delta_Value (Typ)); + Write_Str (" range "); + Sprint_Node (Type_Low_Bound (Typ)); + Write_Str (" .. "); + Sprint_Node (Type_High_Bound (Typ)); + + -- Decimal fixed-point types and subtypes + + when E_Decimal_Fixed_Point_Subtype + | E_Decimal_Fixed_Point_Type + => + Write_Header (Ekind (Typ) = E_Decimal_Fixed_Point_Type); + + Write_Str ("delta "); + Write_Ureal_With_Col_Check_Sloc (Delta_Value (Typ)); + Write_Str (" digits "); + Write_Uint_With_Col_Check (Digits_Value (Typ), Decimal); + -- Record subtypes when E_Record_Subtype @@ -4493,16 +4520,16 @@ package body Sprint is when E_String_Literal_Subtype => declare - LB : constant Uint := + L : constant Uint := Expr_Value (String_Literal_Low_Bound (Typ)); Len : constant Uint := String_Literal_Length (Typ); begin Write_Header (False); Write_Str ("String ("); - Write_Int (UI_To_Int (LB)); + Write_Int (UI_To_Int (L)); Write_Str (" .. "); - Write_Int (UI_To_Int (LB + Len) - 1); + Write_Int (UI_To_Int (L + Len) - 1); Write_Str (");"); end; -- cgit v1.1 From 137dabdd82648ccd5f0adedea2fbb8504f6c7485 Mon Sep 17 00:00:00 2001 From: Javier Miranda Date: Mon, 22 Jul 2019 13:58:09 +0000 Subject: [Ada] Spurious error passing access to class-wide interface type The compiler reports an spurious error when the formal parameter of a subprogram is an access to a class wide interface type and the actual parameter is an allocator of an object covering such interface type. 2019-07-22 Javier Miranda gcc/ada/ * sem_res.adb (Resolve_Actuals): Replace code that displaces the pointer to an allocated object to reference its secondary dispatch table by a type conversion (which takes care of handling all cases). gcc/testsuite/ * gnat.dg/class_wide5.adb: New testcase. From-SVN: r273690 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_res.adb | 13 ++++++------- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/class_wide5.adb | 11 +++++++++++ 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/class_wide5.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4b817ce..4711b6d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Javier Miranda + + * sem_res.adb (Resolve_Actuals): Replace code that displaces the + pointer to an allocated object to reference its secondary + dispatch table by a type conversion (which takes care of + handling all cases). + 2019-07-22 Eric Botcazou * sprint.adb (Sprint_Node_Actual) diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index fd4fedc..b668a51 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -4190,17 +4190,16 @@ package body Sem_Res is DDT : constant Entity_Id := Directly_Designated_Type (Base_Type (Etype (F))); - New_Itype : Entity_Id; - begin + -- Displace the pointer to the object to reference its + -- secondary dispatch table. + if Is_Class_Wide_Type (DDT) and then Is_Interface (DDT) then - New_Itype := Create_Itype (E_Anonymous_Access_Type, A); - Set_Etype (New_Itype, Etype (A)); - Set_Directly_Designated_Type - (New_Itype, Directly_Designated_Type (Etype (A))); - Set_Etype (A, New_Itype); + Rewrite (A, Convert_To (Etype (F), Relocate_Node (A))); + Analyze_And_Resolve (A, Etype (F), + Suppress => Access_Check); end if; -- Ada 2005, AI-162:If the actual is an allocator, the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index acc6063..2ac298f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Javier Miranda + + * gnat.dg/class_wide5.adb: New testcase. + 2019-07-22 Ed Schonberg * gnat.dg/opt80.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/class_wide5.adb b/gcc/testsuite/gnat.dg/class_wide5.adb new file mode 100644 index 0000000..008273f --- /dev/null +++ b/gcc/testsuite/gnat.dg/class_wide5.adb @@ -0,0 +1,11 @@ +-- { dg-do compile } + +procedure Class_Wide5 is + type B is interface; + type B_Child is new B with null record; + type B_Ptr is access B'Class; + + procedure P (Obj : B_Ptr) is begin null; end; +begin + P (new B_child); -- Test +end Class_Wide5; -- cgit v1.1 From c936411fab42b991839ce8cd95a5d883867f9466 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:58:14 +0000 Subject: [Ada] Sprint: fix pasto in comment 2019-07-22 Eric Botcazou gcc/ada/ * sprint.ads: Fix pasto in comment. From-SVN: r273691 --- gcc/ada/ChangeLog | 4 ++++ gcc/ada/sprint.ads | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4711b6d..3706cd7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Eric Botcazou + + * sprint.ads: Fix pasto in comment. + 2019-07-22 Javier Miranda * sem_res.adb (Resolve_Actuals): Replace code that displaces the diff --git a/gcc/ada/sprint.ads b/gcc/ada/sprint.ads index b76b5d9..11a552f 100644 --- a/gcc/ada/sprint.ads +++ b/gcc/ada/sprint.ads @@ -70,7 +70,7 @@ package Sprint is -- Multiple concatenation expr && expr && expr ... && expr -- Multiply wi Treat_Fixed_As_Integer x #* y -- Multiply wi Rounded_Result x @* y - -- Operator with range check {operator} (e.g. {+}) + -- Operator with overflow check {operator} (e.g. {+}) -- Others choice for cleanup when all others -- Pop exception label %pop_xxx_exception_label -- Push exception label %push_xxx_exception_label (label) -- cgit v1.1 From 8113b0c7385727d9969db2c8420bc0a3d6b8f0ed Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:58:19 +0000 Subject: [Ada] Overhaul code implementing conversions involving fixed-point types This ovehauls the code implementing conversions involving fixed-point types in the front-end because it leaks the Do_Range_Check flag in several places to the back-end, which is a violation of the documented interface between front-end and back-end. This also does a bit of housekeeping work throughout it in the process. There should be essentially no functional changes. 2019-07-22 Eric Botcazou gcc/ada/ * checks.adb (Apply_Type_Conversion_Checks): Do not set Do_Range_Check flag on conversions from fixed-point types either. * exp_attr.adb: Add use and with clause for Expander. (Expand_N_Attribute_Reference) : Set the Conversion_OK flag and do not generate overflow/range checks manually. * exp_ch4.adb (Expand_N_Qualified_Expression): Remove superfluous clearing of Do_Range_Check flag. (Discrete_Range_Check): New procedure to generate a range check for discrete types. (Real_Range_Check): Remove redundant local variable and adjust. Remove useless shortcut. Clear Do_Range_Check flag on all paths. (Expand_N_Type_Conversion): Remove redundant test on Conversion_OK. Call Discrete_Range_Check to generate range checks on discrete types. Remove obsolete code for float-to-integer conversions. Add code to generate range checks for conversions involving fixed-point types. From-SVN: r273692 --- gcc/ada/ChangeLog | 22 +++++ gcc/ada/checks.adb | 5 +- gcc/ada/exp_attr.adb | 74 +++------------ gcc/ada/exp_ch4.adb | 251 +++++++++++++++++++++------------------------------ 4 files changed, 142 insertions(+), 210 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 3706cd7..8bb8d34 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,27 @@ 2019-07-22 Eric Botcazou + * checks.adb (Apply_Type_Conversion_Checks): Do not set + Do_Range_Check flag on conversions from fixed-point types + either. + * exp_attr.adb: Add use and with clause for Expander. + (Expand_N_Attribute_Reference) : Set + the Conversion_OK flag and do not generate overflow/range checks + manually. + * exp_ch4.adb (Expand_N_Qualified_Expression): Remove + superfluous clearing of Do_Range_Check flag. + (Discrete_Range_Check): New procedure to generate a range check + for discrete types. + (Real_Range_Check): Remove redundant local variable and adjust. + Remove useless shortcut. Clear Do_Range_Check flag on all + paths. + (Expand_N_Type_Conversion): Remove redundant test on + Conversion_OK. Call Discrete_Range_Check to generate range + checks on discrete types. Remove obsolete code for + float-to-integer conversions. Add code to generate range checks + for conversions involving fixed-point types. + +2019-07-22 Eric Botcazou + * sprint.ads: Fix pasto in comment. 2019-07-22 Javier Miranda diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 73f7edc..e1f7f9a 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -3622,13 +3622,14 @@ package body Checks is -- will not be generated. if GNATprove_Mode - or else not Is_Fixed_Point_Type (Expr_Type) + or else (not Is_Fixed_Point_Type (Expr_Type) + and then not Is_Fixed_Point_Type (Target_Type)) then Apply_Scalar_Range_Check (Expr, Target_Type, Fixed_Int => Conv_OK); else - Set_Do_Range_Check (Expression (N), False); + Set_Do_Range_Check (Expr, False); end if; -- If the target type has predicates, we need to indicate diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 60102a9..9d6da33 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -39,6 +39,7 @@ with Exp_Pakd; use Exp_Pakd; with Exp_Strm; use Exp_Strm; with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; +with Expander; use Expander; with Freeze; use Freeze; with Gnatvsn; use Gnatvsn; with Itypes; use Itypes; @@ -3540,7 +3541,7 @@ package body Exp_Attr is -- We transform -- fixtype'Fixed_Value (integer-value) - -- inttype'Fixed_Value (fixed-value) + -- inttype'Integer_Value (fixed-value) -- into @@ -3549,75 +3550,30 @@ package body Exp_Attr is -- respectively. - -- We do all the required analysis of the conversion here, because we do - -- not want this to go through the fixed-point conversion circuits. Note - -- that the back end always treats fixed-point as equivalent to the - -- corresponding integer type anyway. - -- However, in order to remove the handling of Do_Range_Check from the - -- backend, we force the generation of a check on the result by - -- setting the result type appropriately. Apply_Conversion_Checks - -- will generate the required expansion. + -- We set Conversion_OK on the conversion because we do not want it + -- to go through the fixed-point conversion circuits. when Attribute_Fixed_Value | Attribute_Integer_Value => - Rewrite (N, - Make_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Entity (Pref), Loc), - Expression => Relocate_Node (First (Exprs)))); + Rewrite (N, OK_Convert_To (Entity (Pref), First (Exprs))); - -- Indicate that the result of the conversion may require a - -- range check (see below); - - Set_Etype (N, Base_Type (Entity (Pref))); - Set_Analyzed (N); - - -- Note: it might appear that a properly analyzed unchecked + -- Note that it might appear that a properly analyzed unchecked -- conversion would be just fine here, but that's not the case, - -- since the full range checks performed by the following code + -- since the full range checks performed by the following calls -- are critical. - -- Given that Fixed-point conversions are not further expanded - -- to prevent the involvement of real type operations we have to - -- construct two checks explicitly: one on the operand, and one - -- on the result. This used to be done in part in the back-end, - -- but for other targets (E.g. LLVM) it is preferable to create - -- the tests in full in the front-end. - - if Is_Fixed_Point_Type (Etype (N)) then - declare - Loc : constant Source_Ptr := Sloc (N); - Equiv_T : constant Entity_Id := Make_Temporary (Loc, 'T', N); - Expr : constant Node_Id := Expression (N); - Fst : constant Entity_Id := Root_Type (Etype (N)); - Decl : Node_Id; - begin - Decl := - Make_Full_Type_Declaration (Sloc (N), - Defining_Identifier => Equiv_T, - Type_Definition => - Make_Signed_Integer_Type_Definition (Loc, - Low_Bound => - Make_Integer_Literal (Loc, - Intval => - Corresponding_Integer_Value - (Type_Low_Bound (Fst))), - High_Bound => - Make_Integer_Literal (Loc, - Intval => - Corresponding_Integer_Value - (Type_High_Bound (Fst))))); - Insert_Action (N, Decl); - - -- Verify that the conversion is possible + Apply_Type_Conversion_Checks (N); - Generate_Range_Check (Expr, Equiv_T, CE_Overflow_Check_Failed); + -- Note that Apply_Type_Conversion_Checks only deals with the + -- overflow checks on conversions involving fixed-point types + -- so we must apply range checks manually on them and expand. - -- and verify that the result is in range + Apply_Scalar_Range_Check + (Expression (N), Etype (N), Fixed_Int => True); - Generate_Range_Check (N, Etype (N), CE_Range_Check_Failed); - end; - end if; + Set_Analyzed (N); + Expand (N); ----------- -- Floor -- diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 117d6d6..a062434 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -10274,7 +10274,6 @@ package body Exp_Ch4 is Apply_Constraint_Check (Operand, Target_Type, No_Sliding => True); if Do_Range_Check (Operand) then - Set_Do_Range_Check (Operand, False); Generate_Range_Check (Operand, Target_Type, CE_Range_Check_Failed); end if; end Expand_N_Qualified_Expression; @@ -10929,9 +10928,12 @@ package body Exp_Ch4 is procedure Expand_N_Type_Conversion (N : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Operand : constant Node_Id := Expression (N); - Target_Type : constant Entity_Id := Etype (N); + Target_Type : Entity_Id := Etype (N); Operand_Type : Entity_Id := Etype (Operand); + procedure Discrete_Range_Check; + -- Handles generation of range check for discrete target value + procedure Handle_Changed_Representation; -- This is called in the case of record and array type conversions to -- see if there is a change of representation to be handled. Change of @@ -10954,6 +10956,44 @@ package body Exp_Ch4 is -- True iff Present (Effective_Extra_Accessibility (Id)) successfully -- evaluates to True. + -------------------------- + -- Discrete_Range_Check -- + -------------------------- + + -- Case of conversions to a discrete type + + procedure Discrete_Range_Check is + Expr : Node_Id; + Ityp : Entity_Id; + + begin + -- Nothing to do if conversion was rewritten + + if Nkind (N) /= N_Type_Conversion then + return; + end if; + + Expr := Expression (N); + + -- Before we do a range check, we have to deal with treating + -- a fixed-point operand as an integer. The way we do this + -- is simply to do an unchecked conversion to an appropriate + -- integer type large enough to hold the result. + + if Is_Fixed_Point_Type (Etype (Expr)) then + if Esize (Base_Type (Etype (Expr))) > Esize (Standard_Integer) then + Ityp := Standard_Long_Long_Integer; + else + Ityp := Standard_Integer; + end if; + + Set_Do_Range_Check (Expr, False); + Rewrite (Expr, Unchecked_Convert_To (Ityp, Expr)); + end if; + + Generate_Range_Check (Expr, Target_Type, CE_Range_Check_Failed); + end Discrete_Range_Check; + ----------------------------------- -- Handle_Changed_Representation -- ----------------------------------- @@ -11169,7 +11209,6 @@ package body Exp_Ch4 is Btyp : constant Entity_Id := Base_Type (Target_Type); Lo : constant Node_Id := Type_Low_Bound (Target_Type); Hi : constant Node_Id := Type_High_Bound (Target_Type); - Xtyp : constant Entity_Id := Etype (Operand); Conv : Node_Id; Hi_Arg : Node_Id; @@ -11193,6 +11232,12 @@ package body Exp_Ch4 is and then Hi = Type_High_Bound (Btyp)) then + -- Unset the range check flag on the current value of + -- Expression (N), since the captured Operand may have + -- been rewritten (such as for the case of a conversion + -- to a fixed-point type). + + Set_Do_Range_Check (Expression (N), False); return; end if; @@ -11202,6 +11247,7 @@ package body Exp_Ch4 is if Is_Entity_Name (Operand) and then Range_Checks_Suppressed (Entity (Operand)) then + Set_Do_Range_Check (Expression (N), False); return; end if; @@ -11211,12 +11257,12 @@ package body Exp_Ch4 is -- not trust it to be in range (might be infinite) declare - S_Lo : constant Node_Id := Type_Low_Bound (Xtyp); - S_Hi : constant Node_Id := Type_High_Bound (Xtyp); + S_Lo : constant Node_Id := Type_Low_Bound (Operand_Type); + S_Hi : constant Node_Id := Type_High_Bound (Operand_Type); begin - if (not Is_Floating_Point_Type (Xtyp) - or else Is_Constrained (Xtyp)) + if (not Is_Floating_Point_Type (Operand_Type) + or else Is_Constrained (Operand_Type)) and then Compile_Time_Known_Value (S_Lo) and then Compile_Time_Known_Value (S_Hi) and then Compile_Time_Known_Value (Hi) @@ -11229,7 +11275,7 @@ package body Exp_Ch4 is S_Hiv : Ureal; begin - if Is_Real_Type (Xtyp) then + if Is_Real_Type (Operand_Type) then S_Lov := Expr_Value_R (S_Lo); S_Hiv := Expr_Value_R (S_Hi); else @@ -11241,30 +11287,17 @@ package body Exp_Ch4 is and then S_Lov >= D_Lov and then S_Hiv <= D_Hiv then - -- Unset the range check flag on the current value of - -- Expression (N), since the captured Operand may have - -- been rewritten (such as for the case of a conversion - -- to a fixed-point type). - Set_Do_Range_Check (Expression (N), False); - return; end if; end; end if; end; - -- For float to float conversions, we are done - - if Is_Floating_Point_Type (Xtyp) - and then - Is_Floating_Point_Type (Btyp) - then - return; - end if; - -- Otherwise rewrite the conversion as described above + Set_Do_Range_Check (Expression (N), False); + Conv := Relocate_Node (N); Rewrite (Subtype_Mark (Conv), New_Occurrence_Of (Btyp, Loc)); Set_Etype (Conv, Btyp); @@ -11273,7 +11306,7 @@ package body Exp_Ch4 is -- where it is never required, since we can never have overflow in -- this case. - if not Is_Integer_Type (Etype (Operand)) then + if not Is_Integer_Type (Operand_Type) then Enable_Overflow_Check (Conv); end if; @@ -11895,31 +11928,21 @@ package body Exp_Ch4 is then Set_Rounded_Result (N); Set_Etype (N, Etype (Parent (N))); + Target_Type := Etype (N); end if; - -- Otherwise do correct fixed-conversion, but skip these if the - -- Conversion_OK flag is set, because from a semantic point of view - -- these are simple integer conversions needing no further processing - -- (the backend will simply treat them as integers). - - if not Conversion_OK (N) then - if Is_Fixed_Point_Type (Etype (N)) then - Expand_Convert_Fixed_To_Fixed (N); - Real_Range_Check; - - elsif Is_Integer_Type (Etype (N)) then - Expand_Convert_Fixed_To_Integer (N); - - -- The result of the conversion might need a range check, so do - -- not assume that the result is in bounds. + if Is_Fixed_Point_Type (Target_Type) then + Expand_Convert_Fixed_To_Fixed (N); + Real_Range_Check; - Set_Etype (N, Base_Type (Target_Type)); + elsif Is_Integer_Type (Target_Type) then + Expand_Convert_Fixed_To_Integer (N); + Discrete_Range_Check; - else - pragma Assert (Is_Floating_Point_Type (Etype (N))); - Expand_Convert_Fixed_To_Float (N); - Real_Range_Check; - end if; + else + pragma Assert (Is_Floating_Point_Type (Target_Type)); + Expand_Convert_Fixed_To_Float (N); + Real_Range_Check; end if; -- Case of conversions to a fixed-point type @@ -11941,42 +11964,6 @@ package body Exp_Ch4 is Real_Range_Check; end if; - -- Case of float-to-integer conversions - - -- We also handle float-to-fixed conversions with Conversion_OK set - -- since semantically the fixed-point target is treated as though it - -- were an integer in such cases. - - elsif Is_Floating_Point_Type (Operand_Type) - and then - (Is_Integer_Type (Target_Type) - or else - (Is_Fixed_Point_Type (Target_Type) and then Conversion_OK (N))) - then - -- One more check here, gcc is still not able to do conversions of - -- this type with proper overflow checking, and so gigi is doing an - -- approximation of what is required by doing floating-point compares - -- with the end-point. But that can lose precision in some cases, and - -- give a wrong result. Converting the operand to Universal_Real is - -- helpful, but still does not catch all cases with 64-bit integers - -- on targets with only 64-bit floats. - - -- The above comment seems obsoleted by Apply_Float_Conversion_Check - -- Can this code be removed ??? - - if Do_Range_Check (Operand) then - Rewrite (Operand, - Make_Type_Conversion (Loc, - Subtype_Mark => - New_Occurrence_Of (Universal_Real, Loc), - Expression => - Relocate_Node (Operand))); - - Set_Etype (Operand, Universal_Real); - Enable_Range_Check (Operand); - Set_Do_Range_Check (Expression (Operand), False); - end if; - -- Case of array conversions -- Expansion of array conversions, add required length/range checks but @@ -12059,11 +12046,6 @@ package body Exp_Ch4 is Analyze_And_Resolve (N, Target_Type); end if; - - -- Case of conversions to floating-point - - elsif Is_Floating_Point_Type (Target_Type) then - Real_Range_Check; end if; -- At this stage, either the conversion node has been transformed into @@ -12081,80 +12063,51 @@ package body Exp_Ch4 is -- Check: are these rules stated in sinfo??? if so, why restate here??? -- The only remaining step is to generate a range check if we still have - -- a type conversion at this stage and Do_Range_Check is set. For now we - -- do this only for conversions of discrete types and for float-to-float - -- conversions. - - if Nkind (N) = N_Type_Conversion then + -- a type conversion at this stage and Do_Range_Check is set. - -- For now we only support floating-point cases where both source - -- and target are floating-point types. Conversions where the source - -- and target involve integer or fixed-point types are still TBD, - -- though not clear whether those can even happen at this point, due - -- to transformations above. ??? + if Nkind (N) = N_Type_Conversion + and then Do_Range_Check (Expression (N)) + then + -- Float-to-float conversions - if Is_Floating_Point_Type (Etype (N)) + if Is_Floating_Point_Type (Target_Type) and then Is_Floating_Point_Type (Etype (Expression (N))) then - if Do_Range_Check (Expression (N)) - and then Is_Floating_Point_Type (Target_Type) - then - Generate_Range_Check - (Expression (N), Target_Type, CE_Range_Check_Failed); - end if; - - -- Discrete-to-discrete conversions + Generate_Range_Check + (Expression (N), Target_Type, CE_Range_Check_Failed); - elsif Is_Discrete_Type (Etype (N)) then - declare - Expr : constant Node_Id := Expression (N); - Ftyp : Entity_Id; - Ityp : Entity_Id; + -- Discrete-to-discrete conversions or fixed-point-to-discrete + -- conversions when Conversion_OK is set. - begin - if Do_Range_Check (Expr) - and then Is_Discrete_Type (Etype (Expr)) - then - Set_Do_Range_Check (Expr, False); - - -- Before we do a range check, we have to deal with treating - -- a fixed-point operand as an integer. The way we do this - -- is simply to do an unchecked conversion to an appropriate - -- integer type large enough to hold the result. - - -- This code is not active yet, because we are only dealing - -- with discrete types so far ??? - - if Nkind (Expr) in N_Has_Treat_Fixed_As_Integer - and then Treat_Fixed_As_Integer (Expr) - then - Ftyp := Base_Type (Etype (Expr)); + elsif Is_Discrete_Type (Target_Type) + and then (Is_Discrete_Type (Etype (Expression (N))) + or else (Is_Fixed_Point_Type (Etype (Expression (N))) + and then Conversion_OK (N))) + then + -- Reset overflow flag, since the range check will include + -- dealing with possible overflow, and generate the check. - if Esize (Ftyp) >= Esize (Standard_Integer) then - Ityp := Standard_Long_Long_Integer; - else - Ityp := Standard_Integer; - end if; + Set_Do_Overflow_Check (N, False); - Rewrite (Expr, Unchecked_Convert_To (Ityp, Expr)); - end if; + -- If Address is either a source type or target type, + -- suppress range check to avoid typing anomalies when + -- it is a visible integer type. - -- Reset overflow flag, since the range check will include - -- dealing with possible overflow, and generate the check. - -- If Address is either a source type or target type, - -- suppress range check to avoid typing anomalies when - -- it is a visible integer type. + if Is_Descendant_Of_Address (Etype (Expression (N))) + or else Is_Descendant_Of_Address (Target_Type) + then + Set_Do_Range_Check (Expression (N), False); + else + Discrete_Range_Check; + end if; - Set_Do_Overflow_Check (N, False); + -- Conversions to floating- or fixed-point when Conversion_OK is set - if not Is_Descendant_Of_Address (Etype (Expr)) - and then not Is_Descendant_Of_Address (Target_Type) - then - Generate_Range_Check - (Expr, Target_Type, CE_Range_Check_Failed); - end if; - end if; - end; + elsif Is_Floating_Point_Type (Target_Type) + or else (Is_Fixed_Point_Type (Target_Type) + and then Conversion_OK (N)) + then + Real_Range_Check; end if; end if; -- cgit v1.1 From a211917585ca978a84123c4c934f2f68bb545bcd Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Mon, 22 Jul 2019 13:58:23 +0000 Subject: [Ada] Adapt ownership checking in SPARK to traversal functions A traversal function, especially when implemented as an expression function, may need to return an if-expression or case-expression, while still respecting Legality Rule SPARK RM 3.10(5). This case is now allowed in GNATprove. There is no impact on compilation. 2019-07-22 Yannick Moy gcc/ada/ * sem_spark.adb (Get_Root_Object, Is_Path_Expression, Is_Subpath_Expression): Add parameter Is_Traversal to adapt these functions to the case of paths returned from a traversal function. (Read_Indexes): Handle the case of an if-expression or case-expression. (Check_Statement): Check Emit_Messages only when issuing an error message. This is important as Emit_Messages may store the information that an error was detected. From-SVN: r273693 --- gcc/ada/ChangeLog | 12 +++ gcc/ada/sem_spark.adb | 223 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 217 insertions(+), 18 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8bb8d34..17d21f5 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,15 @@ +2019-07-22 Yannick Moy + + * sem_spark.adb (Get_Root_Object, Is_Path_Expression, + Is_Subpath_Expression): Add parameter Is_Traversal to adapt + these functions to the case of paths returned from a traversal + function. + (Read_Indexes): Handle the case of an if-expression or + case-expression. + (Check_Statement): Check Emit_Messages only when issuing an + error message. This is important as Emit_Messages may store the + information that an error was detected. + 2019-07-22 Eric Botcazou * checks.adb (Apply_Type_Conversion_Checks): Do not set diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 67aa453..0de51f8 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -715,10 +715,14 @@ package body Sem_SPARK is function Get_Root_Object (Expr : Node_Id; - Through_Traversal : Boolean := True) return Entity_Id; + Through_Traversal : Boolean := True; + Is_Traversal : Boolean := False) return Entity_Id; -- Return the root of the path expression Expr, or Empty for an allocator, -- NULL, or a function call. Through_Traversal is True if it should follow - -- through calls to traversal functions. + -- through calls to traversal functions. Is_Traversal is True if this + -- corresponds to a value returned from a traversal function, which should + -- allow if-expressions and case-expressions that refer to the same root, + -- even if the paths are not the same in all branches. generic with procedure Handle_Parameter_Or_Global @@ -745,11 +749,19 @@ package body Sem_SPARK is -- A procedure that is called when deep globals or aliased globals are used -- without any global aspect. - function Is_Path_Expression (Expr : Node_Id) return Boolean; - -- Return whether Expr corresponds to a path + function Is_Path_Expression + (Expr : Node_Id; + Is_Traversal : Boolean := False) return Boolean; + -- Return whether Expr corresponds to a path. Is_Traversal is True if this + -- corresponds to a value returned from a traversal function, which should + -- allow if-expressions and case-expressions. - function Is_Subpath_Expression (Expr : Node_Id) return Boolean; - -- Return True if Expr can be part of a path expression + function Is_Subpath_Expression + (Expr : Node_Id; + Is_Traversal : Boolean := False) return Boolean; + -- Return True if Expr can be part of a path expression. Is_Traversal is + -- True if this corresponds to a value returned from a traversal function, + -- which should allow if-expressions and case-expressions. function Is_Prefix_Or_Almost (Pref, Expr : Node_Id) return Boolean; -- Determine if the candidate Prefix is indeed a prefix of Expr, or almost @@ -1749,6 +1761,31 @@ package body Sem_SPARK is end loop; end; + when N_If_Expression => + declare + Cond : constant Node_Id := First (Expressions (Expr)); + Then_Part : constant Node_Id := Next (Cond); + Else_Part : constant Node_Id := Next (Then_Part); + begin + Read_Expression (Cond); + Read_Indexes (Then_Part); + Read_Indexes (Else_Part); + end; + + when N_Case_Expression => + declare + Cases : constant List_Id := Alternatives (Expr); + Cur_Case : Node_Id := First (Cases); + + begin + Read_Expression (Expression (Expr)); + + while Present (Cur_Case) loop + Read_Indexes (Expression (Cur_Case)); + Next (Cur_Case); + end loop; + end; + when N_Attribute_Reference => pragma Assert (Get_Attribute_Id (Attribute_Name (Expr)) = @@ -3115,14 +3152,14 @@ package body Sem_SPARK is if Is_Anonymous_Access_Type (Return_Typ) then pragma Assert (Is_Traversal_Function (Subp)); - if Nkind (Expr) /= N_Null and then Emit_Messages then + if Nkind (Expr) /= N_Null then declare Expr_Root : constant Entity_Id := - Get_Root_Object (Expr); + Get_Root_Object (Expr, Is_Traversal => True); Param : constant Entity_Id := First_Formal (Subp); begin - if Param /= Expr_Root then + if Param /= Expr_Root and then Emit_Messages then Error_Msg_NE ("returned value must be rooted in " & "traversed parameter & " @@ -3642,10 +3679,31 @@ package body Sem_SPARK is function Get_Root_Object (Expr : Node_Id; - Through_Traversal : Boolean := True) return Entity_Id + Through_Traversal : Boolean := True; + Is_Traversal : Boolean := False) return Entity_Id is + function GRO (Expr : Node_Id) return Entity_Id; + -- Local wrapper on the actual function, to propagate the values of + -- optional parameters. + + --------- + -- GRO -- + --------- + + function GRO (Expr : Node_Id) return Entity_Id is + begin + return Get_Root_Object (Expr, Through_Traversal, Is_Traversal); + end GRO; + + Get_Root_Object : Boolean; + pragma Unmodified (Get_Root_Object); + -- Local variable to mask the name of function Get_Root_Object, to + -- prevent direct call. Instead GRO wrapper should be called. + + -- Start of processing for Get_Root_Object + begin - if not Is_Subpath_Expression (Expr) then + if not Is_Subpath_Expression (Expr, Is_Traversal) then if Emit_Messages then Error_Msg_N ("name expected here for path", Expr); end if; @@ -3663,7 +3721,7 @@ package body Sem_SPARK is | N_Selected_Component | N_Slice => - return Get_Root_Object (Prefix (Expr), Through_Traversal); + return GRO (Prefix (Expr)); -- There is no root object for an (extension) aggregate, allocator, -- concat, or NULL. @@ -3684,7 +3742,7 @@ package body Sem_SPARK is if Through_Traversal and then Is_Traversal_Function_Call (Expr) then - return Get_Root_Object (First_Actual (Expr), Through_Traversal); + return GRO (First_Actual (Expr)); else return Empty; end if; @@ -3693,7 +3751,7 @@ package body Sem_SPARK is | N_Type_Conversion | N_Unchecked_Type_Conversion => - return Get_Root_Object (Expression (Expr), Through_Traversal); + return GRO (Expression (Expr)); when N_Attribute_Reference => pragma Assert @@ -3706,6 +3764,69 @@ package body Sem_SPARK is Attribute_Image); return Empty; + when N_If_Expression => + if Is_Traversal then + declare + Cond : constant Node_Id := First (Expressions (Expr)); + Then_Part : constant Node_Id := Next (Cond); + Else_Part : constant Node_Id := Next (Then_Part); + Then_Root : constant Entity_Id := GRO (Then_Part); + Else_Root : constant Entity_Id := GRO (Else_Part); + begin + if Nkind (Then_Part) = N_Null then + return Else_Root; + elsif Nkind (Else_Part) = N_Null then + return Then_Part; + elsif Then_Root = Else_Root then + return Then_Root; + else + if Emit_Messages then + Error_Msg_N + ("same name expected here in each branch", Expr); + end if; + return Empty; + end if; + end; + else + if Emit_Messages then + Error_Msg_N ("name expected here for path", Expr); + end if; + return Empty; + end if; + + when N_Case_Expression => + if Is_Traversal then + declare + Cases : constant List_Id := Alternatives (Expr); + Cur_Case : Node_Id := First (Cases); + Cur_Root : Entity_Id; + Common_Root : Entity_Id := Empty; + + begin + while Present (Cur_Case) loop + Cur_Root := GRO (Expression (Cur_Case)); + + if Common_Root = Empty then + Common_Root := Cur_Root; + elsif Common_Root /= Cur_Root then + if Emit_Messages then + Error_Msg_N + ("same name expected here in each branch", Expr); + end if; + return Empty; + end if; + Next (Cur_Case); + end loop; + + return Common_Root; + end; + else + if Emit_Messages then + Error_Msg_N ("name expected here for path", Expr); + end if; + return Empty; + end if; + when others => raise Program_Error; end case; @@ -3876,7 +3997,30 @@ package body Sem_SPARK is -- Is_Path_Expression -- ------------------------ - function Is_Path_Expression (Expr : Node_Id) return Boolean is + function Is_Path_Expression + (Expr : Node_Id; + Is_Traversal : Boolean := False) return Boolean + is + function IPE (Expr : Node_Id) return Boolean; + -- Local wrapper on the actual function, to propagate the values of + -- optional parameter Is_Traversal. + + --------- + -- IPE -- + --------- + + function IPE (Expr : Node_Id) return Boolean is + begin + return Is_Path_Expression (Expr, Is_Traversal); + end IPE; + + Is_Path_Expression : Boolean; + pragma Unmodified (Is_Path_Expression); + -- Local variable to mask the name of function Is_Path_Expression, to + -- prevent direct call. Instead IPE wrapper should be called. + + -- Start of processing for Is_Path_Expression + begin case Nkind (Expr) is when N_Expanded_Name @@ -3907,7 +4051,47 @@ package body Sem_SPARK is | N_Type_Conversion | N_Unchecked_Type_Conversion => - return Is_Path_Expression (Expression (Expr)); + return IPE (Expression (Expr)); + + -- When returning from a traversal function, consider an + -- if-expression as a possible path expression. + + when N_If_Expression => + if Is_Traversal then + declare + Cond : constant Node_Id := First (Expressions (Expr)); + Then_Part : constant Node_Id := Next (Cond); + Else_Part : constant Node_Id := Next (Then_Part); + begin + return IPE (Then_Part) + and then IPE (Else_Part); + end; + else + return False; + end if; + + -- When returning from a traversal function, consider + -- a case-expression as a possible path expression. + + when N_Case_Expression => + if Is_Traversal then + declare + Cases : constant List_Id := Alternatives (Expr); + Cur_Case : Node_Id := First (Cases); + + begin + while Present (Cur_Case) loop + if not IPE (Expression (Cur_Case)) then + return False; + end if; + Next (Cur_Case); + end loop; + + return True; + end; + else + return False; + end if; when others => return False; @@ -4033,9 +4217,12 @@ package body Sem_SPARK is -- Is_Subpath_Expression -- --------------------------- - function Is_Subpath_Expression (Expr : Node_Id) return Boolean is + function Is_Subpath_Expression + (Expr : Node_Id; + Is_Traversal : Boolean := False) return Boolean + is begin - return Is_Path_Expression (Expr) + return Is_Path_Expression (Expr, Is_Traversal) or else (Nkind (Expr) = N_Attribute_Reference and then (Get_Attribute_Id (Attribute_Name (Expr)) = -- cgit v1.1 From ad277369b236a39fff13c87a51a8e67f7562a80a Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Mon, 22 Jul 2019 13:58:27 +0000 Subject: [Ada] Remove misleading warning/suggestion in membership test This patch removes a warning on a membership test whose right operand is given by a range. In many cases the check can be replaced by the use of attribute 'Valid, but if the bounds of range are type conversion this replacement would be invorrect and the warning and suggestion are misleading. 2019-07-22 Ed Schonberg gcc/ada/ * exp_ch4.adb (Expand_N_In): Do not suggest the use of attribute 'Valid as a replacement for a range check on a discrete type when the bounds of the range are given by type conversions, because in such a case there are distinct types involved and the subbested attribute replacement would be misplaced. gcc/testsuite/ * gnat.dg/warn26.adb: New testcase. From-SVN: r273694 --- gcc/ada/ChangeLog | 8 ++++++++ gcc/ada/exp_ch4.adb | 9 +++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/warn26.adb | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/warn26.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 17d21f5..ef32945 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2019-07-22 Ed Schonberg + + * exp_ch4.adb (Expand_N_In): Do not suggest the use of attribute + 'Valid as a replacement for a range check on a discrete type + when the bounds of the range are given by type conversions, + because in such a case there are distinct types involved and the + subbested attribute replacement would be misplaced. + 2019-07-22 Yannick Moy * sem_spark.adb (Get_Root_Object, Is_Path_Expression, diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index a062434..7ef75f6 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -6272,6 +6272,10 @@ package body Exp_Ch4 is -- Similarly, do not rewrite membership as a validity check if -- within the predicate function for the type. + -- Finally, if the original bounds are type conversions, even + -- if they have been folded into constants, there are different + -- types involved and 'Valid is not appropriate. + then if In_Instance or else (Ekind (Current_Scope) = E_Function @@ -6279,6 +6283,11 @@ package body Exp_Ch4 is then null; + elsif Nkind (Lo_Orig) = N_Type_Conversion + or else Nkind (Hi_Orig) = N_Type_Conversion + then + null; + else Substitute_Valid_Check; goto Leave; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2ac298f..d8daa2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Ed Schonberg + + * gnat.dg/warn26.adb: New testcase. + 2019-07-22 Javier Miranda * gnat.dg/class_wide5.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/warn26.adb b/gcc/testsuite/gnat.dg/warn26.adb new file mode 100644 index 0000000..08b681f --- /dev/null +++ b/gcc/testsuite/gnat.dg/warn26.adb @@ -0,0 +1,20 @@ +-- { dg-do compile } + +procedure Warn26 is + + Monitor_Period_Min : constant := 5; + Monitor_Period_Max : constant := 30; + + type Monitor_Period is range Monitor_Period_Min .. Monitor_Period_Max; + + subtype Period_T is Positive range 5 .. 30; + + function Id (X : Period_T) return Period_T is (X); + Input_Period : Period_T := Id (20); +begin + if Input_Period in + Integer (Monitor_Period'First) .. Integer ( Monitor_Period'Last) + then + null; + end if; +end Warn26; -- cgit v1.1 From 267c7ff6a07158cb9b904a8a5182ab498b039c72 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:58:32 +0000 Subject: [Ada] Fix missing check for no-op conversion to fixed-point type This plugs a small loophole in the compiler for the case of a multiplication or a division in a fixed-point type wrapped in a no-op conversion, e.g. to the same fixed-point type. The front-end fails to generate a range check for the operation. This used to be caught by the back-end, which would generate the range check, but this is no longer the case because we now make sure to reset the Do_Range_Check flag in all cases before invoking the back-end. 2019-07-22 Eric Botcazou gcc/ada/ * exp_ch4.adb (Expand_N_Type_Conversion): Beef up comment. (Fixup_Universal_Fixed_Operation): Set the base type instead of the type of the enclosing type conversion on the operation. gcc/testsuite/ * gnat.dg/fixedpnt6.adb: New testcase. From-SVN: r273695 --- gcc/ada/ChangeLog | 6 ++++++ gcc/ada/exp_ch4.adb | 9 ++++++--- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/fixedpnt6.adb | 21 +++++++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/fixedpnt6.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ef32945..e9b1c3f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-07-22 Eric Botcazou + + * exp_ch4.adb (Expand_N_Type_Conversion): Beef up comment. + (Fixup_Universal_Fixed_Operation): Set the base type instead of + the type of the enclosing type conversion on the operation. + 2019-07-22 Ed Schonberg * exp_ch4.adb (Expand_N_In): Do not suggest the use of attribute diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 7ef75f6..dc2146c 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -12072,7 +12072,10 @@ package body Exp_Ch4 is -- Check: are these rules stated in sinfo??? if so, why restate here??? -- The only remaining step is to generate a range check if we still have - -- a type conversion at this stage and Do_Range_Check is set. + -- a type conversion at this stage and Do_Range_Check is set. Note that + -- we need to deal with at most 8 out of the 9 possible cases of numeric + -- conversions here, because the float-to-integer case is entirely dealt + -- with by Apply_Float_Conversion_Check. if Nkind (N) = N_Type_Conversion and then Do_Range_Check (Expression (N)) @@ -12726,13 +12729,13 @@ package body Exp_Ch4 is if Nkind (Parent (Conv)) = N_Attribute_Reference and then Attribute_Name (Parent (Conv)) = Name_Round then - Set_Etype (N, Etype (Parent (Conv))); + Set_Etype (N, Base_Type (Etype (Parent (Conv)))); Set_Rounded_Result (N); -- Normal case where type comes from conversion above us else - Set_Etype (N, Etype (Conv)); + Set_Etype (N, Base_Type (Etype (Conv))); end if; end Fixup_Universal_Fixed_Operation; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d8daa2d..9d20101 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-22 Eric Botcazou + + * gnat.dg/fixedpnt6.adb: New testcase. + 2019-07-22 Ed Schonberg * gnat.dg/warn26.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/fixedpnt6.adb b/gcc/testsuite/gnat.dg/fixedpnt6.adb new file mode 100644 index 0000000..01c1747 --- /dev/null +++ b/gcc/testsuite/gnat.dg/fixedpnt6.adb @@ -0,0 +1,21 @@ +-- { dg-do run } +-- { dg-options "-O0" } + +procedure Fixedpnt6 is + + type T is delta 0.125 range -2.0 .. 1.875; + + function Mult (A, B : T) return T is + begin + return T (A * B); + end; + + R : T; + +begin + R := Mult (T'Last, T'Last); + raise Program_Error; +exception + when Constraint_Error => + null; +end; -- cgit v1.1 From ae3f6530573deaa7485be45662e506af7a56cfa9 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:58:37 +0000 Subject: [Ada] Sinfo: update doc about Do_Division/Overlflow/Range_Check 2019-07-22 Eric Botcazou gcc/ada/ * sinfo.ads: Update the documentation about the Do_Division_Check, Do_Overflow_Check and Do_Range_Check flags. From-SVN: r273696 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/sinfo.ads | 43 +++++++++++++++++-------------------------- 2 files changed, 22 insertions(+), 26 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e9b1c3f..26af730 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-22 Eric Botcazou + * sinfo.ads: Update the documentation about the + Do_Division_Check, Do_Overflow_Check and Do_Range_Check flags. + +2019-07-22 Eric Botcazou + * exp_ch4.adb (Expand_N_Type_Conversion): Beef up comment. (Fixup_Universal_Fixed_Operation): Set the base type instead of the type of the enclosing type conversion on the operation. diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index 6310016..064147e 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -755,14 +755,15 @@ package Sinfo is -- Do_Division_Check flag on float exponentiation expressions, for the case -- where the value is 0.0 and the exponent is negative, although this case -- does lead to a division check failure. As another special case, - -- the frontend does not insert a Do_Range_Check on an allocator where + -- the front end does not insert a Do_Range_Check on an allocator where -- the designated type is scalar, and the designated type is more -- constrained than the type of the initialized allocator value or the type -- of the default value for an uninitialized allocator. - -- Note: the expander always takes care of the Do_Range check case, - -- so this flag will never be set in the expanded tree passed to the - -- back end code generator. + -- Note that the expander always takes care of the Do_Range_Check case, so + -- this flag will never be set in the expanded tree passed to the back end. + -- For the other two flags, the check can be generated either by the back + -- end or by the front end, depending on the setting of a target parameter. -- Note that this accounts for all nodes that trigger the corresponding -- checks, except for range checks on subtype_indications, which may be @@ -1186,9 +1187,10 @@ package Sinfo is -- conversion nodes (and set if the conversion requires a check). -- Do_Division_Check (Flag13-Sem) - -- This flag is set on a division operator (/ mod rem) to indicate - -- that a zero divide check is required. The actual check is dealt - -- with by the backend (all the front end does is to set the flag). + -- This flag is set on a division operator (/ mod rem) to indicate that + -- a zero divide check is required. The actual check is either dealt with + -- by the back end if Backend_Divide_Checks is set to true, or by the + -- front end itself if it is set to false. -- Do_Length_Check (Flag4-Sem) -- This flag is set in an N_Assignment_Statement, N_Op_And, N_Op_Or, @@ -1197,15 +1199,13 @@ package Sinfo is -- Do_Overflow_Check (Flag17-Sem) -- This flag is set on an operator where an overflow check is required on - -- the operation. The actual check is dealt with by the backend (all the - -- front end does is to set the flag). The other cases where this flag is - -- used is on a Type_Conversion node and for attribute reference nodes. + -- the operation. The actual check is either dealt with by the back end + -- if Backend_Overflow_Checks is set to true, or by the front end itself + -- if it is set to false. The other cases where this flag is used is on a + -- Type_Conversion node as well on if and case expression nodes. -- For a type conversion, it means that the conversion is from one base -- type to another, and the value may not fit in the target base type. - -- See also the description of Do_Range_Check for this case. The only - -- attribute references which use this flag are Pred and Succ, where it - -- means that the result should be checked for going outside the base - -- range. Note that this flag is not set for modular types. This flag is + -- See also the description of Do_Range_Check for this case. This flag is -- also set on if and case expression nodes if we are operating in either -- MINIMIZED or ELIMINATED overflow checking mode (to make sure that we -- properly process overflow checking for dependent expressions). @@ -1215,9 +1215,9 @@ package Sinfo is -- range check is required. The target type is clear from the context. -- The contexts in which this flag can appear are the following: - -- Right side of an assignment. In this case the target type is - -- taken from the left side of the assignment, which is referenced - -- by the Name of the N_Assignment_Statement node. + -- Right side of an assignment. In this case the target type is taken + -- from the left side of the assignment, which is referenced by the + -- Name of the N_Assignment_Statement node. -- Subscript expressions in an indexed component. In this case the -- target type is determined from the type of the array, which is @@ -1251,15 +1251,6 @@ package Sinfo is -- listed above (e.g. in a return statement), an additional type -- conversion node is introduced to represent the required check. - -- A special case arises for the arguments of the Pred/Succ attributes. - -- Here the range check needed is against First + 1 .. Last (Pred) or - -- First .. Last - 1 (Succ) of the corresponding base type. Essentially - -- these checks are what would be performed within the implicit body of - -- the functions that correspond to these attributes. In these cases, - -- the Do_Range check flag is set on the argument to the attribute - -- function, and the back end must special case the appropriate range - -- to check against. - -- Do_Storage_Check (Flag17-Sem) -- This flag is set in an N_Allocator node to indicate that a storage -- check is required for the allocation, or in an N_Subprogram_Body node -- cgit v1.1 From 46ebb491f19cfdb9c8953afc0f30c6417555a2c1 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Jul 2019 13:58:41 +0000 Subject: [Ada] More complete information level for -gnatR4 output This instructs -gnatR4 to also list the Etype of user-declared objects if it is compiler-generated, for example in: package P2 is Arr_V : array (1 .. 5) of Integer; end P2; 2019-07-22 Eric Botcazou gcc/ada/ * repinfo.adb (List_Entities): Also list compiled-generated types present as Etype of objects. From-SVN: r273697 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/repinfo.adb | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 26af730..db77736 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-07-22 Eric Botcazou + * repinfo.adb (List_Entities): Also list compiled-generated + types present as Etype of objects. + +2019-07-22 Eric Botcazou + * sinfo.ads: Update the documentation about the Do_Division_Check, Do_Overflow_Check and Do_Range_Check flags. diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index c378fb6..a277bab 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -563,6 +563,13 @@ package body Repinfo is E_Loop_Parameter, E_Variable) then + -- The type is relevant for an object + + if List_Representation_Info = 4 and then Is_Itype (Etype (E)) + then + Relevant_Entities.Set (Etype (E), True); + end if; + if List_Representation_Info >= 2 then List_Object_Info (E); end if; -- cgit v1.1 From 1c4547f16138b69f955fdc24c9523e7f8d28aa15 Mon Sep 17 00:00:00 2001 From: "Paul A. Clarke" Date: Mon, 22 Jul 2019 14:07:10 +0000 Subject: [rs6000] Add _mm_blend_epi16 and _mm_blendv_epi8 Add compatibility implementations of _mm_blend_epi16 and _mm_blendv_epi8 intrinsics. Respective test cases are copied almost verbatim (minor changes to the dejagnu head lines) from i386. 2019-07-22 Paul A. Clarke [gcc] * config/rs6000/smmintrin.h (_mm_blend_epi16): New. (_mm_blendv_epi8): New. [gcc/testsuite] * gcc.target/powerpc/sse4_1-check.h: New. * gcc.target/powerpc/sse4_1-pblendvb.c: New. * gcc.target/powerpc/sse4_1-pblendw.c: New. * gcc.target/powerpc/sse4_1-pblendw-2.c: New. From-SVN: r273698 --- gcc/ChangeLog | 5 ++ gcc/config/rs6000/smmintrin.h | 20 +++++ gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/gcc.target/powerpc/sse4_1-check.h | 27 +++++++ gcc/testsuite/gcc.target/powerpc/sse4_1-pblendvb.c | 71 +++++++++++++++++ .../gcc.target/powerpc/sse4_1-pblendw-2.c | 80 +++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw.c | 89 ++++++++++++++++++++++ 7 files changed, 299 insertions(+) create mode 100644 gcc/testsuite/gcc.target/powerpc/sse4_1-check.h create mode 100644 gcc/testsuite/gcc.target/powerpc/sse4_1-pblendvb.c create mode 100644 gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw-2.c create mode 100644 gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e58dfe1..eb786a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Paul A. Clarke + + * config/rs6000/smmintrin.h (_mm_blend_epi16): New. + (_mm_blendv_epi8): New. + 2019-07-22 Richard Biener PR tree-optimization/91221 diff --git a/gcc/config/rs6000/smmintrin.h b/gcc/config/rs6000/smmintrin.h index 914dade..5ef0822 100644 --- a/gcc/config/rs6000/smmintrin.h +++ b/gcc/config/rs6000/smmintrin.h @@ -66,4 +66,24 @@ _mm_extract_ps (__m128 __X, const int __N) return ((__v4si)__X)[__N & 3]; } +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blend_epi16 (__m128i __A, __m128i __B, const int __imm8) +{ + __v16qi __charmask = vec_splats ((signed char) __imm8); + __charmask = vec_gb (__charmask); + __v8hu __shortmask = (__v8hu) vec_unpackh (__charmask); + #ifdef __BIG_ENDIAN__ + __shortmask = vec_reve (__shortmask); + #endif + return (__m128i) vec_sel ((__v8hu) __A, (__v8hu) __B, __shortmask); +} + +extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_blendv_epi8 (__m128i __A, __m128i __B, __m128i __mask) +{ + const __v16qu __seven = vec_splats ((unsigned char) 0x07); + __v16qu __lmask = vec_sra ((__v16qu) __mask, __seven); + return (__m128i) vec_sel ((__v16qu) __A, (__v16qu) __B, __lmask); +} + #endif diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9d20101..d005ca6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Paul A. Clarke + + * gcc.target/powerpc/sse4_1-check.h: New. + * gcc.target/powerpc/sse4_1-pblendvb.c: New. + * gcc.target/powerpc/sse4_1-pblendw.c: New. + * gcc.target/powerpc/sse4_1-pblendw-2.c: New. + 2019-07-22 Eric Botcazou * gnat.dg/fixedpnt6.adb: New testcase. diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-check.h b/gcc/testsuite/gcc.target/powerpc/sse4_1-check.h new file mode 100644 index 0000000..5f855b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-check.h @@ -0,0 +1,27 @@ +#include +#include + +#include "m128-check.h" + +//#define DEBUG 1 + +#define TEST sse4_1_test + +static void sse4_1_test (void); + +static void +__attribute__ ((noinline)) +do_test (void) +{ + sse4_1_test (); +} + +int +main () +{ + do_test (); +#ifdef DEBUG + printf ("PASSED\n"); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendvb.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendvb.c new file mode 100644 index 0000000..6aa77fe --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendvb.c @@ -0,0 +1,71 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mpower8-vector -Wno-psabi" } */ +/* { dg-require-effective-target p8vector_hw } */ + +#define NO_WARN_X86_INTRINSICS 1 +#ifndef CHECK_H +#define CHECK_H "sse4_1-check.h" +#endif + +#ifndef TEST +#define TEST sse4_1_test +#endif + +#include CHECK_H + +#include +#include + +#define NUM 20 + +static void +init_pblendvb (unsigned char *src1, unsigned char *src2, + unsigned char *mask) +{ + int i, sign = 1; + + for (i = 0; i < NUM * 16; i++) + { + src1[i] = i* i * sign; + src2[i] = (i + 20) * sign; + mask[i] = (i % 3) + ((i * (14 + sign)) + ^ (src1[i] | src2[i] | (i*3))); + sign = -sign; + } +} + +static int +check_pblendvb (__m128i *dst, unsigned char *src1, + unsigned char *src2, unsigned char *mask) +{ + unsigned char tmp[16]; + int j; + + memcpy (&tmp[0], src1, sizeof (tmp)); + for (j = 0; j < 16; j++) + if (mask [j] & 0x80) + tmp[j] = src2[j]; + + return memcmp (dst, &tmp[0], sizeof (tmp)); +} + +static void +TEST (void) +{ + union + { + __m128i x[NUM]; + unsigned char c[NUM * 16]; + } dst, src1, src2, mask; + int i; + + init_pblendvb (src1.c, src2.c, mask.c); + + for (i = 0; i < NUM; i++) + { + dst.x[i] = _mm_blendv_epi8 (src1.x[i], src2.x[i], mask.x[i]); + if (check_pblendvb (&dst.x[i], &src1.c[i * 16], &src2.c[i * 16], + &mask.c[i * 16])) + abort (); + } +} diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw-2.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw-2.c new file mode 100644 index 0000000..d3f96e8 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw-2.c @@ -0,0 +1,80 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mpower8-vector -Wno-psabi" } */ +/* { dg-require-effective-target p8vector_hw } */ + +#define NO_WARN_X86_INTRINSICS 1 +#include "sse4_1-check.h" + +#include +#include + +#define NUM 20 + +#undef MASK +#define MASK 0xfe + +static void +init_pblendw (short *src1, short *src2) +{ + int i, sign = 1; + + for (i = 0; i < NUM * 8; i++) + { + src1[i] = i * i * sign; + src2[i] = (i + 20) * sign; + sign = -sign; + } +} + +static int +check_pblendw (__m128i *dst, short *src1, short *src2) +{ + short tmp[8]; + int j; + + memcpy (&tmp[0], src1, sizeof (tmp)); + for (j = 0; j < 8; j++) + if ((MASK & (1 << j))) + tmp[j] = src2[j]; + + return memcmp (dst, &tmp[0], sizeof (tmp)); +} + +static void +sse4_1_test (void) +{ + __m128i x, y; + union + { + __m128i x[NUM]; + short s[NUM * 8]; + } dst, src1, src2; + union + { + __m128i x; + short s[8]; + } src3; + int i; + + init_pblendw (src1.s, src2.s); + + /* Check pblendw imm8, m128, xmm */ + for (i = 0; i < NUM; i++) + { + dst.x[i] = _mm_blend_epi16 (src1.x[i], src2.x[i], MASK); + if (check_pblendw (&dst.x[i], &src1.s[i * 8], &src2.s[i * 8])) + abort (); + } + + /* Check pblendw imm8, xmm, xmm */ + src3.x = _mm_setzero_si128 (); + + x = _mm_blend_epi16 (dst.x[2], src3.x, MASK); + y = _mm_blend_epi16 (src3.x, dst.x[2], MASK); + + if (check_pblendw (&x, &dst.s[16], &src3.s[0])) + abort (); + + if (check_pblendw (&y, &src3.s[0], &dst.s[16])) + abort (); +} diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw.c b/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw.c new file mode 100644 index 0000000..1c48c76 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/sse4_1-pblendw.c @@ -0,0 +1,89 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -mpower8-vector -Wno-psabi" } */ +/* { dg-require-effective-target p8vector_hw } */ + +#define NO_WARN_X86_INTRINSICS 1 +#ifndef CHECK_H +#define CHECK_H "sse4_1-check.h" +#endif + +#ifndef TEST +#define TEST sse4_1_test +#endif + +#include CHECK_H + +#include +#include + +#define NUM 20 + +#ifndef MASK +#define MASK 0x0f +#endif + +static void +init_pblendw (short *src1, short *src2) +{ + int i, sign = 1; + + for (i = 0; i < NUM * 8; i++) + { + src1[i] = i * i * sign; + src2[i] = (i + 20) * sign; + sign = -sign; + } +} + +static int +check_pblendw (__m128i *dst, short *src1, short *src2) +{ + short tmp[8]; + int j; + + memcpy (&tmp[0], src1, sizeof (tmp)); + for (j = 0; j < 8; j++) + if ((MASK & (1 << j))) + tmp[j] = src2[j]; + + return memcmp (dst, &tmp[0], sizeof (tmp)); +} + +static void +TEST (void) +{ + __m128i x, y; + union + { + __m128i x[NUM]; + short s[NUM * 8]; + } dst, src1, src2; + union + { + __m128i x; + short s[8]; + } src3; + int i; + + init_pblendw (src1.s, src2.s); + + /* Check pblendw imm8, m128, xmm */ + for (i = 0; i < NUM; i++) + { + dst.x[i] = _mm_blend_epi16 (src1.x[i], src2.x[i], MASK); + if (check_pblendw (&dst.x[i], &src1.s[i * 8], &src2.s[i * 8])) + abort (); + } + + /* Check pblendw imm8, xmm, xmm */ + src3.x = _mm_setzero_si128 (); + + x = _mm_blend_epi16 (dst.x[2], src3.x, MASK); + y = _mm_blend_epi16 (src3.x, dst.x[2], MASK); + + if (check_pblendw (&x, &dst.s[16], &src3.s[0])) + abort (); + + if (check_pblendw (&y, &src3.s[0], &dst.s[16])) + abort (); +} -- cgit v1.1 From 9afb91b2d1aeabf49a2b76556ec6fe18dd5790f9 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Mon, 22 Jul 2019 15:33:58 +0000 Subject: [jit] check result_type in gcc_jit_context_new_unary_op 2019-07-22 Andrea Corallo * jit-recording.c (unary_op_reproducer_strings): Make it extern. (binary_op_reproducer_strings): Likewise. * jit-recording.h (unary_op_reproducer_strings): Likewise. (binary_op_reproducer_strings): Likewise. * libgccjit.c (gcc_jit_context_new_unary_op): Check result_type to be a numeric type. * libgccjit.c (gcc_jit_context_new_binary_op): Improve error message. 2019-07-22 Andrea Corallo * jit.dg/test-error-gcc_jit_context_new_unary_op-bad-res-type.c: New testcase. * jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c: Adjust error message. From-SVN: r273700 --- gcc/jit/ChangeLog | 10 ++++++ gcc/jit/jit-recording.c | 4 +-- gcc/jit/jit-recording.h | 3 ++ gcc/jit/libgccjit.c | 14 ++++++-- gcc/testsuite/ChangeLog | 7 ++++ ...or-gcc_jit_context_new_binary_op-bad-res-type.c | 6 ++-- ...ror-gcc_jit_context_new_unary_op-bad-res-type.c | 38 ++++++++++++++++++++++ 7 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_unary_op-bad-res-type.c (limited to 'gcc') diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 41cb60f..af3f6b7 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,13 @@ +2019-07-22 Andrea Corallo + + * jit-recording.c (unary_op_reproducer_strings): Make it extern. + (binary_op_reproducer_strings): Likewise. + * jit-recording.h (unary_op_reproducer_strings): Likewise. + (binary_op_reproducer_strings): Likewise. + * libgccjit.c (gcc_jit_context_new_unary_op): Check result_type to be a + numeric type. + * libgccjit.c (gcc_jit_context_new_binary_op): Improve error message. + 2019-07-04 Andrea Corallo * libgccjit.c (gcc_jit_context_new_binary_op): Check result_type to be a diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 495ac7f..2f75395 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -4888,7 +4888,7 @@ recording::unary_op::make_debug_string () m_a->get_debug_string ()); } -static const char * const unary_op_reproducer_strings[] = { +const char * const unary_op_reproducer_strings[] = { "GCC_JIT_UNARY_OP_MINUS", "GCC_JIT_UNARY_OP_BITWISE_NEGATE", "GCC_JIT_UNARY_OP_LOGICAL_NEGATE", @@ -4968,7 +4968,7 @@ recording::binary_op::make_debug_string () m_b->get_debug_string_parens (prec)); } -static const char * const binary_op_reproducer_strings[] = { +const char * const binary_op_reproducer_strings[] = { "GCC_JIT_BINARY_OP_PLUS", "GCC_JIT_BINARY_OP_MINUS", "GCC_JIT_BINARY_OP_MULT", diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 13ec7ea..4bd346e 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -30,6 +30,9 @@ namespace gcc { namespace jit { +extern const char * const unary_op_reproducer_strings[]; +extern const char * const binary_op_reproducer_strings[]; + class result; class dump; class reproducer; diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 23e83e2..eec2f00 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -1336,6 +1336,13 @@ gcc_jit_context_new_unary_op (gcc_jit_context *ctxt, "unrecognized value for enum gcc_jit_unary_op: %i", op); RETURN_NULL_IF_FAIL (result_type, ctxt, loc, "NULL result_type"); + RETURN_NULL_IF_FAIL_PRINTF3 ( + result_type->is_numeric (), ctxt, loc, + "gcc_jit_unary_op %s with operand %s " + "has non-numeric result_type: %s", + gcc::jit::unary_op_reproducer_strings[op], + rvalue->get_debug_string (), + result_type->get_debug_string ()); RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); return (gcc_jit_rvalue *)ctxt->new_unary_op (loc, op, result_type, rvalue); @@ -1387,9 +1394,10 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, b->get_type ()->get_debug_string ()); RETURN_NULL_IF_FAIL_PRINTF4 ( result_type->is_numeric (), ctxt, loc, - "gcc_jit_binary_op %i with operands a: %s b: %s " - "has non numeric result_type: %s", - op, a->get_debug_string (), b->get_debug_string (), + "gcc_jit_binary_op %s with operands a: %s b: %s " + "has non-numeric result_type: %s", + gcc::jit::binary_op_reproducer_strings[op], + a->get_debug_string (), b->get_debug_string (), result_type->get_debug_string ()); return (gcc_jit_rvalue *)ctxt->new_binary_op (loc, op, result_type, a, b); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d005ca6..d45620e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Andrea Corallo + + * jit.dg/test-error-gcc_jit_context_new_unary_op-bad-res-type.c: + New testcase. + * jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c: + Adjust error message. + 2019-07-22 Paul A. Clarke * gcc.target/powerpc/sse4_1-check.h: New. diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c index abadc9f..fbbb2e7 100644 --- a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_binary_op-bad-res-type.c @@ -35,7 +35,7 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) /* Verify that the correct error message was emitted. */ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), - "gcc_jit_context_new_binary_op: gcc_jit_binary_op 1 with" - " operands a: (int)1 b: (int)2 has non numeric " - "result_type: void *"); + "gcc_jit_context_new_binary_op: gcc_jit_binary_op " + "GCC_JIT_BINARY_OP_MINUS with operands a: " + "(int)1 b: (int)2 has non-numeric result_type: void *"); } diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_unary_op-bad-res-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_unary_op-bad-res-type.c new file mode 100644 index 0000000..fae722a --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_unary_op-bad-res-type.c @@ -0,0 +1,38 @@ +#include +#include + +#include "libgccjit.h" + +#include "harness.h" + +/* Try to create an unary operator with invalid result type. */ + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + gcc_jit_type *void_ptr_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR); + + gcc_jit_context_new_unary_op ( + ctxt, + NULL, + GCC_JIT_UNARY_OP_LOGICAL_NEGATE, + void_ptr_type, + gcc_jit_context_new_rvalue_from_int (ctxt, + int_type, + 1)); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_VALUE (result, NULL); + + /* Verify that the correct error message was emitted. */ + CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), + "gcc_jit_context_new_unary_op: gcc_jit_unary_op " + "GCC_JIT_UNARY_OP_LOGICAL_NEGATE with operand " + "(int)1 has non-numeric result_type: void *"); +} -- cgit v1.1 From 310b5fb79316511295c04f956f4c6630437ba204 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Mon, 22 Jul 2019 16:02:29 +0000 Subject: MSP430: Don't save all callee-saved regs in non-leaf interrupt functions Previously, all callee-saved regs would unconditionally be saved in interrupt functions that call another function. 2019-07-22 Jozef Lawrynowicz * config/msp430/msp430.c (msp430_preserve_reg_p): Don't save callee-saved regs R4->R10 in an interrupt function that calls another function. 2019-07-22 Jozef Lawrynowicz * gcc.target/msp430/isr-push-pop-main.c: New test. * gcc.target/msp430/isr-push-pop-isr-430.c: Likewise. * gcc.target/msp430/isr-push-pop-isr-430x.c: Likewise. * gcc.target/msp430/isr-push-pop-leaf-isr-430.c: Likewise. * gcc.target/msp430/isr-push-pop-leaf-isr-430x.c: Likewise. From-SVN: r273702 --- gcc/ChangeLog | 6 ++ gcc/config/msp430/msp430.c | 18 +++- gcc/testsuite/ChangeLog | 8 ++ .../gcc.target/msp430/isr-push-pop-isr-430.c | 13 +++ .../gcc.target/msp430/isr-push-pop-isr-430x.c | 12 +++ .../gcc.target/msp430/isr-push-pop-leaf-isr-430.c | 27 +++++ .../gcc.target/msp430/isr-push-pop-leaf-isr-430x.c | 24 +++++ .../gcc.target/msp430/isr-push-pop-main.c | 120 +++++++++++++++++++++ 8 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430.c create mode 100644 gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430x.c create mode 100644 gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430.c create mode 100644 gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430x.c create mode 100644 gcc/testsuite/gcc.target/msp430/isr-push-pop-main.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb786a0..687ae89 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-22 Jozef Lawrynowicz + + * config/msp430/msp430.c (msp430_preserve_reg_p): Don't save + callee-saved regs R4->R10 in an interrupt function that calls another + function. + 2019-07-22 Paul A. Clarke * config/rs6000/smmintrin.h (_mm_blend_epi16): New. diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index 365e9eb..265c2f6 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -1755,11 +1755,19 @@ msp430_preserve_reg_p (int regno) if (fixed_regs [regno]) return false; - /* Interrupt handlers save all registers they use, even - ones which are call saved. If they call other functions - then *every* register is saved. */ - if (msp430_is_interrupt_func ()) - return ! crtl->is_leaf || df_regs_ever_live_p (regno); + /* For interrupt functions we must save and restore the used regs that + would normally be caller-saved (R11->R15). */ + if (msp430_is_interrupt_func () && regno >= 11 && regno <= 15) + { + if (crtl->is_leaf && df_regs_ever_live_p (regno)) + /* If the interrupt func is a leaf then we only need to restore the + caller-saved regs that are used. */ + return true; + else if (!crtl->is_leaf) + /* If the interrupt function is not a leaf we must save all + caller-saved regs in case the callee modifies them. */ + return true; + } if (!call_used_regs [regno] && df_regs_ever_live_p (regno)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d45620e..ecd2a9e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-07-22 Jozef Lawrynowicz + + * gcc.target/msp430/isr-push-pop-main.c: New test. + * gcc.target/msp430/isr-push-pop-isr-430.c: Likewise. + * gcc.target/msp430/isr-push-pop-isr-430x.c: Likewise. + * gcc.target/msp430/isr-push-pop-leaf-isr-430.c: Likewise. + * gcc.target/msp430/isr-push-pop-leaf-isr-430x.c: Likewise. + 2019-07-22 Andrea Corallo * jit.dg/test-error-gcc_jit_context_new_unary_op-bad-res-type.c: diff --git a/gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430.c b/gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430.c new file mode 100644 index 0000000..a2bf843 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430x*" "-mlarge" } { "" } } */ +/* { dg-options "-mcpu=msp430" } */ +/* { dg-final { scan-assembler "PUSH\tR11" } } */ +/* { dg-final { scan-assembler-not "PUSH\tR10" } } */ + +void __attribute__((noinline)) callee (void); + +void __attribute__((interrupt)) +isr (void) +{ + callee(); +} diff --git a/gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430x.c b/gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430x.c new file mode 100644 index 0000000..2d65186 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/isr-push-pop-isr-430x.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" } { "" } } */ +/* { dg-final { scan-assembler "PUSHM.*#5" } } */ +/* { dg-final { scan-assembler-not "PUSHM.*#12" } } */ + +void __attribute__((noinline)) callee (void); + +void __attribute__((interrupt)) +isr (void) +{ + callee(); +} diff --git a/gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430.c b/gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430.c new file mode 100644 index 0000000..cbb4597 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430x*" "-mlarge" } { "" } } */ +/* { dg-options "-mcpu=msp430" } */ +/* { dg-final { scan-assembler "PUSH\tR5" } } */ +/* { dg-final { scan-assembler "PUSH\tR12" } } */ +/* { dg-final { scan-assembler-not "PUSH\tR4" } } */ +/* { dg-final { scan-assembler-not "PUSH\tR11" } } */ + +/* To check that the compiler doesn't blindly save all regs, we omit R4 and R11 + from the trashing. */ +#define TRASH_REGS_LITE \ + __asm__ ("mov #0xFFFF, r5" : : : "R5"); \ + __asm__ ("mov #0xFFFF, r6" : : : "R6"); \ + __asm__ ("mov #0xFFFF, r7" : : : "R7"); \ + __asm__ ("mov #0xFFFF, r8" : : : "R8"); \ + __asm__ ("mov #0xFFFF, r9" : : : "R9"); \ + __asm__ ("mov #0xFFFF, r10" : : : "R10"); \ + __asm__ ("mov #0xFFFF, r12" : : : "R12"); \ + __asm__ ("mov #0xFFFF, r13" : : : "R13"); \ + __asm__ ("mov #0xFFFF, r14" : : : "R14"); \ + __asm__ ("mov #0xFFFF, r15" : : : "R15"); + +void __attribute__((interrupt)) +isr_leaf (void) +{ + TRASH_REGS_LITE +} diff --git a/gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430x.c b/gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430x.c new file mode 100644 index 0000000..872a40e --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/isr-push-pop-leaf-isr-430x.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=msp430" } { "" } } */ +/* { dg-final { scan-assembler "PUSHM.*#4.*R15" } } */ +/* { dg-final { scan-assembler "PUSHM.*#6.*R10" } } */ + +/* To check that the compiler doesn't blindly save all regs, we omit R4 and R11 + from the trashing. */ +#define TRASH_REGS_LITE \ + __asm__ ("mov #0xFFFF, r5" : : : "R5"); \ + __asm__ ("mov #0xFFFF, r6" : : : "R6"); \ + __asm__ ("mov #0xFFFF, r7" : : : "R7"); \ + __asm__ ("mov #0xFFFF, r8" : : : "R8"); \ + __asm__ ("mov #0xFFFF, r9" : : : "R9"); \ + __asm__ ("mov #0xFFFF, r10" : : : "R10"); \ + __asm__ ("mov #0xFFFF, r12" : : : "R12"); \ + __asm__ ("mov #0xFFFF, r13" : : : "R13"); \ + __asm__ ("mov #0xFFFF, r14" : : : "R14"); \ + __asm__ ("mov #0xFFFF, r15" : : : "R15"); + +void __attribute__((interrupt)) +isr_leaf (void) +{ + TRASH_REGS_LITE +} diff --git a/gcc/testsuite/gcc.target/msp430/isr-push-pop-main.c b/gcc/testsuite/gcc.target/msp430/isr-push-pop-main.c new file mode 100644 index 0000000..5c7b594 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/isr-push-pop-main.c @@ -0,0 +1,120 @@ +/* { dg-do run } */ + +#ifdef __MSP430X__ +#include "isr-push-pop-isr-430x.c" +#include "isr-push-pop-leaf-isr-430x.c" +#else +#include "isr-push-pop-isr-430.c" +#include "isr-push-pop-leaf-isr-430.c" +#endif + +/* Test that ISRs which call other functions do not save extraneous registers. + They only need to save the caller-saved regs R11->R15. + We use a lot of asm statements to hide what is going on from the compiler to + more accurately simulate an interrupt. */ + +/* Store the register number in each general register R4->R15, so they can be + later checked their value has been kept. */ +#define SETUP_REGS \ + __asm__ ("mov #4, r4"); \ + __asm__ ("mov #5, r5"); \ + __asm__ ("mov #6, r6"); \ + __asm__ ("mov #7, r7"); \ + __asm__ ("mov #8, r8"); \ + __asm__ ("mov #9, r9"); \ + __asm__ ("mov #10, r10"); \ + __asm__ ("mov #11, r11"); \ + __asm__ ("mov #12, r12"); \ + __asm__ ("mov #13, r13"); \ + __asm__ ("mov #14, r14"); \ + __asm__ ("mov #15, r15"); + +/* Write an arbitrary value to all general regs. */ +#define TRASH_REGS \ + __asm__ ("mov #0xFFFF, r4" : : : "R4"); \ + __asm__ ("mov #0xFFFF, r5" : : : "R5"); \ + __asm__ ("mov #0xFFFF, r6" : : : "R6"); \ + __asm__ ("mov #0xFFFF, r7" : : : "R7"); \ + __asm__ ("mov #0xFFFF, r8" : : : "R8"); \ + __asm__ ("mov #0xFFFF, r9" : : : "R9"); \ + __asm__ ("mov #0xFFFF, r10" : : : "R10"); \ + __asm__ ("mov #0xFFFF, r11" : : : "R11"); \ + __asm__ ("mov #0xFFFF, r12" : : : "R12"); \ + __asm__ ("mov #0xFFFF, r13" : : : "R13"); \ + __asm__ ("mov #0xFFFF, r14" : : : "R14"); \ + __asm__ ("mov #0xFFFF, r15" : : : "R15"); + +/* Check the value in all general registers is the same as that set in + SETUP_REGS. */ +#define CHECK_REGS \ + __asm__ ("cmp #4, r4 { jne ABORT"); \ + __asm__ ("cmp #5, r5 { jne ABORT"); \ + __asm__ ("cmp #6, r6 { jne ABORT"); \ + __asm__ ("cmp #7, r7 { jne ABORT"); \ + __asm__ ("cmp #8, r8 { jne ABORT"); \ + __asm__ ("cmp #9, r9 { jne ABORT"); \ + __asm__ ("cmp #10, r10 { jne ABORT"); \ + __asm__ ("cmp #11, r11 { jne ABORT"); \ + __asm__ ("cmp #12, r12 { jne ABORT"); \ + __asm__ ("cmp #13, r13 { jne ABORT"); \ + __asm__ ("cmp #14, r14 { jne ABORT"); \ + __asm__ ("cmp #15, r15 { jne ABORT"); + +void __attribute__((noinline)) +callee (void) +{ + /* Here were modify all the regs, but tell the compiler that we are since + this is just a way to simulate a function that happens to modify all the + registers. */ + TRASH_REGS +} +int +#ifdef __MSP430X_LARGE__ +__attribute__((lower)) +#endif +main (void) +{ + SETUP_REGS + + /* A surprise branch to the ISR that the compiler cannot prepare for. + We must first simulate the interrupt acceptance procedure that the + hardware would normally take care of. + So push the desired PC return address, and then the SR (R2). + MSP430X expects the high bits 19:16 of the PC return address to be stored + in bits 12:15 of the SR stack slot. This is hard to handle in hand-rolled + assembly code, so we always place main() in lower memory so the return + address is 16-bits. */ + __asm__ ("push #CHECK1"); + __asm__ ("push r2"); + __asm__ ("br #isr"); + + __asm__ ("CHECK1:"); + /* If any of the regs R4->R15 don't match their original value, this will + jump to ABORT. */ + CHECK_REGS + + /* Now test that an interrupt function that is a leaf also works + correctly. */ + __asm__ ("push #CHECK2"); + __asm__ ("push r2"); + __asm__ ("br #isr_leaf"); + + __asm__ ("CHECK2:"); + CHECK_REGS + + /* The values in R4->R15 were successfully checked, now jump to FINISH to run + the prologue generated by the compiler. */ + __asm__ ("jmp FINISH"); + + /* CHECK_REGS will branch here if a register holds the wrong value. */ + __asm__ ("ABORT:"); +#ifdef __MSP430X_LARGE__ + __asm__ ("calla #abort"); +#else + __asm__ ("call #abort"); +#endif + + __asm__ ("FINISH:"); + return 0; +} + -- cgit v1.1 From 462e6f9a932a44ca73715dc5c2960e5b332f63f7 Mon Sep 17 00:00:00 2001 From: Sylvia Taylor Date: Mon, 22 Jul 2019 16:21:17 +0000 Subject: [aarch64]: add usra and ssra combine patterns This patch adds support to combine: 1) ushr and add into usra, example: ushr v0.16b, v0.16b, 2 add v0.16b, v0.16b, v2.16b --- usra v2.16b, v0.16b, 2 2) sshr and add into ssra, example: sshr v1.16b, v1.16b, 2 add v1.16b, v1.16b, v3.16b --- ssra v3.16b, v1.16b, 2 Committed on behalf of Sylvia Taylor . Reviewed-by: gcc/ChangeLog: * config/aarch64/aarch64-simd.md (*aarch64_simd_sra): New. * config/aarch64/iterators.md (SHIFTRT): New iterator. (sra_op): New attribute. gcc/testsuite/ChangeLog: * gcc.target/aarch64/simd/ssra.c: New test. * gcc.target/aarch64/simd/usra.c: New test. From-SVN: r273703 --- gcc/ChangeLog | 8 +++++++ gcc/config/aarch64/aarch64-simd.md | 12 ++++++++++ gcc/config/aarch64/iterators.md | 5 ++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.target/aarch64/simd/ssra.c | 36 ++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/simd/usra.c | 36 ++++++++++++++++++++++++++++ 6 files changed, 102 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/simd/ssra.c create mode 100644 gcc/testsuite/gcc.target/aarch64/simd/usra.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 687ae89..faa3bde 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-07-22 Sylvia Taylor + + * config/aarch64/aarch64-simd.md + (*aarch64_simd_sra): New. + * config/aarch64/iterators.md + (SHIFTRT): New iterator. + (sra_op): New attribute. + 2019-07-22 Jozef Lawrynowicz * config/msp430/msp430.c (msp430_preserve_reg_p): Don't save diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index d480e43..c6ccc99 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -986,6 +986,18 @@ [(set_attr "type" "neon_shift_imm")] ) +(define_insn "*aarch64_simd_sra" + [(set (match_operand:VDQ_I 0 "register_operand" "=w") + (plus:VDQ_I + (SHIFTRT:VDQ_I + (match_operand:VDQ_I 1 "register_operand" "w") + (match_operand:VDQ_I 2 "aarch64_simd_rshift_imm" "Dr")) + (match_operand:VDQ_I 3 "register_operand" "0")))] + "TARGET_SIMD" + "sra\t%0., %1., %2" + [(set_attr "type" "neon_shift_acc")] +) + (define_insn "aarch64_simd_imm_shl" [(set (match_operand:VDQ_I 0 "register_operand" "=w") (ashift:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w") diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 410423b..198fc5d 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -1169,6 +1169,8 @@ ;; This code iterator allows the shifts supported in arithmetic instructions (define_code_iterator ASHIFT [ashift ashiftrt lshiftrt]) +(define_code_iterator SHIFTRT [ashiftrt lshiftrt]) + ;; Code iterator for logical operations (define_code_iterator LOGICAL [and ior xor]) @@ -1351,6 +1353,9 @@ (define_code_attr shift [(ashift "lsl") (ashiftrt "asr") (lshiftrt "lsr") (rotatert "ror")]) +;; Op prefix for shift right and accumulate. +(define_code_attr sra_op [(ashiftrt "s") (lshiftrt "u")]) + ;; Map shift operators onto underlying bit-field instructions (define_code_attr bfshift [(ashift "ubfiz") (ashiftrt "sbfx") (lshiftrt "ubfx") (rotatert "extr")]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ecd2a9e..2b3e477 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Sylvia Taylor + + * gcc.target/aarch64/simd/ssra.c: New test. + * gcc.target/aarch64/simd/usra.c: New test. + 2019-07-22 Jozef Lawrynowicz * gcc.target/msp430/isr-push-pop-main.c: New test. diff --git a/gcc/testsuite/gcc.target/aarch64/simd/ssra.c b/gcc/testsuite/gcc.target/aarch64/simd/ssra.c new file mode 100644 index 0000000..e9c2e04 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/simd/ssra.c @@ -0,0 +1,36 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-O3" } */ +/* { dg-skip-if "" { *-*-* } {"*sve*"} {""} } */ + +#include + +#define SSRA(func, vtype, n) \ + void func () \ + { \ + int i; \ + for (i = 0; i < n; i++) \ + { \ + s1##vtype[i] += s2##vtype[i] >> 2; \ + } \ + } + +#define TEST_VDQ_I_MODES(FUNC) \ + FUNC (test_v8qi_v16qi, _char, 16) \ + FUNC (test_v4hi_v8h1, _short, 8) \ + FUNC (test_v2si_v4si, _int, 4) \ + FUNC (test_v2di, _ll, 2) \ + +int8_t s1_char[16], s2_char[16]; +int16_t s1_short[8], s2_short[8]; +int32_t s1_int[4], s2_int[4]; +int64_t s1_ll[2], s2_ll[2]; + +TEST_VDQ_I_MODES(SSRA) + +/* { dg-final { scan-assembler "ssra" } } */ +/* { dg-final { scan-assembler-not "sshr" } } */ + +/* { dg-final { scan-assembler-times {ssra\tv[0-9]+\.16b, v[0-9]+\.16b, [0-9]+} 1 } } */ +/* { dg-final { scan-assembler-times {ssra\tv[0-9]+\.8h, v[0-9]+\.8h, [0-9]+} 1 } } */ +/* { dg-final { scan-assembler-times {ssra\tv[0-9]+\.4s, v[0-9]+\.4s, [0-9]+} 1 } } */ +/* { dg-final { scan-assembler-times {ssra\tv[0-9]+\.2d, v[0-9]+\.2d, [0-9]+} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/simd/usra.c b/gcc/testsuite/gcc.target/aarch64/simd/usra.c new file mode 100644 index 0000000..4e7446d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/simd/usra.c @@ -0,0 +1,36 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-O3" } */ +/* { dg-skip-if "" { *-*-* } {"*sve*"} {""} } */ + +#include + +#define USRA(func, vtype, n) \ + void func () \ + { \ + int i; \ + for (i = 0; i < n; i++) \ + { \ + u1##vtype[i] += u2##vtype[i] >> 2; \ + } \ + } + +#define TEST_VDQ_I_MODES(FUNC) \ + FUNC (test_v8qi_v16qi, _char, 16) \ + FUNC (test_v4hi_v8h1, _short, 8) \ + FUNC (test_v2si_v4si, _int, 4) \ + FUNC (test_v2di, _ll, 2) \ + +uint8_t u1_char[16], u2_char[16]; +uint16_t u1_short[8], u2_short[8]; +uint32_t u1_int[4], u2_int[4]; +uint64_t u1_ll[2], u2_ll[2]; + +TEST_VDQ_I_MODES(USRA) + +/* { dg-final { scan-assembler "usra" } } */ +/* { dg-final { scan-assembler-not "ushr" } } */ + +/* { dg-final { scan-assembler-times {usra\tv[0-9]+\.16b, v[0-9]+\.16b, [0-9]+} 1 } } */ +/* { dg-final { scan-assembler-times {usra\tv[0-9]+\.8h, v[0-9]+\.8h, [0-9]+} 1 } } */ +/* { dg-final { scan-assembler-times {usra\tv[0-9]+\.4s, v[0-9]+\.4s, [0-9]+} 1 } } */ +/* { dg-final { scan-assembler-times {usra\tv[0-9]+\.2d, v[0-9]+\.2d, [0-9]+} 1 } } */ -- cgit v1.1 From 34e646226fd083e18ae6e07a9ceb18e59bc20077 Mon Sep 17 00:00:00 2001 From: Giuliano Belinassi Date: Mon, 22 Jul 2019 21:41:48 +0000 Subject: cgraph.c (dump_graphviz): New function. * cgraph.c (dump_graphviz): New function. * cgraph.h (dump_graphviz): New function. * symtab.c (dump_graphviz): New function. * lang.opt (flag_dump_callgraph): New flag. * lto-dump.c (dump_symtab_graphviz): New function. (dump_tool_help): New option. (lto_main): Handle graphviz dumping. From-SVN: r273708 --- gcc/ChangeLog | 6 ++++++ gcc/cgraph.c | 16 ++++++++++++++++ gcc/cgraph.h | 9 +++++++++ gcc/lto/ChangeLog | 7 +++++++ gcc/lto/lang.opt | 3 +++ gcc/lto/lto-dump.c | 52 ++++++++++++++++++++++++++++++++-------------------- gcc/symtab.c | 17 +++++++++++++++++ 7 files changed, 90 insertions(+), 20 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index faa3bde..eda95a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-02 Giuliano Belinassi + + * cgraph.c (dump_graphviz): New function. + * cgraph.h (dump_graphviz): New function. + * symtab.c (dump_graphviz): New function. + 2019-07-22 Sylvia Taylor * config/aarch64/aarch64-simd.md diff --git a/gcc/cgraph.c b/gcc/cgraph.c index a7e3bcf..477db38 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2204,6 +2204,22 @@ cgraph_node::dump (FILE *f) } } +/* Dump call graph node to file F in graphviz format. */ + +void +cgraph_node::dump_graphviz (FILE *f) +{ + cgraph_edge *edge; + + for (edge = callees; edge; edge = edge->next_callee) + { + cgraph_node *callee = edge->callee; + + fprintf (f, "\t\"%s\" -> \"%s\"\n", name (), callee->name ()); + } +} + + /* Dump call graph node NODE to stderr. */ DEBUG_FUNCTION void diff --git a/gcc/cgraph.h b/gcc/cgraph.h index fa5224f..a7c97de 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -135,6 +135,9 @@ public: /* Dump symtab node to F. */ void dump (FILE *f); + /* Dump symtab callgraph in graphviz format. */ + void dump_graphviz (FILE *f); + /* Dump symtab node to stderr. */ void DEBUG_FUNCTION debug (void); @@ -1106,6 +1109,9 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node /* Dump call graph node to file F. */ void dump (FILE *f); + /* Dump call graph node to file F. */ + void dump_graphviz (FILE *f); + /* Dump call graph node to stderr. */ void DEBUG_FUNCTION debug (void); @@ -2282,6 +2288,9 @@ public: /* Dump symbol table to F. */ void dump (FILE *f); + /* Dump symbol table to F in graphviz format. */ + void dump_graphviz (FILE *f); + /* Dump symbol table to stderr. */ void DEBUG_FUNCTION debug (void); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 22e7739..c18b2c4 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,10 @@ +2019-07-22 Giuliano Belinassi + + * lang.opt (flag_dump_callgraph): New flag. + * lto-dump.c (dump_symtab_graphviz): New function. + (dump_tool_help): New option. + (lto_main): Handle graphviz dumping. + 2019-07-18 Jan Hubicka * lto-common.c (gimple_register_canonical_type_1): Do not look for diff --git a/gcc/lto/lang.opt b/gcc/lto/lang.opt index 5bacef3..c62dd5a 100644 --- a/gcc/lto/lang.opt +++ b/gcc/lto/lang.opt @@ -127,6 +127,9 @@ help LTODump Var(flag_lto_dump_tool_help) Dump the dump tool command line options. +callgraph +LTODump Var(flag_dump_callgraph) +Dump the symtab callgraph. fresolution= LTO Joined diff --git a/gcc/lto/lto-dump.c b/gcc/lto/lto-dump.c index 262f9f2..74d99b5 100644 --- a/gcc/lto/lto-dump.c +++ b/gcc/lto/lto-dump.c @@ -215,6 +215,12 @@ void dump_list_variables (void) } } +/* Dump symbol table in graphviz format. */ +void dump_symtab_graphviz (void) +{ + symtab->dump_graphviz (stdout); +} + /* Dump symbol list. */ void dump_list (void) @@ -269,26 +275,27 @@ void dump_body () /* List of command line options for dumping. */ void dump_tool_help () { - printf ("Usage: lto-dump [OPTION]... SUB_COMMAND [OPTION]...\n\n"); - printf ("LTO dump tool command line options.\n\n"); - printf (" -list [options] Dump the symbol list.\n"); - printf (" -demangle Dump the demangled output.\n"); - printf (" -defined-only Dump only the defined symbols.\n"); - printf (" -print-value Dump initial values of the " - "variables.\n"); - printf (" -name-sort Sort the symbols alphabetically.\n"); - printf (" -size-sort Sort the symbols according to size.\n"); - printf (" -reverse-sort Dump the symbols in reverse order.\n"); - printf (" -symbol= Dump the details of specific symbol.\n"); - printf (" -objects Dump the details of LTO objects.\n"); - printf (" -type-stats Dump statistics of tree types.\n"); - printf (" -tree-stats Dump statistics of trees.\n"); - printf (" -gimple-stats Dump statistics of gimple " - "statements.\n"); - printf (" -dump-body= Dump the specific gimple body.\n"); - printf (" -dump-level= Deciding the optimization level " - "of body.\n"); - printf (" -help Display the dump tool help.\n"); + const char *msg = + "Usage: lto-dump [OPTION]... SUB_COMMAND [OPTION]...\n\n" + "LTO dump tool command line options.\n\n" + " -list [options] Dump the symbol list.\n" + " -demangle Dump the demangled output.\n" + " -defined-only Dump only the defined symbols.\n" + " -print-value Dump initial values of the variables.\n" + " -name-sort Sort the symbols alphabetically.\n" + " -size-sort Sort the symbols according to size.\n" + " -reverse-sort Dump the symbols in reverse order.\n" + " -symbol= Dump the details of specific symbol.\n" + " -objects Dump the details of LTO objects.\n" + " -callgraph Dump the callgraph in graphviz format.\n" + " -type-stats Dump statistics of tree types.\n" + " -tree-stats Dump statistics of trees.\n" + " -gimple-stats Dump statistics of gimple statements.\n" + " -dump-body= Dump the specific gimple body.\n" + " -dump-level= Deciding the optimization level of body.\n" + " -help Display the dump tool help.\n"; + + fputs (msg, stdout); return; } @@ -362,4 +369,9 @@ lto_main (void) dump_body (); return; } + else if (flag_dump_callgraph) + { + dump_symtab_graphviz (); + return; + } } diff --git a/gcc/symtab.c b/gcc/symtab.c index b1589ea..63e2820 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -956,6 +956,13 @@ symtab_node::dump (FILE *f) } void +symtab_node::dump_graphviz (FILE *f) +{ + if (cgraph_node *cnode = dyn_cast (this)) + cnode->dump_graphviz (f); +} + +void symbol_table::dump (FILE *f) { symtab_node *node; @@ -964,6 +971,16 @@ symbol_table::dump (FILE *f) node->dump (f); } +void +symbol_table::dump_graphviz (FILE *f) +{ + symtab_node *node; + fprintf (f, "digraph symtab {\n"); + FOR_EACH_SYMBOL (node) + node->dump_graphviz (f); + fprintf (f, "}\n"); +} + DEBUG_FUNCTION void symbol_table::debug (void) { -- cgit v1.1 From 22e4efa142acc9c7cdabc4ace27e306b8e807a56 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 23 Jul 2019 00:16:30 +0000 Subject: Daily bump. From-SVN: r273712 --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 924bff9..0d94c83 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20190722 +20190723 -- cgit v1.1 From 1d46067b347ab1814de3cdd7f620f5c8ca73232a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 23 Jul 2019 00:34:38 +0000 Subject: compiler: follow-on fix for finalizing imported methods This patch is a revision to CL 185518, which added code to perform finalization of methods on types created by the importer and not directly reachable until inlining is done. The original fix invoked the finalization code at the end of Import::read_types(), but it turns out this doesn't handle the case where a type with methods is read in due to a reference from something later in the export data (a function or variable). The fix is to move the import finalization call to the end of Import::import(). Testcase for this bug is in CL 187057. Fixes golang/go#33219. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/187058 From-SVN: r273713 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/import.cc | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 2c53602..dabd5a3 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -e242929304e7a524ced56dc94605bbf6d83e6489 +b7bce0dbccb978d33eb8ce0bffc02fae2c2857c1 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index be71f04..64c1ef2 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -450,6 +450,14 @@ Import::import(Gogo* gogo, const std::string& local_name, this->require_c_string("\n"); } + // Finalize methods for any imported types. This call is made late in the + // import process so as to A) avoid finalization of a type whose methods + // refer to types that are only partially read in, and B) capture both the + // types imported by read_types() directly, and those imported indirectly + // because they are referenced by an imported function or variable. + // See issues #33013 and #33219 for more on why this is needed. + this->finalize_methods(); + return this->package_; } @@ -678,12 +686,6 @@ Import::read_types() this->gogo_->add_named_type(nt); } - // Finalize methods for any imported types. This is done after most of - // read_types() is complete so as to avoid method finalization of a type - // whose methods refer to types that are only partially read in. - // See issue #33013 for more on why this is needed. - this->finalize_methods(); - return true; } -- cgit v1.1 From ffbb9818b0efd04bff65c372e3e9444fae634363 Mon Sep 17 00:00:00 2001 From: Ilia Diachkov Date: Tue, 23 Jul 2019 01:29:34 +0000 Subject: RISC-V: Add -malign-data= option. gcc/ Ilia Diachkov * config/riscv/riscv-opts.h (struct riscv_align_data): New. * config/riscv/riscv.c (riscv_constant_alignment): Use riscv_align_data_type. * config/riscv/riscv.h (RISCV_EXPAND_ALIGNMENT): New. (DATA_ALIGNMENT): Use RISCV_EXPAND_ALIGNMENT. (LOCAL_ALIGNMENT): Use RISCV_EXPAND_ALIGNMENT. * config/riscv/riscv.opt (malign-data): New. * doc/invoke.texi (RISC-V Options): Document -malign-data=. From-SVN: r273714 --- gcc/ChangeLog | 11 +++++++++++ gcc/config/riscv/riscv-opts.h | 5 +++++ gcc/config/riscv/riscv.c | 3 ++- gcc/config/riscv/riscv.h | 17 +++++++++++------ gcc/config/riscv/riscv.opt | 14 ++++++++++++++ gcc/doc/invoke.texi | 10 +++++++++- 6 files changed, 52 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eda95a0..fd00041 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2019-07-22 Ilia Diachkov + + * config/riscv/riscv-opts.h (struct riscv_align_data): New. + * config/riscv/riscv.c (riscv_constant_alignment): Use + riscv_align_data_type. + * config/riscv/riscv.h (RISCV_EXPAND_ALIGNMENT): New. + (DATA_ALIGNMENT): Use RISCV_EXPAND_ALIGNMENT. + (LOCAL_ALIGNMENT): Use RISCV_EXPAND_ALIGNMENT. + * config/riscv/riscv.opt (malign-data): New. + * doc/invoke.texi (RISC-V Options): Document -malign-data=. + 2019-07-02 Giuliano Belinassi * cgraph.c (dump_graphviz): New function. diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index f3031f2..d00fbe2 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -46,4 +46,9 @@ enum riscv_microarchitecture_type { }; extern enum riscv_microarchitecture_type riscv_microarchitecture; +enum riscv_align_data { + riscv_align_data_type_xlen, + riscv_align_data_type_natural +}; + #endif /* ! GCC_RISCV_OPTS_H */ diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index 8ac09f2..e274f1b 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -4904,7 +4904,8 @@ riscv_can_change_mode_class (machine_mode, machine_mode, reg_class_t rclass) static HOST_WIDE_INT riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) { - if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR) + if ((TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR) + && (riscv_align_data_type == riscv_align_data_type_xlen)) return MAX (align, BITS_PER_WORD); return align; } diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 4509d73..5fc9be8 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -168,6 +168,13 @@ along with GCC; see the file COPYING3. If not see mode that should actually be used. We allow pairs of registers. */ #define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_64BIT ? TImode : DImode) +/* DATA_ALIGNMENT and LOCAL_ALIGNMENT common definition. */ +#define RISCV_EXPAND_ALIGNMENT(COND, TYPE, ALIGN) \ + (((COND) && ((ALIGN) < BITS_PER_WORD) \ + && (TREE_CODE (TYPE) == ARRAY_TYPE \ + || TREE_CODE (TYPE) == UNION_TYPE \ + || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) + /* If defined, a C expression to compute the alignment for a static variable. TYPE is the data type, and ALIGN is the alignment that the object would ordinarily have. The value of this macro is used @@ -180,18 +187,16 @@ along with GCC; see the file COPYING3. If not see cause character arrays to be word-aligned so that `strcpy' calls that copy constants to character arrays can be done inline. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - ((((ALIGN) < BITS_PER_WORD) \ - && (TREE_CODE (TYPE) == ARRAY_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE \ - || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN)) +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + RISCV_EXPAND_ALIGNMENT (riscv_align_data_type == riscv_align_data_type_xlen, \ + TYPE, ALIGN) /* We need this for the same reason as DATA_ALIGNMENT, namely to cause character arrays to be word-aligned so that `strcpy' calls that copy constants to character arrays can be done inline, and 'strcmp' can be optimised to use word loads. */ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ - DATA_ALIGNMENT (TYPE, ALIGN) + RISCV_EXPAND_ALIGNMENT (true, TYPE, ALIGN) /* Define if operations between registers always perform the operation on the full register even if a narrower mode is specified. */ diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 3b25f9a..7f0c35e 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -131,3 +131,17 @@ Mask(RVE) mriscv-attribute Target Report Var(riscv_emit_attribute_p) Init(-1) Emit RISC-V ELF attribute. + +malign-data= +Target RejectNegative Joined Var(riscv_align_data_type) Enum(riscv_align_data) Init(riscv_align_data_type_xlen) +Use the given data alignment. + +Enum +Name(riscv_align_data) Type(enum riscv_align_data) +Known data alignment choices (for use with the -malign-data= option): + +EnumValue +Enum(riscv_align_data) String(xlen) Value(riscv_align_data_type_xlen) + +EnumValue +Enum(riscv_align_data) String(natural) Value(riscv_align_data_type_natural) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7bac080..77a2d56 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1068,7 +1068,8 @@ See RS/6000 and PowerPC Options. -mcmodel=medlow -mcmodel=medany @gol -mexplicit-relocs -mno-explicit-relocs @gol -mrelax -mno-relax @gol --mriscv-attribute -mmo-riscv-attribute} +-mriscv-attribute -mmo-riscv-attribute @gol +-malign-data=@var{type}} @emph{RL78 Options} @gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol @@ -24039,6 +24040,13 @@ linker relaxations. @itemx -mno-emit-attribute Emit (do not emit) RISC-V attribute to record extra information into ELF objects. This feature requires at least binutils 2.32. + +@item -malign-data=@var{type} +@opindex malign-data +Control how GCC aligns variables and constants of array, structure, or union +types. Supported values for @var{type} are @samp{xlen} which uses x register +width as the alignment value, and @samp{natural} which uses natural alignment. +@samp{xlen} is the default. @end table @node RL78 Options -- cgit v1.1 From 0ac608a2cb5ddbc636b8bc1983f136db1f7a7ace Mon Sep 17 00:00:00 2001 From: "Paul A. Clarke" Date: Tue, 23 Jul 2019 02:54:28 +0000 Subject: [rs6000] Add documentation for __builtin_mtfsf 2019-07-22 Paul A. Clarke [gcc] * doc/extend.texi (Basic PowerPC Built-in Functions Available on all Configurations): Add documentation for __builtin_mtfsf. From-SVN: r273715 --- gcc/ChangeLog | 5 +++++ gcc/doc/extend.texi | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fd00041..f4bb577 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-22 Paul A. Clarke + + * doc/extend.texi (Basic PowerPC Built-in Functions Available on all + Configurations): Add documentation for __builtin_mtfsf. + 2019-07-22 Ilia Diachkov * config/riscv/riscv-opts.h (struct riscv_align_data): New. diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 0616074..14b232b 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -16848,6 +16848,7 @@ unsigned long __builtin_ppc_mftb (); double __builtin_unpack_ibm128 (__ibm128, int); __ibm128 __builtin_pack_ibm128 (double, double); double __builtin_mffs (void); +double __builtin_mtfsf (const int, double); void __builtin_mtfsb0 (const int); void __builtin_mtfsb1 (const int); void __builtin_set_fpscr_rn (int); @@ -16863,7 +16864,10 @@ the most significant word on 32-bit environments. The @code{__builtin_mffs} return the value of the FPSCR register. Note, ISA 3.0 supports the @code{__builtin_mffsl()} which permits software to read the control and non-sticky status bits in the FSPCR without the higher latency associated with -accessing the sticky status bits. The +accessing the sticky status bits. The @code{__builtin_mtfsf} takes a constant +8-bit integer field mask and a double precision floating point argument +and generates the @code{mtfsf} (extended mnemonic) instruction to write new +values to selected fields of the FPSCR. The @code{__builtin_mtfsb0} and @code{__builtin_mtfsb1} take the bit to change as an argument. The valid bit range is between 0 and 31. The builtins map to the @code{mtfsb0} and @code{mtfsb1} instructions which take the argument and -- cgit v1.1 From 9215b328075d36cc501fae95e3d522aa85dfd8f6 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 23 Jul 2019 06:58:39 +0000 Subject: tree-cfg.c (label_for_bb): Remove global var. 2019-07-23 Richard Biener * tree-cfg.c (label_for_bb): Remove global var. (main_block_label): Take label_for_bb as argument. (cleanup_dead_labels_eh): Likewise, adjust. (cleanup_dead_labels): Adjust. From-SVN: r273716 --- gcc/ChangeLog | 7 +++++++ gcc/tree-cfg.c | 35 ++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 17 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4bb577..ad612c2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-23 Richard Biener + + * tree-cfg.c (label_for_bb): Remove global var. + (main_block_label): Take label_for_bb as argument. + (cleanup_dead_labels_eh): Likewise, adjust. + (cleanup_dead_labels): Adjust. + 2019-07-22 Paul A. Clarke * doc/extend.texi (Basic PowerPC Built-in Functions Available on all diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 4521fe3..54ee63a 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -1437,19 +1437,19 @@ make_gimple_asm_edges (basic_block bb) (almost) no new labels should be created. */ /* A map from basic block index to the leading label of that block. */ -static struct label_record +struct label_record { /* The label. */ tree label; /* True if the label is referenced from somewhere. */ bool used; -} *label_for_bb; +}; /* Given LABEL return the first label in the same basic block. */ static tree -main_block_label (tree label) +main_block_label (tree label, label_record *label_for_bb) { basic_block bb = label_to_block (cfun, label); tree main_label = label_for_bb[bb->index].label; @@ -1468,7 +1468,7 @@ main_block_label (tree label) /* Clean up redundant labels within the exception tree. */ static void -cleanup_dead_labels_eh (void) +cleanup_dead_labels_eh (label_record *label_for_bb) { eh_landing_pad lp; eh_region r; @@ -1481,7 +1481,7 @@ cleanup_dead_labels_eh (void) for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i) if (lp && lp->post_landing_pad) { - lab = main_block_label (lp->post_landing_pad); + lab = main_block_label (lp->post_landing_pad, label_for_bb); if (lab != lp->post_landing_pad) { EH_LANDING_PAD_NR (lp->post_landing_pad) = 0; @@ -1503,7 +1503,7 @@ cleanup_dead_labels_eh (void) { lab = c->label; if (lab) - c->label = main_block_label (lab); + c->label = main_block_label (lab, label_for_bb); } } break; @@ -1511,7 +1511,7 @@ cleanup_dead_labels_eh (void) case ERT_ALLOWED_EXCEPTIONS: lab = r->u.allowed.label; if (lab) - r->u.allowed.label = main_block_label (lab); + r->u.allowed.label = main_block_label (lab, label_for_bb); break; } } @@ -1526,7 +1526,8 @@ void cleanup_dead_labels (void) { basic_block bb; - label_for_bb = XCNEWVEC (struct label_record, last_basic_block_for_fn (cfun)); + label_record *label_for_bb = XCNEWVEC (struct label_record, + last_basic_block_for_fn (cfun)); /* Find a suitable label for each block. We use the first user-defined label if there is one, or otherwise just the first label we see. */ @@ -1582,7 +1583,7 @@ cleanup_dead_labels (void) label = gimple_cond_true_label (cond_stmt); if (label) { - new_label = main_block_label (label); + new_label = main_block_label (label, label_for_bb); if (new_label != label) gimple_cond_set_true_label (cond_stmt, new_label); } @@ -1590,7 +1591,7 @@ cleanup_dead_labels (void) label = gimple_cond_false_label (cond_stmt); if (label) { - new_label = main_block_label (label); + new_label = main_block_label (label, label_for_bb); if (new_label != label) gimple_cond_set_false_label (cond_stmt, new_label); } @@ -1607,7 +1608,7 @@ cleanup_dead_labels (void) { tree case_label = gimple_switch_label (switch_stmt, i); label = CASE_LABEL (case_label); - new_label = main_block_label (label); + new_label = main_block_label (label, label_for_bb); if (new_label != label) CASE_LABEL (case_label) = new_label; } @@ -1622,7 +1623,7 @@ cleanup_dead_labels (void) for (i = 0; i < n; ++i) { tree cons = gimple_asm_label_op (asm_stmt, i); - tree label = main_block_label (TREE_VALUE (cons)); + tree label = main_block_label (TREE_VALUE (cons), label_for_bb); TREE_VALUE (cons) = label; } break; @@ -1635,7 +1636,7 @@ cleanup_dead_labels (void) { ggoto *goto_stmt = as_a (stmt); label = gimple_goto_dest (goto_stmt); - new_label = main_block_label (label); + new_label = main_block_label (label, label_for_bb); if (new_label != label) gimple_goto_set_dest (goto_stmt, new_label); } @@ -1648,7 +1649,7 @@ cleanup_dead_labels (void) label = gimple_transaction_label_norm (txn); if (label) { - new_label = main_block_label (label); + new_label = main_block_label (label, label_for_bb); if (new_label != label) gimple_transaction_set_label_norm (txn, new_label); } @@ -1656,7 +1657,7 @@ cleanup_dead_labels (void) label = gimple_transaction_label_uninst (txn); if (label) { - new_label = main_block_label (label); + new_label = main_block_label (label, label_for_bb); if (new_label != label) gimple_transaction_set_label_uninst (txn, new_label); } @@ -1664,7 +1665,7 @@ cleanup_dead_labels (void) label = gimple_transaction_label_over (txn); if (label) { - new_label = main_block_label (label); + new_label = main_block_label (label, label_for_bb); if (new_label != label) gimple_transaction_set_label_over (txn, new_label); } @@ -1677,7 +1678,7 @@ cleanup_dead_labels (void) } /* Do the same for the exception region tree labels. */ - cleanup_dead_labels_eh (); + cleanup_dead_labels_eh (label_for_bb); /* Finally, purge dead labels. All user-defined labels and labels that can be the target of non-local gotos and labels which have their -- cgit v1.1 From c0cdef59af5cc7fb67dc8ad4fc501ac47ab88aaf Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Tue, 23 Jul 2019 09:31:50 +0200 Subject: Use -flto instead of -flto=N in DWARF producer string. 2019-07-23 Martin Liska * dwarf2out.c (gen_producer_string): Canonize -flto=N to -flto in dwarf producer string. From-SVN: r273717 --- gcc/ChangeLog | 5 +++++ gcc/dwarf2out.c | 7 +++++++ 2 files changed, 12 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad612c2..3e8953f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-23 Martin Liska + + * dwarf2out.c (gen_producer_string): Canonize -flto=N + to -flto in dwarf producer string. + 2019-07-23 Richard Biener * tree-cfg.c (label_for_bb): Remove global var. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 0449c2b..aa7fd7e 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -24460,6 +24460,13 @@ gen_producer_string (void) case OPT_fchecking_: /* Ignore these. */ continue; + case OPT_flto_: + { + const char *lto_canonical = "-flto"; + switches.safe_push (lto_canonical); + len += strlen (lto_canonical) + 1; + break; + } default: if (cl_options[save_decoded_options[j].opt_index].flags & CL_NO_DWARF_RECORD) -- cgit v1.1 From 58b8c5a87b0bac61bb88e802fc742fdc0d3e6699 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 23 Jul 2019 08:07:49 +0000 Subject: x86/AVX512: improve generated code for mask-to-vector-register conversions Conversion of comparison results to full vectors does, when VPMOVM2* are unavailable, not require any intermediate VMOVDQ{A,U}*: Simply use embedded masking on VPTERNLOG* right away, which is available with AVX512F (while VPMOVM2{D,Q} are available only with AVX512DQ). Note that the chosen immediate is only one of many possible ones; I was trying to make the insn here distinguishable from the pre-existing uses of vpternlog. gcc/ 2019-07-23 Jan Beulich * config/i386/sse.md (_cvtmask2): Require only AVX512F. (*_cvtmask2): Likewise. Add alternative expanding to vpternlog. From-SVN: r273719 --- gcc/ChangeLog | 7 +++++++ gcc/config/i386/sse.md | 16 ++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3e8953f..3b39269 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-23 Jan Beulich + + * config/i386/sse.md (_cvtmask2): + Require only AVX512F. + (*_cvtmask2): Likewise. Add + alternative expanding to vpternlog. + 2019-07-23 Martin Liska * dwarf2out.c (gen_producer_string): Canonize -flto=N diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 8abd161..fa8f13f 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -6565,21 +6565,25 @@ (match_dup 2) (match_dup 3) (match_operand: 1 "register_operand")))] - "TARGET_AVX512DQ" + "TARGET_AVX512F" "{ operands[2] = CONSTM1_RTX (mode); operands[3] = CONST0_RTX (mode); }") (define_insn "*_cvtmask2" - [(set (match_operand:VI48_AVX512VL 0 "register_operand" "=v") + [(set (match_operand:VI48_AVX512VL 0 "register_operand" "=v,v") (vec_merge:VI48_AVX512VL (match_operand:VI48_AVX512VL 2 "vector_all_ones_operand") (match_operand:VI48_AVX512VL 3 "const0_operand") - (match_operand: 1 "register_operand" "k")))] - "TARGET_AVX512DQ" - "vpmovm2\t{%1, %0|%0, %1}" - [(set_attr "prefix" "evex") + (match_operand: 1 "register_operand" "k,Yk")))] + "TARGET_AVX512F" + "@ + vpmovm2\t{%1, %0|%0, %1} + vpternlog\t{$0x81, %0, %0, %0%{%1%}%{z%}|%0%{%1%}%{z%}, %0, %0, 0x81}" + [(set_attr "isa" "avx512dq,*") + (set_attr "length_immediate" "0,1") + (set_attr "prefix" "evex") (set_attr "mode" "")]) (define_insn "sse2_cvtps2pd" -- cgit v1.1 From 39c20502ef7398766a8c9520c4210c2df9769d15 Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 23 Jul 2019 08:13:01 +0000 Subject: [Ada] Fix binding of ghost units with finalizer Linking of an enabled ghost unit which requires a finalizer lead to an error, as the name generated by the binder for calling the finalizer was not the same as the name chosen by the compiler. Now fixed. 2019-07-23 Yannick Moy gcc/ada/ * exp_ch7.adb (Create_Finalizer): Force finalizer not to be Ghost enabled. * exp_dbug.adb (Get_External_Name): Explain special case of Ghost finalizer. gcc/testsuite/ * gnat.dg/ghost6.adb, gnat.dg/ghost6_pkg.ads: New testcase. From-SVN: r273720 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/exp_ch7.adb | 7 +++++++ gcc/ada/exp_dbug.adb | 8 ++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/ghost6.adb | 10 ++++++++++ gcc/testsuite/gnat.dg/ghost6_pkg.ads | 7 +++++++ 6 files changed, 43 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/ghost6.adb create mode 100644 gcc/testsuite/gnat.dg/ghost6_pkg.ads (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index db77736..0f7cd2d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-23 Yannick Moy + + * exp_ch7.adb (Create_Finalizer): Force finalizer not to be + Ghost enabled. + * exp_dbug.adb (Get_External_Name): Explain special case of + Ghost finalizer. + 2019-07-22 Eric Botcazou * repinfo.adb (List_Entities): Also list compiled-generated diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 2ca4109..b00fc92 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -2035,6 +2035,13 @@ package body Exp_Ch7 is Analyze (Fin_Body, Suppress => All_Checks); end if; + + -- Never consider that the finalizer procedure is enabled Ghost, even + -- when the corresponding unit is Ghost, as this would lead to an + -- an external name with a ___ghost_ prefix that the binder cannot + -- generate, as it has no knowledge of the Ghost status of units. + + Set_Is_Checked_Ghost_Entity (Fin_Id, False); end Create_Finalizer; -------------------------- diff --git a/gcc/ada/exp_dbug.adb b/gcc/ada/exp_dbug.adb index 388d247..f0df5e2 100644 --- a/gcc/ada/exp_dbug.adb +++ b/gcc/ada/exp_dbug.adb @@ -914,6 +914,14 @@ package body Exp_Dbug is -- names produced for Ghost entities, while "__ghost_" can appear in -- names of entities inside a child/local package called "Ghost". + -- The compiler-generated finalizer for an enabled Ghost unit is treated + -- specially, as its name must be known to the binder, which has no + -- knowledge of Ghost status. In that case, the finalizer is not marked + -- as Ghost so that no prefix is added. Note that the special ___ghost_ + -- prefix is retained when the Ghost unit is ignored, which still allows + -- inspecting the final executable for the presence of an ignored Ghost + -- finalizer procedure. + if Is_Ghost_Entity (E) and then not Is_Compilation_Unit (E) and then (Name_Len < 9 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2b3e477..0ef05dd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-23 Yannick Moy + + * gnat.dg/ghost6.adb, gnat.dg/ghost6_pkg.ads: New testcase. + 2019-07-22 Sylvia Taylor * gcc.target/aarch64/simd/ssra.c: New test. diff --git a/gcc/testsuite/gnat.dg/ghost6.adb b/gcc/testsuite/gnat.dg/ghost6.adb new file mode 100644 index 0000000..01a2417 --- /dev/null +++ b/gcc/testsuite/gnat.dg/ghost6.adb @@ -0,0 +1,10 @@ +-- { dg-do link } +-- { dg-options "-gnata -g" } + +with Ghost6_Pkg; + +procedure Ghost6 is + X : Ghost6_Pkg.T with Ghost; +begin + null; +end Ghost6; diff --git a/gcc/testsuite/gnat.dg/ghost6_pkg.ads b/gcc/testsuite/gnat.dg/ghost6_pkg.ads new file mode 100644 index 0000000..7fbd942 --- /dev/null +++ b/gcc/testsuite/gnat.dg/ghost6_pkg.ads @@ -0,0 +1,7 @@ +with Ada.Finalization; + +package Ghost6_Pkg with + Ghost +is + type T is new Ada.Finalization.Controlled with null record; +end Ghost6_Pkg; -- cgit v1.1 From 15e79d66f00317d3acbfa1c93c9460a65174454b Mon Sep 17 00:00:00 2001 From: Yannick Moy Date: Tue, 23 Jul 2019 08:13:09 +0000 Subject: [Ada] Issue error on SPARK ownership rule violation A modified rule in SPARK RM specifies that object declarations of anonymous access type should only occur immediately in subprogram, entry or block. Now checked. There is no impact on compilation. 2019-07-23 Yannick Moy gcc/ada/ * sem_spark.ads (Is_Local_Context): New function. * sem_spark.adb (Check_Declaration): Issue errors on violations of SPARK RM 3.10(4) (Process_Path): Do not issue error on borrow/observe during elaboration, as these are caught by the new rule. From-SVN: r273721 --- gcc/ada/ChangeLog | 8 +++++++ gcc/ada/sem_spark.adb | 63 ++++++++++++++++++++++++++++++++++++++++----------- gcc/ada/sem_spark.ads | 4 ++++ 3 files changed, 62 insertions(+), 13 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0f7cd2d..748f1bf 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,13 @@ 2019-07-23 Yannick Moy + * sem_spark.ads (Is_Local_Context): New function. + * sem_spark.adb (Check_Declaration): Issue errors on violations + of SPARK RM 3.10(4) + (Process_Path): Do not issue error on borrow/observe during + elaboration, as these are caught by the new rule. + +2019-07-23 Yannick Moy + * exp_ch7.adb (Create_Finalizer): Force finalizer not to be Ghost enabled. * exp_dbug.adb (Get_External_Name): Explain special case of diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb index 0de51f8..a60a6cb 100644 --- a/gcc/ada/sem_spark.adb +++ b/gcc/ada/sem_spark.adb @@ -1419,9 +1419,37 @@ package body Sem_SPARK is Check_Expression (Subtype_Indication (Decl), Read); when N_Object_Declaration => + Expr := Expression (Decl); + Check_Type (Target_Typ); - Expr := Expression (Decl); + -- A declaration of a stand-alone object of an anonymous access + -- type shall have an explicit initial value and shall occur + -- immediately within a subprogram body, an entry body, or a + -- block statement (SPARK RM 3.10(4)). + + if Is_Anonymous_Access_Type (Target_Typ) then + declare + Scop : constant Entity_Id := Scope (Target); + begin + if not Is_Local_Context (Scop) then + if Emit_Messages then + Error_Msg_N + ("object of anonymous access type must be declared " + & "immediately within a subprogram, entry or block " + & "(SPARK RM 3.10(4))", Decl); + end if; + end if; + end; + + if No (Expr) then + if Emit_Messages then + Error_Msg_N ("object of anonymous access type must be " + & "initialized (SPARK RM 3.10(4))", Decl); + end if; + end if; + end if; + if Present (Expr) then Check_Assignment (Target => Target, Expr => Expr); @@ -2848,9 +2876,14 @@ package body Sem_SPARK is -- independently for R permission. Outputs are checked -- independently to have RW permission on exit. - when Pragma_Contract_Cases + -- Postconditions are checked for correct use of 'Old, but starting + -- from the corresponding declaration, in order to avoid dealing with + -- with contracts on generic subprograms, which are not handled in + -- GNATprove. + + when Pragma_Precondition | Pragma_Postcondition - | Pragma_Precondition + | Pragma_Contract_Cases | Pragma_Refined_Post => null; @@ -3993,6 +4026,16 @@ package body Sem_SPARK is end case; end Is_Deep; + ---------------------- + -- Is_Local_Context -- + ---------------------- + + function Is_Local_Context (Scop : Entity_Id) return Boolean is + begin + return Is_Subprogram_Or_Entry (Scop) + or else Ekind (Scop) = E_Block; + end Is_Local_Context; + ------------------------ -- Is_Path_Expression -- ------------------------ @@ -4863,13 +4906,10 @@ package body Sem_SPARK is when Borrow => - -- Forbidden during elaboration + -- Forbidden during elaboration, an error is already issued in + -- Check_Declaration, just return. if Inside_Elaboration then - if not Inside_Procedure_Call and then Emit_Messages then - Error_Msg_N ("illegal borrow during elaboration", Expr); - end if; - return; end if; @@ -4882,13 +4922,10 @@ package body Sem_SPARK is when Observe => - -- Forbidden during elaboration + -- Forbidden during elaboration, an error is already issued in + -- Check_Declaration, just return. if Inside_Elaboration then - if not Inside_Procedure_Call and then Emit_Messages then - Error_Msg_N ("illegal observe during elaboration", Expr); - end if; - return; end if; diff --git a/gcc/ada/sem_spark.ads b/gcc/ada/sem_spark.ads index 0e8b29b..195e833 100644 --- a/gcc/ada/sem_spark.ads +++ b/gcc/ada/sem_spark.ads @@ -162,4 +162,8 @@ package Sem_SPARK is function Is_Traversal_Function (E : Entity_Id) return Boolean; + function Is_Local_Context (Scop : Entity_Id) return Boolean; + -- Return if a given scope defines a local context where it is legal to + -- declare a variable of anonymous access type. + end Sem_SPARK; -- cgit v1.1 From c910db716273c381b4e2f36f3d04c6e480876b63 Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Tue, 23 Jul 2019 08:13:15 +0000 Subject: [Ada] Iterators are view-specific Operational aspects, such as Default_Iterator, are view-specific, and if such an aspect appears on the full view of a private type, an object of the type cannot be iterated upon if it is not in the scope of the full view, This patch diagnoses properly an attempt to iterate over such an object. 2019-07-23 Ed Schonberg gcc/ada/ * aspects.ads: New table Operational_Aspect, used to distinguish between aspects that are view-specific, such as those related to iterators, and representation aspects that apply to all views of a type. * aspects.adb (Find_Aspect): If the aspect being sought is operational, do not ecamine the full view of a private type to retrieve it. * sem_ch5.adb (Analyze_Iterator_Specification): Improve error message when the intended domain of iteration does not implement the required iterator aspects. gcc/testsuite/ * gnat.dg/iter5.adb: Add an expected error. * gnat.dg/iter6.adb: New testcase. From-SVN: r273722 --- gcc/ada/ChangeLog | 13 +++++++++++++ gcc/ada/aspects.adb | 5 ++++- gcc/ada/aspects.ads | 14 ++++++++++++++ gcc/ada/sem_ch5.adb | 11 ++++++++++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gnat.dg/iter5.adb | 2 +- gcc/testsuite/gnat.dg/iter6.adb | 40 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/iter6.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 748f1bf..a40a774 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2019-07-23 Ed Schonberg + + * aspects.ads: New table Operational_Aspect, used to distinguish + between aspects that are view-specific, such as those related to + iterators, and representation aspects that apply to all views of + a type. + * aspects.adb (Find_Aspect): If the aspect being sought is + operational, do not ecamine the full view of a private type to + retrieve it. + * sem_ch5.adb (Analyze_Iterator_Specification): Improve error + message when the intended domain of iteration does not implement + the required iterator aspects. + 2019-07-23 Yannick Moy * sem_spark.ads (Is_Local_Context): New function. diff --git a/gcc/ada/aspects.adb b/gcc/ada/aspects.adb index 76fa6c8..54c0e56 100644 --- a/gcc/ada/aspects.adb +++ b/gcc/ada/aspects.adb @@ -225,7 +225,10 @@ package body Aspects is Owner := Root_Type (Owner); end if; - if Is_Private_Type (Owner) and then Present (Full_View (Owner)) then + if Is_Private_Type (Owner) + and then Present (Full_View (Owner)) + and then not Operational_Aspect (A) + then Owner := Full_View (Owner); end if; end if; diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads index 9190a635..2a6acc2 100644 --- a/gcc/ada/aspects.ads +++ b/gcc/ada/aspects.ads @@ -277,6 +277,20 @@ package Aspects is Aspect_Warnings => True, others => False); + -- The following array indicates aspects that specify operational + -- characteristics, and thus are view-specific. Representation + -- aspects break privacy, as they are needed during expansion and + -- code generation. + -- List is currently incomplete ??? + + Operational_Aspect : constant array (Aspect_Id) of Boolean := + (Aspect_Constant_Indexing => True, + Aspect_Default_Iterator => True, + Aspect_Iterator_Element => True, + Aspect_Iterable => True, + Aspect_Variable_Indexing => True, + others => False); + -- The following array indicates aspects for which multiple occurrences of -- the same aspect attached to the same declaration are allowed. diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index b77bd7e..ebe610b 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -2234,8 +2234,17 @@ package body Sem_Ch5 is It : Interp; begin + -- THe domain of iteralion must implement either the RM + -- iterator interface, or the SPARK Iterable aspect. + if No (Iterator) then - null; -- error reported below + if No + (Find_Aspect (Etype (Iter_Name), Aspect_Iterable)) + then + Error_Msg_NE ("cannot iterate over&", + N, Base_Type (Etype (Iter_Name))); + return; + end if; elsif not Is_Overloaded (Iterator) then Check_Reverse_Iteration (Etype (Iterator)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0ef05dd..03cf4bb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-23 Ed Schonberg + + * gnat.dg/iter5.adb: Add an expected error. + * gnat.dg/iter6.adb: New testcase. + 2019-07-23 Yannick Moy * gnat.dg/ghost6.adb, gnat.dg/ghost6_pkg.ads: New testcase. diff --git a/gcc/testsuite/gnat.dg/iter5.adb b/gcc/testsuite/gnat.dg/iter5.adb index b17b435..fa21715 100644 --- a/gcc/testsuite/gnat.dg/iter5.adb +++ b/gcc/testsuite/gnat.dg/iter5.adb @@ -4,7 +4,7 @@ with Iter5_Pkg; procedure Iter5 is begin - for The_Filename of Iter5_Pkg.Iterator_For ("C:\Program_Files") loop + for The_Filename of Iter5_Pkg.Iterator_For ("C:\Program_Files") loop -- { dg-error "cannot iterate over \"Item\"" } null; end loop; end Iter5; diff --git a/gcc/testsuite/gnat.dg/iter6.adb b/gcc/testsuite/gnat.dg/iter6.adb new file mode 100644 index 0000000..371352b --- /dev/null +++ b/gcc/testsuite/gnat.dg/iter6.adb @@ -0,0 +1,40 @@ +-- { dg-do compile } + +with Ada.Iterator_Interfaces; + +procedure Iter6 is + package Pkg is + type Item (<>) is limited private; + private + + type Cursor is null record; + + function Constant_Reference (The_Item : aliased Item; + Unused_Index : Cursor) return String + is (""); + + function Has_More (Data : Cursor) return Boolean is (False); + + package List_Iterator_Interfaces is new Ada.Iterator_Interfaces + (Cursor, Has_More); + + function Iterate (The_Item : Item) + return List_Iterator_Interfaces.Forward_Iterator'class + is (raise Program_Error); + + type Item (Name_Length : Natural) is tagged limited record + null; + end record + with + Constant_Indexing => Constant_Reference, + Default_Iterator => Iterate, + Iterator_Element => String; + end Pkg; use Pkg; + + type Item_Ref is access Item; + function F return Item_Ref is (null); +begin + for I of F.all loop -- { dg-error "cannot iterate over \"Item\"" } + null; + end loop; +end; -- cgit v1.1 From f9534f4bd63c9f4be7816f0f9bd8a5feeded5821 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 23 Jul 2019 08:13:21 +0000 Subject: [Ada] Minor tweak to -gnatR output This makes sure that the numbers present in the -gnatR output are printed in decimal format in all cases, since the hexadecimal format is not compatible with the JSON syntax. 2019-07-23 Eric Botcazou gcc/ada/ * repinfo.adb (List_Component_Layout): Pass Decimal to UI_Write. (Write_Val): Likewise. From-SVN: r273723 --- gcc/ada/ChangeLog | 5 +++++ gcc/ada/repinfo.adb | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a40a774..445e70e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2019-07-23 Eric Botcazou + + * repinfo.adb (List_Component_Layout): Pass Decimal to UI_Write. + (Write_Val): Likewise. + 2019-07-23 Ed Schonberg * aspects.ads: New table Operational_Aspect, used to distinguish diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index a277bab..77b5c21 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -1150,7 +1150,7 @@ package body Repinfo is if Ekind (Ent) = E_Discriminant then Spaces (Indent); Write_Str (" ""discriminant"": "); - UI_Write (Discriminant_Number (Ent)); + UI_Write (Discriminant_Number (Ent), Decimal); Write_Line (","); end if; Spaces (Indent); @@ -1181,7 +1181,7 @@ package body Repinfo is Spaces (Max_Spos_Length - 2); if Starting_Position /= Uint_0 then - UI_Write (Starting_Position); + UI_Write (Starting_Position, Decimal); Write_Str (" + "); end if; @@ -1205,7 +1205,7 @@ package body Repinfo is Sbit := Sbit - SSU; end if; - UI_Write (Sbit); + UI_Write (Sbit, Decimal); if List_Representation_Info_To_JSON then Write_Line (", "); @@ -1227,13 +1227,13 @@ package body Repinfo is Lbit := Sbit + Esiz - 1; if List_Representation_Info_To_JSON then - UI_Write (Esiz); + UI_Write (Esiz, Decimal); else if Lbit >= 0 and then Lbit < 10 then Write_Char (' '); end if; - UI_Write (Lbit); + UI_Write (Lbit, Decimal); end if; -- The test for Esize (Ent) not Uint_0 here is an annoying special @@ -2414,7 +2414,7 @@ package body Repinfo is end if; else - UI_Write (Val); + UI_Write (Val, Decimal); end if; end Write_Val; -- cgit v1.1 From a7191e01187b6ff6429699f09fed8f3fbb018b74 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 23 Jul 2019 08:13:26 +0000 Subject: [Ada] Eliminate redundant overflow checks for conversions from fixed-point This eliminates redundant overflow checks that are generated for conversions from fixed-point to integer types when range checks are also enabled (which is the default), as the former checks are subsumed into the latter checks. No functional changes. 2019-07-23 Eric Botcazou gcc/ada/ * checks.adb (Activate_Overflow_Check): Remove redundant argument. * exp_ch4.adb (Discrete_Range_Check): Reset the overflow flag. (Expand_N_Type_Conversion): Do not reset it here. From-SVN: r273724 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/checks.adb | 2 +- gcc/ada/exp_ch4.adb | 10 +++++----- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 445e70e..7869495 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,12 @@ 2019-07-23 Eric Botcazou + * checks.adb (Activate_Overflow_Check): Remove redundant + argument. + * exp_ch4.adb (Discrete_Range_Check): Reset the overflow flag. + (Expand_N_Type_Conversion): Do not reset it here. + +2019-07-23 Eric Botcazou + * repinfo.adb (List_Component_Layout): Pass Decimal to UI_Write. (Write_Val): Likewise. diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index e1f7f9a..2eff274 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -435,7 +435,7 @@ package body Checks is -- Fall through for cases where we do set the flag - Set_Do_Overflow_Check (N, True); + Set_Do_Overflow_Check (N); Possible_Local_Raise (N, Standard_Constraint_Error); end Activate_Overflow_Check; diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index dc2146c..2af54a7 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -11000,6 +11000,11 @@ package body Exp_Ch4 is Rewrite (Expr, Unchecked_Convert_To (Ityp, Expr)); end if; + -- Reset overflow flag, since the range check will include + -- dealing with possible overflow, and generate the check. + + Set_Do_Overflow_Check (N, False); + Generate_Range_Check (Expr, Target_Type, CE_Range_Check_Failed); end Discrete_Range_Check; @@ -12096,11 +12101,6 @@ package body Exp_Ch4 is or else (Is_Fixed_Point_Type (Etype (Expression (N))) and then Conversion_OK (N))) then - -- Reset overflow flag, since the range check will include - -- dealing with possible overflow, and generate the check. - - Set_Do_Overflow_Check (N, False); - -- If Address is either a source type or target type, -- suppress range check to avoid typing anomalies when -- it is a visible integer type. -- cgit v1.1 From 67460d45757a79cdc91fdde1dc1b1a18e4aba6b2 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 23 Jul 2019 08:13:32 +0000 Subject: [Ada] Plug small loophole in Generate_Range_Check The Generate_Range_Check routine is responsible for generating range checks in the scalar case. It automatically deals with possible overflow in the process when the source and the target base types are different. However there is one case where overflow is not dealt with correctly, namely when the target base type is narrower than the source base type and both are floating-point types. In this case, the routine will convert the source type to the target base type without checking for overflow. In practice this does not matter much because the conversion would yield an infinity on overflow, which would then fail the subsequent range check. However it's more correct to have a proper overflow check with -gnateF than relying on the infinity. 2019-07-23 Eric Botcazou gcc/ada/ * checks.adb (Convert_And_Check_Range): Add Suppress parameter and pass it in the call to Insert_Actions. Rename local variable. (Generate_Range_Check): Minor comment fixes. Pass Range_Check in the first call to Convert_And_Check_Range and All_Checks in the second call. * exp_ch4.adb (Expand_N_Type_Conversion): Reset the Do_Overflow_Check flag in the float-to-float case too if there is also a range check. gcc/testsuite/ * gnat.dg/range_check5.adb: New testcase. From-SVN: r273725 --- gcc/ada/ChangeLog | 12 ++++++ gcc/ada/checks.adb | 68 +++++++++++++++++----------------- gcc/ada/exp_ch4.adb | 5 +++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/range_check5.adb | 21 +++++++++++ 5 files changed, 75 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/range_check5.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7869495..86a5491 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,17 @@ 2019-07-23 Eric Botcazou + * checks.adb (Convert_And_Check_Range): Add Suppress parameter + and pass it in the call to Insert_Actions. Rename local + variable. + (Generate_Range_Check): Minor comment fixes. Pass Range_Check + in the first call to Convert_And_Check_Range and All_Checks in + the second call. + * exp_ch4.adb (Expand_N_Type_Conversion): Reset the + Do_Overflow_Check flag in the float-to-float case too if there + is also a range check. + +2019-07-23 Eric Botcazou + * checks.adb (Activate_Overflow_Check): Remove redundant argument. * exp_ch4.adb (Discrete_Range_Check): Reset the overflow flag. diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 2eff274..708bd9e 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -6841,18 +6841,19 @@ package body Checks is Source_Base_Type : constant Entity_Id := Base_Type (Source_Type); Target_Base_Type : constant Entity_Id := Base_Type (Target_Type); - procedure Convert_And_Check_Range; - -- Convert the conversion operand to the target base type and save in - -- a temporary. Then check the converted value against the range of the - -- target subtype. + procedure Convert_And_Check_Range (Suppress : Check_Id); + -- Convert N to the target base type and save the result in a temporary. + -- The action is analyzed using the default checks as modified by the + -- given Suppress argument. Then check the converted value against the + -- range of the target subtype. ----------------------------- -- Convert_And_Check_Range -- ----------------------------- - procedure Convert_And_Check_Range is - Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N); - Conv_Node : Node_Id; + procedure Convert_And_Check_Range (Suppress : Check_Id) is + Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N); + Conv_N : Node_Id; begin -- For enumeration types with non-standard representation this is a @@ -6867,36 +6868,26 @@ package body Checks is and then Present (Enum_Pos_To_Rep (Source_Base_Type)) and then Is_Integer_Type (Target_Base_Type) then - Conv_Node := - OK_Convert_To - (Typ => Target_Base_Type, - Expr => Duplicate_Subexpr (N)); - - -- Common case - + Conv_N := OK_Convert_To (Target_Base_Type, Duplicate_Subexpr (N)); else - Conv_Node := - Make_Type_Conversion (Loc, - Subtype_Mark => New_Occurrence_Of (Target_Base_Type, Loc), - Expression => Duplicate_Subexpr (N)); + Conv_N := Convert_To (Target_Base_Type, Duplicate_Subexpr (N)); end if; - -- We make a temporary to hold the value of the converted value - -- (converted to the base type), and then do the test against this - -- temporary. The conversion itself is replaced by an occurrence of - -- Tnn and followed by the explicit range check. Note that checks - -- are suppressed for this code, since we don't want a recursive - -- range check popping up. + -- We make a temporary to hold the value of the conversion to the + -- target base type, and then do the test against this temporary. + -- N itself is replaced by an occurrence of Tnn and followed by + -- the explicit range check. -- Tnn : constant Target_Base_Type := Target_Base_Type (N); -- [constraint_error when Tnn not in Target_Type] + -- Tnn Insert_Actions (N, New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Tnn, Object_Definition => New_Occurrence_Of (Target_Base_Type, Loc), Constant_Present => True, - Expression => Conv_Node), + Expression => Conv_N), Make_Raise_Constraint_Error (Loc, Condition => @@ -6904,7 +6895,7 @@ package body Checks is Left_Opnd => New_Occurrence_Of (Tnn, Loc), Right_Opnd => New_Occurrence_Of (Target_Type, Loc)), Reason => Reason)), - Suppress => All_Checks); + Suppress => Suppress); Rewrite (N, New_Occurrence_Of (Tnn, Loc)); @@ -6921,7 +6912,7 @@ package body Checks is -- First special case, if the source type is already within the range -- of the target type, then no check is needed (probably we should have -- stopped Do_Range_Check from being set in the first place, but better - -- late than never in preventing junk code and junk flag settings. + -- late than never in preventing junk code and junk flag settings). if In_Subrange_Of (Source_Type, Target_Type) @@ -6998,7 +6989,8 @@ package body Checks is -- Next test for the case where the target type is within the bounds -- of the base type of the source type, since in this case we can - -- simply convert these bounds to the base type of T to do the test. + -- simply convert the bounds of the target type to this base bype + -- to do the test. -- [constraint_error when N not in -- Source_Base_Type (Target_Type'First) @@ -7047,14 +7039,18 @@ package body Checks is Suppress => All_Checks); -- For conversions involving at least one type that is not discrete, - -- first convert to target type and then generate the range check. - -- This avoids problems with values that are close to a bound of the - -- target type that would fail a range check when done in a larger - -- source type before converting but would pass if converted with + -- first convert to the target base type and then generate the range + -- check. This avoids problems with values that are close to a bound + -- of the target type that would fail a range check when done in a + -- larger source type before converting but pass if converted with -- rounding and then checked (such as in float-to-float conversions). + -- Note that overflow checks are not suppressed for this code because + -- we do not know whether the source type is in range of the target + -- base type (unlike in the next case below). + else - Convert_And_Check_Range; + Convert_And_Check_Range (Suppress => Range_Check); end if; -- Note that at this stage we know that the Target_Base_Type is not in @@ -7063,10 +7059,12 @@ package body Checks is -- in range of the target base type since we have not checked that case. -- If that is the case, we can freely convert the source to the target, - -- and then test the target result against the bounds. + -- and then test the target result against the bounds. Note that checks + -- are suppressed for this code, since we don't want a recursive range + -- check popping up. elsif In_Subrange_Of (Source_Type, Target_Base_Type) then - Convert_And_Check_Range; + Convert_And_Check_Range (Suppress => All_Checks); -- At this stage, we know that we have two scalar types, which are -- directly convertible, and where neither scalar type has a base diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 2af54a7..e4dc06b 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -12090,6 +12090,11 @@ package body Exp_Ch4 is if Is_Floating_Point_Type (Target_Type) and then Is_Floating_Point_Type (Etype (Expression (N))) then + -- Reset overflow flag, since the range check will include + -- dealing with possible overflow, and generate the check. + + Set_Do_Overflow_Check (N, False); + Generate_Range_Check (Expression (N), Target_Type, CE_Range_Check_Failed); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 03cf4bb..883befd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-23 Eric Botcazou + + * gnat.dg/range_check5.adb: New testcase. + 2019-07-23 Ed Schonberg * gnat.dg/iter5.adb: Add an expected error. diff --git a/gcc/testsuite/gnat.dg/range_check5.adb b/gcc/testsuite/gnat.dg/range_check5.adb new file mode 100644 index 0000000..dd62296 --- /dev/null +++ b/gcc/testsuite/gnat.dg/range_check5.adb @@ -0,0 +1,21 @@ +-- { dg-do run } +-- { dg-options "-gnateF -O0" } + +procedure Range_Check5 is + + subtype Small_Float is Float range -100.0 .. 100.0; + + function Conv (F : Long_Float) return Small_Float is + begin + return Small_Float (F); + end; + + R : Small_Float; + +begin + R := Conv (4.0E+38); + raise Program_Error; +exception + when Constraint_Error => + null; +end; -- cgit v1.1 From 4e2a165210c07078ad1226ca3f0712a457a73d0e Mon Sep 17 00:00:00 2001 From: Ed Schonberg Date: Tue, 23 Jul 2019 08:13:41 +0000 Subject: [Ada] Aspect CPU may depend on a discriminant of a task type 2019-07-23 Ed Schonberg gcc/ada/ * sem_ch13.adb (Check_Aspect_At_End_Of_Declarations, Freeze_Entity_Checks): Include Aspect_CPU with other aspects whose expresssion may depend on a discriminant, and thus require that components of the type be made visible. gcc/testsuite/ * gnat.dg/task4.adb: New testcase. From-SVN: r273726 --- gcc/ada/ChangeLog | 7 +++++++ gcc/ada/sem_ch13.adb | 2 ++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/task4.adb | 19 +++++++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 gcc/testsuite/gnat.dg/task4.adb (limited to 'gcc') diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 86a5491..64ac98b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2019-07-23 Ed Schonberg + + * sem_ch13.adb (Check_Aspect_At_End_Of_Declarations, + Freeze_Entity_Checks): Include Aspect_CPU with other aspects + whose expresssion may depend on a discriminant, and thus require + that components of the type be made visible. + 2019-07-23 Eric Botcazou * checks.adb (Convert_And_Check_Range): Add Suppress parameter diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index dc7f774..bf80200 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -9388,6 +9388,7 @@ package body Sem_Ch13 is elsif A_Id = Aspect_Dynamic_Predicate or else A_Id = Aspect_Predicate or else A_Id = Aspect_Priority + or else A_Id = Aspect_CPU then Push_Type (Ent); Preanalyze_Spec_Expression (End_Decl_Expr, T); @@ -11279,6 +11280,7 @@ package body Sem_Ch13 is if A_Id = Aspect_Dynamic_Predicate or else A_Id = Aspect_Predicate or else A_Id = Aspect_Priority + or else A_Id = Aspect_CPU then -- Retrieve the visibility to components and discriminants -- in order to properly analyze the aspects. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 883befd..d5efd50 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-07-23 Ed Schonberg + + * gnat.dg/task4.adb: New testcase. + 2019-07-23 Eric Botcazou * gnat.dg/range_check5.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/task4.adb b/gcc/testsuite/gnat.dg/task4.adb new file mode 100644 index 0000000..9a97503 --- /dev/null +++ b/gcc/testsuite/gnat.dg/task4.adb @@ -0,0 +1,19 @@ +-- { dg-do compile } + +with System.Multiprocessors; + +procedure Task4 is + + task type Infinite_Loop (C : System.Multiprocessors.CPU_Range) + with CPU => C; + + task body Infinite_Loop is + begin + loop + null; + end loop; + end Infinite_Loop; + +begin + null; +end Task4; -- cgit v1.1 From 187dd65de84c1e71c8b321bfc2fecc84068e0f1f Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 23 Jul 2019 11:27:11 +0200 Subject: x86-tune-costs.h (znver2_memcpy): Update. * config/i386/x86-tune-costs.h (znver2_memcpy): Update. (znver2_costs): Update 256 bit SSE costs and multiplication. From-SVN: r273728 --- gcc/ChangeLog | 5 +++++ gcc/config/i386/x86-tune-costs.h | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3b39269..2a84ebb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-23 Jan Hubicka + + * config/i386/x86-tune-costs.h (znver2_memcpy): Update. + (znver2_costs): Update 256 bit SSE costs and multiplication. + 2019-07-23 Jan Beulich * config/i386/sse.md (_cvtmask2): diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h index ac06e37..8b963c0 100644 --- a/gcc/config/i386/x86-tune-costs.h +++ b/gcc/config/i386/x86-tune-costs.h @@ -1279,12 +1279,12 @@ struct processor_costs znver1_cost = { static stringop_algs znver2_memcpy[2] = { {libcall, {{6, loop, false}, {14, unrolled_loop, false}, {-1, rep_prefix_4_byte, false}}}, - {libcall, {{16, loop, false}, {8192, rep_prefix_8_byte, false}, + {libcall, {{16, loop, false}, {64, rep_prefix_4_byte, false}, {-1, libcall, false}}}}; static stringop_algs znver2_memset[2] = { {libcall, {{8, loop, false}, {24, unrolled_loop, false}, {2048, rep_prefix_4_byte, false}, {-1, libcall, false}}}, - {libcall, {{48, unrolled_loop, false}, {8192, rep_prefix_8_byte, false}, + {libcall, {{24, rep_prefix_4_byte, false}, {128, rep_prefix_8_byte, false}, {-1, libcall, false}}}}; struct processor_costs znver2_cost = { @@ -1335,11 +1335,11 @@ struct processor_costs znver2_cost = { in SImode and DImode. */ {8, 8}, /* cost of storing MMX registers in SImode and DImode. */ - 2, 3, 6, /* cost of moving XMM,YMM,ZMM + 2, 2, 3, /* cost of moving XMM,YMM,ZMM register. */ - {6, 6, 6, 10, 20}, /* cost of loading SSE registers + {6, 6, 6, 6, 12}, /* cost of loading SSE registers in 32,64,128,256 and 512-bit. */ - {6, 6, 6, 10, 20}, /* cost of unaligned loads. */ + {6, 6, 6, 6, 12}, /* cost of unaligned loads. */ {8, 8, 8, 8, 16}, /* cost of storing SSE registers in 32,64,128,256 and 512-bit. */ {8, 8, 8, 8, 16}, /* cost of unaligned stores. */ @@ -1372,7 +1372,7 @@ struct processor_costs znver2_cost = { COSTS_N_INSNS (1), /* cost of cheap SSE instruction. */ COSTS_N_INSNS (3), /* cost of ADDSS/SD SUBSS/SD insns. */ COSTS_N_INSNS (3), /* cost of MULSS instruction. */ - COSTS_N_INSNS (4), /* cost of MULSD instruction. */ + COSTS_N_INSNS (3), /* cost of MULSD instruction. */ COSTS_N_INSNS (5), /* cost of FMA SS instruction. */ COSTS_N_INSNS (5), /* cost of FMA SD instruction. */ COSTS_N_INSNS (10), /* cost of DIVSS instruction. */ -- cgit v1.1 From ef893a2a769b18c61953d80670b1db8c27bc44e0 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 23 Jul 2019 11:32:44 +0200 Subject: * config/i386/x86-tune.def (X86_TUNE_AVOID_256FMA_CHAINS): Set of ZNVER2. From-SVN: r273729 --- gcc/ChangeLog | 7 +++++++ gcc/config/i386/x86-tune.def | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2a84ebb..181ecc4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2019-07-23 Jan Hubicka + * config/i386/i386-options.c (ix86_option_override_internal): Default + PARAM_AVOID_FMA_MAX_BITS to 256 for znver2. + * config/i386/x86-tune.def (X86_TUNE_AVOID_256FMA_CHAINS): Set + for ZNVER2. + +2019-07-23 Jan Hubicka + * config/i386/x86-tune-costs.h (znver2_memcpy): Update. (znver2_costs): Update 256 bit SSE costs and multiplication. diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def index 01e4986..fd59a84 100644 --- a/gcc/config/i386/x86-tune.def +++ b/gcc/config/i386/x86-tune.def @@ -431,6 +431,10 @@ DEF_TUNE (X86_TUNE_USE_GATHER, "use_gather", smaller FMA chain. */ DEF_TUNE (X86_TUNE_AVOID_128FMA_CHAINS, "avoid_fma_chains", m_ZNVER) +/* X86_TUNE_AVOID_256FMA_CHAINS: Avoid creating loops with tight 256bit or + smaller FMA chain. */ +DEF_TUNE (X86_TUNE_AVOID_256FMA_CHAINS, "avoid_fma256_chains", m_ZNVER2) + /*****************************************************************************/ /* AVX instruction selection tuning (some of SSE flags affects AVX, too) */ /*****************************************************************************/ -- cgit v1.1 From 105c2795b0d63b2cc5cb224ba066fa8b9a0ad0ff Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 23 Jul 2019 09:35:18 +0000 Subject: i386-options.c (ix86_option_override_internal): Default PARAM_AVOID_FMA_MAX_BITS to 256 for znver2. * config/i386/i386-options.c (ix86_option_override_internal): Default PARAM_AVOID_FMA_MAX_BITS to 256 for znver2. From-SVN: r273730 --- gcc/config/i386/i386-options.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c index 6f8851a..a1741c0 100644 --- a/gcc/config/i386/i386-options.c +++ b/gcc/config/i386/i386-options.c @@ -2779,7 +2779,11 @@ ix86_option_override_internal (bool main_args_p, opts->x_flag_cf_protection = (cf_protection_level) (opts->x_flag_cf_protection | CF_SET); - if (ix86_tune_features [X86_TUNE_AVOID_128FMA_CHAINS]) + if (ix86_tune_features [X86_TUNE_AVOID_256FMA_CHAINS]) + maybe_set_param_value (PARAM_AVOID_FMA_MAX_BITS, 256, + opts->x_param_values, + opts_set->x_param_values); + else if (ix86_tune_features [X86_TUNE_AVOID_128FMA_CHAINS]) maybe_set_param_value (PARAM_AVOID_FMA_MAX_BITS, 128, opts->x_param_values, opts_set->x_param_values); -- cgit v1.1 From e1eb82f5aa4f6e9ed9a6a368b54d0eda785be85c Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 23 Jul 2019 11:38:49 +0200 Subject: i386-common.c: Use PROCESSOR_ZNVER2 scheduler for znver2. * i386-common.c: Use PROCESSOR_ZNVER2 scheduler for znver2. * config/i386/znver1.md: Enable patterns for znver2 and add store variants which use extra AGU unit. From-SVN: r273731 --- gcc/ChangeLog | 6 + gcc/common/config/i386/i386-common.c | 2 +- gcc/config/i386/znver1.md | 579 ++++++++++++++++++++++++----------- 3 files changed, 411 insertions(+), 176 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 181ecc4..fb9b0ff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-07-23 Jan Hubicka + * i386-common.c: Use PROCESSOR_ZNVER2 scheduler for znver2. + * config/i386/znver1.md: Enable patterns for znver2 and add store + variants which use extra AGU unit. + +2019-07-23 Jan Hubicka + * config/i386/i386-options.c (ix86_option_override_internal): Default PARAM_AVOID_FMA_MAX_BITS to 256 for znver2. * config/i386/x86-tune.def (X86_TUNE_AVOID_256FMA_CHAINS): Set diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c index a394f87..1f77f7d 100644 --- a/gcc/common/config/i386/i386-common.c +++ b/gcc/common/config/i386/i386-common.c @@ -1760,7 +1760,7 @@ const pta processor_alias_table[] = | PTA_RDRND | PTA_MOVBE | PTA_MWAITX | PTA_ADX | PTA_RDSEED | PTA_CLZERO | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES | PTA_SHA | PTA_LZCNT | PTA_POPCNT}, - {"znver2", PROCESSOR_ZNVER2, CPU_ZNVER1, + {"znver2", PROCESSOR_ZNVER2, CPU_ZNVER2, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2 diff --git a/gcc/config/i386/znver1.md b/gcc/config/i386/znver1.md index c7f49bf..7e3efa8 100644 --- a/gcc/config/i386/znver1.md +++ b/gcc/config/i386/znver1.md @@ -17,10 +17,11 @@ ;; . ;; + (define_attr "znver1_decode" "direct,vector,double" (const_string "direct")) -;; AMD znver1 Scheduling +;; AMD znver1 and znver2 Scheduling ;; Modeling automatons for zen decoders, integer execution pipes, ;; AGU pipes and floating point execution units. (define_automaton "znver1, znver1_ieu, znver1_fp, znver1_agu") @@ -51,13 +52,21 @@ (define_cpu_unit "znver1-ieu3" "znver1_ieu") (define_reservation "znver1-ieu" "znver1-ieu0|znver1-ieu1|znver1-ieu2|znver1-ieu3") -;; 2 AGU pipes. +;; 2 AGU pipes in znver1 and 3 AGU pipes in znver2 +;; According to CPU diagram last AGU unit is used only for stores. (define_cpu_unit "znver1-agu0" "znver1_agu") (define_cpu_unit "znver1-agu1" "znver1_agu") +(define_cpu_unit "znver2-agu2" "znver1_agu") (define_reservation "znver1-agu-reserve" "znver1-agu0|znver1-agu1") +(define_reservation "znver2-store-agu-reserve" "znver1-agu0|znver1-agu1|znver2-agu2") +;; Load is 4 cycles. We do not model reservation of load unit. +;;(define_reservation "znver1-load" "znver1-agu-reserve, nothing, nothing, nothing") (define_reservation "znver1-load" "znver1-agu-reserve") +;; Store operations differs between znver1 and znver2 because extra AGU +;; was added. (define_reservation "znver1-store" "znver1-agu-reserve") +(define_reservation "znver2-store" "znver2-store-agu-reserve") ;; vectorpath (microcoded) instructions are single issue instructions. ;; So, they occupy all the integer units. @@ -65,6 +74,9 @@ +znver1-ieu2+znver1-ieu3 +znver1-agu0+znver1-agu1") +(define_reservation "znver2-ivector" "znver1-ieu0+znver1-ieu1 + +znver1-ieu2+znver1-ieu3 + +znver1-agu0+znver1-agu1+znver2-agu2") ;; Floating point unit 4 FP pipes. (define_cpu_unit "znver1-fp0" "znver1_fp") (define_cpu_unit "znver1-fp1" "znver1_fp") @@ -76,6 +88,9 @@ (define_reservation "znver1-fvector" "znver1-fp0+znver1-fp1 +znver1-fp2+znver1-fp3 +znver1-agu0+znver1-agu1") +(define_reservation "znver2-fvector" "znver1-fp0+znver1-fp1 + +znver1-fp2+znver1-fp3 + +znver1-agu0+znver1-agu1+znver2-agu2") ;; Call instruction (define_insn_reservation "znver1_call" 1 @@ -83,27 +98,36 @@ (eq_attr "type" "call,callv")) "znver1-double,znver1-store,znver1-ieu0|znver1-ieu3") +(define_insn_reservation "znver2_call" 1 + (and (eq_attr "cpu" "znver2") + (eq_attr "type" "call,callv")) + "znver1-double,znver2-store,znver1-ieu0|znver1-ieu3") + ;; General instructions (define_insn_reservation "znver1_push" 1 (and (eq_attr "cpu" "znver1") (and (eq_attr "type" "push") - (eq_attr "memory" "none,unknown"))) + (eq_attr "memory" "store"))) "znver1-direct,znver1-store") - -(define_insn_reservation "znver1_push_store" 1 - (and (eq_attr "cpu" "znver1") +(define_insn_reservation "znver2_push" 1 + (and (eq_attr "cpu" "znver2") (and (eq_attr "type" "push") (eq_attr "memory" "store"))) "znver1-direct,znver1-store") -(define_insn_reservation "znver1_push_both" 5 +(define_insn_reservation "znver1_push_load" 4 (and (eq_attr "cpu" "znver1") (and (eq_attr "type" "push") (eq_attr "memory" "both"))) "znver1-direct,znver1-load,znver1-store") +(define_insn_reservation "znver2_push_load" 4 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "push") + (eq_attr "memory" "both"))) + "znver1-direct,znver1-load,znver2-store") (define_insn_reservation "znver1_pop" 4 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "pop") (eq_attr "memory" "load"))) "znver1-direct,znver1-load") @@ -113,24 +137,33 @@ (and (eq_attr "type" "pop") (eq_attr "memory" "both"))) "znver1-direct,znver1-load,znver1-store") +(define_insn_reservation "znver2_pop_mem" 4 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "pop") + (eq_attr "memory" "both"))) + "znver1-direct,znver1-load,znver2-store") ;; Leave (define_insn_reservation "znver1_leave" 1 (and (eq_attr "cpu" "znver1") (eq_attr "type" "leave")) "znver1-double,znver1-ieu, znver1-store") +(define_insn_reservation "znver2_leave" 1 + (and (eq_attr "cpu" "znver2") + (eq_attr "type" "leave")) + "znver1-double,znver1-ieu, znver2-store") ;; Integer Instructions or General instructions ;; Multiplications ;; Reg operands (define_insn_reservation "znver1_imul" 3 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "imul") (eq_attr "memory" "none"))) "znver1-direct,znver1-ieu1") (define_insn_reservation "znver1_imul_mem" 7 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "imul") (eq_attr "memory" "!none"))) "znver1-direct,znver1-load, znver1-ieu1") @@ -138,28 +171,28 @@ ;; Divisions ;; Reg operands (define_insn_reservation "znver1_idiv_DI" 41 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "memory" "none")))) "znver1-double,znver1-ieu2*41") (define_insn_reservation "znver1_idiv_SI" 25 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "memory" "none")))) "znver1-double,znver1-ieu2*25") (define_insn_reservation "znver1_idiv_HI" 17 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "HI") (eq_attr "memory" "none")))) "znver1-double,znver1-ieu2*17") (define_insn_reservation "znver1_idiv_QI" 12 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "QI") (eq_attr "memory" "none")))) @@ -167,28 +200,28 @@ ;; Mem operands (define_insn_reservation "znver1_idiv_mem_DI" 45 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "DI") (eq_attr "memory" "none")))) "znver1-double,znver1-load,znver1-ieu2*41") (define_insn_reservation "znver1_idiv_mem_SI" 29 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "SI") (eq_attr "memory" "none")))) "znver1-double,znver1-load,znver1-ieu2*25") (define_insn_reservation "znver1_idiv_mem_HI" 21 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "HI") (eq_attr "memory" "none")))) "znver1-double,znver1-load,znver1-ieu2*17") (define_insn_reservation "znver1_idiv_mem_QI" 16 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "idiv") (and (eq_attr "mode" "QI") (eq_attr "memory" "none")))) @@ -201,16 +234,34 @@ (and (eq_attr "type" "str,ishift") (eq_attr "memory" "both,store"))) "znver1-vector,znver1-ivector") + +(define_insn_reservation "znver2_str_ishift" 3 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "ishift") + (eq_attr "memory" "both,store"))) + "znver1-vector,znver1-ivector") +(define_insn_reservation "znver2_str_istr" 19 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "str") + (eq_attr "memory" "both,store"))) + "znver1-vector,znver1-ivector") ;; MOV - integer moves (define_insn_reservation "znver1_load_imov_double" 2 (and (eq_attr "cpu" "znver1") (and (eq_attr "znver1_decode" "double") (and (eq_attr "type" "imovx") (eq_attr "memory" "none")))) - "znver1-double,znver1-ieu") + "znver1-double,znver1-ieu|znver1-ieu") + +(define_insn_reservation "znver2_load_imov_double" 1 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "znver1_decode" "double") + (and (eq_attr "type" "imovx") + (eq_attr "memory" "none")))) + "znver1-double,znver1-ieu|znver1-ieu") (define_insn_reservation "znver1_load_imov_direct" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "imov,imovx") (eq_attr "memory" "none"))) "znver1-direct,znver1-ieu") @@ -220,7 +271,14 @@ (and (eq_attr "znver1_decode" "double") (and (eq_attr "type" "imovx") (eq_attr "memory" "store")))) - "znver1-double,znver1-ieu,znver1-store") + "znver1-double,znver1-ieu|znver1-ieu,znver1-store") + +(define_insn_reservation "znver2_load_imov_double_store" 1 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "znver1_decode" "double") + (and (eq_attr "type" "imovx") + (eq_attr "memory" "store")))) + "znver1-double,znver1-ieu|znver1-ieu,znver2-store") (define_insn_reservation "znver1_load_imov_direct_store" 1 (and (eq_attr "cpu" "znver1") @@ -228,15 +286,28 @@ (eq_attr "memory" "store"))) "znver1-direct,znver1-ieu,znver1-store") +(define_insn_reservation "znver2_load_imov_direct_store" 1 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "imov,imovx") + (eq_attr "memory" "store"))) + "znver1-direct,znver1-ieu,znver2-store") + (define_insn_reservation "znver1_load_imov_double_load" 5 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "znver1_decode" "double") (and (eq_attr "type" "imovx") (eq_attr "memory" "load")))) - "znver1-double,znver1-load") + "znver1-double,znver1-load,znver1-ieu|znver1-ieu") + +(define_insn_reservation "znver2_load_imov_double_load" 4 + (and (eq_attr "cpu" "znver1,znver2") + (and (eq_attr "znver1_decode" "double") + (and (eq_attr "type" "imovx") + (eq_attr "memory" "load")))) + "znver1-double,znver1-load,znver1-ieu|znver1-ieu") (define_insn_reservation "znver1_load_imov_direct_load" 4 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "imov,imovx") (eq_attr "memory" "load"))) "znver1-direct,znver1-load") @@ -244,13 +315,13 @@ ;; INTEGER/GENERAL instructions ;; register/imm operands only: ALU, ICMP, NEG, NOT, ROTATE, ISHIFT, TEST (define_insn_reservation "znver1_insn" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift,ishift1,test,setcc,incdec,icmov") (eq_attr "memory" "none,unknown"))) "znver1-direct,znver1-ieu") (define_insn_reservation "znver1_insn_load" 5 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift,ishift1,test,setcc,incdec,icmov") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-ieu") @@ -261,18 +332,35 @@ (eq_attr "memory" "store"))) "znver1-direct,znver1-ieu,znver1-store") +(define_insn_reservation "znver2_insn_store" 1 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift1,test,setcc,incdec") + (eq_attr "memory" "store"))) + "znver1-direct,znver1-ieu,znver2-store") + (define_insn_reservation "znver1_insn_both" 5 (and (eq_attr "cpu" "znver1") (and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift1,test,setcc,incdec") (eq_attr "memory" "both"))) "znver1-direct,znver1-load,znver1-ieu,znver1-store") +(define_insn_reservation "znver2_insn_both" 5 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "alu,icmp,negnot,rotate,rotate1,ishift1,test,setcc,incdec") + (eq_attr "memory" "both"))) + "znver1-direct,znver1-load,znver1-ieu,znver2-store") + ;; Fix me: Other vector type insns keeping latency 6 as of now. (define_insn_reservation "znver1_ieu_vector" 6 (and (eq_attr "cpu" "znver1") (eq_attr "type" "other,str,multi")) "znver1-vector,znver1-ivector") +(define_insn_reservation "znver2_ieu_vector" 5 + (and (eq_attr "cpu" "znver2") + (eq_attr "type" "other,str,multi")) + "znver1-vector,znver2-ivector") + ;; ALU1 register operands. (define_insn_reservation "znver1_alu1_vector" 3 (and (eq_attr "cpu" "znver1") @@ -281,15 +369,22 @@ (eq_attr "memory" "none,unknown")))) "znver1-vector,znver1-ivector") +(define_insn_reservation "znver2_alu1_vector" 3 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "znver1_decode" "vector") + (and (eq_attr "type" "alu1") + (eq_attr "memory" "none,unknown")))) + "znver1-vector,znver2-ivector") + (define_insn_reservation "znver1_alu1_double" 2 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "znver1_decode" "double") (and (eq_attr "type" "alu1") (eq_attr "memory" "none,unknown")))) "znver1-double,znver1-ieu") (define_insn_reservation "znver1_alu1_direct" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "znver1_decode" "direct") (and (eq_attr "type" "alu1") (eq_attr "memory" "none,unknown")))) @@ -297,7 +392,7 @@ ;; Branches : Fix me need to model conditional branches. (define_insn_reservation "znver1_branch" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "ibr") (eq_attr "memory" "none"))) "znver1-direct") @@ -309,27 +404,33 @@ (eq_attr "memory" "load"))) "znver1-vector,znver1-ivector") +(define_insn_reservation "znver2_indirect_branch_mem" 6 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "ibr") + (eq_attr "memory" "load"))) + "znver1-vector,znver2-ivector") + ;; LEA executes in ALU units with 1 cycle latency. (define_insn_reservation "znver1_lea" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (eq_attr "type" "lea")) "znver1-direct,znver1-ieu") ;; Other integer instrucions (define_insn_reservation "znver1_idirect" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "unit" "integer,unknown") (eq_attr "memory" "none,unknown"))) "znver1-direct,znver1-ieu") ;; Floating point (define_insn_reservation "znver1_fp_cmov" 6 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (eq_attr "type" "fcmov")) "znver1-vector,znver1-fvector") (define_insn_reservation "znver1_fp_mov_direct_load" 8 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "znver1_decode" "direct") (and (eq_attr "type" "fmov") (eq_attr "memory" "load")))) @@ -341,9 +442,15 @@ (and (eq_attr "type" "fmov") (eq_attr "memory" "store")))) "znver1-direct,znver1-fp2|znver1-fp3,znver1-store") +(define_insn_reservation "znver2_fp_mov_direct_store" 5 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "znver1_decode" "direct") + (and (eq_attr "type" "fmov") + (eq_attr "memory" "store")))) + "znver1-direct,znver1-fp2|znver1-fp3,znver2-store") (define_insn_reservation "znver1_fp_mov_double" 4 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "znver1_decode" "double") (and (eq_attr "type" "fmov") (eq_attr "memory" "none")))) @@ -356,13 +463,21 @@ (eq_attr "memory" "load")))) "znver1-double,znver1-load,znver1-fp3") +(define_insn_reservation "znver2_fp_mov_double_load" 12 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "znver1_decode" "double") + (and (eq_attr "type" "fmov") + (eq_attr "memory" "load")))) + "znver1-double,znver1-load,znver1-fp3") + (define_insn_reservation "znver1_fp_mov_direct" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (eq_attr "type" "fmov")) "znver1-direct,znver1-fp3") +;; TODO: AGU? (define_insn_reservation "znver1_fp_spc_direct" 5 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "fpspc") (eq_attr "memory" "store"))) "znver1-direct,znver1-fp3,znver1-fp2") @@ -372,22 +487,27 @@ (and (eq_attr "znver1_decode" "vector") (eq_attr "type" "fpspc,mmxcvt,sselog1,ssemul,ssemov"))) "znver1-vector,znver1-fvector") +(define_insn_reservation "znver2_fp_insn_vector" 6 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "znver1_decode" "vector") + (eq_attr "type" "fpspc,mmxcvt,sselog1,ssemul,ssemov"))) + "znver1-vector,znver2-fvector") ;; FABS (define_insn_reservation "znver1_fp_fsgn" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (eq_attr "type" "fsgn")) "znver1-direct,znver1-fp3") (define_insn_reservation "znver1_fp_fcmp" 2 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "memory" "none") (and (eq_attr "znver1_decode" "double") (eq_attr "type" "fcmp")))) "znver1-double,znver1-fp0,znver1-fp2") (define_insn_reservation "znver1_fp_fcmp_load" 9 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "memory" "none") (and (eq_attr "znver1_decode" "double") (eq_attr "type" "fcmp")))) @@ -395,32 +515,32 @@ ;;FADD FSUB FMUL (define_insn_reservation "znver1_fp_op_mul" 5 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "fop,fmul") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0*5") (define_insn_reservation "znver1_fp_op_mul_load" 12 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "fop,fmul") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0*5") (define_insn_reservation "znver1_fp_op_imul_load" 16 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "fop,fmul") (and (eq_attr "fp_int_src" "true") (eq_attr "memory" "load")))) "znver1-double,znver1-load,znver1-fp3,znver1-fp0") (define_insn_reservation "znver1_fp_op_div" 15 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "fdiv") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp3*15") (define_insn_reservation "znver1_fp_op_div_load" 22 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "fdiv") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp3*15") @@ -432,56 +552,63 @@ (eq_attr "memory" "load")))) "znver1-double,znver1-load,znver1-fp3*19") +(define_insn_reservation "znver2_fp_op_idiv_load" 26 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "fdiv") + (and (eq_attr "fp_int_src" "true") + (eq_attr "memory" "load")))) + "znver1-double,znver1-load,znver1-fp3*19") + ;; MMX, SSE, SSEn.n, AVX, AVX2 instructions (define_insn_reservation "znver1_fp_insn" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (eq_attr "type" "mmx")) "znver1-direct,znver1-fpu") (define_insn_reservation "znver1_mmx_add" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxadd") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0|znver1-fp1|znver1-fp3") (define_insn_reservation "znver1_mmx_add_load" 8 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxadd") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0|znver1-fp1|znver1-fp3") (define_insn_reservation "znver1_mmx_cmp" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxcmp") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0|znver1-fp3") (define_insn_reservation "znver1_mmx_cmp_load" 8 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxcmp") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0|znver1-fp3") (define_insn_reservation "znver1_mmx_cvt_pck_shuf" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxcvt,sseshuf,sseshuf1") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp1|znver1-fp2") (define_insn_reservation "znver1_mmx_cvt_pck_shuf_load" 8 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxcvt,sseshuf,sseshuf1") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp1|znver1-fp2") (define_insn_reservation "znver1_mmx_shift_move" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxshft,mmxmov") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp2") (define_insn_reservation "znver1_mmx_shift_move_load" 8 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxshft,mmxmov") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp2") @@ -491,19 +618,25 @@ (and (eq_attr "type" "mmxshft,mmxmov") (eq_attr "memory" "store,both"))) "znver1-direct,znver1-fp2,znver1-store") +(define_insn_reservation "znver2_mmx_move_store" 1 + (and (eq_attr "cpu" "znver1") + (and (eq_attr "type" "mmxshft,mmxmov") + (eq_attr "memory" "store,both"))) + "znver1-direct,znver1-fp2,znver2-store") (define_insn_reservation "znver1_mmx_mul" 3 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxmul") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0*3") (define_insn_reservation "znver1_mmx_load" 10 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "mmxmul") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0*3") +;; TODO (define_insn_reservation "znver1_avx256_log" 1 (and (eq_attr "cpu" "znver1") (and (eq_attr "mode" "V8SF,V4DF,OI") @@ -519,13 +652,13 @@ "znver1-double,znver1-load,znver1-fpu") (define_insn_reservation "znver1_sse_log" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "sselog") (eq_attr "memory" "none"))) "znver1-direct,znver1-fpu") (define_insn_reservation "znver1_sse_log_load" 8 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "sselog") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fpu") @@ -545,13 +678,13 @@ "znver1-double,znver1-load,znver1-fp1|znver1-fp2") (define_insn_reservation "znver1_sse_log1" 1 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "sselog1") (eq_attr "memory" "none"))) "znver1-direct,znver1-fp1|znver1-fp2") (define_insn_reservation "znver1_sse_log1_load" 8 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "type" "sselog1") (eq_attr "memory" "!none"))) "znver1-direct,znver1-load,znver1-fp1|znver1-fp2") @@ -566,46 +699,50 @@ "znver1-direct,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sse_comi_load" 8 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF") - (and (eq_attr "prefix" "!vex") - (and (eq_attr "prefix_extra" "0") - (and (eq_attr "type" "ssecomi") - (eq_attr "memory" "load")))))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "prefix_extra" "0") + (and (eq_attr "type" "ssecomi") + (eq_attr "memory" "load")))) "znver1-direct,znver1-load,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sse_comi_double" 2 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V4SF,V2DF,TI") - (and (eq_attr "prefix" "vex") - (and (eq_attr "prefix_extra" "0") - (and (eq_attr "type" "ssecomi") - (eq_attr "memory" "none")))))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "prefix" "vex") + (and (eq_attr "prefix_extra" "0") + (and (eq_attr "type" "ssecomi") + (eq_attr "memory" "none"))))) "znver1-double,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sse_comi_double_load" 10 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V4SF,V2DF,TI") - (and (eq_attr "prefix" "vex") - (and (eq_attr "prefix_extra" "0") - (and (eq_attr "type" "ssecomi") - (eq_attr "memory" "load")))))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "prefix" "vex") + (and (eq_attr "prefix_extra" "0") + (and (eq_attr "type" "ssecomi") + (eq_attr "memory" "load"))))) "znver1-double,znver1-load,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sse_test" 1 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF,TI") - (and (eq_attr "prefix_extra" "1") - (and (eq_attr "type" "ssecomi") - (eq_attr "memory" "none"))))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "prefix_extra" "1") + (and (eq_attr "type" "ssecomi") + (eq_attr "memory" "none")))) "znver1-direct,znver1-fp1|znver1-fp2") (define_insn_reservation "znver1_sse_test_load" 8 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF,TI") - (and (eq_attr "prefix_extra" "1") - (and (eq_attr "type" "ssecomi") - (eq_attr "memory" "load"))))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "prefix_extra" "1") + (and (eq_attr "type" "ssecomi") + (eq_attr "memory" "load")))) "znver1-direct,znver1-load,znver1-fp1|znver1-fp2") ;; SSE moves @@ -619,6 +756,14 @@ (eq_attr "memory" "none"))))) "znver1-direct,znver1-ieu0") +(define_insn_reservation "znver2_sse_mov" 1 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "mode" "SI") + (and (eq_attr "isa" "avx") + (and (eq_attr "type" "ssemov") + (eq_attr "memory" "none"))))) + "znver1-direct,znver1-ieu0") + (define_insn_reservation "znver1_avx_mov" 2 (and (eq_attr "cpu" "znver1") (and (eq_attr "mode" "TI") @@ -628,11 +773,21 @@ (eq_attr "memory" "none")))))) "znver1-direct,znver1-ieu2") +(define_insn_reservation "znver2_avx_mov" 1 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "mode" "TI") + (and (eq_attr "isa" "avx") + (and (eq_attr "type" "ssemov") + (and (match_operand:SI 1 "register_operand") + (eq_attr "memory" "none")))))) + "znver1-direct,znver1-ieu2") + (define_insn_reservation "znver1_sseavx_mov" 1 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF,TI") - (and (eq_attr "type" "ssemov") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "ssemov") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fpu") (define_insn_reservation "znver1_sseavx_mov_store" 1 @@ -641,12 +796,18 @@ (and (eq_attr "type" "ssemov") (eq_attr "memory" "store")))) "znver1-direct,znver1-fpu,znver1-store") +(define_insn_reservation "znver2_sseavx_mov_store" 1 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "ssemov") + (eq_attr "memory" "store"))) + "znver1-direct,znver1-fpu,znver2-store") (define_insn_reservation "znver1_sseavx_mov_load" 8 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF,TI") - (and (eq_attr "type" "ssemov") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "ssemov") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fpu") (define_insn_reservation "znver1_avx256_mov" 1 @@ -672,17 +833,19 @@ ;; SSE add (define_insn_reservation "znver1_sseavx_add" 3 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF,TI") - (and (eq_attr "type" "sseadd") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "sseadd") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp2|znver1-fp3") (define_insn_reservation "znver1_sseavx_add_load" 10 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF,TI") - (and (eq_attr "type" "sseadd") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "sseadd") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp2|znver1-fp3") (define_insn_reservation "znver1_avx256_add" 3 @@ -700,17 +863,19 @@ "znver1-double,znver1-load,znver1-fp2|znver1-fp3") (define_insn_reservation "znver1_sseavx_fma" 5 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF") - (and (eq_attr "type" "ssemuladd") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "ssemuladd") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sseavx_fma_load" 12 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF") - (and (eq_attr "type" "ssemuladd") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "ssemuladd") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_avx256_fma" 5 @@ -728,17 +893,19 @@ "znver1-double,znver1-load,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sseavx_iadd" 1 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "DI,TI") - (and (eq_attr "type" "sseiadd") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "DI,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "sseiadd") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0|znver1-fp1|znver1-fp3") (define_insn_reservation "znver1_sseavx_iadd_load" 8 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "DI,TI") - (and (eq_attr "type" "sseiadd") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "DI,TI")) + (eq_attr "cpu" "znver2")) + (and (eq_attr "type" "sseiadd") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0|znver1-fp1|znver1-fp3") (define_insn_reservation "znver1_avx256_iadd" 1 @@ -757,7 +924,7 @@ ;; SSE conversions. (define_insn_reservation "znver1_ssecvtsf_si_load" 12 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "mode" "SI") (and (eq_attr "type" "sseicvt") (and (match_operand:SF 1 "memory_operand") @@ -771,6 +938,13 @@ (and (eq_attr "type" "sseicvt") (eq_attr "memory" "none"))))) "znver1-double,znver1-fp3,znver1-ieu0") +(define_insn_reservation "znver2_ssecvtdf_si" 4 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "mode" "SI") + (and (match_operand:DF 1 "register_operand") + (and (eq_attr "type" "sseicvt") + (eq_attr "memory" "none"))))) + "znver1-double,znver1-fp3,znver1-ieu0") (define_insn_reservation "znver1_ssecvtdf_si_load" 12 (and (eq_attr "cpu" "znver1") @@ -780,6 +954,14 @@ (eq_attr "memory" "load"))))) "znver1-double,znver1-load,znver1-fp3,znver1-ieu0") +(define_insn_reservation "znver2_ssecvtdf_si_load" 11 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "mode" "SI") + (and (eq_attr "type" "sseicvt") + (and (match_operand:DF 1 "memory_operand") + (eq_attr "memory" "load"))))) + "znver1-double,znver1-load,znver1-fp3,znver1-ieu0") + ;; All other used ssecvt fp3 pipes ;; Check: Need to revisit this again. ;; Some SSE converts may use different pipe combinations. @@ -789,39 +971,59 @@ (eq_attr "memory" "none"))) "znver1-direct,znver1-fp3") +(define_insn_reservation "znver2_ssecvt" 3 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "ssecvt") + (eq_attr "memory" "none"))) + "znver1-direct,znver1-fp3") + (define_insn_reservation "znver1_ssecvt_load" 11 (and (eq_attr "cpu" "znver1") (and (eq_attr "type" "ssecvt") (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp3") +(define_insn_reservation "znver2_ssecvt_load" 11 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "ssecvt") + (eq_attr "memory" "load"))) + "znver1-direct,znver1-load,znver1-fp3") + ;; SSE div (define_insn_reservation "znver1_ssediv_ss_ps" 10 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V4SF,SF") - (and (eq_attr "type" "ssediv") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V4SF,SF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "V8SF,V4SF,SF"))) + (and (eq_attr "type" "ssediv") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp3*10") (define_insn_reservation "znver1_ssediv_ss_ps_load" 17 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V4SF,SF") - (and (eq_attr "type" "ssediv") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V4SF,SF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "V8SF,V4SF,SF"))) + (and (eq_attr "type" "ssediv") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp3*10") (define_insn_reservation "znver1_ssediv_sd_pd" 13 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V2DF,DF") - (and (eq_attr "type" "ssediv") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V2DF,DF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "V4DF,V2DF,DF"))) + (and (eq_attr "type" "ssediv") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp3*13") (define_insn_reservation "znver1_ssediv_sd_pd_load" 20 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V2DF,DF") - (and (eq_attr "type" "ssediv") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V2DF,DF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "V4DF,V2DF,DF"))) + (and (eq_attr "type" "ssediv") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp3*13") (define_insn_reservation "znver1_ssediv_avx256_ps" 12 @@ -853,17 +1055,21 @@ "znver1-double,znver1-load,znver1-fp3*15") ;; SSE MUL (define_insn_reservation "znver1_ssemul_ss_ps" 3 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V4SF,SF") - (and (eq_attr "type" "ssemul") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V4SF,SF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "V8SF,V4SF,SF,V4DF,V2DF,DF"))) + (and (eq_attr "type" "ssemul") + (eq_attr "memory" "none"))) "znver1-direct,(znver1-fp0|znver1-fp1)*3") (define_insn_reservation "znver1_ssemul_ss_ps_load" 10 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "V4SF,SF") - (and (eq_attr "type" "ssemul") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "V4SF,SF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "V8SF,V4SF,SF"))) + (and (eq_attr "type" "ssemul") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,(znver1-fp0|znver1-fp1)*3") (define_insn_reservation "znver1_ssemul_avx256_ps" 3 @@ -894,12 +1100,23 @@ (eq_attr "memory" "load")))) "znver1-direct,znver1-load,(znver1-fp0|znver1-fp1)*4") +(define_insn_reservation "znver2_ssemul_sd_pd" 3 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "ssemul") + (eq_attr "memory" "none"))) + "znver1-direct,(znver1-fp0|znver1-fp1)*3") + +(define_insn_reservation "znver2_ssemul_sd_pd_load" 10 + (and (eq_attr "cpu" "znver2") + (and (eq_attr "type" "ssemul") + (eq_attr "memory" "load"))) + "znver1-direct,znver1-load,(znver1-fp0|znver1-fp1)*3") + (define_insn_reservation "znver1_ssemul_avx256_pd" 5 (and (eq_attr "cpu" "znver1") (and (eq_attr "mode" "V4DF") - (and (eq_attr "mode" "V4DF") - (and (eq_attr "type" "ssemul") - (eq_attr "memory" "none"))))) + (and (eq_attr "type" "ssemul") + (eq_attr "memory" "none")))) "znver1-double,(znver1-fp0|znver1-fp1)*4") (define_insn_reservation "znver1_ssemul_avx256_pd_load" 12 @@ -911,42 +1128,46 @@ ;;SSE imul (define_insn_reservation "znver1_sseimul" 3 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "TI") - (and (eq_attr "type" "sseimul") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "TI")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "TI,OI"))) + (and (eq_attr "type" "sseimul") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0*3") (define_insn_reservation "znver1_sseimul_avx256" 4 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "mode" "OI") (and (eq_attr "type" "sseimul") (eq_attr "memory" "none")))) "znver1-double,znver1-fp0*4") (define_insn_reservation "znver1_sseimul_load" 10 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "TI") - (and (eq_attr "type" "sseimul") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "TI")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "TI,OI"))) + (and (eq_attr "type" "sseimul") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0*3") (define_insn_reservation "znver1_sseimul_avx256_load" 11 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "mode" "OI") (and (eq_attr "type" "sseimul") (eq_attr "memory" "load")))) "znver1-double,znver1-load,znver1-fp0*4") (define_insn_reservation "znver1_sseimul_di" 3 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "mode" "DI") (and (eq_attr "memory" "none") (eq_attr "type" "sseimul")))) "znver1-direct,znver1-fp0*3") (define_insn_reservation "znver1_sseimul_load_di" 10 - (and (eq_attr "cpu" "znver1") + (and (eq_attr "cpu" "znver1,znver2") (and (eq_attr "mode" "DI") (and (eq_attr "type" "sseimul") (eq_attr "memory" "load")))) @@ -954,17 +1175,21 @@ ;; SSE compares (define_insn_reservation "znver1_sse_cmp" 1 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF") - (and (eq_attr "type" "ssecmp") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF"))) + (and (eq_attr "type" "ssecmp") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sse_cmp_load" 8 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "SF,DF,V4SF,V2DF") - (and (eq_attr "type" "ssecmp") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "SF,DF,V4SF,V2DF")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "SF,DF,V4SF,V2DF,V8SF,V4DF"))) + (and (eq_attr "type" "ssecmp") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sse_cmp_avx256" 1 @@ -982,17 +1207,21 @@ "znver1-double,znver1-load,znver1-fp0|znver1-fp1") (define_insn_reservation "znver1_sse_icmp" 1 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "QI,HI,SI,DI,TI") - (and (eq_attr "type" "ssecmp") - (eq_attr "memory" "none")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "QI,HI,SI,DI,TI")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "QI,HI,SI,DI,TI,OI"))) + (and (eq_attr "type" "ssecmp") + (eq_attr "memory" "none"))) "znver1-direct,znver1-fp0|znver1-fp3") (define_insn_reservation "znver1_sse_icmp_load" 8 - (and (eq_attr "cpu" "znver1") - (and (eq_attr "mode" "QI,HI,SI,DI,TI") - (and (eq_attr "type" "ssecmp") - (eq_attr "memory" "load")))) + (and (ior (and (eq_attr "cpu" "znver1") + (eq_attr "mode" "QI,HI,SI,DI,TI")) + (and (eq_attr "cpu" "znver2") + (eq_attr "mode" "QI,HI,SI,DI,TI,OI"))) + (and (eq_attr "type" "ssecmp") + (eq_attr "memory" "load"))) "znver1-direct,znver1-load,znver1-fp0|znver1-fp3") (define_insn_reservation "znver1_sse_icmp_avx256" 1 -- cgit v1.1 From 62e3e66f130fc280eac0bbb6b69e9adca328c03b Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 23 Jul 2019 10:00:24 +0000 Subject: re PR tree-optimization/83518 (Missing optimization: useless instructions should be dropped) 2019-07-23 Richard Biener PR tree-optimization/83518 * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle aggregate init from a constant even when partial defs are already recorded. c/ * gimple-parser.c (c_parser_parse_gimple_body): When we have a CFG also rebuild cgraph edges. * gcc.dg/tree-ssa/ssa-fre-79.c: New testcase. From-SVN: r273732 --- gcc/ChangeLog | 6 ++++++ gcc/c/ChangeLog | 6 ++++++ gcc/c/gimple-parser.c | 2 ++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-79.c | 29 +++++++++++++++++++++++++++++ gcc/tree-ssa-sccvn.c | 30 +++++++++++++++++++++++++----- 6 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-79.c (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fb9b0ff..1add332 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-23 Richard Biener + + PR tree-optimization/83518 + * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle aggregate + init from a constant even when partial defs are already recorded. + 2019-07-23 Jan Hubicka * i386-common.c: Use PROCESSOR_ZNVER2 scheduler for znver2. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index a75f0d8..0bb1d4c 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2019-07-23 Richard Biener + + PR tree-optimization/83518 + * gimple-parser.c (c_parser_parse_gimple_body): When we have + a CFG also rebuild cgraph edges. + 2019-07-20 Jakub Jelinek * c-parser.c (c_parser_omp_clause_name): Handle bind clause. diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index 4970ae1..3f57599 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -356,6 +356,8 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, gcov_type t = PARAM_VALUE (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD); set_hot_bb_threshold (t); update_max_bb_count (); + cgraph_node::get_create (cfun->decl); + cgraph_edge::rebuild_edges (); } dump_function (TDI_gimple, current_function_decl); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d5efd50..8e6b026 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-07-23 Richard Biener + + PR tree-optimization/83518 + * gcc.dg/tree-ssa/ssa-fre-79.c: New testcase. + 2019-07-23 Ed Schonberg * gnat.dg/task4.adb: New testcase. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-79.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-79.c new file mode 100644 index 0000000..83aef9a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-79.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "-O -fgimple -fdump-tree-fre1" } */ + +struct S { char a[4]; }; +const struct S cs = { 1, 2, 3, 4 }; + +int __GIMPLE(ssa,startwith("fre")) +main () +{ + struct S s; + short _1; + + __BB(2): + s = cs; + s.a[1] = _Literal (char) 3; + _1 = __MEM (&s + 1); + if (_1 != _Literal (short) 0x303) + goto __BB3; + else + goto __BB4; + + __BB(3): + __builtin_abort (); + + __BB(4): + return 0; +} + +/* { dg-final { scan-tree-dump-not "abort" "fre1" } } */ diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index cab2460..9369c36 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2702,9 +2702,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, && gimple_assign_single_p (def_stmt) && (DECL_P (gimple_assign_rhs1 (def_stmt)) || TREE_CODE (gimple_assign_rhs1 (def_stmt)) == MEM_REF - || handled_component_p (gimple_assign_rhs1 (def_stmt))) - /* Handling this is more complicated, give up for now. */ - && data->partial_defs.is_empty ()) + || handled_component_p (gimple_assign_rhs1 (def_stmt)))) { tree base2; int i, j, k; @@ -2808,8 +2806,30 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, /* Try folding the new reference to a constant. */ tree val = fully_constant_vn_reference_p (vr); if (val) - return vn_reference_lookup_or_insert_for_pieces - (vuse, vr->set, vr->type, vr->operands, val); + { + if (data->partial_defs.is_empty ()) + return vn_reference_lookup_or_insert_for_pieces + (vuse, vr->set, vr->type, vr->operands, val); + /* This is the only interesting case for partial-def handling + coming from targets that like to gimplify init-ctors as + aggregate copies from constant data like aarch64 for + PR83518. */ + if (maxsize.is_constant (&maxsizei) + && known_eq (ref->size, maxsize)) + { + pd_data pd; + pd.rhs = val; + pd.offset = 0; + pd.size = maxsizei / BITS_PER_UNIT; + return data->push_partial_def (pd, vuse, maxsizei); + } + } + + /* Continuing with partial defs isn't easily possible here, we + have to find a full def from further lookups from here. Probably + not worth the special-casing everywhere. */ + if (!data->partial_defs.is_empty ()) + return (void *)-1; /* Adjust *ref from the new operands. */ if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands)) -- cgit v1.1 From 0bd65f4fde4b6a3615fd166bdd0e65dbda99fa9c Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 23 Jul 2019 10:45:59 +0000 Subject: re PR debug/91231 (ICE in dwarf2out_inline_entry, at dwarf2out.c:27642) 2019-07-23 Richard Biener PR debug/91231 * lto-streamer-in.c (input_function): Drop inline-entry markers that ended up with an unknown location block. From-SVN: r273733 --- gcc/ChangeLog | 6 ++++++ gcc/lto-streamer-in.c | 8 ++++++++ 2 files changed, 14 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1add332..4105878 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2019-07-23 Richard Biener + PR debug/91231 + * lto-streamer-in.c (input_function): Drop inline-entry markers + that ended up with an unknown location block. + +2019-07-23 Richard Biener + PR tree-optimization/83518 * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle aggregate init from a constant even when partial defs are already recorded. diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 155805b..3158edd 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1141,6 +1141,14 @@ input_function (tree fn_decl, class data_in *data_in, ? !MAY_HAVE_DEBUG_MARKER_STMTS : !MAY_HAVE_DEBUG_BIND_STMTS)) remove = true; + /* In case the linemap overflows locations can be dropped + to zero. Thus do not keep nonsensical inline entry markers + we'd later ICE on. */ + tree block; + if (gimple_debug_inline_entry_p (stmt) + && (block = gimple_block (stmt)) + && !inlined_function_outer_scope_p (block)) + remove = true; if (is_gimple_call (stmt) && gimple_call_internal_p (stmt)) { -- cgit v1.1 From e41dd06873b728bc62296fca39c526608c897ae2 Mon Sep 17 00:00:00 2001 From: Vladislav Ivanishin Date: Tue, 23 Jul 2019 13:57:43 +0000 Subject: make gdbhooks.py idempotent with respect to reloading gcc/ChangeLog: 2019-07-23 Vladislav Ivanishin * gdbhooks.py: Pass replace=True to gdb.printing.register_pretty_printer. From-SVN: r273737 --- gcc/ChangeLog | 5 +++++ gcc/gdbhooks.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4105878..06d2e4f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-07-23 Vladislav Ivanishin + + * gdbhooks.py: Pass replace=True to + gdb.printing.register_pretty_printer. + 2019-07-23 Richard Biener PR debug/91231 diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py index 09802c9..54056b3 100644 --- a/gcc/gdbhooks.py +++ b/gcc/gdbhooks.py @@ -605,7 +605,8 @@ def build_pretty_printer(): gdb.printing.register_pretty_printer( gdb.current_objfile(), - build_pretty_printer()) + build_pretty_printer(), + replace=True) def find_gcc_source_dir(): # Use location of global "g" to locate the source tree -- cgit v1.1 From d894bafc5b744e8e21cfbd0c254f982a6efc718a Mon Sep 17 00:00:00 2001 From: Vladislav Ivanishin Date: Tue, 23 Jul 2019 14:05:14 +0000 Subject: gdbinit.in: add reload-gdbhooks (rh) command gcc/ChangeLog: 2019-07-23 Vladislav Ivanishin * gdbinit.in (reload-gdbhooks): New command with an attached doc string. (rh): New alias for it. From-SVN: r273738 --- gcc/ChangeLog | 5 +++++ gcc/gdbinit.in | 10 ++++++++++ 2 files changed, 15 insertions(+) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 06d2e4f..87c56e7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2019-07-23 Vladislav Ivanishin + * gdbinit.in (reload-gdbhooks): New command with an attached doc string. + (rh): New alias for it. + +2019-07-23 Vladislav Ivanishin + * gdbhooks.py: Pass replace=True to gdb.printing.register_pretty_printer. diff --git a/gcc/gdbinit.in b/gcc/gdbinit.in index 440fd25..42302ae 100644 --- a/gcc/gdbinit.in +++ b/gcc/gdbinit.in @@ -219,6 +219,16 @@ is emitted (as opposed to those warnings that are suppressed by command-line options). end +define reload-gdbhooks +python import imp; imp.reload(gdbhooks) +end + +document reload-gdbhooks +Load the gdbhooks.py module again in order to pick up any changes made to it. +end + +alias rh = reload-gdbhooks + # Define some macros helpful to gdb when it is expanding macros. macro define __FILE__ "gdb" macro define __LINE__ 1 -- cgit v1.1 From 9bf40084738e155bf69ab7215a69f74d589931d1 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Tue, 23 Jul 2019 17:03:13 +0000 Subject: configure.ac (ACX_PROG_CXX_WARNING_OPTS): Revert r273311. gcc/ChangeLog: * configure.ac (ACX_PROG_CXX_WARNING_OPTS): Revert r273311. From-SVN: r273742 --- gcc/ChangeLog | 10 ++++++++-- gcc/configure.ac | 3 +-- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 87c56e7..d405921 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2019-07-23 Martin Sebor + + * configure.ac (ACX_PROG_CXX_WARNING_OPTS): Revert r273311. + 2019-07-23 Vladislav Ivanishin * gdbinit.in (reload-gdbhooks): New command with an attached doc string. @@ -1364,9 +1368,11 @@ (ix86_noce_conversion_profitable_p): Same. (ix86_init_cost): Same. (ix86_simd_clone_usable): Same. - * configure.ac: Same. + * configure.ac (ACX_PROG_CXX_WARNING_OPTS): Add -Wclass-is-pod and + Wstruct-not-pod. * coretypes.h: Same. - * data-streamer-in.c (string_for_index): Same. + * data-streamer-in.c (string_for_index): Change class-key of PODs + to struct and others to class. (streamer_read_indexed_string): Same. (streamer_read_string): Same. (bp_unpack_indexed_string): Same. diff --git a/gcc/configure.ac b/gcc/configure.ac index c620dd2..137d5b4 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -482,8 +482,7 @@ AC_ARG_ENABLE(build-format-warnings, AS_IF([test $enable_build_format_warnings = no], [wf_opt=-Wno-format],[wf_opt=]) ACX_PROG_CXX_WARNING_OPTS( - m4_quote(m4_do([-W -Wall -Wclass-is-pod -Wmismatched-tags ], - [-Wno-narrowing -Wstruct-not-pod -Wwrite-strings ], + m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings ], [-Wcast-qual -Wno-error=format-diag $wf_opt])), [loose_warn]) ACX_PROG_CC_WARNING_OPTS( -- cgit v1.1 From 40768ee0bc9965d109692f884f8588626e01e3fe Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 23 Jul 2019 17:20:36 +0000 Subject: compiler: use correct value type in 2-case select send In the channel-send case, the value to be sent may needs an (implicit) type conversion to the channel element type. This CL ensures that we use the correct value type for the send. Fixes golang/go#33235. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/187177 From-SVN: r273743 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/statements.cc | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'gcc') diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index dabd5a3..ba7282e 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -b7bce0dbccb978d33eb8ce0bffc02fae2c2857c1 +480477ca64c3001b9c7e92ef8b978dc92a5912d2 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 27c4b95..6d9c0eb 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -5880,6 +5880,7 @@ Select_statement::lower_two_case(Block* b) : this->clauses_->at(1)); Location loc = this->location(); Expression* chan = chancase.channel(); + Type* valtype = chan->type()->channel_type()->element_type(); Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc); b->add_statement(chantmp); @@ -5891,7 +5892,8 @@ Select_statement::lower_two_case(Block* b) { // if selectnbsend(chan, &val) { body } else { default body } - Temporary_statement* ts = Statement::make_temporary(NULL, chancase.val(), loc); + Temporary_statement* ts = + Statement::make_temporary(valtype, chancase.val(), loc); // Tell the escape analysis that the value escapes, as it may be sent // to a channel. ts->set_value_escapes(); @@ -5904,7 +5906,6 @@ Select_statement::lower_two_case(Block* b) } else { - Type* valtype = chan->type()->channel_type()->element_type(); Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc); b->add_statement(ts); -- cgit v1.1