Nodecl::NodeclBase handle_task_statements(
          Nodecl::NodeclBase construct,
          Nodecl::NodeclBase task_statements,
          Nodecl::NodeclBase& task_placeholder, // Do not remove the reference
          TL::Source &new_stmts_src,            // It should be a const reference
          const std::map<TL::Symbol, std::string> &reduction_symbols_map)
    {
       if (IS_FORTRAN_LANGUAGE)
          Source::source_language = SourceLanguage::C;

       Nodecl::NodeclBase new_statements = new_stmts_src.parse_statement(construct);

       if (IS_FORTRAN_LANGUAGE)
          Source::source_language = SourceLanguage::Current;

       TL::Scope new_scope = ReferenceScope(task_placeholder).get_scope();
       std::map<TL::Symbol, Nodecl::NodeclBase> reduction_symbol_to_nodecl_map;
       for (std::map<TL::Symbol, std::string>::const_iterator it = reduction_symbols_map.begin();
             it != reduction_symbols_map.end();
             ++it)
       {
          TL::Symbol reduction_sym = it->first;
          std::string storage_name = it->second;
          TL::Symbol storage_sym = new_scope.get_symbol_from_name(storage_name);
          ERROR_CONDITION(!storage_sym.is_valid(), "This symbol is not valid", 0);

          Nodecl::NodeclBase deref_storage = Nodecl::Dereference::make(
                storage_sym.make_nodecl(/* set_ref_type */ true, storage_sym.get_locus()),
                storage_sym.get_type().points_to());

          reduction_symbol_to_nodecl_map[reduction_sym] = deref_storage;
       }

       ReplaceReductionSymbols visitor(reduction_symbol_to_nodecl_map);
       Nodecl::NodeclBase copied_statements = task_statements.shallow_copy();
       visitor.walk(copied_statements);
       task_placeholder.replace(copied_statements);

       return new_statements;
    }
    static Symbol create_new_function_opencl_allocate(
            Nodecl::NodeclBase expr_stmt,
            Symbol subscripted_symbol,
            Type element_type,
            int num_dimensions,
            bool is_allocatable)
    {
        std::string alloca_or_pointer = is_allocatable ? "ALLOCATABLE" : "POINTER";

        TL::Source dummy_arguments_bounds, dimension_attr, allocate_dims;
        dimension_attr << "DIMENSION(";
        for (int i = 1; i <= num_dimensions; ++i)
        {
            if (i != 1)
            {
                allocate_dims << ", ";
                dummy_arguments_bounds <<", ";
                dimension_attr << ", ";
            }

            dummy_arguments_bounds <<"LB" << i <<", " << "UB" << i;
            dimension_attr << ":";
            allocate_dims << "LB" << i << ":" << "UB" << i;
        }
        dimension_attr << ")";

        size_t size_of_array_descriptor =
            fortran_size_of_array_descriptor(
                    fortran_get_rank0_type(subscripted_symbol.get_type().get_internal_type()),
                    fortran_get_rank_of_type(subscripted_symbol.get_type().get_internal_type()));

        TL::Source new_function_name;
        new_function_name
            << "NANOX_OPENCL_ALLOCATE_INTERNAL_"
            << (ptrdiff_t) subscripted_symbol.get_internal_symbol()
            ;

        Nodecl::NodeclBase nodecl_body;
        TL::Source new_function;
        new_function
            << "SUBROUTINE " << new_function_name << "(ARR, " << dummy_arguments_bounds  << ")\n"
            <<      as_type(element_type) << ", " << dimension_attr << ", " << alloca_or_pointer << " :: ARR\n"
            <<      as_type(element_type) << ", " << dimension_attr << ", ALLOCATABLE :: TMP\n"
            <<      "INTEGER :: " << dummy_arguments_bounds << "\n"
            <<      "INTEGER :: ERR \n"
            <<      "ALLOCATE(TMP(" << allocate_dims << "))\n"
            <<      statement_placeholder(nodecl_body)
            <<      "DEALLOCATE(TMP)\n"
            << "END SUBROUTINE " << new_function_name << "\n"
            ;

        Nodecl::NodeclBase function_code = new_function.parse_global(expr_stmt.retrieve_context().get_global_scope());

        TL::Scope inside_function = ReferenceScope(nodecl_body).get_scope();
        TL::Symbol new_function_sym = inside_function.get_symbol_from_name(strtolower(new_function_name.get_source().c_str()));
        TL::Symbol arr_sym = inside_function.get_symbol_from_name("arr");
        TL::Symbol tmp_sym = inside_function.get_symbol_from_name("tmp");
        TL::Symbol ptr_of_arr_sym = get_function_ptr_of(arr_sym, inside_function);
        TL::Symbol ptr_of_tmp_sym = get_function_ptr_of(tmp_sym, inside_function);

        TL::Source aux;
        aux
            <<  "ERR = NANOS_MEMCPY("
            <<          ptr_of_arr_sym.get_name() << "(ARR),"
            <<          ptr_of_tmp_sym.get_name() << "(TMP),"
            <<          "INT(" << size_of_array_descriptor << "," << type_get_size(get_ptrdiff_t_type()) << "))\n"

            <<  "CALL NANOS_OPENCL_ALLOCATE_FORTRAN("
            <<          "SIZEOF(TMP),"
            <<          ptr_of_arr_sym.get_name() << "(ARR))\n"
            ;

        nodecl_body.replace(aux.parse_statement(inside_function));
        Nodecl::Utils::prepend_to_enclosing_top_level_location(expr_stmt, function_code);

        return new_function_sym;
    }
    void LoweringPhase::fortran_preprocess_api(DTO& dto)
    {
        ERROR_CONDITION(!IS_FORTRAN_LANGUAGE, "This is only for Fortran", 0);

        Nodecl::NodeclBase top_level = *std::static_pointer_cast<Nodecl::NodeclBase>(dto["nodecl"]);

        const char** old_preprocessor_options = CURRENT_CONFIGURATION->preprocessor_options;

        int num_orig_args = count_null_ended_array((void**)old_preprocessor_options);
        int num_args = num_orig_args;

        // -x c
        num_args += 2;

        // NULL ended
        num_args += 1;

        const char** preprocessor_options = new const char*[num_args];

        for (int i = 0;  i < num_orig_args; i++)
        {
            preprocessor_options[i] = old_preprocessor_options[i];
        }

        // We add -x c since we want /dev/null be preprocessed as an empty C file
        // FIXME - This is very gcc specific
        preprocessor_options[num_args - 3] = "-x";
        preprocessor_options[num_args - 2] = "c";
        preprocessor_options[num_args - 1] = NULL;

        CURRENT_CONFIGURATION->preprocessor_options = preprocessor_options;

        const char* output_filename = preprocess_file("/dev/null");

        delete[] preprocessor_options;

        // Restore old flags
        CURRENT_CONFIGURATION->preprocessor_options = old_preprocessor_options;

        TL::Source src;

        std::ifstream preproc_file(output_filename);

        if (preproc_file.is_open())
        {
            std::string str;

            while (preproc_file.good())
            {
                std::getline(preproc_file, str);
                src << str << "\n";
            }
            preproc_file.close();
        }
        else
        {
            fatal_error("Could not open Nanos++ include");
        }

        Source::source_language = SourceLanguage::C;

        Nodecl::NodeclBase new_tree = src.parse_global(top_level);
        // This is actually a top level tree!
        new_tree = Nodecl::TopLevel::make(new_tree);
        // FIXME - keep this?

        Source::source_language = SourceLanguage::Current;
    }
