Skip to content

Commit

Permalink
Fix ASR verify pass error while using Interactive (#2706)
Browse files Browse the repository at this point in the history
* skipping function verification of Interactive ABI

* function verify checks for empty body

* intrinsic function's body & dependency left unchanged

* Fix ASR verify pass error while using Interactive

* updated tests

* fix typos

* update cmake to copy runtime python files to build dir

* fix test for the changes in main

* fix indentation for windows

* fix for windows

* undo indentations

* indentation fix
  • Loading branch information
Vipul-Cariappa committed Jun 8, 2024
1 parent 521941a commit e04c568
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 46 deletions.
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
11 changes: 8 additions & 3 deletions src/libasr/asr_scopes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <libasr/asr_scopes.h>
#include <libasr/asr_utils.h>
#include <libasr/pass/pass_utils.h>

std::string lcompilers_unique_ID;

Expand Down Expand Up @@ -39,9 +40,13 @@ void SymbolTable::mark_all_variables_external(Allocator &al) {
case (ASR::symbolType::Function) : {
ASR::Function_t *v = ASR::down_cast<ASR::Function_t>(a.second);
ASR::FunctionType_t* v_func_type = ASR::down_cast<ASR::FunctionType_t>(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) : {
Expand Down
5 changes: 5 additions & 0 deletions src/libasr/asr_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,11 @@ class VerifyVisitor : public BaseWalkVisitor<VerifyVisitor>
}

void visit_Function(const Function_t &x) {
ASR::FunctionType_t* x_func_type = ASR::down_cast<ASR::FunctionType_t>(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<std::string> function_dependencies_copy = function_dependencies;
function_dependencies.clear();
function_dependencies.reserve(x.n_dependencies);
Expand Down
77 changes: 40 additions & 37 deletions src/libasr/codegen/KaleidoscopeJIT.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#include "llvm/IR/LLVMContext.h"
#include <memory>

#if LLVM_VERSION_MAJOR >= 13
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#endif

#if LLVM_VERSION_MAJOR >= 16
# define RM_OPTIONAL_TYPE std::optional
#else
Expand All @@ -37,77 +41,76 @@ namespace orc {

class KaleidoscopeJIT {
private:
ExecutionSession ES;
std::unique_ptr<ExecutionSession> 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<ExecutionSession> 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<SectionMemoryManager>(); }),
CompileLayer(ES, ObjectLayer, std::make_unique<ConcurrentIRCompiler>(ConcurrentIRCompiler(std::move(JTMB)))),
DL(std::move(DL)), Mangle(ES, this->DL),
Ctx(std::make_unique<LLVMContext>()),
CompileLayer(*this->ES, ObjectLayer, std::make_unique<ConcurrentIRCompiler>(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<Reloc::Model>();
TM = Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);
}

static Expected<std::unique_ptr<KaleidoscopeJIT>> 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<ExecutionSession>(std::move(*EPC));

auto DL = JTMB->getDefaultDataLayoutForTarget();
JITTargetMachineBuilder JTMB(
ES->getExecutorProcessControl().getTargetTriple());
#else
auto ES = std::make_unique<ExecutionSession>();

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<KaleidoscopeJIT>(std::move(*JTMB), std::move(*DL));
return std::make_unique<KaleidoscopeJIT>(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<Module> M) {
return CompileLayer.add(JITDL,
ThreadSafeModule(std::move(M), Ctx));
Error addModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> &Ctx) {
auto res = CompileLayer.add(JITDL,
ThreadSafeModule(std::move(M), std::move(Ctx)));
Ctx = std::make_unique<LLVMContext>();
return res;
}

Expected<JITEvaluatedSymbol> lookup(StringRef Name) {
return ES.lookup({&JITDL}, Mangle(Name.str()));
return ES->lookup({&JITDL}, Mangle(Name.str()));
}

TargetMachine &getTargetMachine() { return *TM; }
};

} // end namespace orc
Expand Down
6 changes: 3 additions & 3 deletions src/libasr/codegen/evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ std::unique_ptr<llvm::Module> 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;
}

Expand All @@ -234,7 +234,7 @@ void LLVMEvaluator::add_module(std::unique_ptr<llvm::Module> 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<char, 128> buf;
llvm::raw_svector_ostream dest(buf);
Expand Down Expand Up @@ -288,7 +288,7 @@ std::string LLVMEvaluator::get_asm(llvm::Module &m)
llvm::CodeGenFileType ft = llvm::CGFT_AssemblyFile;
llvm::SmallVector<char, 128> 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);
Expand Down
2 changes: 1 addition & 1 deletion src/libasr/string_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ std::string read_file(const std::string &filename)
std::vector<char> 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) {
Expand Down
130 changes: 130 additions & 0 deletions src/lpython/tests/test_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<PythonCompiler::EvalResult>

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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<PythonCompiler::EvalResult>

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<PythonCompiler::EvalResult>
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<PythonCompiler::EvalResult>

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<PythonCompiler::EvalResult>

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);
}
1 change: 0 additions & 1 deletion src/runtime/lpython_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1143,4 +1143,3 @@ def list(s: str) -> list[str]:
for i in range(len(s)):
l.append(s[i])
return l

2 changes: 1 addition & 1 deletion src/runtime/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ def python_implementation() -> str:
return "LPython"

def python_version() -> str:
return __LPYTHON_VERSION__
return __LPYTHON_VERSION__

0 comments on commit e04c568

Please sign in to comment.