Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fixed output through c_sym backend for test_gruntz.py #2441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ RUN(NAME symbolics_10 LABELS cpython_sym c_sym llvm_sym NOFAST)
RUN(NAME symbolics_11 LABELS cpython_sym c_sym llvm_sym NOFAST)
RUN(NAME symbolics_12 LABELS cpython_sym c_sym llvm_sym NOFAST)
RUN(NAME symbolics_13 LABELS cpython_sym c_sym llvm_sym NOFAST)
RUN(NAME test_gruntz LABELS cpython_sym llvm_sym NOFAST)
RUN(NAME test_gruntz LABELS cpython_sym c_sym llvm_sym NOFAST)

RUN(NAME sizeof_01 LABELS llvm c
EXTRAFILES sizeof_01b.c)
Expand Down
12 changes: 6 additions & 6 deletions src/libasr/codegen/asr_to_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,11 +415,6 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
headers.insert("complex.h");
convert_variable_decl_util(v, is_array, declare_as_constant, use_ref, dummy,
force_declare, force_declare_name, n_dims, m_dims, v_m_type, dims, sub);
} else if (ASR::is_a<ASR::SymbolicExpression_t>(*v_m_type)) {
headers.insert("symengine/cwrapper.h");
std::string type_name = "basic";
std::string v_m_name = v.m_name;
sub = format_type_c("", type_name, v_m_name, use_ref, dummy);
} else if (ASRUtils::is_logical(*v_m_type)) {
convert_variable_decl_util(v, is_array, declare_as_constant, use_ref, dummy,
force_declare, force_declare_name, n_dims, m_dims, v_m_type, dims, sub);
Expand Down Expand Up @@ -529,7 +524,12 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
} else if (ASR::is_a<ASR::List_t>(*v_m_type)) {
ASR::List_t* t = ASR::down_cast<ASR::List_t>(v_m_type);
std::string list_type_c = c_ds_api->get_list_type(t);
sub = format_type_c("", list_type_c, v.m_name,
std::string name = v.m_name;
if (name == "_lpython_return_variable" && v.m_intent == ASRUtils::intent_out) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is hardwiring a check for _lpython_return_variable at several places in the C backend.

However, the C backend should work with any frontend, and should be independent of how the frontend names its variables.

Is there a way to fix it without any such checks of the type name == "_lpython_return_variable"?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall look into it !

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple places to consider if you think about it

  1. Whenever use use the subroutine_from_function, we would end up with this ASR node
        (=
            (Var 3 _lpython_return_variable)
            (Var 3 some_var)
            ()
        )

As we are finally storing whatever answer we want to return in the variable of intent Out (which in our case and I think most cases would be _lpython_return_variable or basically the variable to be returned.)
So I think we could do with just the m_intent == ASRUtils::intent_out check for any normal case as we know the return_var is changed to out. Only when some exceptional/corner case comes up we might have to think about this

The "_lpython_return_variable" just adds another level of security and in general gives more protection.

Copy link
Collaborator Author

@anutosh491 anutosh491 Dec 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say we can just use it once in the beggining (when we hit the variable)

  mmrv:
      (Function
          (SymbolTable
              3
              {
                  _lpython_return_variable:
                      (Variable
                          3
                          _lpython_return_variable
                          []
                          Out
                          ()
                          ()
                          Default
                          (List
                              (CPtr)
                          )
                          ()
                          Source
                          Public
                          Required
                          .false.
                      ),

Here we can check

              if (name == "_lpython_return_variable" && v.m_intent == ASRUtils::intent_out) {
                  is_return_var_intent_out = true;

Once this is done we can always use the bool variable is_return_var_intent_out for anything we want.
If we don't want to do this, we can obviously make it a bit more specific to cater to cases relevant to us for now

              if (t->m_type->type == ASR::ttypeType::CPtr && v.m_intent == ASRUtils::intent_out) {
                  is_return_var_intent_out = true;
              }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some thought and checking for some corner cases I've realized that we might be able to do without using "_lpython_return_variable" but it's best (in terms of convinience) to use it. Let's discuss more in the call today.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix might be as simple as:

Suggested change
if (name == "_lpython_return_variable" && v.m_intent == ASRUtils::intent_out) {
if (v.m_intent == ASRUtils::intent_out) {

If it doesn't work, then let's figure out an example where this fails and understand if there are other corner cases to be fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the condition is that if it is a List, it should be passes as a pointer.

is_return_var_intent_out = true;
name = "*" + name;
}
sub = format_type_c("", list_type_c, name,
false, false);
} else if (ASR::is_a<ASR::Tuple_t>(*v_m_type)) {
ASR::Tuple_t* t = ASR::down_cast<ASR::Tuple_t>(v_m_type);
Expand Down
19 changes: 18 additions & 1 deletion src/libasr/codegen/asr_to_c_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class BaseCCPPVisitor : public ASR::BaseVisitor<Struct>
SymbolTable* current_scope;
bool is_string_concat_present;

bool is_return_var_intent_out = false;

BaseCCPPVisitor(diag::Diagnostics &diag, Platform &platform,
CompilerOptions &_compiler_options, bool gen_stdstring, bool gen_stdcomplex, bool is_c,
int64_t default_lower_bound) : diag{diag},
Expand Down Expand Up @@ -1077,6 +1079,16 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) {
|| param->m_intent == ASRUtils::intent_out)
&& !ASRUtils::is_aggregate_type(param->m_type))) {
args += "&" + src;
} else if (std::string(param->m_name) == "_lpython_return_variable"
&& param->m_intent == ASRUtils::intent_out) {
if (ASR::is_a<ASR::List_t>(*param->m_type)) {
ASR::List_t* list_type = ASR::down_cast<ASR::List_t>(param->m_type);
if (list_type->m_type->type == ASR::ttypeType::CPtr){
args += "&" + src;
}
} else {
args += src;
}
} else {
args += src;
}
Expand Down Expand Up @@ -1367,7 +1379,12 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) {
if( is_target_list && is_value_list ) {
ASR::List_t* list_target = ASR::down_cast<ASR::List_t>(ASRUtils::expr_type(x.m_target));
std::string list_dc_func = c_ds_api->get_list_deepcopy_func(list_target);
src += indent + list_dc_func + "(&" + value + ", &" + target + ");\n\n";
if (target == "_lpython_return_variable" && is_return_var_intent_out) {
src += indent + list_dc_func + "(&" + value + ", " + target + ");\n\n";
is_return_var_intent_out = false;
} else {
src += indent + list_dc_func + "(&" + value + ", &" + target + ");\n\n";
}
} else if ( is_target_tup && is_value_tup ) {
ASR::Tuple_t* tup_target = ASR::down_cast<ASR::Tuple_t>(ASRUtils::expr_type(x.m_target));
std::string dc_func = c_ds_api->get_tuple_deepcopy_func(tup_target);
Expand Down