Beispiel #4
0
void LoweringVisitor::visit(const Nodecl::OpenMP::TaskExpression& task_expr)
{
    Nodecl::NodeclBase join_task = task_expr.get_join_task();
    Nodecl::List task_calls = task_expr.get_task_calls().as<Nodecl::List>();

    if (!_lowering->final_clause_transformation_disabled()
            && Nanos::Version::interface_is_at_least("master", 5024))
    {
        ERROR_CONDITION(!task_expr.get_parent().is<Nodecl::ExpressionStatement>(), "Unexpected node", 0);
        Nodecl::NodeclBase expr_stmt = task_expr.get_parent();

        TL::Source code;
        code
            << "{"
            <<      as_type(TL::Type::get_bool_type()) << "mcc_is_in_final;"
            <<      "nanos_err_t mcc_err_in_final = nanos_in_final(&mcc_is_in_final);"
            <<      "if (mcc_err_in_final != NANOS_OK) nanos_handle_error(mcc_err_in_final);"
            <<      "if (mcc_is_in_final)"
            <<      "{"
            <<          as_statement(task_expr.get_sequential_code())
            <<      "}"
            <<      "else"
            <<      "{"
            <<          as_statement(Nodecl::ExpressionStatement::make(task_expr))
            <<      "}"
            << "}"
            ;

        std::cout << "In expression\n";

        if (IS_FORTRAN_LANGUAGE)
            Source::source_language = SourceLanguage::C;

        Nodecl::NodeclBase if_else_tree = code.parse_statement(expr_stmt);

        if (IS_FORTRAN_LANGUAGE)
            Source::source_language = SourceLanguage::Current;

        expr_stmt.replace(if_else_tree);
    }

    Nodecl::NodeclBase placeholder_task_expr_transformation;
    if (join_task.is<Nodecl::OpenMP::Task>())
    {
        // Note: don't walk over the OpenMP::Task node because Its visitor ignores
        // the placeholder and sets to false the 'inside_task_expression' boolean
        visit_task(
                join_task.as<Nodecl::OpenMP::Task>(),
                /* inside_task_expression */ true,
                &placeholder_task_expr_transformation);
    }
    else if (join_task.is<Nodecl::ExpressionStatement>() &&
            join_task.as<Nodecl::ExpressionStatement>().get_nest().is<Nodecl::OpenMP::TaskCall>())
    {
        visit_task_call(
                join_task.as<Nodecl::ExpressionStatement>().get_nest().as<Nodecl::OpenMP::TaskCall>(),
                /* inside_task_expression */ true,
                &placeholder_task_expr_transformation);
    }
    else
    {
        internal_error("Unreachable code", 0);
    }


    // Note: don't walk over the OpenMP::TaskCall because It's visitor sets to
    // false the 'inside_task_expression' boolean
    for (Nodecl::List::iterator it = task_calls.begin();
            it != task_calls.end();
            ++it)
    {
        Nodecl::ExpressionStatement current_expr_stmt = it->as<Nodecl::ExpressionStatement>();
        Nodecl::OpenMP::TaskCall current_task_call = current_expr_stmt.get_nest().as<Nodecl::OpenMP::TaskCall>();

        visit_task_call(current_task_call,
                /* inside_task_expression */ true,
                /* placeholder_task_expr_transformation */ NULL);

        Nodecl::Utils::prepend_items_before(placeholder_task_expr_transformation, *it);
    }

    ERROR_CONDITION(!task_expr.get_parent().is<Nodecl::ExpressionStatement>(), "Unexpected node", 0);
    Nodecl::NodeclBase expr_stmt = task_expr.get_parent();
    Nodecl::Utils::prepend_items_before(expr_stmt, task_expr.get_join_task());

    // Finally, remove from the tree the TaskExpression node
    Nodecl::Utils::remove_from_enclosing_list(expr_stmt);
}