diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 483d22f..6adabf2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -67,6 +67,8 @@ jobs: lc tests/array_02.cpp --backend=llvm --extra-arg="-Isrc/runtime/include" -- + lc tests/array_03.cpp --backend=llvm --extra-arg="-I$CONDA_PREFIX/include" -- + # Test generating object files lc examples/expr2.c --backend c --extra-arg="-Isrc/runtime/include" -o c_o -c -- lc examples/expr2.c --backend llvm --extra-arg="-Isrc/runtime/include" -o llvm_o -c -- diff --git a/environment_unix.yml b/environment_unix.yml index 9857cca..699bcb9 100644 --- a/environment_unix.yml +++ b/environment_unix.yml @@ -11,3 +11,4 @@ dependencies: - git=2.43.0 - python=3.12.0 - toml=0.10.2 + - xtensor=0.24.7 diff --git a/src/lc/clang_ast_to_asr.h b/src/lc/clang_ast_to_asr.h index c02c994..b782342 100644 --- a/src/lc/clang_ast_to_asr.h +++ b/src/lc/clang_ast_to_asr.h @@ -43,12 +43,15 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor* current_body; bool is_stmt_created; std::vector> scopes; + std::string cxx_operator_name; + ASR::expr_t* assignment_target; explicit ClangASTtoASRVisitor(clang::ASTContext *Context_, Allocator& al_, ASR::asr_t*& tu_): Context(Context_), al{al_}, tu{tu_}, tmp{nullptr}, current_body{nullptr}, - is_stmt_created{true} {} + is_stmt_created{true}, cxx_operator_name{""}, + assignment_target{nullptr} {} template Location Lloc(T *x) { @@ -58,6 +61,17 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor + std::string get_file_name(T* x) { + clang::SourceLocation loc = x->getLocation(); + if( loc.isInvalid() ) { + return ""; + } + + clang::FullSourceLoc full_source_loc = Context->getFullLoc(loc); + return std::string(full_source_loc.getPresumedLoc().getFilename()); + } + template std::string loc(T *x) { uint64_t first = Context->getFullLoc(x->getBeginLoc()).getFileOffset(); @@ -190,7 +204,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorisIntegerType() ) { type = ASRUtils::TYPE(ASR::make_Integer_t(al, l, 4)); } else if( clang_type->isFloatingType() ) { - type = ASRUtils::TYPE(ASR::make_Real_t(al, l, 4)); + type = ASRUtils::TYPE(ASR::make_Real_t(al, l, 8)); } else if( clang_type->isPointerType() ) { type = ClangTypeToASRType(qual_type->getPointeeType()); if( !ASRUtils::is_character(*type) ) { @@ -228,6 +242,42 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorgetTypeClass() == clang::Type::TypeClass::Elaborated ) { + const clang::ElaboratedType* elaborated_type = clang_type->getAs(); + clang::QualType desugared_type = elaborated_type->desugar(); + type = ClangTypeToASRType(desugared_type); + } else if( clang_type->getTypeClass() == clang::Type::TypeClass::TemplateSpecialization ) { + const clang::TemplateSpecializationType* template_specialization = clang_type->getAs(); + std::string template_name = template_specialization->getTemplateName().getAsTemplateDecl()->getNameAsString(); + if( template_name == "xtensor" ) { + const std::vector& template_arguments = template_specialization->template_arguments(); + if( template_arguments.size() != 2 ) { + throw std::runtime_error("xtensor type must be initialised with element type and rank."); + } + const clang::QualType& qual_type = template_arguments.at(0).getAsType(); + clang::Expr* clang_rank = template_arguments.at(1).getAsExpr(); + TraverseStmt(clang_rank); + int rank = 0; + if( !ASRUtils::extract_value(ASRUtils::EXPR(tmp), rank) ) { + throw std::runtime_error("Rank provided in the xtensor initialisation must be a constant."); + } + tmp = nullptr; + Vec empty_dims; empty_dims.reserve(al, rank); + for( int dim = 0; dim < rank; dim++ ) { + ASR::dimension_t empty_dim; + empty_dim.loc = l; + empty_dim.m_start = nullptr; + empty_dim.m_length = nullptr; + empty_dims.push_back(al, empty_dim); + } + type = ASRUtils::TYPE(ASR::make_Array_t(al, l, + ClangTypeToASRType(qual_type), + empty_dims.p, empty_dims.size(), + ASR::array_physical_typeType::DescriptorArray)); + type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, l, type)); + } else { + throw std::runtime_error(std::string("Unrecognized type ") + template_name); + } } else { throw std::runtime_error("clang::QualType not yet supported " + std::string(clang_type->getTypeClassName())); @@ -308,6 +358,31 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorm_v)) == "printf"; } + bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr* x) { + clang::Expr* callee = x->getCallee(); + TraverseStmt(callee); + if( cxx_operator_name == "operator<<" ) { + clang::Expr** args = x->getArgs(); + TraverseStmt(args[0]); + if( cxx_operator_name != "cout" ) { + throw std::runtime_error("Only cout is supported in operator<<."); + } + size_t n_args = x->getNumArgs(); + Vec print_args; + print_args.reserve(al, n_args); + for( size_t i = 1; i < n_args; i++ ) { + TraverseStmt(args[i]); + ASR::expr_t* arg = ASRUtils::EXPR(tmp); + print_args.push_back(al, arg); + } + tmp = ASR::make_Print_t(al, Lloc(x), print_args.p, print_args.size(), nullptr, nullptr); + is_stmt_created = true; + } else { + throw std::runtime_error("Only std::ostream operator is supported."); + } + return true; + } + bool TraverseCallExpr(clang::CallExpr *x) { TraverseStmt(x->getCallee()); ASR::expr_t* callee = ASRUtils::EXPR(tmp); @@ -398,6 +473,14 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorgetNumArgs() >= 0 ) { + return clang::RecursiveASTVisitor::TraverseCXXConstructExpr(x); + } + tmp = nullptr; + return true; + } + bool TraverseVarDecl(clang::VarDecl *x) { std::string name = x->getName().str(); if( scopes.size() > 0 ) { @@ -421,11 +504,16 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitoradd_symbol(name, v); is_stmt_created = false; if (x->hasInit()) { - TraverseStmt(x->getInit()); - ASR::expr_t* init_val = ASRUtils::EXPR(tmp); + tmp = nullptr; ASR::expr_t* var = ASRUtils::EXPR(ASR::make_Var_t(al, Lloc(x), v)); - tmp = ASR::make_Assignment_t(al, Lloc(x), var, init_val, nullptr); - is_stmt_created = true; + assignment_target = var; + TraverseStmt(x->getInit()); + assignment_target = nullptr; + if( tmp != nullptr ) { + ASR::expr_t* init_val = ASRUtils::EXPR(tmp); + tmp = ASR::make_Assignment_t(al, Lloc(x), var, init_val, nullptr); + is_stmt_created = true; + } } return true; } @@ -465,6 +553,44 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorm_type = new_type; } + bool extract_dimensions_from_array_type(ASR::ttype_t* array_type, + Vec& alloc_dims) { + if( !ASRUtils::is_array(array_type) ) { + return false; + } + + ASR::Array_t* array_t = ASR::down_cast( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_const(array_type)))); + for( int i = 0; i < array_t->n_dims; i++ ) { + alloc_dims.push_back(al, array_t->m_dims[i]); + } + + extract_dimensions_from_array_type(array_t->m_type, alloc_dims); + return true; + } + + void create_allocate_stmt(ASR::expr_t* var, ASR::ttype_t* array_type) { + if( var == nullptr || !ASRUtils::is_allocatable(var) ) { + return ; + } + + const Location& loc = var->base.loc; + Vec alloc_dims; alloc_dims.reserve(al, 1); + if( extract_dimensions_from_array_type(array_type, alloc_dims) ) { + Vec alloc_args; alloc_args.reserve(al, 1); + ASR::alloc_arg_t alloc_arg; alloc_arg.loc = loc; + alloc_arg.m_a = var; + alloc_arg.m_dims = alloc_dims.p; alloc_arg.n_dims = alloc_dims.size(); + alloc_arg.m_type = nullptr; alloc_arg.m_len_expr = nullptr; + alloc_args.push_back(al, alloc_arg); + ASR::stmt_t* allocate_stmt = ASRUtils::STMT(ASR::make_Allocate_t(al, loc, + alloc_args.p, alloc_args.size(), nullptr, nullptr, nullptr)); + current_body->push_back(al, allocate_stmt); + } + } + bool TraverseInitListExpr(clang::InitListExpr* x) { Vec init_exprs; init_exprs.reserve(al, x->getNumInits()); @@ -485,6 +611,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorgetNameInfo().getAsString(); + if( name == "operator<<" || name == "cout" ) { + cxx_operator_name = name; + return true; + } ASR::symbol_t* sym = resolve_symbol(name); LCOMPILERS_ASSERT(sym != nullptr); tmp = ASR::make_Var_t(al, Lloc(x), sym); @@ -754,6 +885,45 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor + bool process_AST_node(T* x) { + std::string file_path = get_file_name(x); + if( file_path.size() == 0 ) { + return false; + } + + std::vector include_paths = { + "include/c++/v1", + "include/stddef.h", + "include/__stddef_max_align_t.h", + "usr/include", + "mambaforge/envs", + "lib/gcc", + "lib/clang", + "micromamba-root/envs" + }; + for( std::string& path: include_paths ) { + if( file_path.find(path) != std::string::npos ) { + return false; + } + } + + return true; + } + + bool TraverseDecl(clang::Decl* x) { + if( x->isImplicit() ) { + return true; + } + + if( process_AST_node(x) || x->getKind() == clang::Decl::Kind::TranslationUnit ) { + return clang::RecursiveASTVisitor::TraverseDecl(x); + } else { + return true; + } + + return false; + } private: clang::ASTContext *Context; diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index b84a10d..acc74cc 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -9231,6 +9231,7 @@ Result> asr_to_llvm(ASR::TranslationUnit_t &asr, v.module->print(os, nullptr); std::cout << os.str(); msg = "asr_to_llvm: module failed verification. Error:\n" + err.str(); + std::cout << msg << std::endl; diagnostics.diagnostics.push_back(diag::Diagnostic(msg, diag::Level::Error, diag::Stage::CodeGen)); Error error; diff --git a/tests/array_03.cpp b/tests/array_03.cpp new file mode 100644 index 0000000..6620feb --- /dev/null +++ b/tests/array_03.cpp @@ -0,0 +1,19 @@ +#include +#include "xtensor/xtensor.hpp" +#include "xtensor/xio.hpp" +#include "xtensor/xview.hpp" + +int main() { + + xt::xtensor arr1; /* { // TODO: Uncomment this initializer + {1.0, 2.0, 3.0}, + {2.0, 5.0, 7.0}, + {2.0, 5.0, 7.0}}; */ + + xt::xtensor arr2 {5.0, 6.0, 7.0}; + + // xt::xarray res = xt::view(arr1, 1) + arr2; // TODO: Uncomment this statement + std::cout << arr2; + + return 0; +} diff --git a/tests/reference/asr-array_02-0507073.json b/tests/reference/asr-array_02-0507073.json index e546a5f..5c1b7a1 100644 --- a/tests/reference/asr-array_02-0507073.json +++ b/tests/reference/asr-array_02-0507073.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-array_02-0507073.stdout", - "stdout_hash": "0baf3d16bb054881ea07f3b263006e49d1cbbad16dafe435cbd78e35", + "stdout_hash": "330d65993b5445881264552aaa9b7415b7be4a04a3ec05f5b8ae3d92", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-array_02-0507073.stdout b/tests/reference/asr-array_02-0507073.stdout index 9ef4c81..1008f37 100644 --- a/tests/reference/asr-array_02-0507073.stdout +++ b/tests/reference/asr-array_02-0507073.stdout @@ -32,7 +32,7 @@ () () Default - (Real 4) + (Real 8) () Source Public @@ -65,7 +65,7 @@ [((IntegerConstant 4 (Integer 4))) ((IntegerConstant 10 (Integer 4))) ((IntegerConstant 4 (Integer 4)))] - (Real 4) + (Real 8) () () ) @@ -75,7 +75,7 @@ [(Cast (Var 4 sum) RealToReal - (Real 4) + (Real 8) () )] () @@ -144,7 +144,7 @@ () () Default - (Real 4) + (Real 8) () Source Public @@ -161,7 +161,7 @@ () Default (Array - (Real 4) + (Real 8) [((IntegerConstant 0 (Integer 4)) (Var 3 n))] PointerToDataArray @@ -182,7 +182,7 @@ () Default (Array - (Real 4) + (Real 8) [((IntegerConstant 0 (Integer 4)) (Var 3 nums)) ((IntegerConstant 0 (Integer 4)) @@ -366,7 +366,7 @@ () () Default - (Real 4) + (Real 8) () Source Public @@ -382,7 +382,7 @@ () () Default - (Real 4) + (Real 8) () Source Public @@ -395,7 +395,7 @@ [(Integer 4) (Integer 4) (Integer 4)] - (Real 4) + (Real 8) Source Implementation () @@ -465,7 +465,7 @@ (() (Var 3 j) ())] - (Real 4) + (Real 8) RowMajor () ) @@ -479,7 +479,7 @@ () ) IntegerToReal - (Real 4) + (Real 8) () ) Div @@ -492,10 +492,10 @@ () ) IntegerToReal - (Real 4) + (Real 8) () ) - (Real 4) + (Real 8) () ) () @@ -556,7 +556,7 @@ [(() (Var 3 k) ())] - (Real 4) + (Real 8) RowMajor () ) @@ -564,17 +564,17 @@ (Cast (Var 3 k) IntegerToReal - (Real 4) + (Real 8) () ) Div (Cast (Var 3 n) IntegerToReal - (Real 4) + (Real 8) () ) - (Real 4) + (Real 8) () ) () @@ -599,7 +599,7 @@ (Real 8) ) RealToReal - (Real 4) + (Real 8) () ) () @@ -640,7 +640,7 @@ (Real 8) ) RealToReal - (Real 4) + (Real 8) () ) () @@ -676,7 +676,7 @@ (() (Var 3 j1) ())] - (Real 4) + (Real 8) RowMajor () ) @@ -686,14 +686,14 @@ [(() (Var 3 j1) ())] - (Real 4) + (Real 8) RowMajor () ) - (Real 4) + (Real 8) () ) - (Real 4) + (Real 8) () ) () @@ -716,7 +716,7 @@ (Var 3 sum) Add (Var 3 output) - (Real 4) + (Real 8) () ) ()