/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2006-2010. */ package x10; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.jar.JarEntry; import java.util.jar.JarFile; import polyglot.ast.ClassMember; import polyglot.ast.Node; import polyglot.ast.NodeFactory; import polyglot.ast.SourceFile; import polyglot.ast.TopLevelDecl; import polyglot.ast.TypeNode; import polyglot.frontend.AllBarrierGoal; import polyglot.frontend.BarrierGoal; import polyglot.frontend.Compiler; import polyglot.frontend.CyclicDependencyException; import polyglot.frontend.FileResource; import polyglot.frontend.FileSource; import polyglot.frontend.ForgivingVisitorGoal; import polyglot.frontend.Globals; import polyglot.frontend.Goal; import polyglot.frontend.JLScheduler; import polyglot.frontend.Job; import polyglot.frontend.JobExt; import polyglot.frontend.OutputGoal; import polyglot.frontend.Parser; import polyglot.frontend.ParserGoal; import polyglot.frontend.Scheduler; import polyglot.frontend.Source; import polyglot.frontend.SourceGoal; import polyglot.frontend.SourceGoal_c; import polyglot.frontend.Stats; import polyglot.frontend.TargetFactory; import polyglot.frontend.VisitorGoal; import polyglot.main.Options; import polyglot.main.Report; import polyglot.types.Flags; import polyglot.types.MemberClassResolver; import polyglot.types.QName; import polyglot.types.SemanticException; import polyglot.types.TopLevelResolver; import polyglot.types.TypeSystem; import polyglot.types.TypeSystem_c; import polyglot.util.ErrorInfo; import polyglot.util.ErrorQueue; import polyglot.util.InternalCompilerError; import polyglot.util.Position; import polyglot.util.CollectionUtil; import x10.util.CollectionFactory; import polyglot.visit.ConformanceChecker; import polyglot.visit.ConstructorCallChecker; import polyglot.visit.ContextVisitor; import polyglot.visit.ExceptionChecker; import polyglot.visit.ExitChecker; import polyglot.visit.FwdReferenceChecker; import polyglot.visit.InitChecker; import polyglot.visit.NodeVisitor; import polyglot.visit.PruningVisitor; import polyglot.visit.ReachChecker; import polyglot.visit.Translator; import x10.ast.X10ClassDecl; import x10.ast.X10NodeFactory_c; import x10.compiler.ws.WSCodeGenerator; import x10.compiler.ws.WSCodePreprocessor; import x10.compiler.ws.util.WSTransformationContent; import x10.errors.Warnings; import x10.extension.X10Ext; //import x10.finish.table.CallTableKey; //import x10.finish.table.CallTableVal; import x10.optimizations.Optimizer; import x10.parser.X10Lexer; import x10.parser.X10SemanticRules; import x10.plugin.CompilerPlugin; import x10.plugin.LoadJobPlugins; import x10.plugin.LoadPlugins; import x10.plugin.RegisterPlugins; import x10.types.X10SourceClassResolver; import polyglot.types.TypeSystem; import x10.visit.CheckNativeAnnotationsVisitor; import x10.visit.Lowerer; import x10.visit.Desugarer; import x10.visit.ExpressionFlattener; import x10.visit.FieldInitializerMover; //import x10.visit.FinishAsyncVisitor; import x10.visit.FinallyEliminator; import x10.visit.IfdefVisitor; import x10.visit.MainMethodFinder; import x10.visit.NativeClassVisitor; import x10.visit.RewriteAtomicMethodVisitor; import x10.visit.StaticFieldAnalyzer; import x10.visit.StaticNestedClassRemover; import x10.visit.TypeParamAlphaRenamer; import x10.visit.X10ImplicitDeclarationExpander; import x10.visit.X10InnerClassRemover; import x10.visit.X10MLVerifier; import x10.visit.X10Translator; import x10.visit.X10TypeBuilder; import x10.visit.X10TypeChecker; import x10.visit.PositionInvariantChecker; import x10.visit.InstanceInvariantChecker; import x10.visit.CheckEscapingThis; import x10.visit.AnnotationChecker; import x10.visit.ErrChecker; import x10cpp.postcompiler.PrecompiledLibrary; import x10.visit.DotTranslator; import x10.visit.CommunicationOptimizer; /** * Extension information for x10 extension. */ public class ExtensionInfo extends polyglot.frontend.ParserlessJLExtensionInfo { static final boolean DEBUG_ = false; protected Map<QName,CompilerPlugin> plugins; public static final String XML_FILE_EXTENSION = "x10ml"; public static final String XML_FILE_DOT_EXTENSION = "." + XML_FILE_EXTENSION; /*** Compiler statistics gatherer. */ public Stats stats; // private static HashMap<CallTableKey, LinkedList<CallTableVal>> calltable = CollectionFactory.newHashMap(); /*** Construct an ExtensionInfo */ public ExtensionInfo() { stats = new Stats(); } public polyglot.main.Version version() { return new Version(); } public String[] fileExtensions() { return new String[] { "x10", XML_FILE_EXTENSION }; } // public String defaultFileExtension() { // return "x10"; // } public String compilerName() { return "x10c"; } // // Replace the Flex/Cup parser with a JikesPG parser // // public Parser parser(Reader reader, FileSource source, ErrorQueue eq) { // Lexer lexer = new Lexer_c(reader, source.name(), eq); // Grm grm = new Grm(lexer, ts, nf, eq); // return new CupParser(grm, source, eq); // } // public Parser parser(Reader reader, FileSource source, ErrorQueue eq) { // ### // if (source.path().endsWith(XML_FILE_DOT_EXTENSION)) { // return new DomParser(reader, (X10TypeSystem) ts, (X10NodeFactory) nf, source, eq); // } try { // // X10Lexer may be invoked using one of two constructors. // One constructor takes as argument a string representing // a (fully-qualified) filename; the other constructor takes // as arguments a (file) Reader and a string representing the // name of the file in question. Invoking the first // constructor is more efficient because a buffered File is created // from that string and read with one (read) operation. However, // we depend on Polyglot to provide us with a fully qualified // name for the file. In Version 1.3.0, source.name() yielded a // fully-qualied name. In 1.3.2, source.path() yields a fully- // qualified name. If this assumption still holds then the // first constructor will work. // The advantage of using the Reader constructor is that it // will always work, though not as efficiently. // // X10Lexer x10_lexer = new X10Lexer(reader, source.name()); // // FIXME: HACK! Unwrap the escaping unicode reader, because LPG will do its own decoding // if (reader instanceof polyglot.lex.EscapedUnicodeReader) // reader = ((polyglot.lex.EscapedUnicodeReader)reader).getSource(); X10Lexer x10_lexer = // Optimization: it's faster to read from a file source.resource().getClass() == FileResource.class ? new X10Lexer(source.path()) : new X10Lexer(reader, source.toString()); X10SemanticRules x10_parser = new X10SemanticRules(x10_lexer, ts, nf, source, eq); // Create the parser x10_lexer.lexer(x10_parser.getIPrsStream()); return x10_parser; // Parse the token stream to produce an AST } catch (IOException e) { e.printStackTrace(); } throw new IllegalStateException("Could not parse " + source.path()); } protected Set<String> manifest = CollectionFactory.newHashSet(); public boolean manifestContains(String path) { path = path.replace(File.separatorChar, '/'); // FIXME: HACK! Try all prefixes int s = 0; while ((s = path.indexOf('/')) != -1) { if (manifest.contains(path)) return true; path = path.substring(s+1); } if (manifest.contains(path)) return true; return false; } static class WarningComparator implements Comparator<ErrorInfo> { // todo: why Warnings are ordered differently than exceptions? (see ExceptionComparator) public int compare(ErrorInfo a, ErrorInfo b) { Position pa = a.getPosition(); Position pb = b.getPosition(); if (pa == null && pb == null) { if (a.getMessage() == null && b.getMessage() == null) return 0; else if (a.getMessage() != null && a.getMessage().equals(b.getMessage())) return 0; } if (pa == null) return -1; if (pb == null) return 1; if (pa.line() < pb.line()) return -1; if (pb.line() < pa.line()) return 1; if (pa.column() < pb.column()) return -1; if (pb.column() < pa.column()) return 1; return 0; } } Set<ErrorInfo> warnings = new TreeSet<ErrorInfo>(new WarningComparator()); public Set<ErrorInfo> warningSet() { return warnings; } // todo: can't we merge warning and exceptions into a single object (ErrorInfo?) static class ExceptionComparator implements Comparator<SemanticException> { public int compare(SemanticException a, SemanticException b) { int r = (a.getClass().toString().compareToIgnoreCase(b.getClass().toString())); if (r != 0) return r; Position pa = a.position(); Position pb = b.position(); if (pa == null && pb == null) { if (a.getMessage() == null && b.getMessage() == null) return 0; else if (a.getMessage() != null && a.getMessage().equals(b.getMessage())) return 0; } if (pa == null) return -1; if (pb == null) return 1; // todo: what about path & file ? (we should first order by file, right?) if (pa.line() < pb.line()) return -1; if (pb.line() < pa.line()) return 1; // If they have the same message and are on the same line, they're equal if (a.getMessage() == null && b.getMessage() == null) return 0; if (a.getMessage() == null) return -1; if (b.getMessage() == null) return 1; if (!a.getMessage().equals(b.getMessage())) return a.getMessage().compareToIgnoreCase(b.getMessage()); if (a.getMessage().equals(b.getMessage())) return 0; if (pa.column() < pb.column()) return -1; if (pb.column() < pa.column()) return 1; return 0; } } Set<SemanticException> errors = new TreeSet<SemanticException>(new ExceptionComparator()); public Set<SemanticException> errorSet() { return errors; } private int weakCallsCount = 0; public void incrWeakCallsCount() { weakCallsCount++; } public int weakCallsCount() { return weakCallsCount; } protected void initTypeSystem() { X10CompilerOptions opts = getOptions(); TopLevelResolver r = new X10SourceClassResolver(compiler, this, opts.constructFullClasspath(), opts.compile_command_line_only, opts.ignore_mod_times); for (PrecompiledLibrary pco : opts.x10libs) { pco.updateManifest(manifest, this); } // Resolver to handle lookups of member classes. if (true || TypeSystem.SERIALIZE_MEMBERS_WITH_CONTAINER) { MemberClassResolver mcr = new MemberClassResolver(ts, r, true); r = mcr; } ts.initialize(r); } protected NodeFactory createNodeFactory() { return new X10NodeFactory_c(this); } protected TypeSystem createTypeSystem() { return new TypeSystem_c(this); } // ================================= // X10-specific goals and scheduling // ================================= protected Scheduler createScheduler() { return new X10Scheduler(this); } public static class X10Scheduler extends JLScheduler { public X10Scheduler(ExtensionInfo extInfo) { super(extInfo); } public ExtensionInfo extensionInfo() { return (ExtensionInfo) this.extInfo; } @Override public void clearAll(Collection<Source> sources) { super.clearAll(sources); PrintWeakCallsCount = null; } /** * Create a list of goals for a given job that performs all operations through parsing. * @return the created list of goals */ protected List<Goal> parseSourceGoals(Job job) { List<Goal> goals = new ArrayList<Goal>(); addParseSourceGoals(job, goals); goals.add(End(job)); return goals; } /** * Create a list of goals for a given job that only performs parsing. * @return the created list of goals */ protected List<Goal> typecheckSourceGoals(Job job) { List<Goal> goals = new ArrayList<Goal>(); addTypecheckSourceGoals(job, goals); goals.add(End(job)); return goals; } /** * Create a list of goals for a given job that only performs parsing. * @return the created list of goals */ protected List<Goal> semanticCheckSourceGoals(Job job) { List<Goal> goals = new ArrayList<Goal>(); addSemanticCheckSourceGoals(job, goals); goals.add(End(job)); return goals; } /** * Given a list of goals and a job, append the goal that performs position checking * to the end of that list (just before the End goal). * @return the new list of goals that includes all of the original goals plus the new one */ protected List<Goal> appendPositionCheckGoal(Job job, List<Goal> goals) { return appendPositionCheckGoal(job, goals, "PositionInvariantChecker"); } /** * Given a list of goals and a job, append the goal that performs position checking * with a given name to the end of that list (just before the End goal). A unique name * is required if there will be multiple such goals added. * @param name the name of the position checker goal * @return the new list of goals that includes all of the original goals plus the new one */ protected List<Goal> appendPositionCheckGoal(Job job, List<Goal> goals, String name) { List<Goal> newgoals = new ArrayList<Goal>(goals); assert (newgoals.size() > 0); Goal endGoal = newgoals.remove(goals.size()-1); assert (endGoal.name().equals("End")); addPositionCheckGoal(name, job, newgoals); newgoals.add(endGoal); return newgoals; } /** * Given a list of goals and a job, append the goal that performs full invariant checking * to the end of that list (just before the End goal). * @return the new list of goals that includes all of the original goals plus the new one */ protected List<Goal> appendInvariantCheckGoal(Job job, List<Goal> goals) { List<Goal> newgoals = new ArrayList<Goal>(goals); assert (newgoals.size() > 0); Goal endGoal = newgoals.remove(goals.size()-1); assert (endGoal.name().equals("End")); addInvariantCheckGoal(job, newgoals); newgoals.add(endGoal); return newgoals; } private void addParseSourceGoals(Job job, List<Goal> goals) { goals.add(Parsed(job)); } private void addTypecheckSourceGoals(Job job, List<Goal> goals) { addParseSourceGoals(job, goals); X10CompilerOptions opts = extensionInfo().getOptions(); if (opts.x10_config.CHECK_ERR_MARKERS) goals.add(ErrChecker(job)); // must be the first phase after parsing because later phases might fail and stop type checking (it shouldn't happen, but it does) goals.add(ImportTableInitialized(job)); goals.add(TypesInitialized(job)); if (job.source() != null && job.source().path().endsWith(XML_FILE_DOT_EXTENSION)) { goals.add(X10MLTypeChecked(job)); } // Do not include LoadPlugins in list. It would cause prereqs to be added // goals.add(LoadPlugins()); goals.add(PropagateAnnotations(job)); goals.add(LoadJobPlugins(job)); goals.add(RegisterPlugins(job)); goals.add(PreTypeCheck(job)); goals.add(Ifdef(job)); goals.add(TypesInitializedForCommandLineBarrier()); goals.add(TypeChecked(job)); goals.add(ReassembleAST(job)); } private void addSemanticCheckSourceGoals(Job job, List<Goal> goals) { addTypecheckSourceGoals(job, goals); goals.add(ConformanceChecked(job)); // Data-flow analyses goals.add(ReachabilityChecked(job)); // This must be the first dataflow analysis (see DataFlow.reportCFG_Errors) goals.add(ExceptionsChecked(job)); goals.add(ExitPathsChecked(job)); goals.add(InitializationsChecked(job)); goals.add(ConstructorCallsChecked(job)); //goals.add(ForwardReferencesChecked(job)); //goals.add(CheckNativeAnnotations(job)); goals.add(CheckEscapingThis(job)); goals.add(AnnotationChecker(job)); goals.add(CheckASTForErrors(job)); //goals.add(TypeCheckBarrier()); } private Goal addPreOptimizationGoals(Job job, List<Goal> goals) { final Goal typeCheckBarrierGoal = TypeCheckBarrier(); goals.add(CommunicationOptimizer(job)); goals.add(StaticFieldAnalyzer(job)); goals.add(MoveFieldInitializers(job)); // should do this before desugaring final Goal desugarerGoal = Desugarer(job); goals.add(desugarerGoal); desugarerGoal.addPrereq(typeCheckBarrierGoal); X10CompilerOptions opts = extensionInfo().getOptions(); Goal walaBarrier = null; if (opts.x10_config.WALA || opts.x10_config.WALADEBUG || opts.x10_config.FINISH_ASYNCS) { try{ ClassLoader cl = Thread.currentThread().getContextClassLoader(); Class<?> c = cl.loadClass("x10.wala.translator.X102IRGoal"); Constructor<?> con = c.getConstructor(Job.class); Method hasMain = c.getMethod("hasMain", String.class); Goal ir = ((Goal) con.newInstance(job)).intern(this); goals.add(ir); Goal finder = MainMethodFinder(job, hasMain); finder.addPrereq(typeCheckBarrierGoal); ir.addPrereq(finder); if (opts.x10_config.FINISH_ASYNCS) { Method buildCallTableMethod = c.getMethod("analyze"); walaBarrier = IRBarrier(ir, buildCallTableMethod); } else if(opts.x10_config.WALADEBUG) { Method printCallGraph = c.getMethod("printCallGraph"); walaBarrier = IRBarrier(ir, printCallGraph); } else { Method wsAnalyzeCallGraph = c.getMethod("wsAnalyzeCallGraph", Collection.class); walaBarrier = IRBarrier(ir, wsAnalyzeCallGraph); } goals.add(walaBarrier); goals.add(FinishAsyncBarrier(walaBarrier,job,this)); } catch (Throwable e) { System.err.println("WALA not found."); e.printStackTrace(); } } goals.add(X10Expanded(job)); goals.add(X10RewriteAtomicMethods(job)); final Goal nativeClassVisitorGoal = NativeClassVisitor(job); goals.add(nativeClassVisitorGoal); goals.add(TypeParameterAlphaRenamer(job)); final Goal innerClassRemoverGoal = InnerClassRemover(job); goals.add(innerClassRemoverGoal); // TODO: move even earlier innerClassRemoverGoal.addPrereq(nativeClassVisitorGoal); innerClassRemoverGoal.addPrereq(typeCheckBarrierGoal); goals.add(Serialized(job)); if (opts.x10_config.WORK_STEALING) { Goal wsCodePreprocessorGoal = WSCodePreprocessor(job); goals.add(wsCodePreprocessorGoal); if(walaBarrier != null){ //WALA call graph builder to detect the transformation target wsCodePreprocessorGoal.addPrereq(walaBarrier); } else{ //Simple call graph builder to detect the transformation target wsCodePreprocessorGoal.addPrereq(WSCallGraphBarrier()); } Goal wsCodeGenGoal = WSCodeGenerator(job); goals.add(wsCodeGenGoal); wsCodeGenGoal.addPrereq(wsCodePreprocessorGoal); } return typeCheckBarrierGoal; } private void addPositionCheckGoal(Job job, List<Goal> goals) { addPositionCheckGoal("PositionInvariantChecker", job, goals); } private void addPositionCheckGoal(String name, Job job, List<Goal> goals) { String current = ""; if (goals.size() > 0) current = goals.get(goals.size() - 1).name(); addPositionCheckGoal(name, current, job, goals); } private void addPositionCheckGoal(String name, String previous, Job job, List<Goal> goals) { goals.add(new ForgivingVisitorGoal(name, job, new PositionInvariantChecker(job, previous)).intern(this)); } private void addInvariantCheckGoal(Job job, List<Goal> goals) { goals.add(new ForgivingVisitorGoal("InstanceInvariantChecker", job, new InstanceInvariantChecker(job)).intern(this)); } public List<Goal> goals(Job job) { List<Goal> goals = new ArrayList<Goal>(); addSemanticCheckSourceGoals(job, goals); X10CompilerOptions opts = extensionInfo().getOptions(); if (!opts.x10_config.ONLY_TYPE_CHECKING) { final Goal typeCheckBarrierGoal = addPreOptimizationGoals(job, goals); goals.add(Preoptimization(job)); goals.addAll(Optimizer.goals(this, job)); goals.add(Postoptimization(job)); final Goal lowererGoal = Lowerer(job); goals.add(lowererGoal); final Goal codeGeneratedGoal = CodeGenerated(job); goals.add(codeGeneratedGoal); // the barrier will handle prereqs on its own codeGeneratedGoal.addPrereq(CodeGenBarrier()); lowererGoal.addPrereq(typeCheckBarrierGoal); codeGeneratedGoal.addPrereq(lowererGoal); List<Goal> optimizations = Optimizer.goals(this, job); for (Goal goal : optimizations) { goal.addPrereq(typeCheckBarrierGoal); codeGeneratedGoal.addPrereq(goal); } } goals.add(End(job)); if (opts.x10_config.CHECK_INVARIANTS) { ArrayList<Goal> newGoals = new ArrayList<Goal>(goals.size()*2); boolean reachedTypeChecking = false; int ctr = 0; for (Goal g : goals) { newGoals.add(g); if (!reachedTypeChecking) { addPositionCheckGoal("PositionInvariantChecker"+(ctr++), g.name(), job, newGoals); } if (g==TypeChecked(job)) { addInvariantCheckGoal(job, newGoals); reachedTypeChecking = true; } } goals = newGoals; } return goals; } public Goal Preoptimization(Job job) { return new SourceGoal_c("Preoptimization", job) { private static final long serialVersionUID = 1L; public boolean runTask() { return true; } }.intern(this); } public Goal Postoptimization(Job job) { return new SourceGoal_c("Postoptimization", job) { private static final long serialVersionUID = 1L; public boolean runTask() { return true; } }.intern(this); } Goal PrintWeakCallsCount; @Override protected Goal EndAll() { if (PrintWeakCallsCount == null) { PrintWeakCallsCount = new PrintWeakCallsCount((ExtensionInfo) extInfo).intern(this); Goal postcompiled = PostCompiled(); PrintWeakCallsCount.addPrereq(postcompiled); } return PrintWeakCallsCount; } static class PrintWeakCallsCount extends AllBarrierGoal { private static final long serialVersionUID = 6978580691962888126L; ExtensionInfo ext; public PrintWeakCallsCount(ExtensionInfo extInfo) { super("PrintWeakCallsCount",extInfo.scheduler()); this.ext = extInfo; } public Goal prereqForJob(Job job) { if (scheduler.shouldCompile(job)) { return scheduler.End(job); } else { return new SourceGoal_c("WCCDummyEnd", job) { private static final long serialVersionUID = 1L; public boolean runTask() { return true; } }.intern(scheduler); } } public boolean runTask() { Compiler compiler = ext.compiler(); X10CompilerOptions opts = ext.getOptions(); if ((!opts.x10_config.VERBOSE_CHECKS) && (!opts.x10_config.STATIC_CHECKS)) { int count = ext.weakCallsCount(); if (count > 0) { compiler.errorQueue().enqueue(ErrorInfo.WARNING, count + " dynamically checked calls or field accesses, run with -VERBOSE_CHECKS for more details."); } } return true; } } @SuppressWarnings("unchecked") public static <T> T invokeGeneric(Method method) { try { return (T) method.invoke(null); } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } return null; } public Goal IRBarrier(final Goal goal, final Method method) { return new AllBarrierGoal("IRBarrier", this) { private static final long serialVersionUID = -3692329571101709400L; @Override public Goal prereqForJob(Job job) { if (!super.scheduler.commandLineJobs().contains(job) && ((ExtensionInfo) extInfo).manifestContains(job.source().path())) { return null; } return goal; } public boolean runTask() { X10CompilerOptions opts = extensionInfo().getOptions(); if (opts.x10_config.FINISH_ASYNCS) { // calltable = X10Scheduler.<HashMap<CallTableKey, LinkedList<CallTableVal>>>invokeGeneric(method); } else if (opts.x10_config.WALADEBUG) { try { method.invoke(null); } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } } else { //This path is only for WALA call graph analysis for Work-Stealing try { WSTransformationContent transTarget = (WSTransformationContent) method.invoke(null, jobs()); //now use this one to construct WSTransformationState TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); WSCodePreprocessor.setWALATransTarget(extensionInfo(), transTarget); } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } } return true; } }.intern(this); } public Goal TypeCheckBarrier() { String name = "TypeCheckBarrier"; if (extInfo.getOptions().compile_command_line_only) { return new BarrierGoal(name, commandLineJobs()) { private static final long serialVersionUID = -1495893515710977644L; @Override public Goal prereqForJob(Job job) { return CheckASTForErrors(job); } }.intern(this); } else { return new AllBarrierGoal(name, this) { private static final long serialVersionUID = 6757229496093951388L; @Override public Goal prereqForJob(Job job) { if (!super.scheduler.commandLineJobs().contains(job) && ((ExtensionInfo) extInfo).manifestContains(job.source().path())) { return null; } return CheckASTForErrors(job); } }.intern(this); } } protected Goal codegenPrereq(Job job) { return Lowerer(job); } public Goal CodeGenBarrier() { String name = "CodeGenBarrier"; if (extInfo.getOptions().compile_command_line_only) { return new BarrierGoal(name, commandLineJobs()) { private static final long serialVersionUID = 2258041064037983928L; @Override public Goal prereqForJob(Job job) { return codegenPrereq(job); } }.intern(this); } else { return new AllBarrierGoal(name, this) { private static final long serialVersionUID = 4089824072381830523L; @Override public Goal prereqForJob(Job job) { if (!super.scheduler.commandLineJobs().contains(job) && ((ExtensionInfo) extInfo).manifestContains(job.source().path())) { return null; } return codegenPrereq(job); } }.intern(this); } } public Goal CheckASTForErrors(Job job) { return new SourceGoal_c("CheckASTForErrors", job) { private static final long serialVersionUID = 565345690079406384L; public boolean runTask() { if (job.reportedErrors()) { Node ast = job.ast(); job.ast(((X10Ext)ast.ext()).setSubtreeValid(false)); } return true; } }.intern(this); } public Goal Serialized(Job job) { Compiler compiler = job.extensionInfo().compiler(); TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); TargetFactory tf = job.extensionInfo().targetFactory(); return new SourceGoal_c("Serialized", job) { private static final long serialVersionUID = 4813624372034550114L; public boolean runTask() { return true; } }.intern(this); } // @Override // public Goal ImportTableInitialized(Job job) { // TypeSystem ts = job.extensionInfo().typeSystem(); // NodeFactory nf = job.extensionInfo().nodeFactory(); // Goal g = new VisitorGoal("ImportTableInitialized", job, new X10InitImportsVisitor(job, ts, nf)); // Goal g2 = g.intern(this); // if (g == g2) { // g.addPrereq(TypesInitializedForCommandLine()); // } // return g2; // } public Goal LoadPlugins() { return new LoadPlugins((ExtensionInfo) extInfo).intern(this); } public Goal LoadJobPlugins(Job job) { return new LoadJobPlugins(job).intern(this); } public Goal RegisterPlugins(Job job) { Goal g = new RegisterPlugins(job); Goal g2 = g.intern(this); if (g == g2) { g.addPrereq(LoadPlugins()); } return g2; } public Goal PropagateAnnotations(Job job) { // ### return new VisitorGoal("PropagateAnnotations", job, new PruningVisitor()).intern(this); } @Override public Goal InitializationsChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("InitializationsChecked", job, new InitChecker(job, ts, nf)).intern(this); } public static class ValidatingOutputGoal extends OutputGoal { private static final long serialVersionUID = -7021152686342225925L; public ValidatingOutputGoal(Job job, Translator translator) { super(job, translator); } public boolean runTask() { Node ast = job().ast(); if (ast != null && !((X10Ext)ast.ext()).subtreeValid()) { return false; } return super.runTask(); } } @Override public Goal CodeGenerated(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); Goal cg = new ValidatingOutputGoal(job, new X10Translator(job, ts, nf, extInfo.targetFactory())); Goal cg2 = cg.intern(this); return cg2; } static class X10ParserGoal extends ParserGoal { private static final long serialVersionUID = 6811976416160592748L; public X10ParserGoal(Compiler compiler, Job job) { super(compiler, job); } @Override protected SourceFile createDummyAST() { NodeFactory nf = job().extensionInfo().nodeFactory(); String fName = job.source().name(); Position pos = new Position("", job.source().path(), 1, 1).markCompilerGenerated(); String name = fName.substring(fName.lastIndexOf(File.separatorChar)+1, fName.lastIndexOf('.')); X10ClassDecl decl = (X10ClassDecl) nf.ClassDecl(pos, nf.FlagsNode(pos, Flags.PUBLIC), nf.Id(pos, name), null, Collections.<TypeNode>emptyList(), nf.ClassBody(pos, Collections.<ClassMember>emptyList())); decl = decl.errorInAST(new SemanticException("", pos)); SourceFile ast = nf.SourceFile(pos, Collections.<TopLevelDecl>singletonList(decl)).source(job.source()); ast = (SourceFile) ((X10Ext)ast.ext()).setSubtreeValid(false); return ast; } } @Override public Goal Parsed(Job job) { return new X10ParserGoal(extInfo.compiler(), job).intern(this); } public Goal DotOutputted(Job job, String name) { Goal cg = new OutputGoal(job, new DotTranslator(job, extInfo.typeSystem(), extInfo.nodeFactory(), extInfo.targetFactory(), name), name); return cg.intern(this); } @Override public Goal constructTypesInitialized(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("TypesInitialized", job, new X10TypeBuilder(job, ts, nf)).intern(this); } public Goal X10MLTypeChecked(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ForgivingVisitorGoal("X10MLTypeChecked", job, new X10MLVerifier(job, ts, nf)).intern(this); } @Override public Goal TypeChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("TypeChecked", job, new X10TypeChecker(job, ts, nf, job.nodeMemo())).intern(this); } public Goal ConformanceChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("ConformanceChecked", job, new ConformanceChecker(job, ts, nf)).intern(this); } public Goal ReachabilityChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("ReachChecked", job, new ReachChecker(job, ts, nf)).intern(this); } public Goal ExceptionsChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("ExceptionsChecked", job, new ExceptionChecker(job, ts, nf)).intern(this); } public Goal ExitPathsChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("ExitChecked", job, new ExitChecker(job, ts, nf)).intern(this); } public Goal ConstructorCallsChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("ContructorCallsChecked", job, new ConstructorCallChecker(job, ts, nf)).intern(this); } public Goal ForwardReferencesChecked(Job job) { TypeSystem ts = job.extensionInfo().typeSystem(); NodeFactory nf = job.extensionInfo().nodeFactory(); return new ForgivingVisitorGoal("ForwardRefsChecked", job, new FwdReferenceChecker(job, ts, nf)).intern(this); } public Goal CheckEscapingThis(Job job) { return new ForgivingVisitorGoal("CheckEscapingThis", job, new CheckEscapingThis.Main(job)).intern(this); } private Goal AnnotationChecker(Job job) { return new ForgivingVisitorGoal("AnnotationChecker", job, new AnnotationChecker(job,job.extensionInfo().typeSystem(),job.extensionInfo().nodeFactory())).intern(this); } private Goal Ifdef(Job job) { return new ForgivingVisitorGoal("IfdefVisitor", job, new IfdefVisitor(job,job.extensionInfo().typeSystem(),job.extensionInfo().nodeFactory())).intern(this); } private Goal ErrChecker(Job job) { return new ForgivingVisitorGoal("ErrChecker", job, new ErrChecker(job)).intern(this); } public String nativeAnnotationLanguage() { return "java"; } public Goal CheckNativeAnnotations(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ForgivingVisitorGoal("CheckNativeAnnotations", job, new CheckNativeAnnotationsVisitor(job, ts, nf, nativeAnnotationLanguage())).intern(this); } public Goal CommunicationOptimizer(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new VisitorGoal("CommunicationOptimizer", job, new CommunicationOptimizer(job, ts, nf)).intern(this); } public static class ValidatingVisitorGoal extends VisitorGoal { private static final long serialVersionUID = 5119557747721488612L; public ValidatingVisitorGoal(String name, Job job, NodeVisitor v) { super(name, job, v); } public boolean runTask() { Node ast = job().ast(); if (ast != null && !((X10Ext)ast.ext()).subtreeValid()) { //Warnings.issue(job(), "Invalid Visitor Goal: " +this.name()+ ", visitor: " +this.visitor(), Position.COMPILER_GENERATED); return true; } return super.runTask(); } } public Goal MoveFieldInitializers(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("MoveFieldInitializers", job, new FieldInitializerMover(job, ts, nf)).intern(this); } public Goal StaticFieldAnalyzer(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("StaticFieldAnalyzer", job, new StaticFieldAnalyzer(job, ts, nf)).intern(this); } public Goal X10RewriteAtomicMethods(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("X10RewriteAtomicMethods", job, new RewriteAtomicMethodVisitor(job, ts, nf)).intern(this); } public Goal X10Expanded(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("X10Expanded", job, new X10ImplicitDeclarationExpander(job, ts, nf)).intern(this); } public Goal NativeClassVisitor(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("NativeClassVisitor", job, new NativeClassVisitor(job, ts, nf, nativeAnnotationLanguage())).intern(this); } public Goal MainMethodFinder(Job job, Method hasMain) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("MainMethodFinder", job, new MainMethodFinder(job, ts, nf, hasMain)).intern(this); } public Goal WSCallGraphBarrier() { final TypeSystem ts = extInfo.typeSystem(); final NodeFactory nf = extInfo.nodeFactory(); return new AllBarrierGoal("WSCallGraphBarrier", this) { @Override public Goal prereqForJob(Job job) { return TypeChecked(job); } @Override public boolean runTask() { WSCodePreprocessor.buildCallGraph(extensionInfo()); return true; } }.intern(this); } public Goal WSCodePreprocessor(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("WSCodePreprocessor", job, new WSCodePreprocessor(job, ts, nf)).intern(this); } public Goal WSCodeGenerator(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("WSCodeGenerator", job, new WSCodeGenerator(job, ts, nf)).intern(this); } public Goal Desugarer(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("Desugarer", job, new Desugarer(job, ts, nf)).intern(this); } public Goal Lowerer(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("Lowerer", job, new Lowerer(job, ts, nf)).intern(this); } public Goal InnerClassRemover(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("InnerClassRemover", job, new X10InnerClassRemover(job, ts, nf)).intern(this); } public Goal StaticNestedClassRemover(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("StaticNestedClassRemover", job, new StaticNestedClassRemover(job, ts, nf)).intern(this); } public Goal TypeParameterAlphaRenamer(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("TypeParameterAlphaRenamer", job, new TypeParamAlphaRenamer(job, ts, nf)).intern(this); } public Goal FinallyEliminator(Job job) { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); return new ValidatingVisitorGoal("FinallyEliminator", job, new FinallyEliminator(job, ts, nf)).intern(this); } public Goal FinishAsyncBarrier(final Goal goal, final Job job, final Scheduler s) { return new AllBarrierGoal("FinishAsyncBarrier", this) { private static final long serialVersionUID = -4172220184246138069L; @Override public Goal prereqForJob(Job job) { //TODO: probably need to also annotation code in "runtime" if (!super.scheduler.commandLineJobs().contains(job) && ((ExtensionInfo) extInfo).manifestContains(job.source().path())) { return null; } return goal; } public boolean runTask() { try { TypeSystem ts = extInfo.typeSystem(); NodeFactory nf = extInfo.nodeFactory(); // FinishAsyncVisitor favisitor = new FinishAsyncVisitor(job, ts, nf, nativeAnnotationLanguage(), calltable); // Goal finish = new ValidatingVisitorGoal("FinishAsyncs", job, favisitor).intern(s); // finish.runTask(); } catch (Throwable t) {} return true; } }.intern(this); } public static class X10Job extends Job { public X10Job(polyglot.frontend.ExtensionInfo lang, JobExt ext, Source source, Node ast) { super(lang, ext, source, ast); } public int initialErrorCount() { return initialErrorCount; } public void initialErrorCount(int count) { initialErrorCount = count; } public void setReportedErrors(boolean flag) { reportedErrors = flag; } } @Override protected Job createSourceJob(Source source, Node ast) { return new X10Job(extInfo, extInfo.jobExt(), source, ast); } @Override protected boolean runPass(Goal goal) throws CyclicDependencyException { Job job = goal instanceof SourceGoal ? ((SourceGoal) goal).job() : null; int savedInitialErrorCount = -1; if (job != null) savedInitialErrorCount = ((X10Job) job).initialErrorCount(); boolean result = super.runPass(goal); if (job != null) ((X10Job) job).initialErrorCount(savedInitialErrorCount); return result; } } protected X10CompilerOptions createOptions() { return new X10CompilerOptions(this); } public X10CompilerOptions getOptions() { return (X10CompilerOptions) super.getOptions(); } public Map<QName,CompilerPlugin> plugins() { if (plugins == null) { return Collections.emptyMap(); } return plugins; } public void addPlugin(QName pluginName, CompilerPlugin plugin) { if (plugins == null) { plugins = CollectionFactory.newHashMap(); } plugins.put(pluginName, plugin); } public CompilerPlugin getPlugin(QName pluginName) { if (plugins == null) { return null; } return plugins.get(pluginName); } public Desugarer makeDesugarer(Job job) { return new Desugarer(job, job.extensionInfo().typeSystem(), job.extensionInfo().nodeFactory()); } }