Skip to content

Bug in C codegen #1152

Closed
Closed
@Smit-create

Description

@Smit-create

I was trying to compile and run the C code generated from integration_tests/test_builtin_str.py (#1109 ). I found the following issue with the C codegen:
Python:

def f():
    s: str
    s = "abcde"
    c: str
    for c in s[::-1]:
        print(c)

f()

The generated C code on the main branch is:

void f()
{
    int32_t __explicit_iterator;
    char * __tmp_assign_for_loop = (char*) malloc(40 * sizeof(char));
    char * c = (char*) malloc(40 * sizeof(char));
    char * s = (char*) malloc(40 * sizeof(char));
    strcpy(s, "abcde");
    for (__explicit_iterator=0; __explicit_iterator<=strlen(__tmp_assign_for_loop) - 1; __explicit_iterator++) {
        strcpy(c, (char *)memcpy((char *)calloc(2U, sizeof(char)), __tmp_assign_for_loop + __explicit_iterator + 1 - 1, 1U));
        printf("%s\n", c);
    }
}

The above code is incorrect because we expect __tmp_assign_for_loop to contain the value of s[::-1]. This is because of this line in the ASR frontend:

std::string tmp_assign_name = current_scope->get_unique_name("__tmp_assign_for_loop");

The variable value is ignored in C code generation as seen in the above code __tmp_assign_for_loop does not contain the correct value and so essentially will give segmentation fault due to memory errors.

I tried to fix that by using the following diff(changed made to wherever variables are declared):

diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h
index b696d8d1e..bed985fc9 100644
--- a/src/libasr/codegen/asr_to_c_cpp.h
+++ b/src/libasr/codegen/asr_to_c_cpp.h
@@ -520,6 +520,17 @@ R"(#include <stdio.h>
             }
         }

+        for (auto &item : x.m_symtab->get_scope()) {
+            if (ASR::is_a<ASR::Variable_t>(*item.second)) {
+                ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(item.second);
+                if (v->m_value) {
+                    self().visit_expr(*v->m_value);
+                    std::string name(v->m_name);
+                    decl += name +  " = " + src + ";\n";
+                }
+            }
+        }
+

And got the following C code:

void f()
{
    int32_t __explicit_iterator;
    char * __tmp_assign_for_loop = (char*) malloc(40 * sizeof(char));
    char * c = (char*) malloc(40 * sizeof(char));
    char * s = (char*) malloc(40 * sizeof(char));
    __tmp_assign_for_loop = _lfortran_str_slice(s, 0, 0, -1, false, false);
    strcpy(s, "abcde");
    for (__explicit_iterator=0; __explicit_iterator<=strlen(__tmp_assign_for_loop) - 1; __explicit_iterator++) {
        strcpy(c, (char *)memcpy((char *)calloc(2U, sizeof(char)), __tmp_assign_for_loop + __explicit_iterator + 1 - 1, 1U));
        printf("%s\n", c);
    }
}

That still won't work because __tmp_assign_for_loop is assigned before s is assigned. Any suggestions to fix it?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcLabel for C language related changes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions