// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Generate code using the cps-based IR pipeline.
library code_generator_task;

import 'glue.dart';
import 'codegen.dart';
import 'unsugar.dart';

import '../js_backend.dart';

import '../../common.dart';
import '../../common/codegen.dart' show
    CodegenWorkItem;
import '../../common/tasks.dart' show
    CompilerTask,
    GenericTask;
import '../../compiler.dart' show
    Compiler;
import '../../constants/constant_system.dart';
import '../../cps_ir/cps_ir_builder_task.dart';
import '../../cps_ir/cps_ir_nodes.dart' as cps;
import '../../cps_ir/cps_ir_nodes_sexpr.dart';
import '../../cps_ir/cps_ir_integrity.dart';
import '../../cps_ir/optimizers.dart';
import '../../cps_ir/optimizers.dart' as cps_opt;
import '../../cps_ir/type_mask_system.dart';
import '../../cps_ir/finalize.dart' show Finalize;
import '../../diagnostics/invariant.dart' show
    DEBUG_MODE;
import '../../elements/elements.dart';
import '../../js/js.dart' as js;
import '../../js_backend/codegen/codegen.dart';
import '../../io/source_information.dart' show
    SourceInformationStrategy;
import '../../tree_ir/tree_ir_builder.dart' as tree_builder;
import '../../tracer.dart';
import '../../ssa/ssa.dart' as ssa;
import '../../tree_ir/optimization/optimization.dart';
import '../../tree_ir/optimization/optimization.dart' as tree_opt;
import '../../tree_ir/tree_ir_integrity.dart';
import '../../tree_ir/tree_ir_nodes.dart' as tree_ir;
import '../../types/types.dart' show
    FlatTypeMask,
    ForwardingTypeMask,
    TypeMask,
    UnionTypeMask;

class CpsFunctionCompiler implements FunctionCompiler {
  final ConstantSystem constantSystem;
  // TODO(karlklose): remove the compiler.
  final Compiler compiler;
  final Glue glue;
  final SourceInformationStrategy sourceInformationFactory;

  // TODO(karlklose,sigurdm): remove and update dart-doc of [compile].
  final FunctionCompiler fallbackCompiler;
  TypeMaskSystem typeSystem;

  Tracer get tracer => compiler.tracer;

  final IrBuilderTask cpsBuilderTask;
  final GenericTask cpsOptimizationTask;
  final GenericTask treeBuilderTask;
  final GenericTask treeOptimizationTask;

  Inliner inliner;

  CpsFunctionCompiler(Compiler compiler, JavaScriptBackend backend,
                      SourceInformationStrategy sourceInformationFactory)
      : fallbackCompiler =
            new ssa.SsaFunctionCompiler(backend, sourceInformationFactory),
        cpsBuilderTask = new IrBuilderTask(compiler, sourceInformationFactory),
        sourceInformationFactory = sourceInformationFactory,
        constantSystem = backend.constantSystem,
        compiler = compiler,
        glue = new Glue(compiler),
        cpsOptimizationTask = new GenericTask('CPS optimization', compiler),
        treeBuilderTask = new GenericTask('Tree builder', compiler),
      treeOptimizationTask = new GenericTask('Tree optimization', compiler) {
    inliner = new Inliner(this);
  }

  String get name => 'CPS Ir pipeline';

  JavaScriptBackend get backend => compiler.backend;

  DiagnosticReporter get reporter => compiler.reporter;

  /// Generates JavaScript code for `work.element`.
  js.Fun compile(CodegenWorkItem work) {
    if (typeSystem == null) typeSystem = new TypeMaskSystem(compiler);
    AstElement element = work.element;
    return reporter.withCurrentElement(element, () {
      try {
        // TODO(karlklose): remove this fallback when we do not need it for
        // testing anymore.
        if (false) {
          reporter.log('Using SSA compiler for platform element $element');
          return fallbackCompiler.compile(work);
        }

        if (tracer != null) {
          tracer.traceCompilation('$element', null);
        }
        cps.FunctionDefinition cpsFunction = compileToCpsIr(element);
        optimizeCpsBeforeInlining(cpsFunction);
        applyCpsPass(inliner, cpsFunction);
        optimizeCpsAfterInlining(cpsFunction);
        cpsIntegrityChecker = null;
        tree_ir.FunctionDefinition treeFunction = compileToTreeIr(cpsFunction);
        treeFunction = optimizeTreeIr(treeFunction);
        return compileToJavaScript(work, treeFunction);
      } on CodegenBailout catch (e) {
        String message = "Unable to compile $element with the new compiler.\n"
            "  Reason: ${e.message}";
        reporter.internalError(element, message);
      }
    });
  }

  void giveUp(String reason) {
    throw new CodegenBailout(null, reason);
  }

