diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index c5816d6b32..541c53ae7f 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -1006,14 +1006,14 @@ int interactive_python_repl( } break; } - case (LCompilers::PythonCompiler::EvalResult::structt) : { + case (LCompilers::PythonCompiler::EvalResult::struct_type) : { if (verbose) { std::cout << "Return type: " << LCompilers::ASRUtils::get_type_code(r.structure.ttype) << std::endl; } if (verbose) section("Result:"); - std::cout << fe.string_aggregate_type(r) << std::endl; + std::cout << fe.aggregate_type_to_string(r) << std::endl; break; } case (LCompilers::PythonCompiler::EvalResult::none) : { diff --git a/src/libasr/pass/global_stmts.cpp b/src/libasr/pass/global_stmts.cpp index 6a1a9ac822..4295d37ca8 100644 --- a/src/libasr/pass/global_stmts.cpp +++ b/src/libasr/pass/global_stmts.cpp @@ -102,27 +102,6 @@ void pass_wrap_global_stmts(Allocator &al, unit.m_symtab->add_symbol(global_underscore_name, down_cast(global_underscore)); ASR::stmt_t* asr_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, global_underscore_ref, return_var_ref, nullptr)); body.push_back(al, asr_stmt); - - // if ((type->type == ASR::ttypeType::Tuple) || - // (type->type == ASR::ttypeType::List)) { - // s.from_str(al, fn_name_s + std::to_string(idx)); - // var_name = s.c_str(al); - - // ASR::ttype_t *type_pointer = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, type)); - // ASR::expr_t *value = EXPR(ASR::make_GetPointer_t(al, loc, global_underscore_ref, type_pointer, nullptr)); - - // return_var = ASR::make_Variable_t(al, loc, - // fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, - // ASR::storage_typeType::Default, type_pointer, - // nullptr, ASR::abiType::BindC, - // ASR::Public, ASR::presenceType::Required, false); - // return_var_ref = EXPR(ASR::make_Var_t(al, loc, down_cast(return_var))); - // ASR::stmt_t* asr_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, return_var_ref, value, nullptr)); - // body.push_back(al, asr_stmt); - // idx++; - // return_var_ref = nullptr; - // return_var = nullptr; - // } } ASR::asr_t *fn = ASRUtils::make_Function_t_util( diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index 0b570c5439..252244e968 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -127,35 +127,19 @@ Result PythonCompiler::evaluate( call_run_fn = true; } - llvm::Type *type = nullptr; - ASR::symbol_t *f = symbol_table->get_symbol("_" + run_fn); - if ((return_type == "struct") && (f)) { - llvm::Function *fn = m->get_function(run_fn); - type = fn->getReturnType(); - LCOMPILERS_ASSERT(type->isStructTy()) + ASR::symbol_t *global_underscore_sym = symbol_table->get_symbol("_" + run_fn); + if ((return_type == "struct") && (global_underscore_sym)) { + // we compute the offsets of the struct's attribute here + // we will be using it later in aggregate_type_to_string to print the struct - const llvm::DataLayout &dl = e->get_jit_data_layout(); - size_t elements_count = type->getStructNumElements(); - LCompilers::Vec offsets; - offsets.reserve(al, elements_count); - for (size_t i = 0; i < elements_count; i++) { - size_t offset = dl.getStructLayout((llvm::StructType*)type)->getElementOffset(i); - offsets.push_back(al, offset); - } - result.structure.offsets = offsets.p; + // we compute the offsets here instead of computing it in aggregate_type_to_string + // because once we call `e->add_module`, internally LLVM may deallocate all the + // type info after compiling the IR into machine code - result.structure.ttype = ASR::down_cast(f)->m_type; - if (result.structure.ttype->type == ASR::ttypeType::List) { - type = type->getStructElementType(2); - LCOMPILERS_ASSERT(type->isPointerTy()) - result.structure.element_size = e->get_jit_data_layout().getTypeAllocSize( -#if LLVM_VERSION_MAJOR >= 14 - type->getNonOpaquePointerElementType() -#else - type->getPointerElementType() -#endif - ); - } + llvm::Function *fn = m->get_function(run_fn); + llvm::Type *llvm_type = fn->getReturnType(); + LCOMPILERS_ASSERT(llvm_type->isStructTy()) + compute_offsets(llvm_type, global_underscore_sym, result); } e->add_module(std::move(m)); @@ -247,11 +231,11 @@ Result PythonCompiler::evaluate( result.b = r; } else if (return_type == "struct") { e->execfn(run_fn); - if (f) { + if (global_underscore_sym) { void *r = (void*)e->get_symbol_address("_" + run_fn); LCOMPILERS_ASSERT(r) result.structure.structure = r; - result.type = EvalResult::structt; + result.type = EvalResult::struct_type; } } else if (return_type == "void") { e->execfn(run_fn); @@ -362,7 +346,7 @@ Result> PythonCompiler::get_llvm3( void print_type(ASR::ttype_t *t, void *data, std::string &result); -std::string PythonCompiler::string_aggregate_type(const struct EvalResult &r) { +std::string PythonCompiler::aggregate_type_to_string(const struct EvalResult &r) { ASR::ttype_t *asr_type = r.structure.ttype; void *data = r.structure.structure; size_t *offsets = r.structure.offsets; @@ -392,6 +376,33 @@ std::string PythonCompiler::string_aggregate_type(const struct EvalResult &r) { return result; } +void PythonCompiler::compute_offsets(llvm::Type *type, ASR::symbol_t *asr_type, EvalResult &result) { + LCOMPILERS_ASSERT(type->isStructTy()) + + const llvm::DataLayout &dl = e->get_jit_data_layout(); + size_t elements_count = type->getStructNumElements(); + LCompilers::Vec offsets; + offsets.reserve(al, elements_count); + for (size_t i = 0; i < elements_count; i++) { + size_t offset = dl.getStructLayout((llvm::StructType*)type)->getElementOffset(i); + offsets.push_back(al, offset); + } + result.structure.offsets = offsets.p; + + result.structure.ttype = ASR::down_cast(asr_type)->m_type; + if (result.structure.ttype->type == ASR::ttypeType::List) { + type = type->getStructElementType(2); + LCOMPILERS_ASSERT(type->isPointerTy()) + result.structure.element_size = e->get_jit_data_layout().getTypeAllocSize( +#if LLVM_VERSION_MAJOR >= 14 + type->getNonOpaquePointerElementType() +#else + type->getPointerElementType() +#endif + ); + } +} + void print_type(ASR::ttype_t *t, void *data, std::string &result) { switch (t->type) { case ASR::ttypeType::Logical: diff --git a/src/lpython/python_evaluator.h b/src/lpython/python_evaluator.h index 9c3f73f00f..004e147c73 100644 --- a/src/lpython/python_evaluator.h +++ b/src/lpython/python_evaluator.h @@ -13,6 +13,10 @@ #include #include +namespace llvm { + class Type; +} + namespace LCompilers { class LLVMModule; @@ -51,7 +55,7 @@ class PythonCompiler complex8, boolean, string, - structt, + struct_type, statement, none } type; @@ -95,7 +99,10 @@ class PythonCompiler LCompilers::PassManager& lpm, diag::Diagnostics &diagnostics, const std::string &infile); - std::string string_aggregate_type(const struct EvalResult &r); + std::string aggregate_type_to_string(const struct EvalResult &r); + +private: + void compute_offsets(llvm::Type *type, ASR::symbol_t *asr_type, EvalResult &result); private: Allocator al; diff --git a/src/lpython/tests/test_llvm.cpp b/src/lpython/tests/test_llvm.cpp index d28d48dfca..3042140d24 100644 --- a/src/lpython/tests/test_llvm.cpp +++ b/src/lpython/tests/test_llvm.cpp @@ -1479,15 +1479,15 @@ TEST_CASE("PythonCompiler lists") { r = e.evaluate2("[1, 2, 3]"); CHECK(r.ok); - CHECK(r.result.type == PythonCompiler::EvalResult::structt); + CHECK(r.result.type == PythonCompiler::EvalResult::struct_type); CHECK(LCompilers::ASRUtils::get_type_code(r.result.structure.ttype) == "list[i32]"); - CHECK(e.string_aggregate_type(r.result) == "[1, 2, 3]"); + CHECK(e.aggregate_type_to_string(r.result) == "[1, 2, 3]"); r = e.evaluate2("[u8(1), u8(2), u8(3)] + [u8(1), u8(2), u8(3)]"); CHECK(r.ok); - CHECK(r.result.type == PythonCompiler::EvalResult::structt); + CHECK(r.result.type == PythonCompiler::EvalResult::struct_type); CHECK(LCompilers::ASRUtils::get_type_code(r.result.structure.ttype) == "list[u8]"); - CHECK(e.string_aggregate_type(r.result) == "[1, 2, 3, 1, 2, 3]"); + CHECK(e.aggregate_type_to_string(r.result) == "[1, 2, 3, 1, 2, 3]"); r = e.evaluate2("x: list[f64] = [1.5, 2.5, 3.5]"); CHECK(r.ok); @@ -1495,15 +1495,15 @@ TEST_CASE("PythonCompiler lists") { r = e.evaluate2("x + [4.5]"); CHECK(r.ok); - CHECK(r.result.type == PythonCompiler::EvalResult::structt); + CHECK(r.result.type == PythonCompiler::EvalResult::struct_type); CHECK(LCompilers::ASRUtils::get_type_code(r.result.structure.ttype) == "list[r64]"); - CHECK(e.string_aggregate_type(r.result) == "[1.500000, 2.500000, 3.500000, 4.500000]"); + CHECK(e.aggregate_type_to_string(r.result) == "[1.500000, 2.500000, 3.500000, 4.500000]"); r = e.evaluate2("[\"lfortran\", \"lpython\", \"lc\"]"); CHECK(r.ok); - CHECK(r.result.type == PythonCompiler::EvalResult::structt); + CHECK(r.result.type == PythonCompiler::EvalResult::struct_type); CHECK(LCompilers::ASRUtils::get_type_code(r.result.structure.ttype) == "list[str]"); - CHECK(e.string_aggregate_type(r.result) == "[\"lfortran\", \"lpython\", \"lc\"]"); + CHECK(e.aggregate_type_to_string(r.result) == "[\"lfortran\", \"lpython\", \"lc\"]"); } TEST_CASE("PythonCompiler asr verify 1") {