void LoweringVisitor::create_reduction_function(OpenMP::Reduction* red, Nodecl::NodeclBase construct, TL::Type reduction_type, TL::Symbol& basic_reduction_function, TL::Symbol& vector_reduction_function) { if (IS_C_LANGUAGE || IS_CXX_LANGUAGE) { basic_reduction_function = create_basic_reduction_function_c(red, construct); // This is not yet well supported in Nanos++ if (!reduction_type.is_array()) { vector_reduction_function = create_vector_reduction_function_c(red, construct); } } else if (IS_FORTRAN_LANGUAGE) { basic_reduction_function = create_basic_reduction_function_fortran(red, construct); } else { internal_error("Code unreachable", 0); } }
static TL::Symbol create_initializer_function_fortran( OpenMP::Reduction* red, TL::Type reduction_type, Nodecl::NodeclBase construct) { std::string fun_name; { std::stringstream ss; ss << "nanos_ini_" << red << "_" << reduction_type.get_internal_type() << "_" << simple_hash_str(construct.get_filename().c_str()); fun_name = ss.str(); } Nodecl::NodeclBase initializer = red->get_initializer().shallow_copy(); TL::Type omp_out_type = reduction_type, omp_ori_type = reduction_type; // These sources are only used in array reductions TL::Source omp_out_extra_attributes, extra_stuff_array_red; if (reduction_type.is_array()) { Source dims_descr; TL::Type t = reduction_type; int rank = 0; if (t.is_fortran_array()) { rank = t.fortran_rank(); } dims_descr << "("; omp_out_extra_attributes << ", POINTER, DIMENSION("; int i; for (i = 0; i < rank; i++) { if (i != 0) { dims_descr << ","; omp_out_extra_attributes << ","; } dims_descr << "LBOUND(omp_orig, DIM = " << (rank - i) << ")" << ":" << "UBOUND(omp_orig, DIM = " << (rank - i) << ")" ; omp_out_extra_attributes << ":"; t = t.array_element(); } dims_descr << ")"; omp_out_extra_attributes << ")"; omp_out_type = t; extra_stuff_array_red << "ALLOCATE(omp_out" << dims_descr <<")\n"; } Source src; src << "SUBROUTINE " << fun_name << "(omp_out, omp_orig)\n" << "IMPLICIT NONE\n" << as_type(omp_out_type) << omp_out_extra_attributes << " :: omp_out\n" << as_type(omp_ori_type) << " :: omp_orig\n" << extra_stuff_array_red << "omp_out = " << as_expression(initializer) << "\n" << "END SUBROUTINE " << fun_name << "\n" ; TL::Scope global_scope = construct.retrieve_context().get_global_scope(); Nodecl::NodeclBase function_code = src.parse_global(global_scope); TL::Symbol function_sym = global_scope.get_symbol_from_name(fun_name); ERROR_CONDITION(!function_sym.is_valid(), "Symbol %s not found", fun_name.c_str()); // As the initializer function is needed during the instantiation of // the task, this function should be inserted before the construct Nodecl::Utils::prepend_to_enclosing_top_level_location(construct, function_code); return function_sym; }
Type Type::fix_references_() { if ((IS_C_LANGUAGE && this->is_any_reference()) || (IS_CXX_LANGUAGE && this->is_rebindable_reference())) { TL::Type ref = this->references_to(); if (ref.is_array()) { // T (&a)[10] -> T * const // T (&a)[10][20] -> T (* const)[20] ref = ref.array_element(); } // T &a -> T * const a TL::Type ptr = ref.get_pointer_to(); if (!this->is_rebindable_reference()) { ptr = ptr.get_const_type(); } return ptr; } else if (IS_FORTRAN_LANGUAGE && this->is_any_reference()) { return this->references_to(); } else if (this->is_array()) { if (this->array_is_region()) { Nodecl::NodeclBase lb, reg_lb, ub, reg_ub; this->array_get_bounds(lb, ub); this->array_get_region_bounds(reg_lb, reg_ub); TL::Scope sc = array_type_get_region_size_expr_context(this->get_internal_type()); return this->array_element().fix_references_().get_array_to_with_region(lb, ub, reg_lb, reg_ub, sc); } else { Nodecl::NodeclBase size = this->array_get_size(); TL::Scope sc = array_type_get_array_size_expr_context(this->get_internal_type()); return this->array_element().fix_references_().get_array_to(size, sc); } } else if (this->is_pointer()) { TL::Type fixed = this->points_to().fix_references_().get_pointer_to(); cv_qualifier_t cv_qualif = CV_NONE; ::advance_over_typedefs_with_cv_qualif(this->get_internal_type(), &cv_qualif); fixed = ::get_cv_qualified_type(fixed.get_internal_type(), cv_qualif); return fixed; } else if (this->is_function()) { // Do not fix unprototyped functions if (this->lacks_prototype()) return (*this); cv_qualifier_t cv_qualif = CV_NONE; ::advance_over_typedefs_with_cv_qualif(this->get_internal_type(), &cv_qualif); ref_qualifier_t ref_qualifier = function_type_get_ref_qualifier(this->get_internal_type()); TL::Type fixed_result = this->returns().fix_references_(); bool has_ellipsis = 0; TL::ObjectList<TL::Type> fixed_parameters = this->parameters(has_ellipsis); for (TL::ObjectList<TL::Type>::iterator it = fixed_parameters.begin(); it != fixed_parameters.end(); it++) { *it = it->fix_references_(); } TL::ObjectList<TL::Type> nonadjusted_fixed_parameters = this->nonadjusted_parameters(); for (TL::ObjectList<TL::Type>::iterator it = nonadjusted_fixed_parameters.begin(); it != nonadjusted_fixed_parameters.end(); it++) { *it = it->fix_references_(); } TL::Type fixed_function = fixed_result.get_function_returning( fixed_parameters, nonadjusted_fixed_parameters, has_ellipsis, ref_qualifier); fixed_function = TL::Type(get_cv_qualified_type(fixed_function.get_internal_type(), cv_qualif)); return fixed_function; } // Note: we are not fixing classes else { // Anything else must be left untouched return (*this); } }