  void traceGraph(String title, var irObject) {
    if (tracer != null) {
      tracer.traceGraph(title, irObject);
    }
  }

  String stringify(cps.FunctionDefinition node) {
    return new SExpressionStringifier().withTypes().visit(node);
  }

  /// For debugging purposes, replace a call to [applyCpsPass] with a call
  /// to [debugCpsPass] to check that this pass is idempotent.
  ///
  /// This runs [pass] followed by shrinking reductions, and then checks that
  /// one more run of [pass] does not change the IR.  The intermediate shrinking
  /// reductions pass is omitted if [pass] itself is shrinking reductions.
  ///
  /// If [targetName] is given, functions whose name contains that substring
  /// will be dumped out if the idempotency test fails.
  void debugCpsPass(cps_opt.Pass makePass(),
                    cps.FunctionDefinition cpsFunction,
                    [String targetName]) {
    String original = stringify(cpsFunction);
    cps_opt.Pass pass = makePass();
    pass.rewrite(cpsFunction);
    assert(checkCpsIntegrity(cpsFunction, pass.passName));
    if (pass is! ShrinkingReducer) {
      new ShrinkingReducer().rewrite(cpsFunction);
    }
    String before = stringify(cpsFunction);
    makePass().rewrite(cpsFunction);
    String after = stringify(cpsFunction);
    if (before != after) {
      print('SExpression changed for ${cpsFunction.element}');
      if (targetName != null && '${cpsFunction.element}'.contains(targetName)) {
        print(original);
        print('\n-->\n');
        print(before);
        print('\n-->\n');
        print(after);
        compiler.outputProvider('original', 'dump')..add(original)..close();
        compiler.outputProvider('before', 'dump')..add(before)..close();
        compiler.outputProvider('after', 'dump')..add(after)..close();
      }
    }
    traceGraph(pass.passName, cpsFunction);
    dumpTypedIr(pass.passName, cpsFunction);
  }

  void applyCpsPass(cps_opt.Pass pass, cps.FunctionDefinition cpsFunction) {
    cpsOptimizationTask.measureSubtask(pass.passName, () {
      pass.rewrite(cpsFunction);
    });
    traceGraph(pass.passName, cpsFunction);
    dumpTypedIr(pass.passName, cpsFunction);
    assert(checkCpsIntegrity(cpsFunction, pass.passName));
  }

  cps.FunctionDefinition compileToCpsIr(AstElement element) {
    cps.FunctionDefinition cpsFunction = inliner.cache.getUnoptimized(element);
    if (cpsFunction != null) return cpsFunction;

    cpsFunction = cpsBuilderTask.buildNode(element, typeSystem);
    if (cpsFunction == null) {
      if (cpsBuilderTask.bailoutMessage == null) {
        giveUp('unable to build cps definition of $element');
      } else {
        giveUp(cpsBuilderTask.bailoutMessage);
      }
    }
    ParentVisitor.setParents(cpsFunction);
    traceGraph('IR Builder', cpsFunction);
    dumpTypedIr('IR Builder', cpsFunction);
    // Eliminating redundant phis before the unsugaring pass will make it
    // insert fewer getInterceptor calls.
    applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
    applyCpsPass(new UnsugarVisitor(glue), cpsFunction);
    applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
    applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
    applyCpsPass(new InsertRefinements(typeSystem), cpsFunction);

    inliner.cache.putUnoptimized(element, cpsFunction);
    return cpsFunction;
  }

  static const Pattern PRINT_TYPED_IR_FILTER = null;

  String formatTypeMask(TypeMask type) {
    if (type is UnionTypeMask) {
      return '[${type.disjointMasks.map(formatTypeMask).join(', ')}]';
    } else if (type is FlatTypeMask) {
      if (type.isEmpty) return "empty";
      if (type.isNull) return "null";
      String suffix = (type.isExact ? "" : "+") + (type.isNullable ? "?" : "!");
      return '${type.base.name}$suffix';
    } else if (type is ForwardingTypeMask) {
      return formatTypeMask(type.forwardTo);
    }
    throw 'unsupported: $type';
  }

