diff --git a/CMakeLists.txt b/CMakeLists.txt index 9545f67832..4e1e2ea0b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,6 +120,20 @@ if (WITH_LCOMPILERS_FAST_ALLOC) add_definitions("-DLCOMPILERS_FAST_ALLOC=1") endif() +# copy runtime files +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython/lpython.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython/lpython.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/cmath.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/cmath.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython_builtin.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython_builtin.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython_intrinsic_numpy.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython_intrinsic_numpy.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/lpython_parser.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/lpython_parser.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/math.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/math.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/os.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/os.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/platform.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/platform.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/random.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/random.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/statistics.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/statistics.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/sys.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/sys.py") +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/runtime/time.py" "${CMAKE_CURRENT_BINARY_DIR}/src/runtime/time.py") + # LLVM set(WITH_LLVM no CACHE BOOL "Build with LLVM support") set(WITH_TARGET_AARCH64 no CACHE BOOL "Enable target AARCH64") diff --git a/src/libasr/asr_scopes.cpp b/src/libasr/asr_scopes.cpp index 4fae6739e8..c999eaec69 100644 --- a/src/libasr/asr_scopes.cpp +++ b/src/libasr/asr_scopes.cpp @@ -3,6 +3,7 @@ #include #include +#include std::string lcompilers_unique_ID; @@ -39,9 +40,13 @@ void SymbolTable::mark_all_variables_external(Allocator &al) { case (ASR::symbolType::Function) : { ASR::Function_t *v = ASR::down_cast(a.second); ASR::FunctionType_t* v_func_type = ASR::down_cast(v->m_function_signature); - v_func_type->m_abi = ASR::abiType::Interactive; - v->m_body = nullptr; - v->n_body = 0; + if (v_func_type->m_abi != ASR::abiType::Interactive) { + v_func_type->m_abi = ASR::abiType::Interactive; + v->m_body = nullptr; + v->n_body = 0; + PassUtils::UpdateDependenciesVisitor ud(al); + ud.visit_Function(*v); + } break; } case (ASR::symbolType::Module) : { diff --git a/src/libasr/asr_verify.cpp b/src/libasr/asr_verify.cpp index 16b255f8cc..19adc83ae8 100644 --- a/src/libasr/asr_verify.cpp +++ b/src/libasr/asr_verify.cpp @@ -420,6 +420,11 @@ class VerifyVisitor : public BaseWalkVisitor } void visit_Function(const Function_t &x) { + ASR::FunctionType_t* x_func_type = ASR::down_cast(x.m_function_signature); + if (x_func_type->m_abi == abiType::Interactive) { + require(x.n_body == 0, + "The Function::n_body should be 0 if abi set to Interactive"); + } std::vector function_dependencies_copy = function_dependencies; function_dependencies.clear(); function_dependencies.reserve(x.n_dependencies); diff --git a/src/libasr/codegen/KaleidoscopeJIT.h b/src/libasr/codegen/KaleidoscopeJIT.h index 28829bcad6..df83c850d2 100644 --- a/src/libasr/codegen/KaleidoscopeJIT.h +++ b/src/libasr/codegen/KaleidoscopeJIT.h @@ -26,6 +26,10 @@ #include "llvm/IR/LLVMContext.h" #include +#if LLVM_VERSION_MAJOR >= 13 +#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" +#endif + #if LLVM_VERSION_MAJOR >= 16 # define RM_OPTIONAL_TYPE std::optional #else @@ -37,77 +41,76 @@ namespace orc { class KaleidoscopeJIT { private: - ExecutionSession ES; + std::unique_ptr ES; RTDyldObjectLinkingLayer ObjectLayer; IRCompileLayer CompileLayer; DataLayout DL; MangleAndInterner Mangle; - ThreadSafeContext Ctx; JITDylib &JITDL; - TargetMachine *TM; - public: - KaleidoscopeJIT(JITTargetMachineBuilder JTMB, DataLayout DL) + KaleidoscopeJIT(std::unique_ptr ES, JITTargetMachineBuilder JTMB, DataLayout DL) : -#if LLVM_VERSION_MAJOR >= 13 - ES(cantFail(SelfExecutorProcessControl::Create())), -#endif - ObjectLayer(ES, + ES(std::move(ES)), + ObjectLayer(*this->ES, []() { return std::make_unique(); }), - CompileLayer(ES, ObjectLayer, std::make_unique(ConcurrentIRCompiler(std::move(JTMB)))), - DL(std::move(DL)), Mangle(ES, this->DL), - Ctx(std::make_unique()), + CompileLayer(*this->ES, ObjectLayer, std::make_unique(std::move(JTMB))), + DL(std::move(DL)), Mangle(*this->ES, this->DL), JITDL( #if LLVM_VERSION_MAJOR >= 11 cantFail #endif - (ES.createJITDylib("Main"))) { + (this->ES->createJITDylib("Main"))) { JITDL.addGenerator( cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess( DL.getGlobalPrefix()))); - - std::string Error; - auto TargetTriple = sys::getDefaultTargetTriple(); - auto Target = TargetRegistry::lookupTarget(TargetTriple, Error); - if (!Target) { - throw std::runtime_error("Failed to lookup the target"); + if (JTMB.getTargetTriple().isOSBinFormatCOFF()) { + ObjectLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); + ObjectLayer.setAutoClaimResponsibilityForObjectSymbols(true); } - auto CPU = "generic"; - auto Features = ""; - TargetOptions opt; - auto RM = RM_OPTIONAL_TYPE(); - TM = Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM); } static Expected> Create() { - auto JTMB = JITTargetMachineBuilder::detectHost(); +#if LLVM_VERSION_MAJOR >= 13 + auto EPC = SelfExecutorProcessControl::Create(); + if (!EPC) + return EPC.takeError(); - if (!JTMB) - return JTMB.takeError(); + auto ES = std::make_unique(std::move(*EPC)); - auto DL = JTMB->getDefaultDataLayoutForTarget(); + JITTargetMachineBuilder JTMB( + ES->getExecutorProcessControl().getTargetTriple()); +#else + auto ES = std::make_unique(); + + auto JTMB_P = JITTargetMachineBuilder::detectHost(); + if (!JTMB_P) + return JTMB_P.takeError(); + + auto JTMB = *JTMB_P; +#endif + + auto DL = JTMB.getDefaultDataLayoutForTarget(); if (!DL) return DL.takeError(); - return std::make_unique(std::move(*JTMB), std::move(*DL)); + return std::make_unique(std::move(ES), std::move(JTMB), + std::move(*DL)); } const DataLayout &getDataLayout() const { return DL; } - LLVMContext &getContext() { return *Ctx.getContext(); } - - Error addModule(std::unique_ptr M) { - return CompileLayer.add(JITDL, - ThreadSafeModule(std::move(M), Ctx)); + Error addModule(std::unique_ptr M, std::unique_ptr &Ctx) { + auto res = CompileLayer.add(JITDL, + ThreadSafeModule(std::move(M), std::move(Ctx))); + Ctx = std::make_unique(); + return res; } Expected lookup(StringRef Name) { - return ES.lookup({&JITDL}, Mangle(Name.str())); + return ES->lookup({&JITDL}, Mangle(Name.str())); } - - TargetMachine &getTargetMachine() { return *TM; } }; } // end namespace orc diff --git a/src/libasr/codegen/evaluator.cpp b/src/libasr/codegen/evaluator.cpp index d96e729da7..dadf4fb50d 100644 --- a/src/libasr/codegen/evaluator.cpp +++ b/src/libasr/codegen/evaluator.cpp @@ -212,7 +212,7 @@ std::unique_ptr LLVMEvaluator::parse_module(const std::string &sou throw LCompilersException("parse_module(): module failed verification."); }; module->setTargetTriple(target_triple); - module->setDataLayout(jit->getTargetMachine().createDataLayout()); + module->setDataLayout(jit->getDataLayout()); return module; } @@ -234,7 +234,7 @@ void LLVMEvaluator::add_module(std::unique_ptr mod) { // cases when the Module was constructed directly, not via parse_module(). mod->setTargetTriple(target_triple); mod->setDataLayout(jit->getDataLayout()); - llvm::Error err = jit->addModule(std::move(mod)); + llvm::Error err = jit->addModule(std::move(mod), context); if (err) { llvm::SmallVector buf; llvm::raw_svector_ostream dest(buf); @@ -288,7 +288,7 @@ std::string LLVMEvaluator::get_asm(llvm::Module &m) llvm::CodeGenFileType ft = llvm::CGFT_AssemblyFile; llvm::SmallVector buf; llvm::raw_svector_ostream dest(buf); - if (jit->getTargetMachine().addPassesToEmitFile(pass, dest, nullptr, ft)) { + if (TM->addPassesToEmitFile(pass, dest, nullptr, ft)) { throw std::runtime_error("TargetMachine can't emit a file of this type"); } pass.run(m); diff --git a/src/libasr/string_utils.cpp b/src/libasr/string_utils.cpp index bd496d0899..04d68033a8 100644 --- a/src/libasr/string_utils.cpp +++ b/src/libasr/string_utils.cpp @@ -116,7 +116,7 @@ std::string read_file(const std::string &filename) std::vector bytes(filesize); ifs.read(&bytes[0], filesize); - return std::string(&bytes[0], filesize); + return replace(std::string(&bytes[0], filesize), "\r\n", "\n"); } std::string parent_path(const std::string &path) { diff --git a/src/lpython/tests/test_llvm.cpp b/src/lpython/tests/test_llvm.cpp index 8891a9a8ce..8d2b91f919 100644 --- a/src/lpython/tests/test_llvm.cpp +++ b/src/lpython/tests/test_llvm.cpp @@ -624,6 +624,25 @@ TEST_CASE("PythonCompiler 1") { CHECK(r.result.i32 == 1); } +TEST_CASE("PythonCompiler 2") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i: i32 = 3 % 2"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer4); + CHECK(r.result.i32 == 1); +} + TEST_CASE("PythonCompiler i32 expressions") { CompilerOptions cu; cu.po.disable_main = true; @@ -845,6 +864,7 @@ TEST_CASE("PythonCompiler u32 declaration") { r = e.evaluate2("i: u32"); CHECK(r.ok); CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i = u32(5)"); CHECK(r.ok); CHECK(r.result.type == PythonCompiler::EvalResult::statement); @@ -1358,3 +1378,113 @@ def my_concat(x: str, y: str) -> str: CHECK(r.result.type == PythonCompiler::EvalResult::string); CHECK(std::strcmp(r.result.str, "Python REPL") == 0); } + +TEST_CASE("PythonCompiler asr verify 1") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2("i: i32 = 3 % 2"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("i"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer4); + CHECK(r.result.i32 == 1); +} + +TEST_CASE("PythonCompiler asr verify 2") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + r = e.evaluate2(R"( +def is_even(x: i32) -> i32: + if x % 2 == 0: + return 1 + return 0 +)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("is_even(4)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer4); + CHECK(r.result.i32 == 1); + r = e.evaluate2("is_even(3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer4); + CHECK(r.result.i32 == 0); +} + +TEST_CASE("PythonCompiler asr verify 3") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2(R"( +def addi(x: i32, y: i32) -> i32: + return x + y +)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2(R"( +def subi(x: i32, y: i32) -> i32: + return addi(x, -y) +)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("addi(2, 3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer4); + CHECK(r.result.i32 == 5); + r = e.evaluate2("subi(2, 3)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::integer4); + CHECK(r.result.i32 == -1); +} + +TEST_CASE("PythonCompiler asr verify 4") { + CompilerOptions cu; + cu.po.disable_main = true; + cu.emit_debug_line_column = false; + cu.generate_object_code = false; + cu.interactive = true; + cu.po.runtime_library_dir = LCompilers::LPython::get_runtime_library_dir(); + PythonCompiler e(cu); + LCompilers::Result + + r = e.evaluate2(R"( +def addr(x: f64, y: f64) -> f64: + return x + y +)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2(R"( +def subr(x: f64, y: f64) -> f64: + return addr(x, -y) +)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::none); + r = e.evaluate2("addr(2.5, 3.5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == 6); + r = e.evaluate2("subr(2.5, 3.5)"); + CHECK(r.ok); + CHECK(r.result.type == PythonCompiler::EvalResult::real8); + CHECK(r.result.f64 == -1); +} diff --git a/src/runtime/lpython_builtin.py b/src/runtime/lpython_builtin.py index 7678cb0de2..6bb7920d5f 100644 --- a/src/runtime/lpython_builtin.py +++ b/src/runtime/lpython_builtin.py @@ -1143,4 +1143,3 @@ def list(s: str) -> list[str]: for i in range(len(s)): l.append(s[i]) return l - diff --git a/src/runtime/platform.py b/src/runtime/platform.py index 4c11b4977a..f408c53219 100644 --- a/src/runtime/platform.py +++ b/src/runtime/platform.py @@ -2,4 +2,4 @@ def python_implementation() -> str: return "LPython" def python_version() -> str: - return __LPYTHON_VERSION__ \ No newline at end of file + return __LPYTHON_VERSION__