diff --git a/integration_tests/nbody.cpp b/integration_tests/nbody.cpp index c5e8f66..1190326 100644 --- a/integration_tests/nbody.cpp +++ b/integration_tests/nbody.cpp @@ -15,10 +15,10 @@ Source: https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbod #include "xtensor/xio.hpp" #include "xtensor/xview.hpp" -const int nb = 5; -const double PI = 3.141592653589793; -const double SOLAR_MASS = 4 * PI * PI; -const int N = (nb - 1) * nb/2; +constexpr int nb = 5; +constexpr double PI = 3.141592653589793; +constexpr double SOLAR_MASS = 4 * PI * PI; +constexpr int N = (nb - 1) * nb/2; void offset_momentum(const int k, xt::xtensor_fixed>& v, const xt::xtensor_fixed>& mass) { @@ -101,7 +101,7 @@ double energy(const xt::xtensor_fixed>& x, struct body { double x, y, z, u, vx, vy, vz, vu, mass; - body(double x_, double y_, double z_, double u_, + constexpr body(double x_, double y_, double z_, double u_, double vx_, double vy_, double vz_, double vu_, double mass_) : x{x_}, y{y_}, z{z_}, u{u_}, vx{vx_}, vy{vy_}, vz{vz_}, vu{vu_}, mass{mass_} { @@ -112,16 +112,16 @@ struct body { int main() { const double tstep = 0.01; - const double DAYS_PER_YEAR = 365.24; + constexpr double DAYS_PER_YEAR = 365.24; - const struct body jupiter = body( + constexpr struct body jupiter = body( 4.84143144246472090, -1.16032004402742839, -1.03622044471123109e-01, 0.0, 1.66007664274403694e-03 * DAYS_PER_YEAR, 7.69901118419740425e-03 * DAYS_PER_YEAR, -6.90460016972063023e-05 * DAYS_PER_YEAR, 0.0, 9.54791938424326609e-04 * SOLAR_MASS); - const struct body saturn = body( + constexpr struct body saturn = body( 8.34336671824457987, 4.12479856412430479, -4.03523417114321381e-01, 0.0, -2.76742510726862411e-03 * DAYS_PER_YEAR, @@ -129,7 +129,7 @@ int main() { 2.30417297573763929e-05 * DAYS_PER_YEAR, 0.0, 2.85885980666130812e-04 * SOLAR_MASS); - const struct body uranus = body( + constexpr struct body uranus = body( 1.28943695621391310e+01, -1.51111514016986312e+01, -2.23307578892655734e-01, 0.0, 2.96460137564761618e-03 * DAYS_PER_YEAR, @@ -137,7 +137,7 @@ int main() { -2.96589568540237556e-05 * DAYS_PER_YEAR, 0.0, 4.36624404335156298e-05 * SOLAR_MASS); - const struct body neptune = body( + constexpr struct body neptune = body( 1.53796971148509165e+01, -2.59193146099879641e+01, 1.79258772950371181e-01, 0.0, 2.68067772490389322e-03 * DAYS_PER_YEAR, @@ -145,7 +145,7 @@ int main() { -9.51592254519715870e-05 * DAYS_PER_YEAR, 0.0, 5.15138902046611451e-05 * SOLAR_MASS); - const struct body sun = body(0.0, 0.0, 0.0, 0.0, 0.0, + constexpr struct body sun = body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS); xt::xtensor_fixed> mass = { diff --git a/src/lc/clang_ast_to_asr.cpp b/src/lc/clang_ast_to_asr.cpp index 3e486ac..1ae1565 100644 --- a/src/lc/clang_ast_to_asr.cpp +++ b/src/lc/clang_ast_to_asr.cpp @@ -160,6 +160,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor* default_stmt; OneTimeUseBool is_break_stmt_present; bool enable_fall_through; + std::map> struct2member_inits; explicit ClangASTtoASRVisitor(clang::ASTContext *Context_, Allocator& al_, ASR::asr_t*& tu_): @@ -481,6 +482,26 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorctor_begin(); constructors != x->ctor_end(); constructors++ ) { + clang::CXXConstructorDecl* constructor = *constructors; + if( constructor->isTrivial() || constructor->isImplicit() ) { + continue ; + } + for( auto ctor = constructor->init_begin(); ctor != constructor->init_end(); ctor++ ) { + clang::CXXCtorInitializer* ctor_init = *ctor; + clang::Expr* init_expr = ctor_init->getInit(); + if( init_expr->getStmtClass() == clang::Stmt::StmtClass::InitListExprClass ) { + init_expr = static_cast(init_expr)->getInit(0); + } + if( init_expr->getStmtClass() != clang::Stmt::StmtClass::ImplicitCastExprClass || + static_cast(init_expr)->getSubExpr()->getStmtClass() != + clang::Stmt::StmtClass::DeclRefExprClass ) { + throw std::runtime_error("Initialisation expression in constructor should " + "only be the argument itself."); + } + } + } + SymbolTable* parent_scope = current_scope; current_scope = al.make_new(parent_scope); std::string struct_name = x->getNameAsString(); @@ -576,6 +597,20 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor(*base) ) { + ASR::Var_t* var_t = ASR::down_cast(base); + ASR::symbol_t* v = ASRUtils::symbol_get_past_external(var_t->m_v); + if( struct2member_inits.find(v) == struct2member_inits.end() ) { + return nullptr; + } + return struct2member_inits[v][member_name]; + } + + return nullptr; + } + bool TraverseMemberExpr(clang::MemberExpr* x) { TraverseStmt(x->getBase()); ASR::expr_t* base = ASRUtils::EXPR(tmp.get()); @@ -596,8 +631,8 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorm_name, nullptr, 0, s2c(al, member_name), ASR::accessType::Public)); current_scope->add_symbol(mangled_name, member); - tmp = ASR::make_StructInstanceMember_t(al, Lloc(x), base, member, - ASRUtils::symbol_type(member), nullptr); + tmp = ASR::make_StructInstanceMember_t(al, Lloc(x), base, member, ASRUtils::symbol_type(member), + evaluate_compile_time_value_for_StructInstanceMember(base, member_name)); } else if( special_function_map.find(member_name) != special_function_map.end() ) { member_name_obj.set(member_name); return clang::RecursiveASTVisitor::TraverseMemberExpr(x); @@ -1308,6 +1343,13 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorgetConstructor()->isConstexpr() ) { + throw std::runtime_error("Constructors for user-define types " + "must be defined with constexpr."); + } + if( static_cast(x->getConstructor()->getBody())->size() > 0 ) { + throw std::runtime_error("Constructor for user-defined must have empty body."); + } std::string type_name = x->getConstructor()->getNameAsString(); ASR::symbol_t* s = current_scope->resolve_symbol(type_name); if( s == nullptr ) { @@ -1322,6 +1364,11 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorm_symtab->resolve_symbol(struct_type_t->m_members[i])); ASR::ttype_t* arg_type = ASRUtils::expr_type(call_arg.m_value); @@ -1338,6 +1385,48 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorgetKind() ) { + case clang::APValue::Struct: { + ASR::ttype_t* v_type = ASRUtils::type_get_past_const(ASRUtils::symbol_type(v)); + if( !ASR::is_a(*v_type) ) { + throw std::runtime_error("Expected ASR::Struct_t type found, " + + ASRUtils::type_to_str(v_type)); + } + ASR::Struct_t* struct_t = ASR::down_cast(v_type); + ASR::StructType_t* struct_type_t = ASR::down_cast( + ASRUtils::symbol_get_past_external(struct_t->m_derived_type)); + for( size_t i = 0; i < ap_value->getStructNumFields(); i++ ) { + clang::APValue& field = ap_value->getStructField(i); + TraverseAPValue(field); + struct2member_inits[v][struct_type_t->m_members[i]] = ASRUtils::EXPR(tmp.get()); + } + break; + } + } + } + bool TraverseVarDecl(clang::VarDecl *x) { std::string name = x->getName().str(); if( scopes.size() > 0 ) { @@ -1385,6 +1474,11 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorgetEvaluatedValue() ) { + clang::APValue* ap_value = x->getEvaluatedValue(); + evaluate_compile_time_value_for_Var(ap_value, v); + } } return true; }