  void dumpTypedIr(String passName, cps.FunctionDefinition cpsFunction) {
    if (PRINT_TYPED_IR_FILTER != null &&
        PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsFunction.element.name) != null) {
      String printType(nodeOrRef, String s) {
        cps.Node node = nodeOrRef is cps.Reference
            ? nodeOrRef.definition
            : nodeOrRef;
        return node is cps.Variable && node.type != null
            ? '$s:${formatTypeMask(node.type)}'
            : s;
      }
      DEBUG_MODE = true;
      print(';;; ==== After $passName ====');
      print(new SExpressionStringifier(printType).visit(cpsFunction));
    }
  }

  CheckCpsIntegrity cpsIntegrityChecker;

  bool checkCpsIntegrity(cps.FunctionDefinition node, String previousPass) {
    cpsOptimizationTask.measureSubtask('Check integrity', () {
      if (cpsIntegrityChecker == null) {
        cpsIntegrityChecker = new CheckCpsIntegrity();
      }
      cpsIntegrityChecker.check(node, previousPass);
    });
    return true; // So this can be used from assert().
  }

  void optimizeCpsBeforeInlining(cps.FunctionDefinition cpsFunction) {
    cpsOptimizationTask.measure(() {
      applyCpsPass(new TypePropagator(this), cpsFunction);
      applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
      applyCpsPass(new ShrinkingReducer(), cpsFunction);
    });
  }

  void optimizeCpsAfterInlining(cps.FunctionDefinition cpsFunction) {
    cpsOptimizationTask.measure(() {
      applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
      applyCpsPass(new ShrinkingReducer(), cpsFunction);
      applyCpsPass(new RedundantRefinementEliminator(typeSystem), cpsFunction);
      applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
      applyCpsPass(new TypePropagator(this, recomputeAll: true), cpsFunction);
      applyCpsPass(new ShrinkingReducer(), cpsFunction);
      applyCpsPass(new EagerlyLoadStatics(), cpsFunction);
      applyCpsPass(new GVN(compiler, typeSystem), cpsFunction);
      applyCpsPass(new PathBasedOptimizer(backend, typeSystem), cpsFunction);
      applyCpsPass(new ShrinkingReducer(), cpsFunction);
      applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
      applyCpsPass(new BoundsChecker(typeSystem, compiler.world), cpsFunction);
      applyCpsPass(new LoopInvariantBranchMotion(), cpsFunction);
      applyCpsPass(new ShrinkingReducer(), cpsFunction);
      applyCpsPass(new ScalarReplacer(compiler), cpsFunction);
      applyCpsPass(new UseFieldInitializers(backend), cpsFunction);
      applyCpsPass(new MutableVariableEliminator(), cpsFunction);
      applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
      applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
      applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
      applyCpsPass(new ShrinkingReducer(), cpsFunction);
      applyCpsPass(new OptimizeInterceptors(backend, typeSystem), cpsFunction);
      applyCpsPass(new BackwardNullCheckRemover(typeSystem), cpsFunction);
      applyCpsPass(new ShrinkingReducer(), cpsFunction);
    });
  }

  tree_ir.FunctionDefinition compileToTreeIr(cps.FunctionDefinition cpsNode) {
    applyCpsPass(new Finalize(backend), cpsNode);
    tree_builder.Builder builder = new tree_builder.Builder(
        reporter.internalError, glue);
    tree_ir.FunctionDefinition treeNode =
        treeBuilderTask.measure(() => builder.buildFunction(cpsNode));
    assert(treeNode != null);
    traceGraph('Tree builder', treeNode);
    assert(checkTreeIntegrity(treeNode));
    return treeNode;
  }

  bool checkTreeIntegrity(tree_ir.FunctionDefinition node) {
    treeOptimizationTask.measureSubtask('Check integrity', () {
      new CheckTreeIntegrity().check(node);
    });
    return true; // So this can be used from assert().
  }

  tree_ir.FunctionDefinition optimizeTreeIr(tree_ir.FunctionDefinition node) {
    void applyTreePass(tree_opt.Pass pass) {
      treeOptimizationTask.measureSubtask(pass.passName, () {
        pass.rewrite(node);
      });
      traceGraph(pass.passName, node);
      assert(checkTreeIntegrity(node));
    }

    treeOptimizationTask.measure(() {
      applyTreePass(new StatementRewriter());
      applyTreePass(new VariableMerger(minifying:
          compiler.options.enableMinification));
      applyTreePass(new LoopRewriter());
      applyTreePass(new LogicalRewriter());
      applyTreePass(new PullIntoInitializers());
    });

    return node;
  }

  js.Fun compileToJavaScript(CodegenWorkItem work,
                             tree_ir.FunctionDefinition definition) {
    CodeGenerator codeGen = new CodeGenerator(glue, work.registry);
    Element element = work.element;
    js.Fun code = codeGen.buildFunction(definition);
    if (element is FunctionElement && element.asyncMarker != AsyncMarker.SYNC) {
      code = backend.rewriteAsync(element, code);
      work.registry.registerAsyncMarker(element);
    }
    return attachPosition(code, element);
  }

  Iterable<CompilerTask> get tasks {
    return <CompilerTask>[
        cpsBuilderTask,
        cpsOptimizationTask,
        treeBuilderTask,
        treeOptimizationTask]
      ..addAll(fallbackCompiler.tasks);
  }

  js.Node attachPosition(js.Node node, AstElement element) {
    return node.withSourceInformation(
        sourceInformationFactory.createBuilderForContext(element)
            .buildDeclaration(element));
  }
}
