From b9bc550b54a8e997f5ecb0d5c86869db37164a2e Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 26 Jul 2023 21:52:48 +0100 Subject: [PATCH] Optimise code generation for protected procedure calls --- src/jit/jit-exits.c | 12 ++++++- src/lower.c | 3 +- src/sem.c | 7 ++-- test/regress/gold/protected11.txt | 1 + test/regress/protected11.vhd | 56 +++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + test/test_lower.c | 17 +++------- 7 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 test/regress/gold/protected11.txt create mode 100644 test/regress/protected11.vhd diff --git a/src/jit/jit-exits.c b/src/jit/jit-exits.c index 2be77accb..df5bba7fa 100644 --- a/src/jit/jit-exits.c +++ b/src/jit/jit-exits.c @@ -529,7 +529,17 @@ void x_unreachable(tree_t where) void x_func_wait(void) { - jit_msg(NULL, DIAG_FATAL, "cannot wait inside function call"); + jit_stack_trace_t *trace = jit_stack_trace(); + tree_t inner = trace->frames[0].decl; + free(trace); + + if (tree_kind(inner) == T_PROC_BODY) { + // Must be procedure body in protected object + jit_msg(NULL, DIAG_FATAL, "cannot wait inside call to protected " + "type method"); + } + else + jit_msg(NULL, DIAG_FATAL, "cannot wait inside function call"); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/lower.c b/src/lower.c index ba3fca4b2..c89dfc587 100644 --- a/src/lower.c +++ b/src/lower.c @@ -9858,7 +9858,8 @@ static void lower_predef(lower_unit_t *parent, tree_t decl) static void lower_proc_body(lower_unit_t *parent, tree_t body) { - const bool never_waits = !!(tree_flags(body) & TREE_F_NEVER_WAITS); + const bool never_waits = !!(tree_flags(body) & TREE_F_NEVER_WAITS) + || tree_kind(parent->container) == T_PROT_BODY; vcode_select_unit(parent->vunit); diff --git a/src/sem.c b/src/sem.c index f8bd71c11..04073ebfa 100644 --- a/src/sem.c +++ b/src/sem.c @@ -2894,7 +2894,8 @@ static bool sem_check_pcall(tree_t t, nametab_t *tab) if (!tree_has_ref(t)) return false; - if (tree_kind(t) == T_PROT_PCALL && tree_has_name(t) + const bool is_protected = (tree_kind(t) == T_PROT_PCALL); + if (is_protected && tree_has_name(t) && !sem_check(tree_name(t), tab)) return false; @@ -2914,8 +2915,8 @@ static bool sem_check_pcall(tree_t t, nametab_t *tab) const tree_flags_t flags = tree_flags(decl); - const bool never_waits = !!(flags & TREE_F_NEVER_WAITS); - const bool has_wait = !!(flags & TREE_F_HAS_WAIT); + const bool never_waits = is_protected || !!(flags & TREE_F_NEVER_WAITS); + const bool has_wait = !is_protected && !!(flags & TREE_F_HAS_WAIT); assert(!never_waits || !has_wait); diff --git a/test/regress/gold/protected11.txt b/test/regress/gold/protected11.txt new file mode 100644 index 000000000..c37a4e5ad --- /dev/null +++ b/test/regress/gold/protected11.txt @@ -0,0 +1 @@ +0ms+0: cannot wait inside call to protected type method diff --git a/test/regress/protected11.vhd b/test/regress/protected11.vhd new file mode 100644 index 000000000..16f22daed --- /dev/null +++ b/test/regress/protected11.vhd @@ -0,0 +1,56 @@ +entity protected11 is +end entity; + +architecture test of protected11 is + + procedure do_something; + procedure do_wait; + + type pt is protected + procedure proc; + end protected; + + type pt is protected body + variable count : natural; + + procedure proc(arg : integer); + + procedure proc is + begin + count := count + 1; + assert count = 1; + proc(5); + assert count = 2; + proc(-1); + end procedure; + + procedure proc(arg : integer) is + begin + count := count + 1; + do_something; + if arg < 0 then + do_wait; -- Error + end if; + end procedure; + + end protected body; + + procedure do_something is + begin + end procedure; + + procedure do_wait is + begin + wait for 1 ns; + end procedure; + + shared variable v : pt; +begin + + tb: process is + begin + v.proc; + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 5732e9ed7..4fc7350a2 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -827,3 +827,4 @@ psl4 fail,psl,gold,2008 cover17 cover,export=cobertura toplevel3 normal,guut.i=2,guut.s=2 predef4 normal,2008 +protected11 fail,gold,2002 diff --git a/test/test_lower.c b/test/test_lower.c index 404bb3ea7..26e8f9c16 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -5206,15 +5206,7 @@ START_TEST(test_protpcall) { VCODE_OP_ASSERT }, { VCODE_OP_CONTEXT_UPREF, .hops = 1 }, { VCODE_OP_CONST, .value = 5 }, - { VCODE_OP_PCALL, .func = "WORK.PROTECTED11.PT.PROC(I)", .target = 1 }, - }; - - CHECK_BB(0); - - EXPECT_BB(1) = { - { VCODE_OP_RESUME, .func = "WORK.PROTECTED11.PT.PROC(I)" }, - { VCODE_OP_CONST, .value = 2 }, - { VCODE_OP_VAR_UPREF, .name = "COUNT", .hops = 1 }, + { VCODE_OP_FCALL, .func = "WORK.PROTECTED11.PT.PROC(I)" }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 2 }, { VCODE_OP_CMP, .cmp = VCODE_CMP_EQ }, @@ -5223,7 +5215,7 @@ START_TEST(test_protpcall) { VCODE_OP_RETURN }, }; - CHECK_BB(1); + CHECK_BB(0); } { @@ -5231,7 +5223,6 @@ START_TEST(test_protpcall) vcode_select_unit(vu); EXPECT_BB(0) = { - { VCODE_OP_STORE, .name = "ARG" }, { VCODE_OP_VAR_UPREF, .name = "COUNT", .hops = 1 }, { VCODE_OP_LOAD_INDIRECT }, { VCODE_OP_CONST, .value = 1 }, @@ -5239,8 +5230,8 @@ START_TEST(test_protpcall) { VCODE_OP_TRAP_ADD }, { VCODE_OP_STORE_INDIRECT }, { VCODE_OP_CONTEXT_UPREF, .hops = 2 }, - { VCODE_OP_PCALL, .func = "WORK.PROTECTED11.DO_SOMETHING", - .target = 1 }, + { VCODE_OP_FCALL, .func = "WORK.PROTECTED11.DO_SOMETHING" }, + { VCODE_OP_RETURN }, }; CHECK_BB(0);