static void tool_initialization(int argc, const char* argv[]) { atexit(cleanup_routine); #if !defined(WIN32_BUILD) || defined(__CYGWIN__) // Define alternate stack stack_t alternate_stack; // Allocate a maximum of 1 Mbyte or more if MINSIGSTKSZ was // bigger than that (this is unlikely) int allocated_size = 1024 * 1024; if (MINSIGSTKSZ > 1024*1024) { allocated_size = MINSIGSTKSZ; } _alternate_signal_stack = malloc(allocated_size); alternate_stack.ss_flags = 0; alternate_stack.ss_size = allocated_size; alternate_stack.ss_sp = (void*)_alternate_signal_stack; if (alternate_stack.ss_sp == 0 || sigaltstack(&alternate_stack, /* oss */ NULL) != 0) { running_error("Setting alternate signal stack failed (%s)\n", strerror(errno)); } // Program signals struct sigaction terminating_sigaction; memset(&terminating_sigaction, 0, sizeof(terminating_sigaction)); terminating_sigaction.sa_handler = terminating_signal_handler; // Use alternate stack and we want the signal be reset when it happens terminating_sigaction.sa_flags = SA_RESETHAND | SA_ONSTACK; // Block all blockable signals while handling the termination sigfillset(&terminating_sigaction.sa_mask); int result = 0; result |= sigaction(SIGSEGV, &terminating_sigaction, /* old_sigaction */ NULL); result |= sigaction(SIGQUIT, &terminating_sigaction, /* old_sigaction */ NULL); result |= sigaction(SIGINT, &terminating_sigaction, /* old_sigaction */ NULL); result |= sigaction(SIGTERM, &terminating_sigaction, /* old_sigaction */ NULL); result |= sigaction(SIGABRT, &terminating_sigaction, /* old_sigaction */ NULL); if (result != 0) { running_error("Signal programming failed with '%s'\n", strerror(errno)); } #endif memset(&compilation_process, 0, sizeof(compilation_process)); compilation_process.argc = argc; compilation_process.argv = (const char**)argv; compilation_process.exec_basename = give_basename(argv[0]); // Find my own directory compilation_process.home_directory = find_home(argv[0]); }
static void open_files(prescanner_t* prescanner) { if (strcmp(prescanner->input_filename, "-") != 0) { prescanner->input_file = fopen(prescanner->input_filename, "r"); if (prescanner->input_file == NULL) { running_error("Cannot open input file '%s' (%s)\n", prescanner->input_filename, strerror(errno)); } } else { prescanner->input_file = stdin; prescanner->input_filename = "(stdin)"; } if (strcmp(prescanner->output_filename, "-") != 0) { prescanner->output_file = fopen(prescanner->output_filename, "w"); if (prescanner->output_file == NULL) { running_error("Cannot open output file '%s' (%s)\n", prescanner->output_filename, strerror(errno)); } } else { prescanner->output_file = stdout; prescanner->output_filename = "(stdout)"; } }
void Interface::interface_preorder(PragmaCustomConstruct ctr) { PragmaCustomClause version_clause = ctr.get_clause("version"); PragmaCustomClause family_clause = ctr.get_clause("family"); // The runtime must provide always a pair of Family/Version, never only one of them if (family_clause.is_defined() && !family_clause.get_arguments(ExpressionTokenizer()).empty() && version_clause.is_defined() && !version_clause.get_arguments(ExpressionTokenizer()).empty()) { std::string new_family = family_clause.get_arguments(ExpressionTokenizer())[0]; if (Version::_interfaces.find(new_family) != Version::_interfaces.end() && (new_family != Version::DEFAULT_FAMILY || Version::_interfaces[new_family] != Version::DEFAULT_VERSION)) { std::stringstream ss; ss << Version::_interfaces[family_clause.get_arguments(ExpressionTokenizer())[0]]; running_error("error: Nanos family %s previously defined with version %s\n", family_clause.get_arguments(ExpressionTokenizer())[0].c_str(), ss.str().c_str()); } else { Version::_interfaces[family_clause.get_arguments(ExpressionTokenizer())[0]] = atoi(version_clause.get_arguments(ExpressionTokenizer())[0].c_str()); } } else { running_error("error: Both, family and version must be provided by the runtime.\n"); } }
void KNCModuleVisitor::visit(const Nodecl::VectorBitwiseXor& node) { TL::Type type = node.get_type().basic_type(); // Intrinsic name file << "_mm512_xor"; // Postfix if (type.is_float()) { file << "_ps"; } else if (type.is_integral_type()) { file << "_si128"; } else { running_error("KNC Codegen: Node %s at %s has an unsupported type.", ast_print_node_type(node.get_kind()), node.get_locus_str().c_str()); } file << "("; walk(node.get_lhs()); file << ", "; walk(node.get_rhs()); file << ")"; }
static char* read_whole_line(FILE* input) { // It should be enough int buffer_size = 1024; int was_eof; int length_read; char* temporal_buffer = xcalloc(buffer_size, sizeof(char)); // We read buffer_size-1 characters if (fgets(temporal_buffer, buffer_size, input) == NULL) { if (ferror(input)) { running_error("error: while starting to split file\n"); } } if (temporal_buffer[0] == '\0') { xfree(temporal_buffer); return NULL; } length_read = strlen(temporal_buffer); was_eof = feof(input); while ((temporal_buffer[length_read - 1] != '\n') && !was_eof) { temporal_buffer = xrealloc(temporal_buffer, 2*sizeof(char)*buffer_size); if (fgets(&temporal_buffer[length_read], buffer_size, input) == NULL) { if (ferror(input)) { running_error("error: while splitting file\n"); } } length_read = strlen(temporal_buffer); buffer_size = buffer_size * 2; was_eof = feof(input); } return temporal_buffer; }
void OpenMPTransform::critical_postorder(PragmaCustomConstruct critical_construct) { Source critical_source; Statement critical_body = critical_construct.get_statement(); ScopeLink scope_link = critical_construct.get_scope_link(); std::string mutex_variable; if (!critical_construct.is_parameterized()) { mutex_variable = "_nthf_unspecified_critical"; } else { // ObjectList<IdExpression> id_expressions = region_name.id_expressions(TL::ALL_FOUND_SYMBOLS); // IdExpression head = id_expressions[0]; ObjectList<std::string> args = critical_construct.get_parameter_arguments(); if (args.size() > 1) { std::cerr << critical_construct.get_ast().get_locus() << ": warning: #pragma omp critical only receives one argument, using first one" << std::endl; } else if (args.size() == 0) { running_error("%s: error: #pragma omp critical needs an argument", critical_construct.get_ast().get_locus().c_str()); } mutex_variable = "_nthf_" + args[0]; } critical_source << "{" // << "extern void nthf_spin_lock_(void*);" // << "extern void nthf_spin_unlock_(void*);" << "nthf_spin_lock_(&" << mutex_variable << ");" << critical_body.prettyprint() << "nthf_spin_unlock_(&" << mutex_variable << ");" << "}" ; define_global_mutex(mutex_variable, critical_construct.get_ast(), critical_construct.get_scope_link()); AST_t critical_tree = critical_source.parse_statement(critical_construct.get_ast(), critical_construct.get_scope_link()); critical_construct.get_ast().replace(critical_tree); }
void KNCModuleVisitor::visit(const Nodecl::VectorMinus& node) { TL::Type type = node.get_type().basic_type(); // Intrinsic name file << "_mm512_sub"; // Postfix if (type.is_float()) { file << "_ps"; } else if (type.is_double()) { file << "_pd"; } else if (type.is_signed_int() || type.is_unsigned_int()) { file << "_epi32"; } else if (type.is_signed_short_int() || type.is_unsigned_short_int()) { file << "_epi16"; } else if (type.is_char() || type.is_signed_char() || type.is_unsigned_char()) { file << "_epi8"; } else { running_error("KNC Codegen: Node %s at %s has an unsupported type.", ast_print_node_type(node.get_kind()), node.get_locus_str().c_str()); } file << "("; walk(node.get_lhs()); file << ", "; walk(node.get_rhs()); file << ")"; }
static void remove_inlined_comments(void) { line_t* iter = file_lines; char unended_string; while (iter != NULL) { // Getting here that a string is unended // would be a scanning error trim_inline_comment(iter, &unended_string); if (unended_string != 0) { running_error("%s:%d: error: unended string at line %d !\n", prescanner->input_filename, iter->line_number); } iter = iter->next; } }
Nodecl::NodeclBase Source::parse_common(ReferenceScope ref_scope, ParseFlags parse_flags, const std::string& subparsing_prefix, prepare_lexer_fun_t prepare_lexer, parse_fun_t parse, compute_nodecl_fun_t compute_nodecl, decl_context_map_fun_t decl_context_map_fun) { source_language_t kept_language; switch_language(kept_language); std::string extended_source = "\n" + this->get_source(true); std::string mangled_text = subparsing_prefix + extended_source; prepare_lexer(mangled_text.c_str()); int parse_result = 0; AST a = NULL; parse_result = parse(&a); if (parse_result != 0) { running_error("Could not parse source\n\n%s\n", format_source(extended_source).c_str()); } decl_context_t decl_context = decl_context_map_fun(ref_scope.get_scope().get_decl_context()); nodecl_t nodecl_output = nodecl_null(); compute_nodecl(a, decl_context, &nodecl_output); restore_language(kept_language); return nodecl_output; }
void AST_t::prettyprint_in_file(const CompiledFile& compiled_file, bool internal) const { if (!internal) { prettyprint_set_not_internal_output(); } else { prettyprint_set_internal_output(); } FILE *file = fopen(compiled_file.get_filename().c_str(), "a"); if (file == NULL) { running_error("Could not open output file '%s' (%s)\n", compiled_file.get_filename().c_str(), strerror(errno)); } ::prettyprint(file, this->_ast); fclose(file); }
void OpenMPTransform::ordered_postorder(PragmaCustomConstruct ordered_construct) { running_error("%s: error: '#pragma omp ordered' is not supported", ordered_construct.get_ast().get_locus().c_str()); /* Symbol induction_var = induction_var_stack.top(); Statement construct_body = ordered_construct.get_statement(); Source ordered_source; ordered_source << "{" << "in__tone_enter_ordered_ (& "<< induction_var.get_name() << ");" << construct_body.prettyprint() << "in__tone_leave_ordered_ (&" << induction_var.get_name() << ");" << "}" ; AST_t ordered_code = ordered_source.parse_statement(ordered_construct.get_ast(), ordered_construct.get_scope_link()); ordered_construct.get_ast().replace(ordered_code); */ }
void Core::collapse_loop_first(PragmaCustomConstruct& construct) { PragmaCustomClause collapse = construct.get_clause("collapse"); if (!collapse.is_defined()) return; ObjectList<Expression> expr_list = collapse.get_expression_list(); if (expr_list.size() != 1) { running_error("%s: error: 'collapse' clause must have one argument\n", construct.get_ast().get_locus().c_str()); } Expression &expr = expr_list.front(); if (!expr.is_constant()) { running_error("%s: error: 'collapse' clause argument '%s' is not a constant expression\n", expr.get_ast().get_locus().c_str(), expr.prettyprint().c_str()); } bool valid; int nest_level = expr.evaluate_constant_int_expression(valid); if (!valid) { running_error("%s: error: 'collapse' clause argument '%s' is not a constant expression\n", expr.get_ast().get_locus().c_str(), expr.prettyprint().c_str()); } if (nest_level <= 0) { running_error("%s: error: nesting level of 'collapse' clause must be a nonzero positive integer\n", expr.get_ast().get_locus().c_str()); } if (!ForStatement::predicate(construct.get_statement().get_ast())) { running_error("%s: error: collapsed '#pragma omp for' or '#pragma omp parallel for' require a for-statement\n", construct.get_statement().get_ast().get_locus().c_str()); } ForStatement for_stmt(construct.get_statement().get_ast(), construct.get_scope_link()); HLT::LoopCollapse loop_collapse(for_stmt); ObjectList<std::string> ancillary_names; Source header; loop_collapse .set_nesting_level(nest_level) .set_split_transform(header) .set_induction_private(true) .keep_ancillary_names(ancillary_names); Source collapsed_for = loop_collapse; Source transformed_code; AST_t pragma_placeholder; transformed_code << "{" << header << statement_placeholder(pragma_placeholder) << "}" ; AST_t tree = transformed_code.parse_statement(construct.get_ast(), construct.get_scope_link()); Source new_firstprivate_entities; Source pragma_line; Source omp_part_src; omp_part_src << "#pragma omp " << pragma_line << new_firstprivate_entities << "\n" << collapsed_for ; new_firstprivate_entities << "firstprivate(" << concat_strings(ancillary_names, ",") << ")"; pragma_line << construct.get_pragma_line().prettyprint_with_callback(functor(remove_collapse_clause)); AST_t omp_part_tree = omp_part_src.parse_statement(pragma_placeholder, construct.get_scope_link()); // Replace the pragma part pragma_placeholder.replace(omp_part_tree); // Replace the whole construct construct.get_ast().replace(tree); // Now overwrite the old construct with this new one construct = PragmaCustomConstruct(pragma_placeholder, construct.get_scope_link()); }
void fortran_split_lines(FILE* input, FILE* output, int width) { ERROR_CONDITION(width <= 0, "Invalid width = %d\n", width); int length; char* line; while ((line = read_whole_line(input)) != NULL) { // We must remove trailing spaces before "\n" (if any) // since we cannot continuate to an empty line trim_right_line(line); // Comments that will reach here are those created within the compiler // (e.g. TPL) because scanner always trims them char prefix[33] = { 0 }; char is_construct = check_for_construct(line, prefix, 32); char is_comment = check_for_comment(line); length = strlen(line); // Many times we will fall here by means of length <= width if ((length <= width)) { fputs(line, output); } else if (is_construct) { // Do not complicate ourselves, rely on a double continuation int column = 1; double_continuate_construct(output, prefix, line, width, &column); fprintf(output, "\n"); } else if (is_comment) { fputs(line, output); } else { int column, next_column; char* position; char* next_position; YY_BUFFER_STATE scan_line = mf03_scan_string(line); mf03_switch_to_buffer(scan_line); // Initialize stuff column = 1; position = line; // Scan int token = mf03lex(); while (token != EOS) { // Find the token as there can be spaces // next_position has the first character of the token next_position = strstr(position, mf03lval.token_atrib.token_text); if (next_position == NULL) { running_error("Serious problem when splitting line:\n\n %s", line); } // Next column has the column where the token will start next_column = column + (next_position - position); // Check if we have reached the last column or if spaces plus // token will not fit in this line if (column == width || (next_column + (int)strlen(mf03lval.token_atrib.token_text) >= width)) { DEBUG_CODE() DEBUG_MESSAGE("Cutting at '%s'", mf03lval.token_atrib.token_text); // Nothing fits here already fprintf(output, "&\n"); column = 1; } // Write the blanks char* c; for (c = position; c < next_position; c++) { DEBUG_CODE() DEBUG_MESSAGE("%d - Blank - '%c'", column, *c); fprintf(output, "%c", *c); column++; } if ((column + (int)strlen(mf03lval.token_atrib.token_text)) >= width) { // We are very unlucky, the whole token still does not fit // in this line ! double_continuate(output, mf03lval.token_atrib.token_text, width, &column); } else { // Write the token DEBUG_CODE() DEBUG_MESSAGE("%d - Token '%s'", column, mf03lval.token_atrib.token_text); fprintf(output, "%s", mf03lval.token_atrib.token_text); column += strlen(mf03lval.token_atrib.token_text); } // Update state to be coherent before entering the next iteration // column has been updated before position = next_position + strlen(mf03lval.token_atrib.token_text); token = mf03lex(); } // The EOS fprintf(output, "\n"); mf03_delete_buffer(scan_line); } xfree(line); } }
void LoweringVisitor::reduction_initialization_code( OutlineInfo& outline_info, Nodecl::NodeclBase ref_tree, Nodecl::NodeclBase construct) { ERROR_CONDITION(ref_tree.is_null(), "Invalid tree", 0); if (!Nanos::Version::interface_is_at_least("master", 5023)) { running_error("%s: error: a newer version of Nanos++ (>=5023) is required for reductions support\n", construct.get_locus_str().c_str()); } TL::ObjectList<OutlineDataItem*> reduction_items = outline_info.get_data_items().filter( predicate(lift_pointer(functor(&OutlineDataItem::is_reduction)))); ERROR_CONDITION (reduction_items.empty(), "No reductions to process", 0); Source result; Source reduction_declaration, thread_initializing_reduction_info, thread_fetching_reduction_info; result << reduction_declaration << "{" << as_type(get_bool_type()) << " red_single_guard;" << "nanos_err_t err;" << "err = nanos_enter_sync_init(&red_single_guard);" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << "if (red_single_guard)" << "{" << "int nanos_num_threads = nanos_omp_get_num_threads();" << thread_initializing_reduction_info << "err = nanos_release_sync_init();" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << "}" << "else" << "{" << "err = nanos_wait_sync_init();" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << thread_fetching_reduction_info << "}" << "}" ; for (TL::ObjectList<OutlineDataItem*>::iterator it = reduction_items.begin(); it != reduction_items.end(); it++) { std::string nanos_red_name = "nanos_red_" + (*it)->get_symbol().get_name(); std::pair<OpenMP::Reduction*, TL::Type> reduction_info = (*it)->get_reduction_info(); OpenMP::Reduction* reduction = reduction_info.first; TL::Type reduction_type = reduction_info.second; if (reduction_type.is_any_reference()) reduction_type = reduction_type.references_to(); TL::Type reduction_element_type = reduction_type; if (IS_FORTRAN_LANGUAGE) { while (reduction_element_type.is_fortran_array()) reduction_element_type = reduction_element_type.array_element(); } else { while (reduction_element_type.is_array()) reduction_element_type = reduction_element_type.array_element(); } Source element_size; if (IS_FORTRAN_LANGUAGE) { if (reduction_type.is_fortran_array()) { // We need to parse this bit in Fortran Source number_of_bytes; number_of_bytes << "SIZE(" << (*it)->get_symbol().get_name() << ") * " << reduction_element_type.get_size(); element_size << as_expression(number_of_bytes.parse_expression(construct)); } else { element_size << "sizeof(" << as_type(reduction_type) << ")"; } } else { element_size << "sizeof(" << as_type(reduction_type) << ")"; } reduction_declaration << "nanos_reduction_t* " << nanos_red_name << ";" ; Source allocate_private_buffer, cleanup_code; Source num_scalars; TL::Symbol basic_reduction_function, vector_reduction_function; create_reduction_function(reduction, construct, reduction_type, basic_reduction_function, vector_reduction_function); (*it)->reduction_set_basic_function(basic_reduction_function); thread_initializing_reduction_info << "err = nanos_malloc((void**)&" << nanos_red_name << ", sizeof(nanos_reduction_t), " << "\"" << construct.get_filename() << "\", " << construct.get_line() << ");" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << nanos_red_name << "->original = (void*)" << (reduction_type.is_array() ? "" : "&") << (*it)->get_symbol().get_name() << ";" << allocate_private_buffer << nanos_red_name << "->vop = " << (vector_reduction_function.is_valid() ? as_symbol(vector_reduction_function) : "0") << ";" << nanos_red_name << "->bop = (void(*)(void*,void*,int))" << as_symbol(basic_reduction_function) << ";" << nanos_red_name << "->element_size = " << element_size << ";" << nanos_red_name << "->num_scalars = " << num_scalars << ";" << cleanup_code << "err = nanos_register_reduction(" << nanos_red_name << ");" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" ; if (IS_C_LANGUAGE || IS_CXX_LANGUAGE) { if (reduction_type.is_array()) { num_scalars << "sizeof(" << as_type(reduction_type) << ") / sizeof(" << as_type(reduction_element_type) <<")"; } else { num_scalars << "1"; } allocate_private_buffer << "err = nanos_malloc(&" << nanos_red_name << "->privates, sizeof(" << as_type(reduction_type) << ") * nanos_num_threads, " << "\"" << construct.get_filename() << "\", " << construct.get_line() << ");" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << nanos_red_name << "->descriptor = " << nanos_red_name << "->privates;" << "rdv_" << (*it)->get_field_name() << " = (" << as_type( (*it)->get_private_type().get_pointer_to() ) << ")" << nanos_red_name << "->privates;" ; thread_fetching_reduction_info << "err = nanos_reduction_get(&" << nanos_red_name << ", " << (reduction_type.is_array() ? "" : "&") << (*it)->get_symbol().get_name() << ");" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << "rdv_" << (*it)->get_field_name() << " = (" << as_type( (*it)->get_private_type().get_pointer_to() ) << ")" << nanos_red_name << "->privates;" ; cleanup_code << nanos_red_name << "->cleanup = nanos_free0;" ; } else if (IS_FORTRAN_LANGUAGE) { Type private_reduction_vector_type; Source extra_dims; { TL::Type t = (*it)->get_symbol().get_type().no_ref(); int rank = 0; if (t.is_fortran_array()) { rank = t.fortran_rank(); } if (rank != 0) { // We need to parse this bit in Fortran Source size_call; size_call << "SIZE(" << (*it)->get_symbol().get_name() << ")"; num_scalars << as_expression(size_call.parse_expression(construct)); } else { num_scalars << "1"; } private_reduction_vector_type = fortran_get_n_ranked_type_with_descriptor( get_void_type(), rank + 1, construct.retrieve_context().get_decl_context()); int i; for (i = 0; i < rank; i++) { Source lbound_src; lbound_src << "LBOUND(" << (*it)->get_symbol().get_name() << ", DIM = " << (rank - i) << ")"; Source ubound_src; ubound_src << "UBOUND(" << (*it)->get_symbol().get_name() << ", DIM = " << (rank - i) << ")"; extra_dims << "[" << as_expression(lbound_src.parse_expression(construct)) << ":" << as_expression(ubound_src.parse_expression(construct)) << "]"; t = t.array_element(); } } allocate_private_buffer << "@FORTRAN_ALLOCATE@((*rdv_" << (*it)->get_field_name() << ")[0:(nanos_num_threads-1)]" << extra_dims <<");" << nanos_red_name << "->privates = &(*rdv_" << (*it)->get_field_name() << ");" << "err = nanos_malloc(&" << nanos_red_name << "->descriptor, sizeof(" << as_type(private_reduction_vector_type) << "), " << "\"" << construct.get_filename() << "\", " << construct.get_line() << ");" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << "err = nanos_memcpy(" << nanos_red_name << "->descriptor, " "&rdv_" << (*it)->get_field_name() << ", sizeof(" << as_type(private_reduction_vector_type) << "));" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" ; thread_fetching_reduction_info << "err = nanos_reduction_get(&" << nanos_red_name << ", &" << (*it)->get_symbol().get_name() << ");" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" << "err = nanos_memcpy(" << "&rdv_" << (*it)->get_field_name() << "," << nanos_red_name << "->descriptor, " << "sizeof(" << as_type(private_reduction_vector_type) << "));" << "if (err != NANOS_OK)" << "nanos_handle_error(err);" ; TL::Symbol reduction_cleanup = create_reduction_cleanup_function(reduction, construct); cleanup_code << nanos_red_name << "->cleanup = " << as_symbol(reduction_cleanup) << ";" ; } else { internal_error("Code unreachable", 0); } } FORTRAN_LANGUAGE() { Source::source_language = SourceLanguage::C; } ref_tree.replace(result.parse_statement(ref_tree)); FORTRAN_LANGUAGE() { Source::source_language = SourceLanguage::Current; } }
static void manage_included_file( prescanner_t* prescanner, char* included_filename, FILE** handle_included_file, FILE** handle_output_file) { *handle_included_file = NULL; *handle_output_file = NULL; int i; for (i = 0; i < prescanner->num_include_directories; i++) { FILE* handle; char* full_name = xcalloc(strlen(prescanner->include_directories[i]) + strlen("/") + strlen(included_filename) + 1, sizeof(char)); strcat(full_name, prescanner->include_directories[i]); strcat(full_name, "/"); strcat(full_name, included_filename); handle = fopen(full_name, "r"); if (handle != NULL) { prescanner->input_filename = full_name; // We got to open the include then create the output filename // // If the user specified a directory for include regeneration use it // otherwise use the original directory of this include char* full_output_name; if (prescanner->output_include_directory == NULL) { full_output_name = xcalloc(strlen(prescanner->include_directories[i]) + strlen("/"INCLUDES_PREFIX) + strlen(included_filename) + 1, sizeof(char)); strcat(full_output_name, prescanner->include_directories[i]); strcat(full_output_name, "/"INCLUDES_PREFIX); strcat(full_output_name, included_filename); } else { full_output_name = xcalloc(strlen(prescanner->output_include_directory) + strlen("/"INCLUDES_PREFIX) + strlen(included_filename) + 1, sizeof(char)); strcat(full_output_name, prescanner->output_include_directory); strcat(full_output_name, "/"INCLUDES_PREFIX); strcat(full_output_name, included_filename); } FILE* handle_output; handle_output = fopen(full_output_name, "w"); if (handle_output == NULL) { running_error("Cannot open output of included file '%s' (%s)\n", full_output_name, strerror(errno)); } *handle_included_file = handle; *handle_output_file = handle_output; return; } xfree(full_name); } }
static void read_lines(prescanner_t* prescanner) { int line_number = 1; while (!feof(prescanner->input_file)) { // We will start with a width + 10 buffer size int buffer_size = prescanner->width + 10; char* line_buffer = (char*)xcalloc(buffer_size, sizeof(char)); // Read till '\n' or till buffer_size-1 if (fgets(line_buffer, buffer_size, prescanner->input_file) == NULL) { if (ferror(prescanner->input_file)) { running_error("error while reading line"); } } // How many characters have we read int length_read = strlen(line_buffer); // Have we read all the line ? (we could have reach the end of the file ...) char was_eof = feof(prescanner->input_file); // The line is not '\n'-ended and we are not in the EOF // so we must enlarge the buffer while ((length_read > 0) && line_buffer[length_read-1] != '\n' && !was_eof) { DEBUG_CODE() { fprintf(stderr, "DEBUG: Enlarging after having read @%s|\n", line_buffer); } // Enlarge exponentially line_buffer = (char*) xrealloc(line_buffer, 2*buffer_size*sizeof(char)); // We read from the former end if (fgets(&line_buffer[length_read], buffer_size, prescanner->input_file) == NULL) { if (ferror(prescanner->input_file)) { running_error("error while reading line"); } } buffer_size = buffer_size * 2; length_read = strlen(line_buffer); was_eof = feof(prescanner->input_file); } // Remove '\n' if (!was_eof) { line_buffer[length_read-1] = '\0'; length_read--; } if (length_read > 0) { // We found \r\n, kill the '\r' as well if (line_buffer[length_read-1] == '\r') { line_buffer[length_read-1] = '\0'; length_read--; } } if (is_blank_string(line_buffer)) { // Merrily ignore this line xfree(line_buffer); } else { line_t* new_line = (line_t*) xcalloc(1, sizeof(line_t)); DEBUG_CODE() { fprintf(stderr, "DEBUG: We have read @%s|\n", line_buffer); } new_line->line = line_buffer; new_line->line_number = line_number; new_line->next = NULL; new_line->joined_lines = 0; if (file_lines == NULL) { file_lines = new_line; last_line = new_line; } else { last_line->next = new_line; last_line = new_line; } } line_number++; } }
static void join_continuated_lines(prescanner_t* prescanner) { int code; line_t* iter = file_lines; regex_t match_continuated; line_t* previous_line = NULL; // First we prepare a regex to match continuated lines if ((code = regcomp(&match_continuated, "^(([ ]{5})|(![$](omp))|(![$][ ]{3}))[^0[:blank:]]", REG_EXTENDED | REG_NOSUB | REG_ICASE)) != 0) { char error_message[120]; regerror(code, &match_continuated, error_message, 120); internal_error("Error when compiling regular expression (%s)\n", error_message); } while (iter != NULL) { if (regexec(&match_continuated, iter->line, 0, NULL, 0) == 0) { if (previous_line == NULL) { running_error("%s:%d: error: cannot continuate the first non-comment line", prescanner->input_filename, iter->line_number); } // Pay attention to not to b0rk 'iter' join_two_lines(prescanner, previous_line, iter); line_t* old_line = iter; iter = iter->next; xfree_line_t(old_line); } else // Not a continuating one { char ignored_line = 1; if (iter->line[0] == '!') { // We spring over this comment unless it is a coco line or an omp line if ((strncmp(iter->line, "!$ ", 3) == 0) || (strncasecmp(iter->line, "!$omp", 5) == 0)) { ignored_line = 0; } } else { ignored_line = 0; } if (!ignored_line) { // It could have an annoying zero if (iter->line[5] == '0') { iter->line[5] = ' '; } previous_line = iter; } iter = iter->next; } } regfree(&match_continuated); }
static void handle_include_line( prescanner_t* prescanner, line_t* iter, regmatch_t *sub_matching) { static int maximum_nesting_level = 0; // We save current information line_t* current_file_lines = file_lines; line_t* current_last_line = last_line; FILE* current_input_file = prescanner->input_file; FILE* current_output_file = prescanner->output_file; const char* current_filename = prescanner->input_filename; if (maximum_nesting_level > 99) { running_error("%s:%d: error: too many levels of nesting (> %d)", prescanner->input_filename, iter->line_number, maximum_nesting_level); } maximum_nesting_level++; // Get the filename char* included_filename = get_filename_include(iter->line, sub_matching); char* new_included_filename = create_new_filename(included_filename); char* fortran_literal_filename = fortran_literal(new_included_filename); // We replace the include with the new file iter->line[0] = '\0'; strcat(iter->line, " INCLUDE \""); strcat(iter->line, fortran_literal_filename); strcat(iter->line, "\""); DEBUG_CODE() { fprintf(stderr, "DEBUG: INCLUDE LINE-> Opening file '%s'\n", included_filename); } manage_included_file(prescanner, included_filename, &prescanner->input_file, &prescanner->output_file); if (prescanner->input_file == NULL) { running_error("%s:%d: error: cannot open included file '%s' (%s)\n", prescanner->input_filename, iter->line_number, included_filename, strerror(errno)); } // Now, recursive processing fortran_prescanner_process(prescanner); xfree(included_filename); xfree(new_included_filename); xfree(fortran_literal_filename); maximum_nesting_level--; // We restore saved information file_lines = current_file_lines; last_line = current_last_line; prescanner->input_filename = current_filename; prescanner->input_file = current_input_file; prescanner->output_file = current_output_file; }
void VectorizerVisitorExpression::visit(const Nodecl::FunctionCall& n) { Nodecl::NodeclBase called = n.get_called(); ERROR_CONDITION(!called.is<Nodecl::Symbol>(), "Vectorizer: %s found. This kind of function call is not supported yet", ast_print_node_type(called.get_kind())); Nodecl::Symbol called_sym = called.as<Nodecl::Symbol>(); // Vectorizing arguments walk(n.get_arguments()); // Special functions if (called_sym.get_symbol().get_name() == "fabsf") { const Nodecl::VectorFabs vector_fabs_call = Nodecl::VectorFabs::make( n.get_arguments().as<Nodecl::List>().front().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_fabs_call); } else //Common functions { // Get the best vector version of the function available Nodecl::NodeclBase best_version = TL::Vectorization::Vectorizer::_function_versioning.get_best_version( called_sym.get_symbol().get_name(), _device, _vector_length, _target_type); ERROR_CONDITION(best_version.is_null(), "Vectorizer: the best vector function for '%s' is null", called_sym.get_symbol().get_name().c_str()); // Create new called symbol Nodecl::Symbol new_called; if (best_version.is<Nodecl::FunctionCode>()) { new_called = best_version.as<Nodecl::FunctionCode>().get_symbol(). make_nodecl(n.get_locus()); } else if (best_version.is<Nodecl::Symbol>()) { new_called = best_version.as<Nodecl::Symbol>().get_symbol(). make_nodecl(n.get_locus()); } else { running_error("Vectorizer: %s found as vector function version in function versioning.", ast_print_node_type(best_version.get_kind())); } const Nodecl::VectorFunctionCall vector_function_call = Nodecl::VectorFunctionCall::make( new_called, n.get_arguments().shallow_copy(), n.get_alternate_name().shallow_copy(), n.get_function_form().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_function_call); } }
void VectorizerVisitorExpression::visit(const Nodecl::Symbol& n) { TL::Type sym_type = n.get_type(); //std::cerr << "scalar_type: " << n.prettyprint() << std::endl; if (!sym_type.is_vector()) { // Vectorize BASIC induction variable if (Vectorizer::_analysis_info->is_basic_induction_variable( Vectorizer::_analysis_scopes->back(), n)) { std::cerr << "Basic IV: " << n.prettyprint() << "\n"; // Computing IV offset {0, 1, 2, 3} TL::ObjectList<Nodecl::NodeclBase> literal_list; const_value_t *ind_var_increment = Vectorizer::_analysis_info->get_induction_variable_increment( Vectorizer::_analysis_scopes->back(), n); for(const_value_t *i = const_value_get_zero(4, 0); const_value_is_nonzero(const_value_lt(i, const_value_get_unsigned_int(_unroll_factor))); i = const_value_add(i, ind_var_increment)) { literal_list.prepend(const_value_to_nodecl(i)); } Nodecl::List offset = Nodecl::List::make(literal_list); // IV cannot be a reference TL::Type ind_var_type = get_qualified_vector_to(n.get_type(), _vector_length).no_ref(); TL::Type offset_type = ind_var_type; Nodecl::ParenthesizedExpression vector_induction_var = Nodecl::ParenthesizedExpression::make( Nodecl::VectorAdd::make( Nodecl::VectorPromotion::make( n.shallow_copy(), ind_var_type, n.get_locus()), Nodecl::VectorLiteral::make( offset, offset_type, n.get_locus()), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_induction_var); } // Vectorize symbols declared in the SIMD scope else if (is_declared_in_scope( _simd_inner_scope.get_decl_context().current_scope, n.get_symbol().get_scope().get_decl_context().current_scope)) { //std::cerr << "NS scalar_type: " << n.prettyprint() << std::endl; TL::Symbol tl_sym = n.get_symbol(); TL::Type tl_sym_type = tl_sym.get_type(); //TL::Symbol if (tl_sym_type.is_scalar_type()) { //std::cerr << "TS scalar_type: " << n.prettyprint() << std::endl; tl_sym.set_type(get_qualified_vector_to(tl_sym_type, _vector_length)); tl_sym_type = tl_sym.get_type(); } //Nodecl::Symbol Nodecl::Symbol new_sym = Nodecl::Symbol::make(tl_sym, n.get_locus()); new_sym.set_type(tl_sym_type.get_lvalue_reference_to()); n.replace(new_sym); } // Vectorize constants else if (Vectorizer::_analysis_info->is_constant( Vectorizer::_analysis_scopes->back(), n)) { const Nodecl::VectorPromotion vector_prom = Nodecl::VectorPromotion::make( n.shallow_copy(), get_qualified_vector_to(sym_type, _vector_length), n.get_locus()); n.replace(vector_prom); } else { //TODO: If you are from outside of the loop -> Vector local copy. running_error("Vectorizer: Loop is not vectorizable. '%s' is not IV or Constant or Local.", n.get_symbol().get_name().c_str()); } } }