private static bool GenerateOMPParallelForCall(statement_node body, SyntaxTree.for_node for_node, var_definition_node loop_variable, statements_list omp_stmts, syntax_tree_visitor syntax_tree_visitor, expression_node fromInclusive, expression_node toInclusive) { SyntaxTree.statement syntax_body = for_node.statements; expression_node omp_call = null; base_function_call bfc = body as base_function_call; if (bfc != null && bfc.parameters.Count == 1 && bfc.parameters[0] is variable_reference && ((variable_reference)bfc.parameters[0]).VariableDefinition == loop_variable && ((bfc.function.parameters[0].type as type_node).PrintableName.ToLower() == "integer")) { //если тело цикла - вызов функции с одни параметром - переменной цикла, //если при этом у вызываемой функции тип параметра - integer, а не какой-нибудь object, как это бывает с write и вообще может быть с перегрузкой //то генерировать класс не надо. //генерируем вызов и все omp_call = syntax_tree_visitor.CreateDelegateCall(bfc); if (omp_call == null) { syntax_tree_visitor.AddWarning(new OMP_ConstructionNotSupportedNow(body.location)); syntax_tree_visitor.convertion_data_and_alghoritms.statement_list_stack_pop(); return false; } base_function_call omp_parallel_for_call = null; if (SystemLibrary.SystemLibInitializer.OMP_ParallelFor.sym_info is common_namespace_function_node) omp_parallel_for_call = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.OMP_ParallelFor.sym_info as common_namespace_function_node, body.location); else omp_parallel_for_call = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.OMP_ParallelFor.sym_info as compiled_function_node, body.location); omp_parallel_for_call.parameters.AddElement(fromInclusive); omp_parallel_for_call.parameters.AddElement(toInclusive); omp_parallel_for_call.parameters.AddElement(omp_call); omp_stmts.statements.AddElement(omp_parallel_for_call); } else { //ищем используемые переменные, получаем редукцию из директивы и составляем список переменных по типам VarFinderSyntaxVisitor VFvis = new VarFinderSyntaxVisitor(syntax_body, syntax_tree_visitor.context, true); SyntaxTree.compiler_directive dir = syntax_tree_visitor.DirectivesToNodesLinks[for_node]; //if (DirInfosTable[dir].ErrorName == "WARNING_IN_CLAUSE_PARAMETERS_REPEATED_VARS") // syntax_tree_visitor.AddWarning(new Errors.CommonWarning(StringResources.Get(DirInfosTable[dir].ErrorName), for_node.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); //else if (DirInfosTable[dir].ErrorName == "ERROR_IN_CLAUSE_PARAMETERS") //{ // syntax_tree_visitor.AddWarning(new Errors.CommonWarning(StringResources.Get(DirInfosTable[dir].ErrorName), for_node.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); //} //else if (DirInfosTable[dir].ErrorName !=null)//== "ERROR_IN_CLAUSE") { syntax_tree_visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get(DirInfosTable[dir].ErrorName), for_node.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); } VarInfoContainer Vars = GetVarInfoContainer(VFvis, DirInfosTable[dir].Reductions, DirInfosTable[dir].Privates, syntax_tree_visitor, dir); //сохраняем контекст ContextInfo contextInfo = new ContextInfo(syntax_tree_visitor); string ClassName = syntax_tree_visitor.context.get_free_name("$for_class{0}"); try { //создаем и конвертируем класс SyntaxTree.class_members member; SyntaxTree.type_declarations Decls = CreateClass(ClassName, out member, Vars); member.members.Add(CreateMethod("Method", syntax_body, for_node.loop_variable.name, member, Vars)); syntax_tree_visitor.visit(Decls); } finally { //восстанавливаем контекст contextInfo.RestoreContext(syntax_tree_visitor); } //создаем инициализацию, вызов и финализацию string ObjName = syntax_tree_visitor.context.get_free_name("$for_obj{0}"); SyntaxTree.dot_node dn = new SyntaxTree.dot_node(new SyntaxTree.ident(ObjName), new SyntaxTree.ident("Method")); SyntaxTree.statement_list stl = CreateInitPart(ClassName, ObjName, Vars); stl.subnodes.Add(CreateNestedRegionBorder(true)); stl.subnodes.Add(CreateOMPParallelForCall(dn, for_node.initial_value, for_node.finish_value)); stl.subnodes.Add(CreateNestedRegionBorder(false)); stl.subnodes.AddRange(CreateFinalPart(ObjName, Vars).subnodes); omp_stmts.statements.AddElement(syntax_tree_visitor.ret.visit(stl)); } return true; }
private static VarInfoContainer GetVarInfoContainer(VarFinderSyntaxVisitor VFVis, List<ReductionDirective> Reductions, List<string> PrivateVars, syntax_tree_visitor visitor, SyntaxTree.compiler_directive dir) { if (Reductions == null) Reductions = new List<ReductionDirective>(); if (PrivateVars == null) PrivateVars = new List<string>(); VarInfoContainer Result = new VarInfoContainer(); //константы копируются сразу Result.Constants = VFVis.Constants; //список переменных для редукции //ищем переменные с такими именами, проверяем их наличие, тип и если все хорошо - добавляем в список foreach (ReductionDirective rd in Reductions) foreach (string rdVarName in rd.variables) { if (LoopVariables.Contains(rdVarName)) { visitor.AddWarning(new PascalABCCompiler.Errors.CommonWarning(String.Format(PascalABCCompiler.StringResources.Get("OMPERROR_REDUCTION_WITH_LOOPVAR_{0}"), rdVarName), visitor.CurrentDocument.file_name, dir.source_context.begin_position.line_num, dir.source_context.begin_position.column_num)); continue; } SymbolInfo si = visitor.context.find(rdVarName); if (si == null) { visitor.AddWarning(new PascalABCCompiler.Errors.CommonWarning(String.Format(PascalABCCompiler.StringResources.Get("OMPERROR_UNKNOWN_VARNAME_{0}"), rdVarName), visitor.CurrentDocument.file_name, dir.source_context.begin_position.line_num, dir.source_context.begin_position.column_num)); continue; } if (!(si.sym_info is SemanticTree.IVAriableDefinitionNode)) { visitor.AddWarning(new PascalABCCompiler.Errors.CommonWarning(String.Format(PascalABCCompiler.StringResources.Get("OMPERROR_NAME_IS_NOT_VAR_{0}"), rdVarName), visitor.CurrentDocument.file_name, dir.source_context.begin_position.line_num, dir.source_context.begin_position.column_num)); continue; } if (!IsValidVarForReduction(si.sym_info as SemanticTree.IVAriableDefinitionNode)) { visitor.AddWarning(new PascalABCCompiler.Errors.CommonWarning(String.Format(PascalABCCompiler.StringResources.Get("OMPERROR_IS_NOT_POSSIBLE_REDUCTION_WITH_THIS_VAR_{0}"), rdVarName), visitor.CurrentDocument.file_name, dir.source_context.begin_position.line_num, dir.source_context.begin_position.column_num)); continue; } Result.ReductionVariables.Add(si.sym_info as SemanticTree.IVAriableDefinitionNode); Result.ReductionActions.Add(rd.Oper); //for (int i = 0; i < VFVis.Variables.Count; ++i) // if (VFVis.Variables[i].name.ToLower() == rdVarName.ToLower()) // { // Result.ReductionVariables.Add(VFVis.Variables[i]); // Result.ReductionActions.Add(rd.Oper); // break; // } } //приватные переменные - аналогично, но без проверки на тип foreach (string privateVar in PrivateVars) { SymbolInfo si = visitor.context.find(privateVar); if (si == null) { visitor.AddWarning(new PascalABCCompiler.Errors.CommonWarning(String.Format(PascalABCCompiler.StringResources.Get("OMPERROR_UNKNOWN_VARNAME_{0}"), privateVar), visitor.CurrentDocument.file_name, dir.source_context.begin_position.line_num, dir.source_context.begin_position.column_num)); continue; } if (!(si.sym_info is SemanticTree.IVAriableDefinitionNode)) { visitor.AddWarning(new PascalABCCompiler.Errors.CommonWarning(String.Format(PascalABCCompiler.StringResources.Get("OMPERROR_NAME_IS_NOT_VAR_{0}"), privateVar), visitor.CurrentDocument.file_name, dir.source_context.begin_position.line_num, dir.source_context.begin_position.column_num)); continue; } Result.PrivateVariables.Add(si.sym_info as SemanticTree.IVAriableDefinitionNode); } //по всем переменным: //если она не приватная и по ней нет редукции - переписываем ее в список разделяемых foreach (SemanticTree.IVAriableDefinitionNode var in VFVis.Variables) { bool NotShared = false; foreach (SemanticTree.IVAriableDefinitionNode rdn in Result.ReductionVariables) if (rdn.name.ToLower() == var.name.ToLower()) { NotShared = true; break; } if (!NotShared) foreach (SemanticTree.IVAriableDefinitionNode prVar in Result.PrivateVariables) if (prVar.name.ToLower() == var.name.ToLower()) { NotShared = true; break; } if (!NotShared) Result.SharedVariables.Add(var); } return Result; }
//инициализация OpenMP public static void InitOpenMP(List<SyntaxTree.compiler_directive> directives, syntax_tree_visitor visitor, SyntaxTree.compilation_unit cu) { //Из-за переноса этой проверки в секцию инициализации - оно не всегда успевает инициализироваться до выполнения этого кода. //Будем надеяться, что условие никогда не выполнится. Без постороннего вмешательства (замена файлов старыми версиями) - не должно. //if (SystemLibrary.SystemLibInitializer.OMP_Available == null || SystemLibrary.SystemLibInitializer.OMP_Available.NotFound) //{ // visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get("OMPERROR_OMP_NOT_AVAILABLE"), cu.file_name, cu.source_context.begin_position.line_num, cu.source_context.begin_position.column_num)); // return; //} foreach (SyntaxTree.compiler_directive dir in directives) { if (dir.Name.text.ToLower() == "omp") { string DirText = dir.Directive.text.ToLower(); DirectiveInfo dirInf = new DirectiveInfo(dir); DirInfosTable.Add(dir, dirInf); if (dirInf.Kind == DirectiveKind.ParallelFor) ForsFound = true; else if (dirInf.Kind == DirectiveKind.ParallelSections) SectionsFound = true; else if (dirInf.Kind == DirectiveKind.Critical) LocksFound = true; else { visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get(dirInf.ErrorName), dir.Directive.source_context.FileName, dirInf.SC.begin_position.line_num, dirInf.SC.begin_position.column_num)); } } } //уже не нужно //if (ForsFound && SystemLibrary.SystemLibInitializer.OMP_ParallelFor.NotFound) //{ // visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get("OMPERROR_PARALLELIZATION_FOR_NOT_AVAILABLE"), cu.file_name, cu.source_context.begin_position.line_num, cu.source_context.begin_position.column_num)); // ForsFound = false; //} //if (SectionsFound && SystemLibrary.SystemLibInitializer.OMP_ParallelSections.NotFound) //{ // visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get("OMPERROR_PARALLELIZATION_SECTIONS_NOT_AVAILABLE"), cu.file_name, cu.source_context.begin_position.line_num, cu.source_context.begin_position.column_num)); // SectionsFound = false; //} //"оторванные" директивы: //можно использовать директивы синхронизации и вне параллельных областей. //if (!SectionsFound && !ForsFound && LocksFound) //{ // visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get("OMPERROR_USING_CRITICAL_SECTIONS_OUTSIDE_PARALLEL_STRUCTURES"), cu.file_name, cu.source_context.begin_position.line_num, cu.source_context.begin_position.column_num)); // LocksFound = false; //} }
private static bool GenerateOMPParallelSectionsCall(statements_list stmts, SyntaxTree.statement_list syntax_stmts, statements_list omp_stmts, syntax_tree_visitor syntax_tree_visitor) { SyntaxTree.expression_list delegates = new PascalABCCompiler.SyntaxTree.expression_list(); SyntaxTree.statement_list stlInit = new PascalABCCompiler.SyntaxTree.statement_list(); SyntaxTree.statement_list stlFinal = new PascalABCCompiler.SyntaxTree.statement_list(); VarInfoContainer Vars = new VarInfoContainer(); string ClassName = syntax_tree_visitor.context.get_free_name("$section_class{0}"); List<SyntaxTree.statement> Sections = new List<PascalABCCompiler.SyntaxTree.statement>(); foreach (SyntaxTree.statement syntax_statement in syntax_stmts.subnodes) { if (syntax_statement is SyntaxTree.empty_statement) continue; //А зачем? ;-) if (syntax_statement is SyntaxTree.var_statement) { //выдать предупреждение. Это не нормально для параллельных секций syntax_tree_visitor.visit(syntax_statement as SyntaxTree.var_statement); } else { //ищем используемые переменные VarFinderSyntaxVisitor VFvis = new VarFinderSyntaxVisitor(syntax_statement, syntax_tree_visitor.context, false); SyntaxTree.compiler_directive dir = syntax_tree_visitor.DirectivesToNodesLinks[syntax_stmts]; //if (DirInfosTable[dir].ErrorName == "WARNING_IN_CLAUSE_PARAMETERS_REPEATED_VARS") // syntax_tree_visitor.AddWarning(new Errors.CommonWarning(StringResources.Get(DirInfosTable[dir].ErrorName), syntax_stmts.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); //else if (DirInfosTable[dir].ErrorName == "ERROR_IN_CLAUSE_PARAMETERS") //{ // syntax_tree_visitor.AddWarning(new Errors.CommonWarning(StringResources.Get(DirInfosTable[dir].ErrorName), syntax_stmts.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); //} //else if (DirInfosTable[dir].ErrorName != null) { syntax_tree_visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get(DirInfosTable[dir].ErrorName), syntax_stmts.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); } Vars.UnionWith(GetVarInfoContainer(VFvis, null, DirInfosTable[dir].Privates, syntax_tree_visitor, dir)); Sections.Add(syntax_statement); } } //сохраняем контекст ContextInfo contextInfo = new ContextInfo(syntax_tree_visitor); try { //создание и конвертирование класса SyntaxTree.class_members member; SyntaxTree.type_declarations Decls = CreateClass(ClassName, out member, Vars); for (int i = 0; i < Sections.Count; ++i) member.members.Add(CreateMethod("method" + i.ToString(), Sections[i], "", member, Vars)); syntax_tree_visitor.visit(Decls); } finally { //восстанавливаем контекст contextInfo.RestoreContext(syntax_tree_visitor); } //создаем инициализацию и финализацию int NameNum = 0; string ObjName = GetFreeName("$section_obj", ref NameNum, syntax_tree_visitor.context); stlInit.subnodes.AddRange(CreateInitPart(ClassName, ObjName, Vars).subnodes); stlFinal.subnodes.AddRange(CreateFinalPart(ObjName, Vars).subnodes); SyntaxTree.procedure_call pc = new PascalABCCompiler.SyntaxTree.procedure_call(); SyntaxTree.method_call mc = new PascalABCCompiler.SyntaxTree.method_call(); mc.dereferencing_value = CreateTPLFunctionReference("Invoke"); pc.func_name = mc; SyntaxTree.expression_list exl = new PascalABCCompiler.SyntaxTree.expression_list(); //foreach (string str in ObjNames) for (int i=0; i<Sections.Count; ++i) exl.Add(new SyntaxTree.dot_node(new SyntaxTree.ident(ObjName), new SyntaxTree.ident("Method"+i.ToString()))); mc.parameters = exl; stlInit.subnodes.Add(CreateNestedRegionBorder(true)); stlInit.subnodes.Add(pc); stlInit.subnodes.AddRange(stlFinal.subnodes); stlInit.subnodes.Add(CreateNestedRegionBorder(false)); statement_node st = syntax_tree_visitor.ret.visit(stlInit); omp_stmts.statements.AddElement(st); return true; }