From 31d73adea9cd465fe8fe217d0f7607204d580d0e Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Tue, 4 Apr 2023 00:45:08 -0500 Subject: [PATCH 01/39] Better is_circular function --- analyze/aps-dnc.c | 119 +++++++++++++++++++++++++++++++++- analyze/aps-dnc.h | 5 ++ analyze/canonical-signature.h | 3 + analyze/canonical-type.c | 2 + examples/first.aps | 6 +- 5 files changed, 131 insertions(+), 4 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 39e1076e..1239bda8 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -5,6 +5,7 @@ * for productions until we reach a fixed point. */ #include +#include #include "jbb-alloc.h" #include "aps-ag.h" @@ -80,7 +81,7 @@ DEPENDENCY dependency_trans(DEPENDENCY k1, DEPENDENCY k2) (k2 & DEPENDENCY_NOT_JUST_FIBER)) | ((k1 & DEPENDENCY_MAYBE_CARRYING)& (k2 & DEPENDENCY_MAYBE_CARRYING)) | - ((k1 & DEPENDENCY_MAYBE_SIMPLE)& + ((k1 & DEPENDENCY_MAYBE_SIMPLE) | (k2 & DEPENDENCY_MAYBE_SIMPLE)) | SOME_DEPENDENCY); } @@ -1048,10 +1049,18 @@ static BOOL decl_is_collection(Declaration d) { } } +static MONOTONICITY expr_monotonicity(Expression); +static BOOL formal_is_circular(Declaration); +static BOOL function_decl_is_circular(Declaration); + BOOL decl_is_circular(Declaration d) { if (!d) return FALSE; switch (Declaration_KEY(d)) { + case KEYfunction_decl: + return function_decl_is_circular(d); + case KEYnormal_formal: + return formal_is_circular(d); case KEYvalue_decl: return direction_is_circular(value_decl_direction(d)); case KEYattribute_decl: @@ -1061,6 +1070,114 @@ BOOL decl_is_circular(Declaration d) } } +/** + * Utility function that detects if canonical type is circular + * by checking if its inferred signature set includes any of the + * LATTICE types. + * + * @param ctype canonical type + * @return BOOL indicating whether canonical type can be considered circular + */ +static BOOL canonical_type_is_circular(CanonicalType* ctype) { + CanonicalSignatureSet set = infer_canonical_signatures(ctype); + int i; + for (i = 0; i < set->num_elements; i++) { + CanonicalSignature* csig = (CanonicalSignature*)set->elements[i]; + + if (strstr(decl_name(csig->source_class), "LATTICE") != NULL) { + return TRUE; + } + } + + return FALSE; +} + +/** + * Utility function that detects if function declaration is circular + * if its parameter type(s) and return type are circular. + * + * @param fdecl Declaration + * @return BOOL indicating whether function declaration can be considered circular + */ +static BOOL function_decl_is_circular(Declaration fdecl) { + switch (Declaration_KEY(fdecl)) { + case KEYfunction_decl: { + struct Canonical_function_type* cfunc_type = + (struct Canonical_function_type*)canonical_type( + function_decl_type(fdecl)); + + BOOL return_type_circular = + canonical_type_is_circular(cfunc_type->return_type); + BOOL formals_circular = TRUE; + + int i; + for (i = 0; i < cfunc_type->num_formals; i++) { + formals_circular &= + canonical_type_is_circular(cfunc_type->param_types[i]); + } + + return return_type_circular && formals_circular; + } + default: + return FALSE; + } +} + +/** + * Utility function that returns the monotonicity of an expression + * + * @param expr Expression + * @return MONOTONICITY of an expression + */ +static MONOTONICITY expr_monotonicity(Expression expr) { + switch (Expression_KEY(expr)) { + case KEYvalue_use: { + Declaration udecl = USE_DECL(value_use_use(expr)); + if (DECL_IS_SYNTAX(udecl)) { + return NO_USE; + } else { + return decl_is_circular(udecl) ? MONOTONE_USE : SIMPLE_USE; + } + } + case KEYfuncall: { + MONOTONICITY result = NO_USE; + Expression actual = first_Actual(funcall_actuals(expr)); + while (actual != NULL) { + result |= expr_monotonicity(actual); + + actual = Expression_info(actual)->next_actual; + } + + return result; + } + default: + return NO_USE; + } +} + +/** + * Utility function that detects if formal is circular if + * its inside case statement that uses only circular defined things. + * + * @param decl Declaration + * @return BOOL indicating whether formal can be considered circular + */ +static BOOL formal_is_circular(Declaration decl) { + switch (Declaration_KEY(decl)) { + case KEYnormal_formal: { + Declaration target = formal_in_case_p(decl); + // If formal is bound to a case statement, then check its case stmt's expression + if (target != NULL && Declaration_KEY(target) == KEYcase_stmt) { + MONOTONICITY re = expr_monotonicity(case_stmt_expr(target)); + return !(re & SIMPLE_USE); + } + return TRUE; + } + default: + return FALSE; + } +} + // return true if we are sure this vertex represents an input dependency static BOOL vertex_is_input(VERTEX* v) { diff --git a/analyze/aps-dnc.h b/analyze/aps-dnc.h index 72b14e58..ff07310f 100644 --- a/analyze/aps-dnc.h +++ b/analyze/aps-dnc.h @@ -163,4 +163,9 @@ extern int analysis_debug; #define ASSERT_CLOSED (1<<13) #define EDGESET_ASSERTIONS (1<<14) +typedef unsigned MONOTONICITY; +#define NO_USE 0 +#define SIMPLE_USE 1 +#define MONOTONE_USE 2 + #endif diff --git a/analyze/canonical-signature.h b/analyze/canonical-signature.h index fdf7742c..54c0e997 100644 --- a/analyze/canonical-signature.h +++ b/analyze/canonical-signature.h @@ -1,6 +1,9 @@ #ifndef CANONICAL_SIGNATURE_H #define CANONICAL_SIGNATURE_H +#include +#include "canonical-type.h" + struct CanonicalSignature_type { bool is_input; diff --git a/analyze/canonical-type.c b/analyze/canonical-type.c index df01d7b5..1f2a3fa3 100755 --- a/analyze/canonical-type.c +++ b/analyze/canonical-type.c @@ -371,6 +371,8 @@ static CanonicalType *canonical_type_use(Use use) case KEYfunction_type: return canonical_type(some_type_decl_type(td)); + case KEYremote_type: + return canonical_type(remote_type_nodetype(some_type_decl_type(td))); default: fatal_error("Unknown type use_decl type key %d", (int)Type_KEY(some_type_decl_type(td))); return NULL; diff --git a/examples/first.aps b/examples/first.aps index 67054d97..3ebb3be9 100644 --- a/examples/first.aps +++ b/examples/first.aps @@ -16,7 +16,7 @@ module FIRST[T :: var GRAMMAR[]] extends T begin circular attribute Items.items_first : SymbolLattice; pragma synthesized(items_first); - attribute Grammar.grammar_first : DeclarationTable; + circular attribute Grammar.grammar_first : DeclarationTable; pragma synthesized(grammar_first); epsilon : Symbol := make_symbol("epsilon"); @@ -67,11 +67,11 @@ module FIRST[T :: var GRAMMAR[]] extends T begin end; - var function contains_epsilon(s_set: Symbols) :Boolean begin + var function contains_epsilon(s_set: SymbolLattice) : OrLattice begin result := Symbols$member(epsilon, s_set); end; - var function black_dot(s1 :Symbols; s2 :Symbols) : Symbols begin + var function black_dot(s1 :SymbolLattice; s2 :SymbolLattice) : SymbolLattice begin if contains_epsilon(s1) then result := (s1 /\~ { epsilon }) \/ s2; else From d3c2434021485a34cd1c0236b98cba98ba81758d Mon Sep 17 00:00:00 2001 From: Amir Date: Tue, 4 Apr 2023 00:54:22 -0500 Subject: [PATCH 02/39] Comment improvement --- analyze/aps-dnc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 1239bda8..d6a9532b 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1084,6 +1084,8 @@ static BOOL canonical_type_is_circular(CanonicalType* ctype) { for (i = 0; i < set->num_elements; i++) { CanonicalSignature* csig = (CanonicalSignature*)set->elements[i]; + // If class declaration extends any of the LATTICE types (UNION_LATTICE, MAKE_LATTICE and etc.) + // Check if class declaration name contains the name LATTICE if (strstr(decl_name(csig->source_class), "LATTICE") != NULL) { return TRUE; } From 6737c812deb532ebfe1a31977780c4cb814a51a1 Mon Sep 17 00:00:00 2001 From: Amir Date: Tue, 11 Apr 2023 23:31:20 -0500 Subject: [PATCH 03/39] Small but important improvement --- analyze/aps-dnc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index d6a9532b..316adab3 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1253,6 +1253,9 @@ void add_edges_to_graph(VERTEX* v1, // if carrying, then we add fiber dependencies. kind &= ~DEPENDENCY_NOT_JUST_FIBER; + + // Fiber dependencies are always monotone. + kind &= ~DEPENDENCY_MAYBE_SIMPLE; for (i=0; i < s->fibers.length; ++i) { FIBER f = s->fibers.array[i]; From 4c7d12344766477758168e35b6093db9035fb4a0 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 12 Apr 2023 00:02:18 -0500 Subject: [PATCH 04/39] hacky fix to an important problem --- analyze/aps-dnc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 316adab3..93481664 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1358,6 +1358,16 @@ static void record_expression_dependencies(VERTEX *sink, CONDITION *cond, source.node = NULL; source.attr = decl; source.modifier = mod; + + // TODO: what if mod.next is not NULL? + if (mod != NULL && mod->field != NULL) { + if (decl_is_circular(mod->field)) { + new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; + } else { + new_kind |= DEPENDENCY_MAYBE_SIMPLE; + } + } + if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } From 109a1f6ed42d20109471c8976a69ba6d7a64f1e5 Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Wed, 12 Apr 2023 17:28:35 -0500 Subject: [PATCH 05/39] more progress --- analyze/aps-dnc.c | 3 +-- analyze/aps-type.c | 5 +++++ analyze/aps-type.h | 3 +++ analyze/canonical-signature.c | 38 +++++++++++++++++++++++++++++++++++ analyze/canonical-signature.h | 8 ++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 93481664..fa0909d2 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1085,8 +1085,7 @@ static BOOL canonical_type_is_circular(CanonicalType* ctype) { CanonicalSignature* csig = (CanonicalSignature*)set->elements[i]; // If class declaration extends any of the LATTICE types (UNION_LATTICE, MAKE_LATTICE and etc.) - // Check if class declaration name contains the name LATTICE - if (strstr(decl_name(csig->source_class), "LATTICE") != NULL) { + if (canonical_signature_hierarchy_contains(csig, module_lattice)) { return TRUE; } } diff --git a/analyze/aps-type.c b/analyze/aps-type.c index b9022163..b3a50f1d 100644 --- a/analyze/aps-type.c +++ b/analyze/aps-type.c @@ -441,6 +441,7 @@ static void* validate_canonicals(void* ignore, void*node) { static Declaration module_TYPE; static Declaration module_PHYLUM; +extern Declaration module_lattice; static void* set_root_phylum(void *ignore, void *node) { @@ -461,6 +462,10 @@ static void* set_root_phylum(void *ignore, void *node) { module_PHYLUM = d; } + else if (streq(decl_name(d), "LATTICE")) + { + module_lattice = d; + } return NULL; } diff --git a/analyze/aps-type.h b/analyze/aps-type.h index b1bb07cb..aaf84079 100644 --- a/analyze/aps-type.h +++ b/analyze/aps-type.h @@ -1,6 +1,9 @@ #ifndef APS_TYPE_H #define APS_TYPE_H +// Lattice module declaration. +Declaration module_lattice; + extern Type function_type_return_type(Type); /* We use local type inference a la Turner and Pierce diff --git a/analyze/canonical-signature.c b/analyze/canonical-signature.c index fea01ac9..e2253694 100644 --- a/analyze/canonical-signature.c +++ b/analyze/canonical-signature.c @@ -693,3 +693,41 @@ void initialize_canonical_signature(Declaration module_TYPE_decl, Declaration mo initialized = true; } + +/** + * Given a signature, it returns whether it contains module declaration + * @param sig signature + * @param mdecl module declaration + * @return boolean indicating if module is in the type hierarchy of signature + */ +bool signature_hierarchy_contains(Signature sig, Declaration mdecl) +{ + switch (Signature_KEY(sig)) + { + case KEYsig_inst: + Declaration some_mdecl = USE_DECL(class_use_use(sig_inst_class(sig))); + return some_mdecl == mdecl || + signature_hierarchy_contains(some_class_decl_parent(some_mdecl), mdecl); + case KEYmult_sig: + return signature_hierarchy_contains(mult_sig_sig1(sig), mdecl) || + signature_hierarchy_contains(mult_sig_sig2(sig), mdecl); + case KEYsig_use: + return USE_DECL(sig_use_use(sig)) == mdecl; + case KEYno_sig: + case KEYfixed_sig: + return false; + } +} + +/** + * Given a canonical signature, it returns whether it contains module declaration + * @param csig canonical signature + * @param mdecl module declaration + * @return boolean indicating if module is in the type hierarchy of signature + */ +bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration mdecl) +{ + if (csig->source_class == mdecl) return true; + + return signature_hierarchy_contains(some_class_decl_parent(csig->source_class), mdecl); +} diff --git a/analyze/canonical-signature.h b/analyze/canonical-signature.h index 54c0e997..fe97d812 100644 --- a/analyze/canonical-signature.h +++ b/analyze/canonical-signature.h @@ -45,4 +45,12 @@ void print_canonical_signature(void *untyped, FILE *f); */ void print_canonical_signature_set(void *untyped, FILE *f); +/** + * Given a canonical signature, it returns whether it contains module declaration + * @param csig canonical signature + * @param mdecl module declaration + * @return boolean indicating if module is in the type hierarchy of signature + */ +bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration mdecl); + #endif From 7451c05cfdbf31bfbfad5bcd539c60b78f4333f8 Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Fri, 14 Apr 2023 01:04:39 -0500 Subject: [PATCH 06/39] small change --- analyze/aps-type.c | 4 ++-- analyze/aps-type.h | 2 +- analyze/canonical-type.h | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/analyze/aps-type.c b/analyze/aps-type.c index b3a50f1d..6fd2c96c 100644 --- a/analyze/aps-type.c +++ b/analyze/aps-type.c @@ -441,7 +441,7 @@ static void* validate_canonicals(void* ignore, void*node) { static Declaration module_TYPE; static Declaration module_PHYLUM; -extern Declaration module_lattice; +Declaration module_lattice; static void* set_root_phylum(void *ignore, void *node) { @@ -452,7 +452,7 @@ static void* set_root_phylum(void *ignore, void *node) Declaration d = (Declaration)node; switch (Declaration_KEY(d)) { - case KEYmodule_decl: + case KEYsome_class_decl: { if (module_TYPE == 0 && streq(decl_name(d), "TYPE")) { diff --git a/analyze/aps-type.h b/analyze/aps-type.h index aaf84079..06d42eaf 100644 --- a/analyze/aps-type.h +++ b/analyze/aps-type.h @@ -2,7 +2,7 @@ #define APS_TYPE_H // Lattice module declaration. -Declaration module_lattice; +extern Declaration module_lattice; extern Type function_type_return_type(Type); diff --git a/analyze/canonical-type.h b/analyze/canonical-type.h index 68338162..cb93ad87 100755 --- a/analyze/canonical-type.h +++ b/analyze/canonical-type.h @@ -65,6 +65,14 @@ CanonicalType *canonical_type_join(CanonicalType *ctype_outer, CanonicalType *ct */ CanonicalType *new_canonical_type_use(Declaration decl); +/** + * Creates an instance of Canonical_qual_type + * @param from + * @param decl + * @return Canonical_qual_type + */ +CanonicalType *new_canonical_type_qual(CanonicalType *from, Declaration decl); + /** * Compares two canonical types * @param ctype1 Canonical type A From 18296c4e6c77d76575646576a6e5be88e9fae029 Mon Sep 17 00:00:00 2001 From: Amir Date: Fri, 14 Apr 2023 13:15:43 -0500 Subject: [PATCH 07/39] small fix ups --- analyze/aps-dnc.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index fa0909d2..a2f36589 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1079,10 +1079,11 @@ BOOL decl_is_circular(Declaration d) * @return BOOL indicating whether canonical type can be considered circular */ static BOOL canonical_type_is_circular(CanonicalType* ctype) { - CanonicalSignatureSet set = infer_canonical_signatures(ctype); + CanonicalSignatureSet cset = infer_canonical_signatures(ctype); + int i; - for (i = 0; i < set->num_elements; i++) { - CanonicalSignature* csig = (CanonicalSignature*)set->elements[i]; + for (i = 0; i < cset->num_elements; i++) { + CanonicalSignature* csig = (CanonicalSignature*)cset->elements[i]; // If class declaration extends any of the LATTICE types (UNION_LATTICE, MAKE_LATTICE and etc.) if (canonical_signature_hierarchy_contains(csig, module_lattice)) { @@ -1126,7 +1127,7 @@ static BOOL function_decl_is_circular(Declaration fdecl) { /** * Utility function that returns the monotonicity of an expression - * + * * @param expr Expression * @return MONOTONICITY of an expression */ @@ -1143,16 +1144,24 @@ static MONOTONICITY expr_monotonicity(Expression expr) { case KEYfuncall: { MONOTONICITY result = NO_USE; Expression actual = first_Actual(funcall_actuals(expr)); + + // Return type should be circular + result |= canonical_type_is_circular(canonical_type(infer_expr_type(expr))) ? MONOTONE_USE : SIMPLE_USE; + + // Actual types(s) should be circular while (actual != NULL) { + Type actual_ty = infer_expr_type(actual); + CanonicalType* actual_ctype = canonical_type(actual_ty); + result |= expr_monotonicity(actual); - actual = Expression_info(actual)->next_actual; + actual = EXPR_NEXT(actual); } return result; } default: - return NO_USE; + return SIMPLE_USE; } } @@ -1358,7 +1367,6 @@ static void record_expression_dependencies(VERTEX *sink, CONDITION *cond, source.attr = decl; source.modifier = mod; - // TODO: what if mod.next is not NULL? if (mod != NULL && mod->field != NULL) { if (decl_is_circular(mod->field)) { new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; From 3f023382ebb9f325693f126028af561c38c28618 Mon Sep 17 00:00:00 2001 From: Amir Date: Fri, 14 Apr 2023 13:17:52 -0500 Subject: [PATCH 08/39] removed unnecessary import --- analyze/aps-dnc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index a2f36589..86b483fb 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -5,7 +5,6 @@ * for productions until we reach a fixed point. */ #include -#include #include "jbb-alloc.h" #include "aps-ag.h" From d4f61df402e56b4907a26ed3ab76e908db6a195b Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Fri, 14 Apr 2023 13:19:00 -0500 Subject: [PATCH 09/39] Update canonical-type.h --- analyze/canonical-type.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/analyze/canonical-type.h b/analyze/canonical-type.h index cb93ad87..68338162 100755 --- a/analyze/canonical-type.h +++ b/analyze/canonical-type.h @@ -65,14 +65,6 @@ CanonicalType *canonical_type_join(CanonicalType *ctype_outer, CanonicalType *ct */ CanonicalType *new_canonical_type_use(Declaration decl); -/** - * Creates an instance of Canonical_qual_type - * @param from - * @param decl - * @return Canonical_qual_type - */ -CanonicalType *new_canonical_type_qual(CanonicalType *from, Declaration decl); - /** * Compares two canonical types * @param ctype1 Canonical type A From a4a3548fc26fbeb78bdc451c392fb6e78a0befba Mon Sep 17 00:00:00 2001 From: Amir Date: Fri, 14 Apr 2023 13:21:14 -0500 Subject: [PATCH 10/39] small reordering --- analyze/aps-dnc.c | 5 +++++ analyze/aps-dnc.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 86b483fb..1d5594d7 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1048,6 +1048,11 @@ static BOOL decl_is_collection(Declaration d) { } } +typedef unsigned MONOTONICITY; +#define NO_USE 0 +#define SIMPLE_USE 1 +#define MONOTONE_USE 2 + static MONOTONICITY expr_monotonicity(Expression); static BOOL formal_is_circular(Declaration); static BOOL function_decl_is_circular(Declaration); diff --git a/analyze/aps-dnc.h b/analyze/aps-dnc.h index ff07310f..72b14e58 100644 --- a/analyze/aps-dnc.h +++ b/analyze/aps-dnc.h @@ -163,9 +163,4 @@ extern int analysis_debug; #define ASSERT_CLOSED (1<<13) #define EDGESET_ASSERTIONS (1<<14) -typedef unsigned MONOTONICITY; -#define NO_USE 0 -#define SIMPLE_USE 1 -#define MONOTONE_USE 2 - #endif From 35dfa61897fc287ea957117f92a905470441aa99 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 10:46:38 -0500 Subject: [PATCH 11/39] committing stuff --- analyze/aps-dnc.c | 217 ++++++++++++++++++++-------------- analyze/aps-dnc.h | 2 +- analyze/canonical-signature.c | 8 ++ analyze/canonical-type.c | 4 +- 4 files changed, 140 insertions(+), 91 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 1d5594d7..12e36254 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1053,18 +1053,10 @@ typedef unsigned MONOTONICITY; #define SIMPLE_USE 1 #define MONOTONE_USE 2 -static MONOTONICITY expr_monotonicity(Expression); -static BOOL formal_is_circular(Declaration); -static BOOL function_decl_is_circular(Declaration); - BOOL decl_is_circular(Declaration d) { if (!d) return FALSE; switch (Declaration_KEY(d)) { - case KEYfunction_decl: - return function_decl_is_circular(d); - case KEYnormal_formal: - return formal_is_circular(d); case KEYvalue_decl: return direction_is_circular(value_decl_direction(d)); case KEYattribute_decl: @@ -1105,21 +1097,24 @@ static BOOL canonical_type_is_circular(CanonicalType* ctype) { * @param fdecl Declaration * @return BOOL indicating whether function declaration can be considered circular */ -static BOOL function_decl_is_circular(Declaration fdecl) { +static BOOL function_decl_is_circular(Type sink_type, Declaration fdecl) { switch (Declaration_KEY(fdecl)) { case KEYfunction_decl: { - struct Canonical_function_type* cfunc_type = - (struct Canonical_function_type*)canonical_type( - function_decl_type(fdecl)); + struct Canonical_function_type* cfunc_type = (struct Canonical_function_type*) canonical_type(function_decl_type(fdecl)); + + if (analysis_debug & ADD_EDGE) { + printf("fdecl %s (lineno %d)\n", decl_name(fdecl), tnode_line_number(fdecl)); + printf("sink type: "); + print_Type(sink_type, stdout); + printf("\n"); + } - BOOL return_type_circular = - canonical_type_is_circular(cfunc_type->return_type); + BOOL return_type_circular = canonical_type_is_circular(cfunc_type->return_type); BOOL formals_circular = TRUE; int i; for (i = 0; i < cfunc_type->num_formals; i++) { - formals_circular &= - canonical_type_is_circular(cfunc_type->param_types[i]); + formals_circular &= canonical_type_is_circular(cfunc_type->param_types[i]); } return return_type_circular && formals_circular; @@ -1129,67 +1124,86 @@ static BOOL function_decl_is_circular(Declaration fdecl) { } } -/** - * Utility function that returns the monotonicity of an expression - * - * @param expr Expression - * @return MONOTONICITY of an expression - */ -static MONOTONICITY expr_monotonicity(Expression expr) { - switch (Expression_KEY(expr)) { - case KEYvalue_use: { - Declaration udecl = USE_DECL(value_use_use(expr)); - if (DECL_IS_SYNTAX(udecl)) { - return NO_USE; - } else { - return decl_is_circular(udecl) ? MONOTONE_USE : SIMPLE_USE; - } - } - case KEYfuncall: { - MONOTONICITY result = NO_USE; - Expression actual = first_Actual(funcall_actuals(expr)); - - // Return type should be circular - result |= canonical_type_is_circular(canonical_type(infer_expr_type(expr))) ? MONOTONE_USE : SIMPLE_USE; +static BOOL funcall_result_is_circular(Type sink_type, Expression expr, Declaration fdecl) { + Use use = value_use_use(funcall_f(expr)); + TypeEnvironment te = USE_TYPE_ENV(use); - // Actual types(s) should be circular - while (actual != NULL) { - Type actual_ty = infer_expr_type(actual); - CanonicalType* actual_ctype = canonical_type(actual_ty); + if (analysis_debug & ADD_EDGE) { + printf("fdecl: %s (lineno %d)\n", decl_name(fdecl), tnode_line_number(expr)); + printf("type environment: "); + print_TypeEnvironment(te, stdout); + printf("\n"); + } - result |= expr_monotonicity(actual); + Type fdecl_type = some_function_decl_type(fdecl); - actual = EXPR_NEXT(actual); - } + Declaration formal = first_Declaration(function_type_formals(fdecl_type)); + Expression actual = first_Actual(funcall_actuals(expr)); - return result; - } - default: - return SIMPLE_USE; + // return type should be equal to sink type and be circular + Type fdecl_return_type = type_subst(use, function_type_return_type(fdecl_type)); + + if (analysis_debug & ADD_EDGE) { + printf(" return type: "); + print_Type(fdecl_return_type, stdout); + printf("\n"); + printf(" sink type: "); + print_Type(sink_type, stdout); + printf("\n"); } + + CanonicalType* fdecl_return_ctype = canonical_type(fdecl_return_type); + CanonicalType* sink_ctype = canonical_type(sink_type); + + return fdecl_return_ctype == sink_ctype && canonical_type_is_circular(fdecl_return_ctype); } -/** - * Utility function that detects if formal is circular if - * its inside case statement that uses only circular defined things. - * - * @param decl Declaration - * @return BOOL indicating whether formal can be considered circular - */ -static BOOL formal_is_circular(Declaration decl) { - switch (Declaration_KEY(decl)) { - case KEYnormal_formal: { - Declaration target = formal_in_case_p(decl); - // If formal is bound to a case statement, then check its case stmt's expression - if (target != NULL && Declaration_KEY(target) == KEYcase_stmt) { - MONOTONICITY re = expr_monotonicity(case_stmt_expr(target)); - return !(re & SIMPLE_USE); - } - return TRUE; +static BOOL funcall_actual_is_circular(Expression expr, int actual_index, Declaration fdecl) { + Use use = value_use_use(funcall_f(expr)); + TypeEnvironment te = USE_TYPE_ENV(use); + + if (analysis_debug & ADD_EDGE) { + printf("fdecl: %s (lineno %d)\n", decl_name(fdecl), tnode_line_number(expr)); + printf("type environment: "); + print_TypeEnvironment(te, stdout); + printf("\n"); + } + + Type fdecl_type = some_function_decl_type(fdecl); + + Declaration formal = first_Declaration(function_type_formals(fdecl_type)); + Expression actual = first_Actual(funcall_actuals(expr)); + + int index = 0; + + // formal and actual should be equal and be circular + while (formal != NULL && actual != NULL) { + Type formal_ty = type_subst(use, formal_type(formal)); + Type actual_ty = infer_expr_type(actual); + + if (analysis_debug & ADD_EDGE) { + printf(" (%d) formal type: ", index); + print_Type(formal_ty, stdout); + printf("\n"); + printf(" (%d) actual type: ", index); + print_Type(actual_ty, stdout); + printf("\n"); } - default: - return FALSE; + + CanonicalType* formal_ctype = canonical_type(formal_ty); + CanonicalType* actual_ctype = canonical_type(actual_ty); + + if (index == actual_index) { + return formal_ctype == actual_ctype && canonical_type_is_circular(formal_ctype); + } + + formal = DECL_NEXT(formal); + actual = EXPR_NEXT(actual); + index++; } + + fatal_error("Failed to find actual at index %d", actual_index); + return FALSE; } // return true if we are sure this vertex represents an input dependency @@ -1238,7 +1252,7 @@ void add_edges_to_graph(VERTEX* v1, STATE *s = aug_graph->global_state; int i; - if (analysis_debug & ADD_EDGE) { + if (analysis_debug & ADD_EDGE && kind & DEPENDENCY_MAYBE_SIMPLE) { print_dep_vertex(v1,stdout); fputs("->",stdout); print_dep_vertex(v2,stdout); @@ -1302,7 +1316,7 @@ Declaration attr_ref_node_decl(Expression e) * @param mod modifier to apply to instances found * @param kind whether carrying/non-fiber etc. */ -static void record_expression_dependencies(VERTEX *sink, CONDITION *cond, +static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITION *cond, DEPENDENCY kind, MODIFIER *mod, Expression e, AUG_GRAPH *aug_graph) { @@ -1329,7 +1343,7 @@ static void record_expression_dependencies(VERTEX *sink, CONDITION *cond, /* nothing to do */ break; case KEYrepeat: - record_expression_dependencies(sink,cond,kind,mod, + record_expression_dependencies(sink,sink_type,cond,kind,mod, repeat_expr(e),aug_graph); break; case KEYvalue_use: @@ -1400,22 +1414,31 @@ static void record_expression_dependencies(VERTEX *sink, CONDITION *cond, new_mod.field = decl; new_mod.next = mod; // first the dependency on the pointer itself (NOT carrying) - record_expression_dependencies(sink,cond, + record_expression_dependencies(sink,sink_type,cond, new_kind&~DEPENDENCY_MAYBE_CARRYING, NO_MODIFIER,object,aug_graph); // then the dependency on the field (possibly carrying) - record_expression_dependencies(sink,cond,new_kind,&new_mod,object, + record_expression_dependencies(sink,sink_type,cond,new_kind,&new_mod,object, aug_graph); } else if ((decl = local_call_p(e)) != NULL) { - if (!decl_is_circular(decl)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; Declaration result = some_function_decl_result(decl); Expression actual = first_Actual(funcall_actuals(e)); /* first depend on the arguments (not carrying, no fibers) */ if (mod == NO_MODIFIER) { + int actual_index = 0; for (;actual!=NULL; actual=Expression_info(actual)->next_actual) { - record_expression_dependencies(sink,cond, + + if (funcall_actual_is_circular(e, actual_index, decl)) { + new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; + } else { + new_kind |= DEPENDENCY_MAYBE_SIMPLE; + } + + record_expression_dependencies(sink,sink_type,cond, new_kind&~DEPENDENCY_MAYBE_CARRYING, NO_MODIFIER,actual,aug_graph); + new_kind = kind; // restore new_kind + actual_index++; } } @@ -1424,18 +1447,24 @@ static void record_expression_dependencies(VERTEX *sink, CONDITION *cond, * tnode_line_number(e),decl_name(decl)); */ { + if (funcall_result_is_circular(sink_type, e, decl)) { + new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; + } else { + new_kind |= DEPENDENCY_MAYBE_SIMPLE; + } + Declaration proxy = Expression_info(e)->funcall_proxy; source.node = proxy; source.attr = result; source.modifier = mod; if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); - add_edges_to_graph(&source,sink,cond,kind,aug_graph); + add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } } else { /* some random (external) function call */ Expression actual = first_Actual(funcall_actuals(e)); for (; actual != NULL; actual=Expression_info(actual)->next_actual) { - record_expression_dependencies(sink,cond,kind,mod, + record_expression_dependencies(sink,sink_type,cond,kind,mod, actual,aug_graph); } } @@ -1501,7 +1530,9 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, break; case KEYvalue_use: { - Declaration decl = USE_DECL(value_use_use(lhs)); + Use use = value_use_use(lhs); + Type sink_type = type_subst(use, infer_expr_type(lhs)); + Declaration decl = USE_DECL(use); VERTEX sink; MODIFIER new_mod; @@ -1548,12 +1579,15 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, set_value_for(&sink,rhs,aug_graph); if (vertex_is_input(&sink)) aps_error(lhs,"Assignment of input value"); // don't make error even if not output: local attributes! - record_expression_dependencies(&sink,cond,kind,NULL,rhs,aug_graph); + record_expression_dependencies(&sink,sink_type,cond,kind,NULL,rhs,aug_graph); record_condition_dependencies(&sink,cond,aug_graph); } break; case KEYfuncall: { + Use use = value_use_use(funcall_f(lhs)); + Type sink_type = type_subst(use, infer_expr_type(lhs)); + int new_kind = kind; Declaration field, attr, fdecl, decl; VERTEX sink; @@ -1578,7 +1612,7 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, sink.modifier = mod; set_value_for(&sink,rhs,aug_graph); if (vertex_is_input(&sink)) aps_error(lhs,"Assignment of input value"); - record_expression_dependencies(&sink,cond,kind,NULL,rhs,aug_graph); + record_expression_dependencies(&sink,sink_type,cond,kind,NULL,rhs,aug_graph); record_condition_dependencies(&sink,cond,aug_graph); } else if ((fdecl = local_call_p(lhs)) != NULL) { if (!decl_is_circular(fdecl)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; @@ -1592,7 +1626,7 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, sink.modifier = mod; set_value_for(&sink,rhs,aug_graph); if (vertex_is_input(&sink)) aps_error(lhs,"Assignment of input value"); - record_expression_dependencies(&sink,cond,new_kind,NULL,rhs,aug_graph); + record_expression_dependencies(&sink,sink_type,cond,new_kind,NULL,rhs,aug_graph); record_condition_dependencies(&sink,cond,aug_graph); } else { Expression actual = first_Actual(funcall_actuals(lhs)); @@ -1649,6 +1683,7 @@ static void *get_edges(void *vaug_graph, void *node) { return NULL; case KEYformal: { Declaration case_stmt = formal_in_case_p(decl); + Type sink_type = formal_type(decl); if (case_stmt != NULL) { Expression expr = some_case_stmt_expr(case_stmt); VERTEX f; @@ -1656,7 +1691,7 @@ static void *get_edges(void *vaug_graph, void *node) { f.attr = decl; f.modifier = NO_MODIFIER; record_condition_dependencies(&f,cond,aug_graph); - record_expression_dependencies(&f,cond,dependency,NO_MODIFIER, + record_expression_dependencies(&f,sink_type,cond,dependency,NO_MODIFIER, expr,aug_graph); } } @@ -1675,10 +1710,10 @@ static void *get_edges(void *vaug_graph, void *node) { case KEYsimple: /* XXX: I don't know I have to do it both ways. */ - record_expression_dependencies(&sink,cond,dependency,NO_MODIFIER, + record_expression_dependencies(&sink,no_type(),cond,dependency,NO_MODIFIER, simple_value(def),aug_graph); sink.node = 0; - record_expression_dependencies(&sink,cond,dependency,NO_MODIFIER, + record_expression_dependencies(&sink,no_type(),cond,dependency,NO_MODIFIER, simple_value(def),aug_graph); if ((cdecl = constructor_call_p(simple_value(def))) != NULL) { FIBERSET fs = fiberset_for(decl,FIBERSET_NORMAL_FINAL); @@ -1721,7 +1756,7 @@ static void *get_edges(void *vaug_graph, void *node) { } break; case KEYcomposite: - record_expression_dependencies(&sink,cond,dependency,NO_MODIFIER, + record_expression_dependencies(&sink,no_type(),cond,dependency,NO_MODIFIER, composite_initial(def),aug_graph); break; } @@ -1765,13 +1800,14 @@ static void *get_edges(void *vaug_graph, void *node) { case KEYif_stmt: { Expression test = if_stmt_cond(decl); + Type sink_type = infer_expr_type(test); VERTEX sink; sink.node = 0; sink.attr = decl; sink.modifier = NO_MODIFIER; record_condition_dependencies(&sink,cond,aug_graph); - record_expression_dependencies(&sink,cond,control_dependency, + record_expression_dependencies(&sink,sink_type,cond,control_dependency, NO_MODIFIER, test, aug_graph); } break; @@ -1784,10 +1820,11 @@ static void *get_edges(void *vaug_graph, void *node) { for (m=first_Match(some_case_stmt_matchers(decl)); m; m=MATCH_NEXT(m)) { Expression test = Match_info(m)->match_test; sink.attr = (Declaration)m; + Type sink_type = infer_expr_type(test); record_condition_dependencies(&sink,cond,aug_graph); for (; test != 0; test = Expression_info(test)->next_expr) { - record_expression_dependencies(&sink,cond,control_dependency, + record_expression_dependencies(&sink,sink_type,cond,control_dependency, NO_MODIFIER, test, aug_graph); } } @@ -1796,12 +1833,13 @@ static void *get_edges(void *vaug_graph, void *node) { case KEYfor_in_stmt: { Declaration formal = for_in_stmt_formal(decl); Expression expr = for_in_stmt_seq(decl); + Type formal_type = infer_formal_type(formal); VERTEX f; f.node = 0; f.attr = formal; f.modifier = NO_MODIFIER; record_condition_dependencies(&f,cond,aug_graph); - record_expression_dependencies(&f,cond,dependency,NO_MODIFIER, + record_expression_dependencies(&f,formal_type,cond,dependency,NO_MODIFIER, expr,aug_graph); } break; @@ -1840,13 +1878,14 @@ static void *get_edges(void *vaug_graph, void *node) { { Type ft = some_function_decl_type(fdecl); Declaration f = first_Declaration(function_type_formals(ft)); + Type formal_type = infer_formal_type(f); Expression a = first_Actual(funcall_actuals(e)); for (; f != NULL; f = DECL_NEXT(f), a = EXPR_NEXT(a)) { VERTEX sink; sink.node = proxy; sink.attr = f; sink.modifier = NO_MODIFIER; - record_expression_dependencies(&sink,cond,dependency, + record_expression_dependencies(&sink,formal_type,cond,dependency, NO_MODIFIER,a,aug_graph); record_condition_dependencies(&sink,cond,aug_graph); } diff --git a/analyze/aps-dnc.h b/analyze/aps-dnc.h index 72b14e58..970a69e5 100644 --- a/analyze/aps-dnc.h +++ b/analyze/aps-dnc.h @@ -29,7 +29,7 @@ enum instance_direction instance_direction(INSTANCE *); extern BOOL fiber_attr_circular(FIBERED_ATTRIBUTE* fiber_attr); extern BOOL instance_circular(INSTANCE* in); -extern BOOL decl_is_circular(Declaration d); +extern BOOL decl_is_circular(Declaration); typedef unsigned DEPENDENCY; diff --git a/analyze/canonical-signature.c b/analyze/canonical-signature.c index e2253694..e4eb9eb6 100644 --- a/analyze/canonical-signature.c +++ b/analyze/canonical-signature.c @@ -482,6 +482,14 @@ static CanonicalSignature* join_canonical_signature_actuals(CanonicalType *sourc struct Canonical_use_type *ctype_use = (struct Canonical_use_type *)source_ctype; Declaration tdecl = ctype_use->decl; + switch (Declaration_KEY(tdecl)) + { + case KEYsome_type_decl: + break; + default: + return canonical_sig; + } + Declaration mdecl = USE_DECL(module_use_use(type_inst_module(some_type_decl_type(tdecl)))); CanonicalType **substituted_actuals = (CanonicalType **)alloca(canonical_sig->num_actuals); diff --git a/analyze/canonical-type.c b/analyze/canonical-type.c index 1f2a3fa3..e57d6a8b 100755 --- a/analyze/canonical-type.c +++ b/analyze/canonical-type.c @@ -516,6 +516,8 @@ CanonicalType *canonical_type(Type t) } case KEYfunction_type: return canonical_type_function(t); + case KEYno_type: + return NULL; default: aps_error(t, "Case of type %d is not implemented in canonical_type()", (int)Type_KEY(t)); return NULL; @@ -726,7 +728,7 @@ static CanonicalType *canonical_type_use_use_join(struct Canonical_use_type *cty break; } default: - fatal_error("Not sure what type of canonical type it is"); + return (CanonicalType *)new_canonical_type_qual((CanonicalType *)ctype_outer, ctype_inner->decl); } Declaration decl = ctype_inner->decl; From 920e7427c0de6cc68e0309e5a63484c57b657d7a Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 10:47:28 -0500 Subject: [PATCH 12/39] unused function --- analyze/aps-dnc.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 12e36254..62fbfd27 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1090,40 +1090,6 @@ static BOOL canonical_type_is_circular(CanonicalType* ctype) { return FALSE; } -/** - * Utility function that detects if function declaration is circular - * if its parameter type(s) and return type are circular. - * - * @param fdecl Declaration - * @return BOOL indicating whether function declaration can be considered circular - */ -static BOOL function_decl_is_circular(Type sink_type, Declaration fdecl) { - switch (Declaration_KEY(fdecl)) { - case KEYfunction_decl: { - struct Canonical_function_type* cfunc_type = (struct Canonical_function_type*) canonical_type(function_decl_type(fdecl)); - - if (analysis_debug & ADD_EDGE) { - printf("fdecl %s (lineno %d)\n", decl_name(fdecl), tnode_line_number(fdecl)); - printf("sink type: "); - print_Type(sink_type, stdout); - printf("\n"); - } - - BOOL return_type_circular = canonical_type_is_circular(cfunc_type->return_type); - BOOL formals_circular = TRUE; - - int i; - for (i = 0; i < cfunc_type->num_formals; i++) { - formals_circular &= canonical_type_is_circular(cfunc_type->param_types[i]); - } - - return return_type_circular && formals_circular; - } - default: - return FALSE; - } -} - static BOOL funcall_result_is_circular(Type sink_type, Expression expr, Declaration fdecl) { Use use = value_use_use(funcall_f(expr)); TypeEnvironment te = USE_TYPE_ENV(use); From 414f590a7f8e95349c8d1a3af683b2b1677e5bdb Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 11:09:35 -0500 Subject: [PATCH 13/39] more progress but have a better understanding --- analyze/aps-dnc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 62fbfd27..95ee789e 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1048,11 +1048,6 @@ static BOOL decl_is_collection(Declaration d) { } } -typedef unsigned MONOTONICITY; -#define NO_USE 0 -#define SIMPLE_USE 1 -#define MONOTONE_USE 2 - BOOL decl_is_circular(Declaration d) { if (!d) return FALSE; @@ -1061,7 +1056,10 @@ BOOL decl_is_circular(Declaration d) return direction_is_circular(value_decl_direction(d)); case KEYattribute_decl: return direction_is_circular(attribute_decl_direction(d)); + case KEYformal: + return TRUE; default: + aps_warning(d, "Not sure how to detect circularity of declaration key %d", Declaration_KEY(d)); return FALSE; } } From ea55228c19ecd470a46d0c9041ad5da0e2206124 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 11:10:21 -0500 Subject: [PATCH 14/39] accidental commit --- analyze/aps-dnc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 95ee789e..2d74da8f 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1216,7 +1216,7 @@ void add_edges_to_graph(VERTEX* v1, STATE *s = aug_graph->global_state; int i; - if (analysis_debug & ADD_EDGE && kind & DEPENDENCY_MAYBE_SIMPLE) { + if (kind & DEPENDENCY_MAYBE_SIMPLE) { print_dep_vertex(v1,stdout); fputs("->",stdout); print_dep_vertex(v2,stdout); From f5335a927a751ffc5cfa32722dc0d69d9678e04e Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 11:11:11 -0500 Subject: [PATCH 15/39] another clean up of accidental commit --- analyze/aps-dnc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 2d74da8f..4a754fe3 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1216,7 +1216,7 @@ void add_edges_to_graph(VERTEX* v1, STATE *s = aug_graph->global_state; int i; - if (kind & DEPENDENCY_MAYBE_SIMPLE) { + if (analysis_debug & ADD_EDGE) { print_dep_vertex(v1,stdout); fputs("->",stdout); print_dep_vertex(v2,stdout); From f89a655bfba42503d105ead2f327fe0c91ce9c82 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 11:15:25 -0500 Subject: [PATCH 16/39] added some comments --- analyze/aps-dnc.c | 1 - analyze/canonical-signature.c | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 4a754fe3..dcdf8ffd 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1496,7 +1496,6 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, { Use use = value_use_use(lhs); Type sink_type = type_subst(use, infer_expr_type(lhs)); - Declaration decl = USE_DECL(use); VERTEX sink; MODIFIER new_mod; diff --git a/analyze/canonical-signature.c b/analyze/canonical-signature.c index e4eb9eb6..b20870d4 100644 --- a/analyze/canonical-signature.c +++ b/analyze/canonical-signature.c @@ -487,6 +487,9 @@ static CanonicalSignature* join_canonical_signature_actuals(CanonicalType *sourc case KEYsome_type_decl: break; default: + // short-circuit. + // only when the source declaration of canonical type is some kind of + // type declaration then "join" would be possible. return canonical_sig; } From a58b7da44da4befe5e367e438a600f6bd16c4fdd Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 11:21:56 -0500 Subject: [PATCH 17/39] undo ing --- analyze/aps-dnc.c | 1 + analyze/canonical-type.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index dcdf8ffd..b060823a 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1494,6 +1494,7 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, break; case KEYvalue_use: { + Declaration decl = USE_DECL(value_use_use(lhs)); Use use = value_use_use(lhs); Type sink_type = type_subst(use, infer_expr_type(lhs)); VERTEX sink; diff --git a/analyze/canonical-type.c b/analyze/canonical-type.c index e57d6a8b..cb188f43 100755 --- a/analyze/canonical-type.c +++ b/analyze/canonical-type.c @@ -517,6 +517,7 @@ CanonicalType *canonical_type(Type t) case KEYfunction_type: return canonical_type_function(t); case KEYno_type: + // canonical type representation of no-type is NULL. return NULL; default: aps_error(t, "Case of type %d is not implemented in canonical_type()", (int)Type_KEY(t)); @@ -728,7 +729,7 @@ static CanonicalType *canonical_type_use_use_join(struct Canonical_use_type *cty break; } default: - return (CanonicalType *)new_canonical_type_qual((CanonicalType *)ctype_outer, ctype_inner->decl); + fatal_error("Not sure what type of canonical type it is"); } Declaration decl = ctype_inner->decl; From 8523d5f00ec48755d8c735cf531d1f6df248b745 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 17 Apr 2023 11:49:30 -0500 Subject: [PATCH 18/39] simplification --- analyze/aps-dnc.c | 58 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index b060823a..fce3fbc2 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1064,6 +1064,32 @@ BOOL decl_is_circular(Declaration d) } } + +Declaration is_in_function_p(void* node) { + while (node != NULL) + { + switch (ABSTRACT_APS_tnode_phylum(node)) + { + case KEYDeclaration: + Declaration decl = (Declaration)node; + switch (Declaration_KEY(decl)) + { + case KEYsome_function_decl: + return decl; + default: + break; + } + break; + default: + break; + } + + node = tnode_parent(node); + } + + return NULL; +} + /** * Utility function that detects if canonical type is circular * by checking if its inferred signature set includes any of the @@ -1142,22 +1168,22 @@ static BOOL funcall_actual_is_circular(Expression expr, int actual_index, Declar // formal and actual should be equal and be circular while (formal != NULL && actual != NULL) { - Type formal_ty = type_subst(use, formal_type(formal)); - Type actual_ty = infer_expr_type(actual); - - if (analysis_debug & ADD_EDGE) { - printf(" (%d) formal type: ", index); - print_Type(formal_ty, stdout); - printf("\n"); - printf(" (%d) actual type: ", index); - print_Type(actual_ty, stdout); - printf("\n"); - } + if (index == actual_index) { + Type formal_ty = type_subst(use, formal_type(formal)); + Type actual_ty = infer_expr_type(actual); + + if (analysis_debug & ADD_EDGE) { + printf(" (%d) formal type: ", index); + print_Type(formal_ty, stdout); + printf("\n"); + printf(" (%d) actual type: ", index); + print_Type(actual_ty, stdout); + printf("\n"); + } - CanonicalType* formal_ctype = canonical_type(formal_ty); - CanonicalType* actual_ctype = canonical_type(actual_ty); + CanonicalType* formal_ctype = canonical_type(formal_ty); + CanonicalType* actual_ctype = canonical_type(actual_ty); - if (index == actual_index) { return formal_ctype == actual_ctype && canonical_type_is_circular(formal_ctype); } @@ -1392,7 +1418,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI int actual_index = 0; for (;actual!=NULL; actual=Expression_info(actual)->next_actual) { - if (funcall_actual_is_circular(e, actual_index, decl)) { + if (is_in_function_p(e) || funcall_actual_is_circular(e, actual_index, decl)) { new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; } else { new_kind |= DEPENDENCY_MAYBE_SIMPLE; @@ -1411,7 +1437,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI * tnode_line_number(e),decl_name(decl)); */ { - if (funcall_result_is_circular(sink_type, e, decl)) { + if (is_in_function_p(e) || funcall_result_is_circular(sink_type, e, decl)) { new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; } else { new_kind |= DEPENDENCY_MAYBE_SIMPLE; From e0ae38fd17ae888cf37d45f410bb3ffab1fefe73 Mon Sep 17 00:00:00 2001 From: Amir Date: Tue, 18 Apr 2023 01:02:44 -0500 Subject: [PATCH 19/39] changes as of April 17th --- analyze/aps-dnc.c | 120 +++++++++++++++------------------- analyze/aps-fiber.h | 4 +- analyze/aps-info.h | 1 + analyze/canonical-signature.c | 22 +++---- analyze/canonical-signature.h | 4 +- 5 files changed, 68 insertions(+), 83 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index fce3fbc2..76b0f308 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1057,39 +1057,13 @@ BOOL decl_is_circular(Declaration d) case KEYattribute_decl: return direction_is_circular(attribute_decl_direction(d)); case KEYformal: - return TRUE; + return Declaration_info(d)->is_circular; default: aps_warning(d, "Not sure how to detect circularity of declaration key %d", Declaration_KEY(d)); return FALSE; } } - -Declaration is_in_function_p(void* node) { - while (node != NULL) - { - switch (ABSTRACT_APS_tnode_phylum(node)) - { - case KEYDeclaration: - Declaration decl = (Declaration)node; - switch (Declaration_KEY(decl)) - { - case KEYsome_function_decl: - return decl; - default: - break; - } - break; - default: - break; - } - - node = tnode_parent(node); - } - - return NULL; -} - /** * Utility function that detects if canonical type is circular * by checking if its inferred signature set includes any of the @@ -1098,7 +1072,7 @@ Declaration is_in_function_p(void* node) { * @param ctype canonical type * @return BOOL indicating whether canonical type can be considered circular */ -static BOOL canonical_type_is_circular(CanonicalType* ctype) { +static BOOL canonical_type_is_lattice_type(CanonicalType* ctype) { CanonicalSignatureSet cset = infer_canonical_signatures(ctype); int i; @@ -1114,8 +1088,7 @@ static BOOL canonical_type_is_circular(CanonicalType* ctype) { return FALSE; } -static BOOL funcall_result_is_circular(Type sink_type, Expression expr, Declaration fdecl) { - Use use = value_use_use(funcall_f(expr)); +static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use use, Declaration fdecl) { TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1145,11 +1118,10 @@ static BOOL funcall_result_is_circular(Type sink_type, Expression expr, Declarat CanonicalType* fdecl_return_ctype = canonical_type(fdecl_return_type); CanonicalType* sink_ctype = canonical_type(sink_type); - return fdecl_return_ctype == sink_ctype && canonical_type_is_circular(fdecl_return_ctype); + return fdecl_return_ctype == sink_ctype && canonical_type_is_lattice_type(fdecl_return_ctype); } -static BOOL funcall_actual_is_circular(Expression expr, int actual_index, Declaration fdecl) { - Use use = value_use_use(funcall_f(expr)); +static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, Use use, Declaration fdecl) { TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1159,41 +1131,50 @@ static BOOL funcall_actual_is_circular(Expression expr, int actual_index, Declar printf("\n"); } - Type fdecl_type = some_function_decl_type(fdecl); + Declaration formal = function_actual_formal(fdecl, actual, expr); - Declaration formal = first_Declaration(function_type_formals(fdecl_type)); - Expression actual = first_Actual(funcall_actuals(expr)); + Type formal_ty = type_subst(use, formal_type(formal)); + Type actual_ty = infer_expr_type(actual); + + if (analysis_debug & ADD_EDGE) { + printf(" formal type: "); + print_Type(formal_ty, stdout); + printf("\n"); + printf(" actual type: "); + print_Type(actual_ty, stdout); + printf("\n"); + } - int index = 0; + CanonicalType* formal_ctype = canonical_type(formal_ty); + CanonicalType* actual_ctype = canonical_type(actual_ty); // formal and actual should be equal and be circular - while (formal != NULL && actual != NULL) { - if (index == actual_index) { - Type formal_ty = type_subst(use, formal_type(formal)); - Type actual_ty = infer_expr_type(actual); - - if (analysis_debug & ADD_EDGE) { - printf(" (%d) formal type: ", index); - print_Type(formal_ty, stdout); - printf("\n"); - printf(" (%d) actual type: ", index); - print_Type(actual_ty, stdout); - printf("\n"); - } - - CanonicalType* formal_ctype = canonical_type(formal_ty); - CanonicalType* actual_ctype = canonical_type(actual_ty); + return formal_ctype == actual_ctype && canonical_type_is_lattice_type(formal_ctype); +} - return formal_ctype == actual_ctype && canonical_type_is_circular(formal_ctype); +Declaration funcall_f_decl(Expression e, Use* use) { + switch (Expression_KEY(e)) + { + case KEYfuncall: + return funcall_f_decl(funcall_f(e), use); + case KEYvalue_use: + *use = value_use_use(e); + Declaration func = USE_DECL(*use); + switch (Declaration_KEY(func)) + { + case KEYsome_function_decl: + return func; + case KEYvalue_renaming: + return funcall_f_decl(value_renaming_old(func), use); + default: + return NULL; } - - formal = DECL_NEXT(formal); - actual = EXPR_NEXT(actual); - index++; + break; + default: + break; } - fatal_error("Failed to find actual at index %d", actual_index); - return FALSE; + return NULL; } // return true if we are sure this vertex represents an input dependency @@ -1411,16 +1392,14 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI record_expression_dependencies(sink,sink_type,cond,new_kind,&new_mod,object, aug_graph); } else if ((decl = local_call_p(e)) != NULL) { + Use use = value_use_use(funcall_f(e)); Declaration result = some_function_decl_result(decl); Expression actual = first_Actual(funcall_actuals(e)); /* first depend on the arguments (not carrying, no fibers) */ if (mod == NO_MODIFIER) { - int actual_index = 0; for (;actual!=NULL; actual=Expression_info(actual)->next_actual) { - if (is_in_function_p(e) || funcall_actual_is_circular(e, actual_index, decl)) { - new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; - } else { + if (!funcall_actual_is_monotone_use(e, actual, use, decl)) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } @@ -1428,7 +1407,6 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI new_kind&~DEPENDENCY_MAYBE_CARRYING, NO_MODIFIER,actual,aug_graph); new_kind = kind; // restore new_kind - actual_index++; } } @@ -1437,9 +1415,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI * tnode_line_number(e),decl_name(decl)); */ { - if (is_in_function_p(e) || funcall_result_is_circular(sink_type, e, decl)) { - new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; - } else { + if (!funcall_result_is_monotone_use(sink_type, e, use, decl)) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } @@ -1451,10 +1427,16 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } } else { + Use use = NULL; + Declaration fdecl = funcall_f_decl(e, &use); + /* some random (external) function call */ Expression actual = first_Actual(funcall_actuals(e)); for (; actual != NULL; actual=Expression_info(actual)->next_actual) { - record_expression_dependencies(sink,sink_type,cond,kind,mod, + Declaration formal = function_actual_formal(fdecl, actual, e); + Declaration_info(formal)->is_circular = funcall_actual_is_monotone_use(e, actual, use, fdecl); + + record_expression_dependencies(sink,sink_type,cond,new_kind,mod, actual,aug_graph); } } diff --git a/analyze/aps-fiber.h b/analyze/aps-fiber.h index 2059dce1..fad601e7 100644 --- a/analyze/aps-fiber.h +++ b/analyze/aps-fiber.h @@ -101,7 +101,9 @@ extern Declaration shared_use_p(Expression); extern Declaration responsible_node_shared_info(void *, struct analysis_state *); extern Declaration formal_in_case_p(Declaration); - +Declaration function_actual_formal(Declaration func, + Expression actual, + Expression call); typedef struct oset { diff --git a/analyze/aps-info.h b/analyze/aps-info.h index 1d0135f9..ca4f11c3 100644 --- a/analyze/aps-info.h +++ b/analyze/aps-info.h @@ -43,6 +43,7 @@ struct Declaration_info { unsigned decl_flags; void * call_sites; void *analysis_state; + BOOL is_circular; /* boolean indicating if decl is circular */ #define DECL_LHS_FLAG 1 #define DECL_RHS_FLAG 2 #define DECL_OBJECT_FLAG 4 diff --git a/analyze/canonical-signature.c b/analyze/canonical-signature.c index b20870d4..8583737b 100644 --- a/analyze/canonical-signature.c +++ b/analyze/canonical-signature.c @@ -708,22 +708,22 @@ void initialize_canonical_signature(Declaration module_TYPE_decl, Declaration mo /** * Given a signature, it returns whether it contains module declaration * @param sig signature - * @param mdecl module declaration + * @param module_or_class_decl module or class declaration * @return boolean indicating if module is in the type hierarchy of signature */ -bool signature_hierarchy_contains(Signature sig, Declaration mdecl) +bool signature_hierarchy_contains(Signature sig, Declaration module_or_class_decl) { switch (Signature_KEY(sig)) { case KEYsig_inst: Declaration some_mdecl = USE_DECL(class_use_use(sig_inst_class(sig))); - return some_mdecl == mdecl || - signature_hierarchy_contains(some_class_decl_parent(some_mdecl), mdecl); + return some_mdecl == module_or_class_decl || + signature_hierarchy_contains(some_class_decl_parent(some_mdecl), module_or_class_decl); case KEYmult_sig: - return signature_hierarchy_contains(mult_sig_sig1(sig), mdecl) || - signature_hierarchy_contains(mult_sig_sig2(sig), mdecl); + return signature_hierarchy_contains(mult_sig_sig1(sig), module_or_class_decl) || + signature_hierarchy_contains(mult_sig_sig2(sig), module_or_class_decl); case KEYsig_use: - return USE_DECL(sig_use_use(sig)) == mdecl; + return USE_DECL(sig_use_use(sig)) == module_or_class_decl; case KEYno_sig: case KEYfixed_sig: return false; @@ -733,12 +733,12 @@ bool signature_hierarchy_contains(Signature sig, Declaration mdecl) /** * Given a canonical signature, it returns whether it contains module declaration * @param csig canonical signature - * @param mdecl module declaration + * @param module_or_class_decl module or class declaration * @return boolean indicating if module is in the type hierarchy of signature */ -bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration mdecl) +bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration module_or_class_decl) { - if (csig->source_class == mdecl) return true; + if (csig->source_class == module_or_class_decl) return true; - return signature_hierarchy_contains(some_class_decl_parent(csig->source_class), mdecl); + return signature_hierarchy_contains(some_class_decl_parent(csig->source_class), module_or_class_decl); } diff --git a/analyze/canonical-signature.h b/analyze/canonical-signature.h index fe97d812..b6b36ee4 100644 --- a/analyze/canonical-signature.h +++ b/analyze/canonical-signature.h @@ -48,9 +48,9 @@ void print_canonical_signature_set(void *untyped, FILE *f); /** * Given a canonical signature, it returns whether it contains module declaration * @param csig canonical signature - * @param mdecl module declaration + * @param module_or_class_decl module or class declaration * @return boolean indicating if module is in the type hierarchy of signature */ -bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration mdecl); +bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration module_or_class_decl); #endif From 6ea29d90fa0e7ed1f0e086d72420d4f07e305adf Mon Sep 17 00:00:00 2001 From: Amir Date: Tue, 18 Apr 2023 14:07:10 -0500 Subject: [PATCH 20/39] more progress --- analyze/aps-dnc.c | 164 +++++++++++++++++++--------------- analyze/aps-fiber.h | 1 - analyze/aps-info.h | 1 + analyze/canonical-signature.c | 22 ++--- analyze/canonical-signature.h | 4 +- analyze/canonical-type.c | 6 +- 6 files changed, 109 insertions(+), 89 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index fce3fbc2..fdc8b7b1 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1057,39 +1057,13 @@ BOOL decl_is_circular(Declaration d) case KEYattribute_decl: return direction_is_circular(attribute_decl_direction(d)); case KEYformal: - return TRUE; + return Declaration_info(d)->is_circular; default: - aps_warning(d, "Not sure how to detect circularity of declaration key %d", Declaration_KEY(d)); + aps_error(d, "Not sure how to detect circularity of declaration key %d", Declaration_KEY(d)); return FALSE; } } - -Declaration is_in_function_p(void* node) { - while (node != NULL) - { - switch (ABSTRACT_APS_tnode_phylum(node)) - { - case KEYDeclaration: - Declaration decl = (Declaration)node; - switch (Declaration_KEY(decl)) - { - case KEYsome_function_decl: - return decl; - default: - break; - } - break; - default: - break; - } - - node = tnode_parent(node); - } - - return NULL; -} - /** * Utility function that detects if canonical type is circular * by checking if its inferred signature set includes any of the @@ -1098,7 +1072,7 @@ Declaration is_in_function_p(void* node) { * @param ctype canonical type * @return BOOL indicating whether canonical type can be considered circular */ -static BOOL canonical_type_is_circular(CanonicalType* ctype) { +static BOOL canonical_type_is_lattice_type(CanonicalType* ctype) { CanonicalSignatureSet cset = infer_canonical_signatures(ctype); int i; @@ -1114,8 +1088,22 @@ static BOOL canonical_type_is_circular(CanonicalType* ctype) { return FALSE; } -static BOOL funcall_result_is_circular(Type sink_type, Expression expr, Declaration fdecl) { - Use use = value_use_use(funcall_f(expr)); +static Declaration function_type_actual_formal(Type func_type, Expression actual, Expression call) { + Expression expr; + Declaration f; + Declarations formals = function_type_formals(func_type); + Actuals actuals = funcall_actuals(call); + for (expr = first_Actual(actuals), f = first_Declaration(formals); + expr != NULL && f != NULL && expr != actual; + expr = Expression_info(expr)->next_expr, f = DECL_NEXT(f)) { + /* nothing */ + } + if (expr == NULL || f == NULL) + fatal_error("%d: cannot find formal",tnode_line_number(actuals)); + return f; +} + +static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use use, Declaration fdecl, Type fdecl_type) { TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1125,8 +1113,6 @@ static BOOL funcall_result_is_circular(Type sink_type, Expression expr, Declarat printf("\n"); } - Type fdecl_type = some_function_decl_type(fdecl); - Declaration formal = first_Declaration(function_type_formals(fdecl_type)); Expression actual = first_Actual(funcall_actuals(expr)); @@ -1145,11 +1131,10 @@ static BOOL funcall_result_is_circular(Type sink_type, Expression expr, Declarat CanonicalType* fdecl_return_ctype = canonical_type(fdecl_return_type); CanonicalType* sink_ctype = canonical_type(sink_type); - return fdecl_return_ctype == sink_ctype && canonical_type_is_circular(fdecl_return_ctype); + return fdecl_return_ctype == sink_ctype && canonical_type_is_lattice_type(fdecl_return_ctype); } -static BOOL funcall_actual_is_circular(Expression expr, int actual_index, Declaration fdecl) { - Use use = value_use_use(funcall_f(expr)); +static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, Use use, Declaration fdecl, Type func_type) { TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1159,41 +1144,50 @@ static BOOL funcall_actual_is_circular(Expression expr, int actual_index, Declar printf("\n"); } - Type fdecl_type = some_function_decl_type(fdecl); + Declaration formal = function_type_actual_formal(func_type, actual, expr); - Declaration formal = first_Declaration(function_type_formals(fdecl_type)); - Expression actual = first_Actual(funcall_actuals(expr)); + Type formal_ty = type_subst(use, formal_type(formal)); + Type actual_ty = infer_expr_type(actual); - int index = 0; + if (analysis_debug & ADD_EDGE) { + printf(" formal type: "); + print_Type(formal_ty, stdout); + printf("\n"); + printf(" actual type: "); + print_Type(actual_ty, stdout); + printf("\n"); + } - // formal and actual should be equal and be circular - while (formal != NULL && actual != NULL) { - if (index == actual_index) { - Type formal_ty = type_subst(use, formal_type(formal)); - Type actual_ty = infer_expr_type(actual); - - if (analysis_debug & ADD_EDGE) { - printf(" (%d) formal type: ", index); - print_Type(formal_ty, stdout); - printf("\n"); - printf(" (%d) actual type: ", index); - print_Type(actual_ty, stdout); - printf("\n"); - } + CanonicalType* formal_ctype = canonical_type(formal_ty); + CanonicalType* actual_ctype = canonical_type(actual_ty); - CanonicalType* formal_ctype = canonical_type(formal_ty); - CanonicalType* actual_ctype = canonical_type(actual_ty); + // formal and actual should be equal and be circular + return formal_ctype == actual_ctype && canonical_type_is_lattice_type(formal_ctype); +} - return formal_ctype == actual_ctype && canonical_type_is_circular(formal_ctype); +static Declaration funcall_f_decl(Expression e, Use* use) { + switch (Expression_KEY(e)) + { + case KEYfuncall: + return funcall_f_decl(funcall_f(e), use); + case KEYvalue_use: + *use = value_use_use(e); + Declaration func = USE_DECL(*use); + switch (Declaration_KEY(func)) + { + case KEYsome_value_decl: + return func; + case KEYvalue_renaming: + return funcall_f_decl(value_renaming_old(func), use); + default: + return NULL; } - - formal = DECL_NEXT(formal); - actual = EXPR_NEXT(actual); - index++; + break; + default: + break; } - fatal_error("Failed to find actual at index %d", actual_index); - return FALSE; + return NULL; } // return true if we are sure this vertex represents an input dependency @@ -1411,16 +1405,14 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI record_expression_dependencies(sink,sink_type,cond,new_kind,&new_mod,object, aug_graph); } else if ((decl = local_call_p(e)) != NULL) { + Use use = value_use_use(funcall_f(e)); Declaration result = some_function_decl_result(decl); Expression actual = first_Actual(funcall_actuals(e)); /* first depend on the arguments (not carrying, no fibers) */ if (mod == NO_MODIFIER) { - int actual_index = 0; for (;actual!=NULL; actual=Expression_info(actual)->next_actual) { - if (is_in_function_p(e) || funcall_actual_is_circular(e, actual_index, decl)) { - new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; - } else { + if (!funcall_actual_is_monotone_use(e, actual, use, decl, some_function_decl_type(decl))) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } @@ -1428,7 +1420,6 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI new_kind&~DEPENDENCY_MAYBE_CARRYING, NO_MODIFIER,actual,aug_graph); new_kind = kind; // restore new_kind - actual_index++; } } @@ -1437,9 +1428,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI * tnode_line_number(e),decl_name(decl)); */ { - if (is_in_function_p(e) || funcall_result_is_circular(sink_type, e, decl)) { - new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; - } else { + if (!funcall_result_is_monotone_use(sink_type, e, use, decl, some_function_decl_type(decl))) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } @@ -1451,10 +1440,41 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } } else { + Use use = NULL; + Declaration fdecl = funcall_f_decl(e, &use); + Type fdecl_type = NULL; + + printf("=> funcall lineno %d\n", tnode_line_number(e)); + dump_lisp_Expression(e); + printf("\n"); + + if (Declaration_KEY(fdecl) == KEYconstructor_decl) { + fdecl_type = constructor_decl_type(fdecl); + } else if (Declaration_KEY(fdecl) == KEYattribute_decl) { + fdecl_type = attribute_decl_type(fdecl); + } else { + fdecl_type = some_function_decl_type(fdecl); + } + + printf("use: "); + print_Use(use, stdout); + printf("\n"); + + printf("=> sink: "); + print_dep_vertex(sink, stdout); + printf("\n"); + /* some random (external) function call */ Expression actual = first_Actual(funcall_actuals(e)); for (; actual != NULL; actual=Expression_info(actual)->next_actual) { - record_expression_dependencies(sink,sink_type,cond,kind,mod, + printf("=> actual lineno %d\n", tnode_line_number(e)); + dump_lisp_Expression(actual); + printf("\n"); + + Declaration formal = function_type_actual_formal(fdecl_type, actual, e); + Declaration_info(formal)->is_circular = funcall_actual_is_monotone_use(e, actual, use, fdecl, fdecl_type); + + record_expression_dependencies(sink,sink_type,cond,new_kind,mod, actual,aug_graph); } } diff --git a/analyze/aps-fiber.h b/analyze/aps-fiber.h index 2059dce1..b4f1ac8b 100644 --- a/analyze/aps-fiber.h +++ b/analyze/aps-fiber.h @@ -103,7 +103,6 @@ extern Declaration responsible_node_shared_info(void *, extern Declaration formal_in_case_p(Declaration); - typedef struct oset { struct oset *rest; Declaration o; diff --git a/analyze/aps-info.h b/analyze/aps-info.h index 1d0135f9..ca4f11c3 100644 --- a/analyze/aps-info.h +++ b/analyze/aps-info.h @@ -43,6 +43,7 @@ struct Declaration_info { unsigned decl_flags; void * call_sites; void *analysis_state; + BOOL is_circular; /* boolean indicating if decl is circular */ #define DECL_LHS_FLAG 1 #define DECL_RHS_FLAG 2 #define DECL_OBJECT_FLAG 4 diff --git a/analyze/canonical-signature.c b/analyze/canonical-signature.c index b20870d4..8583737b 100644 --- a/analyze/canonical-signature.c +++ b/analyze/canonical-signature.c @@ -708,22 +708,22 @@ void initialize_canonical_signature(Declaration module_TYPE_decl, Declaration mo /** * Given a signature, it returns whether it contains module declaration * @param sig signature - * @param mdecl module declaration + * @param module_or_class_decl module or class declaration * @return boolean indicating if module is in the type hierarchy of signature */ -bool signature_hierarchy_contains(Signature sig, Declaration mdecl) +bool signature_hierarchy_contains(Signature sig, Declaration module_or_class_decl) { switch (Signature_KEY(sig)) { case KEYsig_inst: Declaration some_mdecl = USE_DECL(class_use_use(sig_inst_class(sig))); - return some_mdecl == mdecl || - signature_hierarchy_contains(some_class_decl_parent(some_mdecl), mdecl); + return some_mdecl == module_or_class_decl || + signature_hierarchy_contains(some_class_decl_parent(some_mdecl), module_or_class_decl); case KEYmult_sig: - return signature_hierarchy_contains(mult_sig_sig1(sig), mdecl) || - signature_hierarchy_contains(mult_sig_sig2(sig), mdecl); + return signature_hierarchy_contains(mult_sig_sig1(sig), module_or_class_decl) || + signature_hierarchy_contains(mult_sig_sig2(sig), module_or_class_decl); case KEYsig_use: - return USE_DECL(sig_use_use(sig)) == mdecl; + return USE_DECL(sig_use_use(sig)) == module_or_class_decl; case KEYno_sig: case KEYfixed_sig: return false; @@ -733,12 +733,12 @@ bool signature_hierarchy_contains(Signature sig, Declaration mdecl) /** * Given a canonical signature, it returns whether it contains module declaration * @param csig canonical signature - * @param mdecl module declaration + * @param module_or_class_decl module or class declaration * @return boolean indicating if module is in the type hierarchy of signature */ -bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration mdecl) +bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration module_or_class_decl) { - if (csig->source_class == mdecl) return true; + if (csig->source_class == module_or_class_decl) return true; - return signature_hierarchy_contains(some_class_decl_parent(csig->source_class), mdecl); + return signature_hierarchy_contains(some_class_decl_parent(csig->source_class), module_or_class_decl); } diff --git a/analyze/canonical-signature.h b/analyze/canonical-signature.h index fe97d812..b6b36ee4 100644 --- a/analyze/canonical-signature.h +++ b/analyze/canonical-signature.h @@ -48,9 +48,9 @@ void print_canonical_signature_set(void *untyped, FILE *f); /** * Given a canonical signature, it returns whether it contains module declaration * @param csig canonical signature - * @param mdecl module declaration + * @param module_or_class_decl module or class declaration * @return boolean indicating if module is in the type hierarchy of signature */ -bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration mdecl); +bool canonical_signature_hierarchy_contains(CanonicalSignature* csig, Declaration module_or_class_decl); #endif diff --git a/analyze/canonical-type.c b/analyze/canonical-type.c index cb188f43..b156a3a1 100755 --- a/analyze/canonical-type.c +++ b/analyze/canonical-type.c @@ -517,8 +517,8 @@ CanonicalType *canonical_type(Type t) case KEYfunction_type: return canonical_type_function(t); case KEYno_type: - // canonical type representation of no-type is NULL. - return NULL; + // canonical type representation of no-type is itself. + return (CanonicalType*)t; default: aps_error(t, "Case of type %d is not implemented in canonical_type()", (int)Type_KEY(t)); return NULL; @@ -729,7 +729,7 @@ static CanonicalType *canonical_type_use_use_join(struct Canonical_use_type *cty break; } default: - fatal_error("Not sure what type of canonical type it is"); + return new_canonical_type_qual((CanonicalType *)ctype_outer, ctype_inner->decl); } Declaration decl = ctype_inner->decl; From 7b45dacbaeb23c770bafeacaa647d8768ad6a843 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 13:05:35 -0500 Subject: [PATCH 21/39] small changes --- analyze/aps-dnc.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index fdc8b7b1..23df9d00 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1146,7 +1146,7 @@ static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, U Declaration formal = function_type_actual_formal(func_type, actual, expr); - Type formal_ty = type_subst(use, formal_type(formal)); + Type formal_ty = type_subst(use, infer_formal_type(formal)); Type actual_ty = infer_expr_type(actual); if (analysis_debug & ADD_EDGE) { @@ -1437,16 +1437,23 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI source.attr = result; source.modifier = mod; if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); - add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); + + if (Declaration_KEY(decl) == KEYfunction_decl && some_function_decl_result(decl) == result) { + if (analysis_debug & ADD_EDGE) { + printf("skipped adding an edge between: "); + print_dep_vertex(&source, stdout); + printf("->"); + print_dep_vertex(sink, stdout); + printf("\n"); + } + } else { + add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); + } } } else { Use use = NULL; Declaration fdecl = funcall_f_decl(e, &use); Type fdecl_type = NULL; - - printf("=> funcall lineno %d\n", tnode_line_number(e)); - dump_lisp_Expression(e); - printf("\n"); if (Declaration_KEY(fdecl) == KEYconstructor_decl) { fdecl_type = constructor_decl_type(fdecl); @@ -1456,21 +1463,9 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI fdecl_type = some_function_decl_type(fdecl); } - printf("use: "); - print_Use(use, stdout); - printf("\n"); - - printf("=> sink: "); - print_dep_vertex(sink, stdout); - printf("\n"); - /* some random (external) function call */ Expression actual = first_Actual(funcall_actuals(e)); for (; actual != NULL; actual=Expression_info(actual)->next_actual) { - printf("=> actual lineno %d\n", tnode_line_number(e)); - dump_lisp_Expression(actual); - printf("\n"); - Declaration formal = function_type_actual_formal(fdecl_type, actual, e); Declaration_info(formal)->is_circular = funcall_actual_is_monotone_use(e, actual, use, fdecl, fdecl_type); @@ -1827,7 +1822,23 @@ static void *get_edges(void *vaug_graph, void *node) { VERTEX sink; sink.node = 0; sink.modifier = NO_MODIFIER; + + Expression case_expr = some_case_stmt_expr(decl); + BOOL case_expr_is_circular = canonical_type_is_lattice_type(canonical_type(infer_expr_type(case_expr))); + for (m=first_Match(some_case_stmt_matchers(decl)); m; m=MATCH_NEXT(m)) { + + if (case_expr_is_circular) { + Declaration match_formal = match_first_rhs_decl(m); + while (match_formal != NULL) { + if (canonical_type_is_lattice_type(canonical_type(infer_formal_type(match_formal)))) { + Declaration_info(match_formal)->is_circular = true; + } + + match_formal = next_rhs_decl(match_formal); + } + } + Expression test = Match_info(m)->match_test; sink.attr = (Declaration)m; Type sink_type = infer_expr_type(test); From 26d1d958d2e98b7bbf87d108cd5027bd65eda688 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 13:11:51 -0500 Subject: [PATCH 22/39] change wasn't needed --- examples/first.aps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/first.aps b/examples/first.aps index 3ebb3be9..edbd7ebe 100644 --- a/examples/first.aps +++ b/examples/first.aps @@ -67,7 +67,7 @@ module FIRST[T :: var GRAMMAR[]] extends T begin end; - var function contains_epsilon(s_set: SymbolLattice) : OrLattice begin + var function contains_epsilon(s_set: Symbols) : Boolean begin result := Symbols$member(epsilon, s_set); end; From 014d3cfd9ed3c041c264d73c36ffedfb999919b0 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 13:50:44 -0500 Subject: [PATCH 23/39] more undoing --- analyze/aps-dnc.c | 12 +----------- examples/first.aps | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 23df9d00..c132b9f4 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1059,7 +1059,6 @@ BOOL decl_is_circular(Declaration d) case KEYformal: return Declaration_info(d)->is_circular; default: - aps_error(d, "Not sure how to detect circularity of declaration key %d", Declaration_KEY(d)); return FALSE; } } @@ -1368,15 +1367,6 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI source.node = NULL; source.attr = decl; source.modifier = mod; - - if (mod != NULL && mod->field != NULL) { - if (decl_is_circular(mod->field)) { - new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; - } else { - new_kind |= DEPENDENCY_MAYBE_SIMPLE; - } - } - if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } @@ -1688,7 +1678,7 @@ static void *get_edges(void *vaug_graph, void *node) { return NULL; case KEYformal: { Declaration case_stmt = formal_in_case_p(decl); - Type sink_type = formal_type(decl); + Type sink_type = infer_formal_type(decl); if (case_stmt != NULL) { Expression expr = some_case_stmt_expr(case_stmt); VERTEX f; diff --git a/examples/first.aps b/examples/first.aps index edbd7ebe..a551843f 100644 --- a/examples/first.aps +++ b/examples/first.aps @@ -67,7 +67,7 @@ module FIRST[T :: var GRAMMAR[]] extends T begin end; - var function contains_epsilon(s_set: Symbols) : Boolean begin + var function contains_epsilon(s_set: Symbols) :Boolean begin result := Symbols$member(epsilon, s_set); end; From 14301d6d4da2c9966e415765cce097d1591c7a41 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:16:42 -0500 Subject: [PATCH 24/39] a lot of undoing --- analyze/aps-bind.c | 1 + analyze/aps-dnc.c | 42 +----------------------------------------- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/analyze/aps-bind.c b/analyze/aps-bind.c index 5b6b0daf..491ded81 100644 --- a/analyze/aps-bind.c +++ b/analyze/aps-bind.c @@ -1104,6 +1104,7 @@ static void *activate_pragmas(void *ignore, void *node) { } if (ABSTRACT_APS_tnode_phylum(node) == KEYDeclaration) { Declaration decl=(Declaration)node; + Declaration_info(decl)->is_circular = FALSE; // set default value of is_circular switch (Declaration_KEY(decl)) { case KEYpragma_call: { Symbol pragma_sym = pragma_call_name(decl); diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index c132b9f4..09cb3de2 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1164,31 +1164,6 @@ static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, U return formal_ctype == actual_ctype && canonical_type_is_lattice_type(formal_ctype); } -static Declaration funcall_f_decl(Expression e, Use* use) { - switch (Expression_KEY(e)) - { - case KEYfuncall: - return funcall_f_decl(funcall_f(e), use); - case KEYvalue_use: - *use = value_use_use(e); - Declaration func = USE_DECL(*use); - switch (Declaration_KEY(func)) - { - case KEYsome_value_decl: - return func; - case KEYvalue_renaming: - return funcall_f_decl(value_renaming_old(func), use); - default: - return NULL; - } - break; - default: - break; - } - - return NULL; -} - // return true if we are sure this vertex represents an input dependency static BOOL vertex_is_input(VERTEX* v) { @@ -1441,24 +1416,9 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI } } } else { - Use use = NULL; - Declaration fdecl = funcall_f_decl(e, &use); - Type fdecl_type = NULL; - - if (Declaration_KEY(fdecl) == KEYconstructor_decl) { - fdecl_type = constructor_decl_type(fdecl); - } else if (Declaration_KEY(fdecl) == KEYattribute_decl) { - fdecl_type = attribute_decl_type(fdecl); - } else { - fdecl_type = some_function_decl_type(fdecl); - } - /* some random (external) function call */ Expression actual = first_Actual(funcall_actuals(e)); for (; actual != NULL; actual=Expression_info(actual)->next_actual) { - Declaration formal = function_type_actual_formal(fdecl_type, actual, e); - Declaration_info(formal)->is_circular = funcall_actual_is_monotone_use(e, actual, use, fdecl, fdecl_type); - record_expression_dependencies(sink,sink_type,cond,new_kind,mod, actual,aug_graph); } @@ -1822,7 +1782,7 @@ static void *get_edges(void *vaug_graph, void *node) { Declaration match_formal = match_first_rhs_decl(m); while (match_formal != NULL) { if (canonical_type_is_lattice_type(canonical_type(infer_formal_type(match_formal)))) { - Declaration_info(match_formal)->is_circular = true; + Declaration_info(match_formal)->is_circular = TRUE; } match_formal = next_rhs_decl(match_formal); From a24831380cfd4084b9951f005be33b44e073b9f9 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:24:38 -0500 Subject: [PATCH 25/39] remove undoing --- analyze/aps-dnc.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 09cb3de2..ecd7e896 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1087,22 +1087,7 @@ static BOOL canonical_type_is_lattice_type(CanonicalType* ctype) { return FALSE; } -static Declaration function_type_actual_formal(Type func_type, Expression actual, Expression call) { - Expression expr; - Declaration f; - Declarations formals = function_type_formals(func_type); - Actuals actuals = funcall_actuals(call); - for (expr = first_Actual(actuals), f = first_Declaration(formals); - expr != NULL && f != NULL && expr != actual; - expr = Expression_info(expr)->next_expr, f = DECL_NEXT(f)) { - /* nothing */ - } - if (expr == NULL || f == NULL) - fatal_error("%d: cannot find formal",tnode_line_number(actuals)); - return f; -} - -static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use use, Declaration fdecl, Type fdecl_type) { +static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use use, Declaration fdecl) { TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1112,6 +1097,7 @@ static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use printf("\n"); } + Type fdecl_type = some_function_decl_type(fdecl); Declaration formal = first_Declaration(function_type_formals(fdecl_type)); Expression actual = first_Actual(funcall_actuals(expr)); @@ -1133,7 +1119,7 @@ static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use return fdecl_return_ctype == sink_ctype && canonical_type_is_lattice_type(fdecl_return_ctype); } -static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, Use use, Declaration fdecl, Type func_type) { +static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, Use use, Declaration fdecl) { TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1143,7 +1129,7 @@ static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, U printf("\n"); } - Declaration formal = function_type_actual_formal(func_type, actual, expr); + Declaration formal = function_actual_formal(fdecl, actual, expr); Type formal_ty = type_subst(use, infer_formal_type(formal)); Type actual_ty = infer_expr_type(actual); @@ -1377,7 +1363,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI if (mod == NO_MODIFIER) { for (;actual!=NULL; actual=Expression_info(actual)->next_actual) { - if (!funcall_actual_is_monotone_use(e, actual, use, decl, some_function_decl_type(decl))) { + if (!funcall_actual_is_monotone_use(e, actual, use, decl)) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } @@ -1393,7 +1379,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI * tnode_line_number(e),decl_name(decl)); */ { - if (!funcall_result_is_monotone_use(sink_type, e, use, decl, some_function_decl_type(decl))) { + if (!funcall_result_is_monotone_use(sink_type, e, use, decl)) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } From dc40d1f46b8f55b3e8a7582f98d0f614bdd96ef8 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:29:51 -0500 Subject: [PATCH 26/39] more undoing --- analyze/aps-dnc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index ecd7e896..3e8dba61 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1087,7 +1087,8 @@ static BOOL canonical_type_is_lattice_type(CanonicalType* ctype) { return FALSE; } -static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use use, Declaration fdecl) { +static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Declaration fdecl) { + Use use = value_use_use(funcall_f(expr)); TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1119,7 +1120,8 @@ static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Use return fdecl_return_ctype == sink_ctype && canonical_type_is_lattice_type(fdecl_return_ctype); } -static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, Use use, Declaration fdecl) { +static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, Declaration fdecl) { + Use use = value_use_use(funcall_f(expr)); TypeEnvironment te = USE_TYPE_ENV(use); if (analysis_debug & ADD_EDGE) { @@ -1356,14 +1358,13 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI record_expression_dependencies(sink,sink_type,cond,new_kind,&new_mod,object, aug_graph); } else if ((decl = local_call_p(e)) != NULL) { - Use use = value_use_use(funcall_f(e)); Declaration result = some_function_decl_result(decl); Expression actual = first_Actual(funcall_actuals(e)); /* first depend on the arguments (not carrying, no fibers) */ if (mod == NO_MODIFIER) { for (;actual!=NULL; actual=Expression_info(actual)->next_actual) { - if (!funcall_actual_is_monotone_use(e, actual, use, decl)) { + if (!funcall_actual_is_monotone_use(e, actual, decl)) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } @@ -1379,7 +1380,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI * tnode_line_number(e),decl_name(decl)); */ { - if (!funcall_result_is_monotone_use(sink_type, e, use, decl)) { + if (!funcall_result_is_monotone_use(sink_type, e, decl)) { new_kind |= DEPENDENCY_MAYBE_SIMPLE; } From 80ac87e214781331e04f960e8e786059be2e2bb4 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:33:57 -0500 Subject: [PATCH 27/39] more undoing --- examples/first.aps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/first.aps b/examples/first.aps index a551843f..1774b0af 100644 --- a/examples/first.aps +++ b/examples/first.aps @@ -16,7 +16,7 @@ module FIRST[T :: var GRAMMAR[]] extends T begin circular attribute Items.items_first : SymbolLattice; pragma synthesized(items_first); - circular attribute Grammar.grammar_first : DeclarationTable; + attribute Grammar.grammar_first : DeclarationTable; pragma synthesized(grammar_first); epsilon : Symbol := make_symbol("epsilon"); From 8845a0ca27cbd5cdf02def9398263201735a05e0 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:44:38 -0500 Subject: [PATCH 28/39] more reverting --- analyze/aps-dnc.c | 21 +++++++++++++++++++-- analyze/aps-dnc.h | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 3e8dba61..89a0ada4 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1087,6 +1087,16 @@ static BOOL canonical_type_is_lattice_type(CanonicalType* ctype) { return FALSE; } +/** + * Utility function that detects if use of result of some function call is monotone + * by checking if the result of function call equals the LHS type and is extending + * lattice. + * + * @param sink_type LHS type + * @param expr function call expression + * @param fdecl function declaration + * @return BOOL indicating whether result of some function call is monotone + */ static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Declaration fdecl) { Use use = value_use_use(funcall_f(expr)); TypeEnvironment te = USE_TYPE_ENV(use); @@ -1099,8 +1109,6 @@ static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Decl } Type fdecl_type = some_function_decl_type(fdecl); - Declaration formal = first_Declaration(function_type_formals(fdecl_type)); - Expression actual = first_Actual(funcall_actuals(expr)); // return type should be equal to sink type and be circular Type fdecl_return_type = type_subst(use, function_type_return_type(fdecl_type)); @@ -1120,6 +1128,15 @@ static BOOL funcall_result_is_monotone_use(Type sink_type, Expression expr, Decl return fdecl_return_ctype == sink_ctype && canonical_type_is_lattice_type(fdecl_return_ctype); } +/** + * Utility function that detects if use of actual of some function call is monotone + * by checking if formal and actual type are equal and is extending lattice. + * + * @param expr function call expression + * @param actual function call actual expression + * @param fdecl function declaration + * @return BOOL indicating whether use of actual of some function call is monotone + */ static BOOL funcall_actual_is_monotone_use(Expression expr, Expression actual, Declaration fdecl) { Use use = value_use_use(funcall_f(expr)); TypeEnvironment te = USE_TYPE_ENV(use); diff --git a/analyze/aps-dnc.h b/analyze/aps-dnc.h index 970a69e5..72b14e58 100644 --- a/analyze/aps-dnc.h +++ b/analyze/aps-dnc.h @@ -29,7 +29,7 @@ enum instance_direction instance_direction(INSTANCE *); extern BOOL fiber_attr_circular(FIBERED_ATTRIBUTE* fiber_attr); extern BOOL instance_circular(INSTANCE* in); -extern BOOL decl_is_circular(Declaration); +extern BOOL decl_is_circular(Declaration d); typedef unsigned DEPENDENCY; From 3d1bfd56b9a482c6f57f31851b319dc2b433ccd7 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:54:05 -0500 Subject: [PATCH 29/39] more reverts --- analyze/aps-fiber.h | 4 +--- analyze/canonical-type.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/analyze/aps-fiber.h b/analyze/aps-fiber.h index 097d98c3..c91d2285 100644 --- a/analyze/aps-fiber.h +++ b/analyze/aps-fiber.h @@ -101,9 +101,7 @@ extern Declaration shared_use_p(Expression); extern Declaration responsible_node_shared_info(void *, struct analysis_state *); extern Declaration formal_in_case_p(Declaration); -Declaration function_actual_formal(Declaration func, - Expression actual, - Expression call); +Declaration function_actual_formal(Declaration func, Expression actual, Expression call); typedef struct oset { struct oset *rest; diff --git a/analyze/canonical-type.c b/analyze/canonical-type.c index b156a3a1..424772ce 100755 --- a/analyze/canonical-type.c +++ b/analyze/canonical-type.c @@ -729,7 +729,7 @@ static CanonicalType *canonical_type_use_use_join(struct Canonical_use_type *cty break; } default: - return new_canonical_type_qual((CanonicalType *)ctype_outer, ctype_inner->decl); + fatal_error("Not sure what type of canonical type it is"); } Declaration decl = ctype_inner->decl; From c1bb93479d12b08876ddafefb0c83941ea261a32 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:56:51 -0500 Subject: [PATCH 30/39] undoing --- analyze/aps-fiber.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/analyze/aps-fiber.h b/analyze/aps-fiber.h index c91d2285..1cc41634 100644 --- a/analyze/aps-fiber.h +++ b/analyze/aps-fiber.h @@ -103,6 +103,8 @@ extern Declaration responsible_node_shared_info(void *, extern Declaration formal_in_case_p(Declaration); Declaration function_actual_formal(Declaration func, Expression actual, Expression call); + + typedef struct oset { struct oset *rest; Declaration o; From 6d6aebd6bbab5ec0d8dba4ff1a9bc466d25d9ff9 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 19 Apr 2023 15:59:05 -0500 Subject: [PATCH 31/39] better doc --- analyze/canonical-signature.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyze/canonical-signature.c b/analyze/canonical-signature.c index 8583737b..8e0dca49 100644 --- a/analyze/canonical-signature.c +++ b/analyze/canonical-signature.c @@ -489,7 +489,7 @@ static CanonicalSignature* join_canonical_signature_actuals(CanonicalType *sourc default: // short-circuit. // only when the source declaration of canonical type is some kind of - // type declaration then "join" would be possible. + // type declaration then "join" (or simplifying) would be possible. return canonical_sig; } From db77561015ff972a4394312544ec08ed001dc673 Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Mon, 24 Apr 2023 01:11:29 -0500 Subject: [PATCH 32/39] Update aps-dnc.c --- analyze/aps-dnc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 89a0ada4..5bd2bee0 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1409,15 +1409,16 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI if (Declaration_KEY(decl) == KEYfunction_decl && some_function_decl_result(decl) == result) { if (analysis_debug & ADD_EDGE) { - printf("skipped adding an edge between: "); + printf("skipped adding a SIMPLE edge between: "); print_dep_vertex(&source, stdout); printf("->"); print_dep_vertex(sink, stdout); printf("\n"); } - } else { - add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); + + new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; } + add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } } else { /* some random (external) function call */ From c36a808b7123815e8b7666078334201cd9427c5b Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Mon, 24 Apr 2023 01:12:27 -0500 Subject: [PATCH 33/39] Update aps-dnc.c --- analyze/aps-dnc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 5bd2bee0..e3c097cd 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1418,7 +1418,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; } - add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); + add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } } else { /* some random (external) function call */ From 45742a1fe7102d6c9a20e4d0cdbd5a454a8f5e9c Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Mon, 24 Apr 2023 02:09:17 -0500 Subject: [PATCH 34/39] Update aps-dnc.c --- analyze/aps-dnc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index e3c097cd..c5dfc43c 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1342,6 +1342,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI source.attr = decl; source.modifier = mod; if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); + new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } else { source.node = NULL; From 32393bf26bddf07cb1ed7614e15742b90709bec3 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 24 Apr 2023 02:20:54 -0500 Subject: [PATCH 35/39] all the changes required to pass the examples --- analyze/aps-dnc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index c5dfc43c..01bf5e2a 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1313,7 +1313,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI { Declaration decl=Use_info(value_use_use(e))->use_decl; Declaration rdecl; int new_kind = kind; - if (!decl_is_circular(decl)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; + if (!decl_is_circular(mod != NULL && mod->field != NULL ? mod->field : decl)) if (decl == NULL) fatal_error("%d: unbound expression",tnode_line_number(e)); if (DECL_IS_LOCAL(decl) && From 9ea9f7fc49020631363c29bb77a6d733a8dfefa7 Mon Sep 17 00:00:00 2001 From: Seyedamirhossein Hesamian Date: Mon, 24 Apr 2023 11:13:47 -0500 Subject: [PATCH 36/39] Update aps-dnc.c --- analyze/aps-dnc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 01bf5e2a..77b2000b 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1313,7 +1313,9 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI { Declaration decl=Use_info(value_use_use(e))->use_decl; Declaration rdecl; int new_kind = kind; - if (!decl_is_circular(mod != NULL && mod->field != NULL ? mod->field : decl)) + if (!decl_is_circular(mod != NULL && mod->field != NULL ? mod->field : decl)) { + new_kind |= DEPENDENCY_MAYBE_SIMPLE; + } if (decl == NULL) fatal_error("%d: unbound expression",tnode_line_number(e)); if (DECL_IS_LOCAL(decl) && From 05a76fc06d78da32b4b1d5753d4bbfa6a417a765 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 24 Apr 2023 15:35:43 -0500 Subject: [PATCH 37/39] some code changes from today --- analyze/aps-dnc.c | 8 ++++++-- examples/first.aps | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 01bf5e2a..20a653a4 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1313,7 +1313,9 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI { Declaration decl=Use_info(value_use_use(e))->use_decl; Declaration rdecl; int new_kind = kind; - if (!decl_is_circular(mod != NULL && mod->field != NULL ? mod->field : decl)) + if (!decl_is_circular(decl) && mod == NO_MODIFIER) { + new_kind |= DEPENDENCY_MAYBE_SIMPLE; + } if (decl == NULL) fatal_error("%d: unbound expression",tnode_line_number(e)); if (DECL_IS_LOCAL(decl) && @@ -1364,7 +1366,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } else if ((decl = field_ref_p(e)) != NULL) { - if (!decl_is_circular(decl)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; + if (!decl_is_circular(decl) && mod == NO_MODIFIER) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; Expression object = field_ref_object(e); new_mod.field = decl; new_mod.next = mod; @@ -1408,6 +1410,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI source.modifier = mod; if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); + // XXX: If we have procedure, this code needs to be revisted. if (Declaration_KEY(decl) == KEYfunction_decl && some_function_decl_result(decl) == result) { if (analysis_debug & ADD_EDGE) { printf("skipped adding a SIMPLE edge between: "); @@ -1787,6 +1790,7 @@ static void *get_edges(void *vaug_graph, void *node) { if (case_expr_is_circular) { Declaration match_formal = match_first_rhs_decl(m); while (match_formal != NULL) { + // XXX: strictly should look at the parent calls in-between if (canonical_type_is_lattice_type(canonical_type(infer_formal_type(match_formal)))) { Declaration_info(match_formal)->is_circular = TRUE; } diff --git a/examples/first.aps b/examples/first.aps index 1774b0af..a76f44cc 100644 --- a/examples/first.aps +++ b/examples/first.aps @@ -67,11 +67,11 @@ module FIRST[T :: var GRAMMAR[]] extends T begin end; - var function contains_epsilon(s_set: Symbols) :Boolean begin + function contains_epsilon(s_set: Symbols) :Boolean begin result := Symbols$member(epsilon, s_set); end; - var function black_dot(s1 :SymbolLattice; s2 :SymbolLattice) : SymbolLattice begin + function black_dot(s1 :SymbolLattice; s2 :SymbolLattice) : SymbolLattice begin if contains_epsilon(s1) then result := (s1 /\~ { epsilon }) \/ s2; else From ca22d66e25fdad77683d235833072500819c63f8 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 24 Apr 2023 15:42:03 -0500 Subject: [PATCH 38/39] added a comment --- analyze/aps-dnc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 20a653a4..22447ca3 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1344,6 +1344,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI source.attr = decl; source.modifier = mod; if (vertex_is_output(&source)) aps_warning(e,"Dependence on output value"); + // XXX: this needs to be revisited after modifying aps-dnc to not treat functions as procedures new_kind &= ~DEPENDENCY_MAYBE_SIMPLE; add_edges_to_graph(&source,sink,cond,new_kind,aug_graph); } else { From 88d849c1a5b8d65adfe0806627675dde2ad5930f Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 24 Apr 2023 23:52:12 -0500 Subject: [PATCH 39/39] Add no modifer to everywhere else --- analyze/aps-dnc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/analyze/aps-dnc.c b/analyze/aps-dnc.c index 22447ca3..41bc5544 100644 --- a/analyze/aps-dnc.c +++ b/analyze/aps-dnc.c @@ -1360,7 +1360,7 @@ static void record_expression_dependencies(VERTEX *sink, Type sink_type, CONDITI { Declaration decl; int new_kind = kind; if ((decl = attr_ref_p(e)) != NULL) { - if (!decl_is_circular(decl)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; + if (!decl_is_circular(decl) && mod == NO_MODIFIER) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; source.node = attr_ref_node_decl(e); source.attr = decl; source.modifier = mod; @@ -1557,7 +1557,7 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, Declaration field, attr, fdecl, decl; VERTEX sink; if ((field = field_ref_p(lhs)) != NULL) { - if (!decl_is_circular(field)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; + if (!decl_is_circular(field) && mod == NO_MODIFIER) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; /* Assignment of a field, or a field of a field */ Expression object = field_ref_object(lhs); MODIFIER new_mod; @@ -1571,7 +1571,7 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, record_lhs_dependencies(object,cond,control_dependency, &new_mod,object,aug_graph); } else if ((attr = attr_ref_p(lhs)) != NULL) { - if (!decl_is_circular(attr)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; + if (!decl_is_circular(attr) && mod == NO_MODIFIER) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; sink.node = attr_ref_node_decl(lhs); sink.attr = attr; sink.modifier = mod; @@ -1580,7 +1580,7 @@ static void record_lhs_dependencies(Expression lhs, CONDITION *cond, record_expression_dependencies(&sink,sink_type,cond,kind,NULL,rhs,aug_graph); record_condition_dependencies(&sink,cond,aug_graph); } else if ((fdecl = local_call_p(lhs)) != NULL) { - if (!decl_is_circular(fdecl)) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; + if (!decl_is_circular(fdecl) && mod == NO_MODIFIER) new_kind |= DEPENDENCY_MAYBE_SIMPLE; else new_kind = kind; Declaration result = some_function_decl_result(decl); Declaration proxy = Expression_info(lhs)->funcall_proxy; if (mod == NO_MODIFIER) {