// Copyright (c) 2013, 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.

library dart2js.ir_builder_task;

import '../closure.dart' as closure;
import '../common.dart';
import '../common/names.dart' show
    Names,
    Selectors;
import '../common/tasks.dart' show
    CompilerTask;
import '../compiler.dart' show
    Compiler;
import '../constants/expressions.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart' show
    SynthesizedConstructorElementX,
    ConstructorBodyElementX,
    FunctionSignatureX;
import '../io/source_information.dart';
import '../js_backend/backend_helpers.dart' show
    BackendHelpers;
import '../js_backend/js_backend.dart' show
    JavaScriptBackend,
    SyntheticConstantKind;
import '../resolution/tree_elements.dart' show
    TreeElements;
import '../resolution/semantic_visitor.dart';
import '../resolution/operators.dart' as op;
import '../tree/tree.dart' as ast;
import '../types/types.dart' show
    TypeMask;
import '../universe/call_structure.dart' show
    CallStructure;
import '../universe/selector.dart' show
    Selector;
import '../constants/values.dart' show
    ConstantValue;
import 'cps_ir_nodes.dart' as ir;
import 'cps_ir_builder.dart';
import '../native/native.dart' show
    NativeBehavior,
    HasCapturedPlaceholders;

// TODO(karlklose): remove.
import '../js/js.dart' as js show js, Template, Expression, Name;
import '../ssa/ssa.dart' show TypeMaskFactory;
import '../util/util.dart';

import 'package:js_runtime/shared/embedded_names.dart'
    show JsBuiltin, JsGetName;
import '../constants/values.dart';
import 'type_mask_system.dart' show
    TypeMaskSystem;

typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);

/// This task provides the interface to build IR nodes from [ast.Node]s, which
/// is used from the [CpsFunctionCompiler] to generate code.
///
/// This class is mainly there to correctly measure how long building the IR
/// takes.
class IrBuilderTask extends CompilerTask {
  final SourceInformationStrategy sourceInformationStrategy;

  String bailoutMessage = null;

  /// If not null, this function will be called with for each
  /// [ir.FunctionDefinition] node that has been built.
  IrBuilderCallback builderCallback;

  IrBuilderTask(Compiler compiler, this.sourceInformationStrategy,
      [this.builderCallback])
      : super(compiler);

  String get name => 'CPS builder';

  ir.FunctionDefinition buildNode(AstElement element,
                                  TypeMaskSystem typeMaskSystem) {
    return measure(() {
      bailoutMessage = null;

      TreeElements elementsMapping = element.resolvedAst.elements;
      element = element.implementation;
      return reporter.withCurrentElement(element, () {
        SourceInformationBuilder sourceInformationBuilder =
            sourceInformationStrategy.createBuilderForContext(element);

        IrBuilderVisitor builder =
            new IrBuilderVisitor(
                elementsMapping, compiler, sourceInformationBuilder,
                typeMaskSystem);
        ir.FunctionDefinition irNode = builder.buildExecutable(element);
        if (irNode == null) {
          bailoutMessage = builder.bailoutMessage;
        } else if (builderCallback != null) {
          builderCallback(element, irNode);
        }
        return irNode;
      });
    });
  }
}

/// Translates the frontend AST of a method to its CPS IR.
///
/// The visitor has an [IrBuilder] which contains an IR fragment to build upon
/// and the current reaching definition of local variables.
///
/// Visiting a statement or expression extends the IR builder's fragment.
/// For expressions, the primitive holding the resulting value is returned.
/// For statements, `null` is returned.
// TODO(johnniwinther): Implement [SemanticDeclVisitor].
class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
    with IrBuilderMixin<ast.Node>,
         SemanticSendResolvedMixin<ir.Primitive, dynamic>,
         ErrorBulkMixin<ir.Primitive, dynamic>,
         BaseImplementationOfStaticsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfLocalsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfNewMixin<ir.Primitive, dynamic>,
         BaseImplementationOfCompoundsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfSetIfNullsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfIndexCompoundsMixin<ir.Primitive, dynamic>
    implements SemanticSendVisitor<ir.Primitive, dynamic> {
  final TreeElements elements;
  final Compiler compiler;
  final SourceInformationBuilder sourceInformationBuilder;
  final TypeMaskSystem typeMaskSystem;

  /// A map from try statements in the source to analysis information about
  /// them.
  ///
  /// The analysis information includes the set of variables that must be
  /// copied into [ir.MutableVariable]s on entry to the try and copied out on
  /// exit.
  Map<ast.Node, TryStatementInfo> tryStatements = null;

  // In SSA terms, join-point continuation parameters are the phis and the
  // continuation invocation arguments are the corresponding phi inputs.  To
  // support name introduction and renaming for source level variables, we use
  // nested (delimited) visitors for constructing subparts of the IR that will
  // need renaming.  Each source variable is assigned an index.
  //
  // Each nested visitor maintains a list of free variable uses in the body.
  // These are implemented as a list of parameters, each with their own use
  // list of references.  When the delimited subexpression is plugged into the
  // surrounding context, the free occurrences can be captured or become free
  // occurrences in the next outer delimited subexpression.
  //
  // Each nested visitor maintains a list that maps indexes of variables
  // assigned in the delimited subexpression to their reaching definition ---
  // that is, the definition in effect at the hole in 'current'.  These are
  // used to determine if a join-point continuation needs to be passed
  // arguments, and what the arguments are.

  /// Construct a top-level visitor.
  IrBuilderVisitor(this.elements,
                   this.compiler,
                   this.sourceInformationBuilder,
                   this.typeMaskSystem);

  JavaScriptBackend get backend => compiler.backend;
  BackendHelpers get helpers => backend.helpers;
  DiagnosticReporter get reporter => compiler.reporter;

  String bailoutMessage = null;

  ir.Primitive visit(ast.Node node) => node.accept(this);

  @override
  ir.Primitive apply(ast.Node node, _) => node.accept(this);

  SemanticSendVisitor get sendVisitor => this;

  /// Result of closure conversion for the current body of code.
  ///
  /// Will be initialized upon entering the body of a function.
  /// It is computed by the [ClosureTranslator].
  closure.ClosureClassMap closureClassMap;

  /// If [node] has declarations for variables that should be boxed,
  /// returns a [ClosureScope] naming a box to create, and enumerating the
  /// variables that should be stored in the box.
  ///
  /// Also see [ClosureScope].
  ClosureScope getClosureScopeForNode(ast.Node node) {
    // We translate a ClosureScope from closure.dart into IR builder's variant
    // because the IR builder should not depend on the synthetic elements
    // created in closure.dart.
    return new ClosureScope(closureClassMap.capturingScopes[node]);
  }

  /// Returns the [ClosureScope] for any function, possibly different from the
  /// one currently being built.
  ClosureScope getClosureScopeForFunction(FunctionElement function) {
    closure.ClosureClassMap map =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            function,
            function.node,
            elements);
    return new ClosureScope(map.capturingScopes[function.node]);
  }

  /// If the current function is a nested function with free variables (or a
  /// captured reference to `this`), returns a [ClosureEnvironment]
  /// indicating how to access these.
  ClosureEnvironment getClosureEnvironment() {
    return new ClosureEnvironment(closureClassMap);
  }

  IrBuilder getBuilderFor(Element element) {
    return new IrBuilder(
        new GlobalProgramInformation(compiler),
        backend.constants,
        element);
  }

  /// Builds the [ir.FunctionDefinition] for an executable element. In case the
  /// function uses features that cannot be expressed in the IR, this element
  /// returns `null`.
  ir.FunctionDefinition buildExecutable(ExecutableElement element) {
    return nullIfGiveup(() {
      ir.FunctionDefinition root;
      switch (element.kind) {
        case ElementKind.GENERATIVE_CONSTRUCTOR:
          root = buildConstructor(element);
          break;

        case ElementKind.GENERATIVE_CONSTRUCTOR_BODY:
          root = buildConstructorBody(element);
          break;

        case ElementKind.FACTORY_CONSTRUCTOR:
        case ElementKind.FUNCTION:
        case ElementKind.GETTER:
        case ElementKind.SETTER:
          root = buildFunction(element);
          break;

        case ElementKind.FIELD:
          if (Elements.isStaticOrTopLevel(element)) {
            root = buildStaticFieldInitializer(element);
          } else {
            // Instance field initializers are inlined in the constructor,
            // so we shouldn't need to build anything here.
            // TODO(asgerf): But what should we return?
            return null;
          }
          break;

        default:
          reporter.internalError(element, "Unexpected element type $element");
      }
      return root;
    });
  }

  /// Loads the type variables for all super classes of [superClass] into the
  /// IR builder's environment with their corresponding values.
  ///
  /// The type variables for [currentClass] must already be in the IR builder's
  /// environment.
  ///
  /// Type variables are stored as [TypeVariableLocal] in the environment.
  ///
  /// This ensures that access to type variables mentioned inside the
  /// constructors and initializers will happen through the local environment
  /// instead of using 'this'.
  void loadTypeVariablesForSuperClasses(ClassElement currentClass) {
    if (currentClass.isObject) return;
    loadTypeVariablesForType(currentClass.supertype);
    if (currentClass is MixinApplicationElement) {
      loadTypeVariablesForType(currentClass.mixinType);
    }
  }

  /// Loads all type variables for [type] and all of its super classes into
  /// the environment. All type variables mentioned in [type] must already
  /// be in the environment.
  void loadTypeVariablesForType(InterfaceType type) {
    ClassElement clazz = type.element;
    assert(clazz.typeVariables.length == type.typeArguments.length);
    for (int i = 0; i < clazz.typeVariables.length; ++i) {
      irBuilder.declareTypeVariable(clazz.typeVariables[i],
          type.typeArguments[i]);
    }
    loadTypeVariablesForSuperClasses(clazz);
  }

  /// Returns the constructor body associated with the given constructor or
  /// creates a new constructor body, if none can be found.
  ///
  /// Returns `null` if the constructor does not have a body.
  ConstructorBodyElement getConstructorBody(FunctionElement constructor) {
    // TODO(asgerf): This is largely inherited from the SSA builder.
    // The ConstructorBodyElement has an invalid function signature, but we
    // cannot add a BoxLocal as parameter, because BoxLocal is not an element.
    // Instead of forging ParameterElements to forge a FunctionSignature, we
    // need a way to create backend methods without creating more fake elements.
    assert(constructor.isGenerativeConstructor);
    assert(constructor.isImplementation);
    if (constructor.isSynthesized) return null;
    ast.FunctionExpression node = constructor.node;
    // If we know the body doesn't have any code, we don't generate it.
    if (!node.hasBody()) return null;
    if (node.hasEmptyBody()) return null;
    ClassElement classElement = constructor.enclosingClass;
    ConstructorBodyElement bodyElement;
    classElement.forEachBackendMember((Element backendMember) {
      if (backendMember.isGenerativeConstructorBody) {
        ConstructorBodyElement body = backendMember;
        if (body.constructor == constructor) {
          bodyElement = backendMember;
        }
      }
    });
    if (bodyElement == null) {
      bodyElement = new ConstructorBodyElementX(constructor);
      classElement.addBackendMember(bodyElement);

      if (constructor.isPatch) {
        // Create origin body element for patched constructors.
        ConstructorBodyElementX patch = bodyElement;
        ConstructorBodyElementX origin =
        new ConstructorBodyElementX(constructor.origin);
        origin.applyPatch(patch);
        classElement.origin.addBackendMember(bodyElement.origin);
      }
    }
    assert(bodyElement.isGenerativeConstructorBody);
    return bodyElement;
  }

  /// The list of parameters to send from the generative constructor
  /// to the generative constructor body.
  ///
  /// Boxed parameters are not in the list, instead, a [BoxLocal] is passed
  /// containing the boxed parameters.
  ///
  /// For example, given the following constructor,
  ///
  ///     Foo(x, y) : field = (() => ++x) { print(x + y) }
  ///
  /// the argument `x` would be replaced by a [BoxLocal]:
  ///
  ///     Foo_body(box0, y) { print(box0.x + y) }
  ///
  List<Local> getConstructorBodyParameters(ConstructorBodyElement body) {
    List<Local> parameters = <Local>[];
    ClosureScope scope = getClosureScopeForFunction(body.constructor);
    if (scope != null) {
      parameters.add(scope.box);
    }
    body.functionSignature.orderedForEachParameter((ParameterElement param) {
      if (scope != null && scope.capturedVariables.containsKey(param)) {
        // Do not pass this parameter; the box will carry its value.
      } else {
        parameters.add(param);
      }
    });
    return parameters;
  }

  /// Builds the IR for a given constructor.
  ///
  /// 1. Computes the type held in all own or "inherited" type variables.
  /// 2. Evaluates all own or inherited field initializers.
  /// 3. Creates the object and assigns its fields and runtime type.
  /// 4. Calls constructor body and super constructor bodies.
  /// 5. Returns the created object.
  ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
    // TODO(asgerf): Optimization: If constructor is redirecting, then just
    //               evaluate arguments and call the target constructor.
    constructor = constructor.implementation;
    ClassElement classElement = constructor.enclosingClass.implementation;

    IrBuilder builder = getBuilderFor(constructor);

    final bool requiresTypeInformation =
        builder.program.requiresRuntimeTypesFor(classElement);

    return withBuilder(builder, () {
      // Setup parameters and create a box if anything is captured.
      List<Local> parameters = <Local>[];
      constructor.functionSignature.orderedForEachParameter(
          (ParameterElement p) => parameters.add(p));

      int firstTypeArgumentParameterIndex;

      // If instances of the class may need runtime type information, we add a
      // synthetic parameter for each type parameter.
      if (requiresTypeInformation) {
        firstTypeArgumentParameterIndex = parameters.length;
        classElement.typeVariables.forEach((TypeVariableType variable) {
          parameters.add(new closure.TypeVariableLocal(variable, constructor));
        });
      } else {
        classElement.typeVariables.forEach((TypeVariableType variable) {
          irBuilder.declareTypeVariable(variable, const DynamicType());
        });
      }

      // Create IR parameters and setup the environment.
      List<ir.Parameter> irParameters = builder.buildFunctionHeader(parameters,
          closureScope: getClosureScopeForFunction(constructor));

      // Create a list of the values of all type argument parameters, if any.
      ir.Primitive typeInformation;
      if (requiresTypeInformation) {
        typeInformation = new ir.TypeExpression(
            ir.TypeExpressionKind.INSTANCE,
            classElement.thisType,
            irParameters.sublist(firstTypeArgumentParameterIndex));
        irBuilder.add(new ir.LetPrim(typeInformation));
      } else {
        typeInformation = null;
      }

      // -- Load values for type variables declared on super classes --
      // Field initializers for super classes can reference these, so they
      // must be available before evaluating field initializers.
      // This could be interleaved with field initialization, but we choose do
      // get it out of the way here to avoid complications with mixins.
      loadTypeVariablesForSuperClasses(classElement);

      /// Maps each field from this class or a superclass to its initial value.
      Map<FieldElement, ir.Primitive> fieldValues =
      <FieldElement, ir.Primitive>{};

      // -- Evaluate field initializers ---
      // Evaluate field initializers in constructor and super constructors.
      List<ConstructorElement> constructorList = <ConstructorElement>[];
      evaluateConstructorFieldInitializers(
          constructor, constructorList, fieldValues);

      // All parameters in all constructors are now bound in the environment.
      // BoxLocals for captured parameters are also in the environment.
      // The initial value of all fields are now bound in [fieldValues].

      // --- Create the object ---
      // Get the initial field values in the canonical order.
      List<ir.Primitive> instanceArguments = <ir.Primitive>[];
      classElement.forEachInstanceField((ClassElement c, FieldElement field) {
        ir.Primitive value = fieldValues[field];
        if (value != null) {
          instanceArguments.add(value);
        } else {
          assert(backend.isNativeOrExtendsNative(c));
          // Native fields are initialized elsewhere.
        }
      }, includeSuperAndInjectedMembers: true);

      ir.Primitive instance = new ir.CreateInstance(
          classElement,
          instanceArguments,
          typeInformation,
          constructor.hasNode
              ? sourceInformationBuilder.buildCreate(constructor.node)
          // TODO(johnniwinther): Provide source information for creation
          // through synthetic constructors.
              : null);
      irBuilder.add(new ir.LetPrim(instance));

      // --- Call constructor bodies ---
      for (ConstructorElement target in constructorList) {
        ConstructorBodyElement bodyElement = getConstructorBody(target);
        if (bodyElement == null) continue; // Skip if constructor has no body.
        List<ir.Primitive> bodyArguments = <ir.Primitive>[];
        for (Local param in getConstructorBodyParameters(bodyElement)) {
          bodyArguments.add(irBuilder.environment.lookup(param));
        }
        Selector selector = new Selector.call(target.memberName,
            new CallStructure(bodyArguments.length));
        irBuilder.addPrimitive(new ir.InvokeMethodDirectly(
            instance, bodyElement, selector, bodyArguments, null));
      }

      // --- step 4: return the created object ----
      irBuilder.buildReturn(
          value: instance,
          sourceInformation:
          sourceInformationBuilder.buildImplicitReturn(constructor));

      return irBuilder.makeFunctionDefinition();
    });
  }

  /// Make a visitor suitable for translating ASTs taken from [context].
  ///
  /// Every visitor can only be applied to nodes in one context, because
  /// the [elements] field is specific to that context.
  IrBuilderVisitor makeVisitorForContext(AstElement context) {
    return new IrBuilderVisitor(
        context.resolvedAst.elements,
        compiler,
        sourceInformationBuilder.forContext(context),
        typeMaskSystem);
  }

  /// Builds the IR for an [expression] taken from a different [context].
  ///
  /// Such expressions need to be compiled with a different [sourceFile] and
  /// [elements] mapping.
  ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
    IrBuilderVisitor visitor = makeVisitorForContext(context);
    return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
  }

  /// Evaluate the implicit super call in the given mixin constructor.
  void forwardSynthesizedMixinConstructor(
      ConstructorElement constructor,
      List<ConstructorElement> supers,
      Map<FieldElement, ir.Primitive> fieldValues) {
    assert(constructor.enclosingClass.implementation.isMixinApplication);
    assert(constructor.isSynthesized);
    ConstructorElement target =
        constructor.definingConstructor.implementation;
    // The resolver gives us the exact same FunctionSignature for the two
    // constructors. The parameters for the synthesized constructor
    // are already in the environment, so the target constructor's parameters
    // are also in the environment since their elements are the same.
    assert(constructor.functionSignature == target.functionSignature);
    IrBuilderVisitor visitor = makeVisitorForContext(target);
    visitor.withBuilder(irBuilder, () {
      visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
    });
  }

  /// In preparation of inlining (part of) [target], the [arguments] are moved
  /// into the environment bindings for the corresponding parameters.
  ///
  /// Defaults for optional arguments are evaluated in order to ensure
  /// all parameters are available in the environment.
  void loadArguments(ConstructorElement target,
      CallStructure call,
      List<ir.Primitive> arguments) {
    assert(target.isImplementation);
    assert(target == elements.analyzedElement);
    FunctionSignature signature = target.functionSignature;

    // Establish a scope in case parameters are captured.
    ClosureScope scope = getClosureScopeForFunction(target);
    irBuilder.enterScope(scope);

    // Load required parameters
    int index = 0;
    signature.forEachRequiredParameter((ParameterElement param) {
      irBuilder.declareLocalVariable(param, initialValue: arguments[index]);
      index++;
    });

    // Load optional parameters, evaluating default values for omitted ones.
    signature.forEachOptionalParameter((ParameterElement param) {
      ir.Primitive value;
      // Load argument if provided.
      if (signature.optionalParametersAreNamed) {
        int nameIndex = call.namedArguments.indexOf(param.name);
        if (nameIndex != -1) {
          int translatedIndex = call.positionalArgumentCount + nameIndex;
          value = arguments[translatedIndex];
        }
      } else if (index < arguments.length) {
        value = arguments[index];
      }
      // Load default if argument was not provided.
      if (value == null) {
        if (param.initializer != null) {
          value = visit(param.initializer);
        } else {
          value = irBuilder.buildNullConstant();
        }
      }
      irBuilder.declareLocalVariable(param, initialValue: value);
      index++;
    });
  }

  /// Evaluates a call to the given constructor from an initializer list.
  ///
  /// Calls [loadArguments] and [evaluateConstructorFieldInitializers] in a
  /// visitor that has the proper [TreeElements] mapping.
  void evaluateConstructorCallFromInitializer(
      ConstructorElement target,
      CallStructure call,
      List<ir.Primitive> arguments,
      List<ConstructorElement> supers,
      Map<FieldElement, ir.Primitive> fieldValues) {
    IrBuilderVisitor visitor = makeVisitorForContext(target);
    visitor.withBuilder(irBuilder, () {
      visitor.loadArguments(target, call, arguments);
      visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
    });
  }

  /// Evaluates all field initializers on [constructor] and all constructors
  /// invoked through `this()` or `super()` ("superconstructors").
  ///
  /// The resulting field values will be available in [fieldValues]. The values
  /// are not stored in any fields.
  ///
  /// This procedure assumes that the parameters to [constructor] are available
  /// in the IR builder's environment.
  ///
  /// The parameters to superconstructors are, however, assumed *not* to be in
  /// the environment, but will be put there by this procedure.
  ///
  /// All constructors will be added to [supers], with superconstructors first.
  void evaluateConstructorFieldInitializers(
      ConstructorElement constructor,
      List<ConstructorElement> supers,
      Map<FieldElement, ir.Primitive> fieldValues) {
    assert(constructor.isImplementation);
    assert(constructor == elements.analyzedElement);
    ClassElement enclosingClass = constructor.enclosingClass.implementation;
    // Evaluate declaration-site field initializers, unless this constructor
    // redirects to another using a `this()` initializer. In that case, these
    // will be initialized by the effective target constructor.
    if (!constructor.isRedirectingGenerative) {
      enclosingClass.forEachInstanceField((ClassElement c, FieldElement field) {
        if (field.initializer != null) {
          fieldValues[field] = inlineExpression(field, field.initializer);
        } else {
          if (backend.isNativeOrExtendsNative(c)) {
            // Native field is initialized elsewhere.
          } else {
            // Fields without an initializer default to null.
            // This value will be overwritten below if an initializer is found.
            fieldValues[field] = irBuilder.buildNullConstant();
          }
        }
      });
    }
    // If this is a mixin constructor, it does not have its own parameter list
    // or initializer list. Directly forward to the super constructor.
    // Note that the declaration-site initializers originating from the
    // mixed-in class were handled above.
    if (enclosingClass.isMixinApplication) {
      forwardSynthesizedMixinConstructor(constructor, supers, fieldValues);
      return;
    }
    // Evaluate initializing parameters, e.g. `Foo(this.x)`.
    constructor.functionSignature.orderedForEachParameter(
        (ParameterElement parameter) {
      if (parameter.isInitializingFormal) {
        InitializingFormalElement fieldParameter = parameter;
        fieldValues[fieldParameter.fieldElement] =
            irBuilder.buildLocalGet(parameter);
      }
    });
    // Evaluate constructor initializers, e.g. `Foo() : x = 50`.
    ast.FunctionExpression node = constructor.node;
    bool hasConstructorCall = false; // Has this() or super() initializer?
    if (node != null && node.initializers != null) {
      for(ast.Node initializer in node.initializers) {
        if (initializer is ast.SendSet) {
          // Field initializer.
          FieldElement field = elements[initializer];
          fieldValues[field] = visit(initializer.arguments.head);
        } else if (initializer is ast.Send) {
          // Super or this initializer.
          ConstructorElement target = elements[initializer].implementation;
          Selector selector = elements.getSelector(initializer);
          List<ir.Primitive> arguments = initializer.arguments.mapToList(visit);
          evaluateConstructorCallFromInitializer(
              target,
              selector.callStructure,
              arguments,
              supers,
              fieldValues);
          hasConstructorCall = true;
        } else {
          reporter.internalError(initializer,
              "Unexpected initializer type $initializer");
        }
      }
    }
    // If no super() or this() was found, also call default superconstructor.
    if (!hasConstructorCall && !enclosingClass.isObject) {
      ClassElement superClass = enclosingClass.superclass;
      FunctionElement target = superClass.lookupDefaultConstructor();
      if (target == null) {
        reporter.internalError(superClass, "No default constructor available.");
      }
      target = target.implementation;
      evaluateConstructorCallFromInitializer(
          target,
          CallStructure.NO_ARGS,
          const [],
          supers,
          fieldValues);
    }
    // Add this constructor after the superconstructors.
    supers.add(constructor);
  }

  TryBoxedVariables _analyzeTryBoxedVariables(ast.Node node) {
    TryBoxedVariables variables = new TryBoxedVariables(elements);
    try {
      variables.analyze(node);
    } catch (e) {
      bailoutMessage = variables.bailoutMessage;
      rethrow;
    }
    return variables;
  }

  /// Builds the IR for the body of a constructor.
  ///
  /// This function is invoked from one or more "factory" constructors built by
  /// [buildConstructor].
  ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) {
    ConstructorElement constructor = body.constructor;
    ast.FunctionExpression node = constructor.node;
    closureClassMap =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            constructor,
            node,
            elements);

    // We compute variables boxed in mutable variables on entry to each try
    // block, not including variables captured by a closure (which are boxed
    // in the heap).  This duplicates some of the work of closure conversion
    // without directly using the results.  This duplication is wasteful and
    // error-prone.
    // TODO(kmillikin): We should combine closure conversion and try/catch
    // variable analysis in some way.
    TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
    tryStatements = variables.tryStatements;
    IrBuilder builder = getBuilderFor(body);

    return withBuilder(builder, () {
      irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body),
          getClosureScopeForNode(node));
      visit(node.body);
      return irBuilder.makeFunctionDefinition();
    });
  }

  ir.FunctionDefinition buildFunction(FunctionElement element) {
    assert(invariant(element, element.isImplementation));
    ast.FunctionExpression node = element.node;

    assert(!element.isSynthesized);
    assert(node != null);
    assert(elements[node] != null);

    closureClassMap =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            element,
            node,
            elements);
    TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
    tryStatements = variables.tryStatements;
    IrBuilder builder = getBuilderFor(element);
    return withBuilder(builder,
        () => _makeFunctionBody(builder, element, node));
  }

  ir.FunctionDefinition buildStaticFieldInitializer(FieldElement element) {
    if (!backend.constants.lazyStatics.contains(element)) {
      return null; // Nothing to do.
    }
    closureClassMap =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            element,
            element.node,
            elements);
    IrBuilder builder = getBuilderFor(element);
    return withBuilder(builder, () {
      irBuilder.buildFunctionHeader(<Local>[]);
      ir.Primitive initialValue = visit(element.initializer);
      ast.VariableDefinitions node = element.node;
      ast.SendSet sendSet = node.definitions.nodes.head;
      irBuilder.buildReturn(
          value: initialValue,
          sourceInformation:
          sourceInformationBuilder.buildReturn(sendSet.assignmentOperator));
      return irBuilder.makeFunctionDefinition();
    });
  }

  /// Builds the IR for a constant taken from a different [context].
  ///
  /// Such constants need to be compiled with a different [sourceFile] and
  /// [elements] mapping.
  ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
    IrBuilderVisitor visitor = makeVisitorForContext(context);
    return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
  }

  /// Creates a primitive for the default value of [parameter].
  ir.Primitive translateDefaultValue(ParameterElement parameter) {
    if (parameter.initializer == null) {
      return irBuilder.buildNullConstant();
    } else {
      return inlineConstant(parameter.executableContext, parameter.initializer);
    }
  }

  /// Normalizes the argument list of a static invocation.
  ///
  /// A static invocation is one where the target is known.  The argument list
  /// [arguments] is normalized by adding default values for optional arguments
  /// that are not passed, and by sorting it in place so that named arguments
  /// appear in a canonical order.  A [CallStructure] reflecting this order
  /// is returned.
  CallStructure normalizeStaticArguments(CallStructure callStructure,
      FunctionElement target,
      List<ir.Primitive> arguments) {
    target = target.implementation;
    FunctionSignature signature = target.functionSignature;
    if (!signature.optionalParametersAreNamed &&
        signature.parameterCount == arguments.length) {
      return callStructure;
    }

    if (!signature.optionalParametersAreNamed) {
      int i = signature.requiredParameterCount;
      signature.forEachOptionalParameter((ParameterElement element) {
        if (i < callStructure.positionalArgumentCount) {
          ++i;
        } else {
          arguments.add(translateDefaultValue(element));
        }
      });
      return new CallStructure(signature.parameterCount);
    }

    int offset = signature.requiredParameterCount;
    List<ir.Primitive> namedArguments = arguments.sublist(offset);
    arguments.length = offset;
    List<String> normalizedNames = <String>[];
    // Iterate over the optional parameters of the signature, and try to
    // find them in the callStructure's named arguments. If found, we use the
    // value in the temporary list, otherwise the default value.
    signature.orderedOptionalParameters.forEach((ParameterElement element) {
      int nameIndex = callStructure.namedArguments.indexOf(element.name);
      arguments.add(nameIndex == -1 ? translateDefaultValue(element)
          : namedArguments[nameIndex]);
      normalizedNames.add(element.name);
    });
    return new CallStructure(signature.parameterCount, normalizedNames);
  }

  /// Normalizes the argument list of a dynamic invocation.
  ///
  /// A dynamic invocation is one where the target is not known.  The argument
  /// list [arguments] is normalized by sorting it in place so that the named
  /// arguments appear in a canonical order.  A [CallStructure] reflecting this
  /// order is returned.
  CallStructure normalizeDynamicArguments(CallStructure callStructure,
      List<ir.Primitive> arguments) {
    assert(arguments.length == callStructure.argumentCount);
    if (callStructure.namedArguments.isEmpty) return callStructure;
    int destinationIndex = callStructure.positionalArgumentCount;
    List<ir.Primitive> namedArguments = arguments.sublist(destinationIndex);
    for (String argName in callStructure.getOrderedNamedArguments()) {
      int sourceIndex = callStructure.namedArguments.indexOf(argName);
      arguments[destinationIndex++] = namedArguments[sourceIndex];
    }
    return new CallStructure(callStructure.argumentCount,
        callStructure.getOrderedNamedArguments());
  }

  /// Read the value of [field].
  ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) {
    ConstantValue constant = getConstantForVariable(field);
    if (constant != null && !field.isAssignable) {
      typeMaskSystem.associateConstantValueWithElement(constant, field);
      return irBuilder.buildConstant(constant, sourceInformation: src);
    } else if (backend.constants.lazyStatics.contains(field)) {
      return irBuilder.addPrimitive(new ir.GetLazyStatic(field, src));
    } else {
      return irBuilder.addPrimitive(new ir.GetStatic(field, src));
    }
  }

  ir.FunctionDefinition _makeFunctionBody(
      IrBuilder builder,
      FunctionElement element,
      ast.FunctionExpression node) {
    FunctionSignature signature = element.functionSignature;
    List<Local> parameters = <Local>[];
    signature.orderedForEachParameter(
        (LocalParameterElement e) => parameters.add(e));

    bool requiresRuntimeTypes = false;
    if (element.isFactoryConstructor) {
      requiresRuntimeTypes =
          builder.program.requiresRuntimeTypesFor(element.enclosingElement);
      if (requiresRuntimeTypes) {
        // Type arguments are passed in as extra parameters.
        for (DartType typeVariable in element.enclosingClass.typeVariables) {
          parameters.add(new closure.TypeVariableLocal(typeVariable, element));
        }
      }
    }

    irBuilder.buildFunctionHeader(parameters,
                                  closureScope: getClosureScopeForNode(node),
                                  env: getClosureEnvironment());

    if (element == helpers.jsArrayTypedConstructor) {
      // Generate a body for JSArray<E>.typed(allocation):
      //
      //    t1 = setRuntimeTypeInfo(allocation, TypeExpression($E));
      //    return Refinement(t1, <JSArray>);
      //
      assert(parameters.length == 1 || parameters.length == 2);
      ir.Primitive allocation = irBuilder.buildLocalGet(parameters[0]);
      ClassElement classElement = element.enclosingElement;

      // Only call setRuntimeTypeInfo if JSArray requires the type parameter.
      if (requiresRuntimeTypes) {
        assert(parameters.length == 2);
        closure.TypeVariableLocal typeParameter = parameters[1];
        ir.Primitive typeArgument =
            irBuilder.buildTypeVariableAccess(typeParameter.typeVariable);

        ir.Primitive typeInformation = irBuilder.addPrimitive(
            new ir.TypeExpression(ir.TypeExpressionKind.INSTANCE,
                                  element.enclosingClass.thisType,
                                  <ir.Primitive>[typeArgument]));

        MethodElement helper = helpers.setRuntimeTypeInfo;
        CallStructure callStructure = CallStructure.TWO_ARGS;
        Selector selector = new Selector.call(helper.memberName, callStructure);
        allocation = irBuilder.buildInvokeStatic(
            helper, selector, <ir.Primitive>[allocation, typeInformation],
            sourceInformationBuilder.buildGeneric(node));
      }

      ir.Primitive refinement = irBuilder.addPrimitive(
          new ir.Refinement(allocation, typeMaskSystem.arrayType));

      irBuilder.buildReturn(value: refinement,
          sourceInformation:
              sourceInformationBuilder.buildImplicitReturn(element));
    } else {
      visit(node.body);
    }
    return irBuilder.makeFunctionDefinition();
  }

  /// Builds the IR for creating an instance of the closure class corresponding
  /// to the given nested function.
  closure.ClosureClassElement makeSubFunction(ast.FunctionExpression node) {
    closure.ClosureClassMap innerMap =
        compiler.closureToClassMapper.getMappingForNestedFunction(node);
    closure.ClosureClassElement closureClass = innerMap.closureClassElement;
    return closureClass;
  }

  ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
    return irBuilder.buildFunctionExpression(makeSubFunction(node),
        sourceInformationBuilder.buildCreate(node));
  }

  visitFunctionDeclaration(ast.FunctionDeclaration node) {
    LocalFunctionElement element = elements[node.function];
    Object inner = makeSubFunction(node.function);
    irBuilder.declareLocalFunction(element, inner,
        sourceInformationBuilder.buildCreate(node.function));
  }

  // ## Statements ##
  visitBlock(ast.Block node) {
    irBuilder.buildBlock(node.statements.nodes, build);
  }

  ir.Primitive visitBreakStatement(ast.BreakStatement node) {
    if (!irBuilder.buildBreak(elements.getTargetOf(node))) {
      reporter.internalError(node, "'break' target not found");
    }
    return null;
  }

  ir.Primitive visitContinueStatement(ast.ContinueStatement node) {
    if (!irBuilder.buildContinue(elements.getTargetOf(node))) {
      reporter.internalError(node, "'continue' target not found");
    }
    return null;
  }

  // Build(EmptyStatement, C) = C
  ir.Primitive visitEmptyStatement(ast.EmptyStatement node) {
    assert(irBuilder.isOpen);
    return null;
  }

  // Build(ExpressionStatement(e), C) = C'
  //   where (C', _) = Build(e, C)
  ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) {
    assert(irBuilder.isOpen);
    if (node.expression is ast.Throw) {
      // Throw expressions that occur as statements are translated differently
      // from ones that occur as subexpressions.  This is achieved by peeking
      // at statement-level expressions here.
      irBuilder.buildThrow(visit(node.expression));
    } else {
      visit(node.expression);
    }
    return null;
  }

  ir.Primitive visitRethrow(ast.Rethrow node) {
    assert(irBuilder.isOpen);
    irBuilder.buildRethrow();
    return null;
  }

  /// Construct a method that executes the forwarding call to the target
  /// constructor.  This is only required, if the forwarding factory
  /// constructor can potentially be the target of a reflective call, because
  /// the builder shortcuts calls to redirecting factories at the call site
  /// (see [handleConstructorInvoke]).
  visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
    ConstructorElement targetConstructor =
        elements.getRedirectingTargetConstructor(node).implementation;
    ConstructorElement redirectingConstructor =
        irBuilder.state.currentElement.implementation;
    List<ir.Primitive> arguments = <ir.Primitive>[];
    FunctionSignature redirectingSignature =
        redirectingConstructor.functionSignature;
    List<String> namedParameters = <String>[];
    redirectingSignature.forEachParameter((ParameterElement parameter) {
      arguments.add(irBuilder.environment.lookup(parameter));
      if (parameter.isNamed) {
        namedParameters.add(parameter.name);
      }
    });
    ClassElement cls = redirectingConstructor.enclosingClass;
    InterfaceType targetType =
          redirectingConstructor.computeEffectiveTargetType(cls.thisType);
    CallStructure callStructure = new CallStructure(
        redirectingSignature.parameterCount,
        namedParameters);
    callStructure =
        normalizeStaticArguments(callStructure, targetConstructor, arguments);
    ir.Primitive instance = irBuilder.buildConstructorInvocation(
        targetConstructor,
        callStructure,
        targetType,
        arguments,
        sourceInformationBuilder.buildNew(node));
    irBuilder.buildReturn(
        value: instance,
        sourceInformation: sourceInformationBuilder.buildReturn(node));
  }

  visitFor(ast.For node) {
    List<LocalElement> loopVariables = <LocalElement>[];
    if (node.initializer is ast.VariableDefinitions) {
      ast.VariableDefinitions definitions = node.initializer;
      for (ast.Node node in definitions.definitions.nodes) {
        LocalElement loopVariable = elements[node];
        loopVariables.add(loopVariable);
      }
    }

    JumpTarget target = elements.getTargetDefinition(node);
    irBuilder.buildFor(
        buildInitializer: subbuild(node.initializer),
        buildCondition: subbuild(node.condition),
        buildBody: subbuild(node.body),
        buildUpdate: subbuildSequence(node.update),
        closureScope: getClosureScopeForNode(node),
        loopVariables: loopVariables,
        target: target);
  }

  visitIf(ast.If node) {
    irBuilder.buildIf(
        build(node.condition),
        subbuild(node.thenPart),
        subbuild(node.elsePart));
  }

  visitLabeledStatement(ast.LabeledStatement node) {
    ast.Statement body = node.statement;
    if (body is ast.Loop) {
      visit(body);
    } else {
      JumpTarget target = elements.getTargetDefinition(body);
      irBuilder.buildLabeledStatement(
          buildBody: subbuild(body),
          target: target);
    }
  }

  visitDoWhile(ast.DoWhile node) {
    irBuilder.buildDoWhile(
        buildBody: subbuild(node.body),
        buildCondition: subbuild(node.condition),
        target: elements.getTargetDefinition(node),
        closureScope: getClosureScopeForNode(node));
  }

  visitWhile(ast.While node) {
    irBuilder.buildWhile(
        buildCondition: subbuild(node.condition),
        buildBody: subbuild(node.body),
        target: elements.getTargetDefinition(node),
        closureScope: getClosureScopeForNode(node));
  }

  visitAsyncForIn(ast.AsyncForIn node) {
    // await for is not yet implemented.
    return giveup(node, 'await for');
  }

  visitAwait(ast.Await node) {
    assert(irBuilder.isOpen);
    ir.Primitive value = visit(node.expression);
    return irBuilder.addPrimitive(new ir.Await(value));
  }

  visitYield(ast.Yield node) {
    assert(irBuilder.isOpen);
    ir.Primitive value = visit(node.expression);
    return irBuilder.addPrimitive(new ir.Yield(value, node.hasStar));
  }

  visitSyncForIn(ast.SyncForIn node) {
    // [node.declaredIdentifier] can be either an [ast.VariableDefinitions]
    // (defining a new local variable) or a send designating some existing
    // variable.
    ast.Node identifier = node.declaredIdentifier;
    ast.VariableDefinitions variableDeclaration =
        identifier.asVariableDefinitions();
    Element variableElement = elements.getForInVariable(node);
    Selector selector = elements.getSelector(identifier);

    irBuilder.buildForIn(
        buildExpression: subbuild(node.expression),
        buildVariableDeclaration: subbuild(variableDeclaration),
        variableElement: variableElement,
        variableSelector: selector,
        variableMask: elements.getTypeMask(identifier),
        currentMask: elements.getCurrentTypeMask(node),
        moveNextMask: elements.getMoveNextTypeMask(node),
        iteratorMask: elements.getIteratorTypeMask(node),
        buildBody: subbuild(node.body),
        target: elements.getTargetDefinition(node),
        closureScope: getClosureScopeForNode(node));
  }

  /// If compiling with trusted type annotations, assumes that [value] is
  /// now known to be `null` or an instance of [type].
  ///
  /// This is also where we should add type checks in checked mode, but this
  /// is not supported yet.
  ir.Primitive checkType(ir.Primitive value, DartType dartType) {
    if (!compiler.trustTypeAnnotations) return value;
    TypeMask type = typeMaskSystem.subtypesOf(dartType).nullable();
    return irBuilder.addPrimitive(new ir.Refinement(value, type));
  }

  ir.Primitive checkTypeVsElement(ir.Primitive value, TypedElement element) {
    return checkType(value, element.type);
  }

  ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
    assert(irBuilder.isOpen);
    for (ast.Node definition in node.definitions.nodes) {
      Element element = elements[definition];
      ir.Primitive initialValue;
      // Definitions are either SendSets if there is an initializer, or
      // Identifiers if there is no initializer.
      if (definition is ast.SendSet) {
        assert(!definition.arguments.isEmpty);
        assert(definition.arguments.tail.isEmpty);
        initialValue = visit(definition.arguments.head);
        initialValue = checkTypeVsElement(initialValue, element);
      } else {
        assert(definition is ast.Identifier);
      }
      irBuilder.declareLocalVariable(element, initialValue: initialValue);
    }
    return null;
  }

  static final RegExp nativeRedirectionRegExp =
      new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$');

  // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
  //   where (C', x) = Build(e, C)
  //
  // Return without a subexpression is translated as if it were return null.
  visitReturn(ast.Return node) {
    assert(irBuilder.isOpen);
    SourceInformation source = sourceInformationBuilder.buildReturn(node);
    if (node.beginToken.value == 'native') {
      FunctionElement function = irBuilder.state.currentElement;
      assert(backend.isNative(function));
      ast.Node nativeBody = node.expression;
      if (nativeBody != null) {
        ast.LiteralString jsCode = nativeBody.asLiteralString();
        String javaScriptCode = jsCode.dartString.slowToString();
        assert(invariant(nativeBody,
            !nativeRedirectionRegExp.hasMatch(javaScriptCode),
          message: "Deprecated syntax, use @JSName('name') instead."));
        assert(invariant(nativeBody,
            function.functionSignature.parameterCount == 0,
            message: 'native "..." syntax is restricted to '
              'functions with zero parameters.'));
        irBuilder.buildNativeFunctionBody(function, javaScriptCode);
      } else {
        String name = backend.getFixedBackendName(function);
        irBuilder.buildRedirectingNativeFunctionBody(function, name, source);
      }
    } else {
      irBuilder.buildReturn(
          value: build(node.expression),
          sourceInformation: source);
    }
  }

  visitSwitchStatement(ast.SwitchStatement node) {
    // Dart switch cases can be labeled and be the target of continue from
    // within the switch.  Such cases are 'recursive'.  If there are any
    // recursive cases, we implement the switch using a pair of switches with
    // the second one switching over a state variable in a loop.  The first
    // switch contains the non-recursive cases, and the second switch contains
    // the recursive ones.
    //
    // For example, for the Dart switch:
    //
    // switch (E) {
    //   case 0:
    //     BODY0;
    //     break;
    //   LABEL0: case 1:
    //     BODY1;
    //     break;
    //   case 2:
    //     BODY2;
    //     continue LABEL1;
    //   LABEL1: case 3:
    //     BODY3;
    //     continue LABEL0;
    //   default:
    //     BODY4;
    // }
    //
    // We translate it as if it were the JavaScript:
    //
    // var state = -1;
    // switch (E) {
    //   case 0:
    //     BODY0;
    //     break;
    //   case 1:
    //     state = 0;  // Recursive, label ID = 0.
    //     break;
    //   case 2:
    //     BODY2;
    //     state = 1;  // Continue to label ID = 1.
    //     break;
    //   case 3:
    //     state = 1;  // Recursive, label ID = 1.
    //     break;
    //   default:
    //     BODY4;
    // }
    // L: while (state != -1) {
    //   case 0:
    //     BODY1;
    //     break L;  // Break from switch becomes break from loop.
    //   case 1:
    //     BODY2;
    //     state = 0;  // Continue to label ID = 0.
    //     break;
    // }
    assert(irBuilder.isOpen);
    // Preprocess: compute a list of cases that are the target of continue.
    // These are the so-called 'recursive' cases.
    List<JumpTarget> continueTargets = <JumpTarget>[];
    List<ast.Node> switchCases = node.cases.nodes.toList();
    for (ast.SwitchCase switchCase in switchCases) {
      for (ast.Node labelOrCase in switchCase.labelsAndCases) {
        if (labelOrCase is ast.Label) {
          LabelDefinition definition = elements.getLabelDefinition(labelOrCase);
          if (definition != null && definition.isContinueTarget) {
            continueTargets.add(definition.target);
          }
        }
      }
    }

    // If any cases are continue targets, use an anonymous local value to
    // implement a state machine.  The initial value is -1.
    ir.Primitive initial;
    int stateIndex;
    if (continueTargets.isNotEmpty) {
      initial = irBuilder.buildIntegerConstant(-1);
      stateIndex = irBuilder.environment.length;
      irBuilder.environment.extend(null, initial);
    }

    // Use a simple switch for the non-recursive cases.  A break will go to the
    // join-point after the switch.  A continue to a labeled case will assign
    // to the state variable and go to the join-point.
    ir.Primitive value = visit(node.expression);
    JumpCollector join = new ForwardJumpCollector(irBuilder.environment,
        target: elements.getTargetDefinition(node));
    irBuilder.state.breakCollectors.add(join);
    for (int i = 0; i < continueTargets.length; ++i) {
      // The state value is i, the case's position in the list of recursive
      // cases.
      irBuilder.state.continueCollectors.add(new GotoJumpCollector(
          continueTargets[i], stateIndex, i, join));
    }

    // For each non-default case use a pair of functions, one to translate the
    // condition and one to translate the body.  For the default case use a
    // function to translate the body.  Use continueTargetIterator as a pointer
    // to the next recursive case.
    Iterator<JumpTarget> continueTargetIterator = continueTargets.iterator;
    continueTargetIterator.moveNext();
    List<SwitchCaseInfo> cases = <SwitchCaseInfo>[];
    SubbuildFunction buildDefaultBody;
    for (ast.SwitchCase switchCase in switchCases) {
      JumpTarget nextContinueTarget = continueTargetIterator.current;
      if (switchCase.isDefaultCase) {
        if (nextContinueTarget != null &&
            switchCase == nextContinueTarget.statement) {
          // In this simple switch, recursive cases are as if they immediately
          // continued to themselves.
          buildDefaultBody = nested(() {
            irBuilder.buildContinue(nextContinueTarget);
          });
          continueTargetIterator.moveNext();
        } else {
          // Non-recursive cases consist of the translation of the body.
          // For the default case, there is implicitly a break if control
          // flow reaches the end.
          buildDefaultBody = nested(() {
            irBuilder.buildSequence(switchCase.statements, visit);
            if (irBuilder.isOpen) irBuilder.jumpTo(join);
          });
        }
        continue;
      }

      ir.Primitive buildCondition(IrBuilder builder) {
        // There can be multiple cases sharing the same body, because empty
        // cases are allowed to fall through to the next one.  Each case is
        // a comparison, build a short-circuited disjunction of all of them.
        return withBuilder(builder, () {
          ir.Primitive condition;
          for (ast.Node labelOrCase in switchCase.labelsAndCases) {
            if (labelOrCase is ast.CaseMatch) {
              ir.Primitive buildComparison() {
                ir.Primitive constant =
                    translateConstant(labelOrCase.expression);
                return irBuilder.buildIdentical(value, constant);
              }

              if (condition == null) {
                condition = buildComparison();
              } else {
                condition = irBuilder.buildLogicalOperator(condition,
                    nested(buildComparison), isLazyOr: true);
              }
            }
          }
          return condition;
        });
      }

      SubbuildFunction buildBody;
      if (nextContinueTarget != null &&
          switchCase == nextContinueTarget.statement) {
        // Recursive cases are as if they immediately continued to themselves.
        buildBody = nested(() {
          irBuilder.buildContinue(nextContinueTarget);
        });
        continueTargetIterator.moveNext();
      } else {
        // Non-recursive cases consist of the translation of the body.  It is a
        // runtime error if control-flow reaches the end of the body of any but
        // the last case.
        buildBody = (IrBuilder builder) {
          withBuilder(builder, () {
            irBuilder.buildSequence(switchCase.statements, visit);
            if (irBuilder.isOpen) {
              if (switchCase == switchCases.last) {
                irBuilder.jumpTo(join);
              } else {
                Element error = helpers.fallThroughError;
                ir.Primitive exception = irBuilder.buildInvokeStatic(
                    error,
                    new Selector.fromElement(error),
                    <ir.Primitive>[],
                    sourceInformationBuilder.buildGeneric(node));
                irBuilder.buildThrow(exception);
              }
            }
          });
          return null;
        };
      }

      cases.add(new SwitchCaseInfo(buildCondition, buildBody));
    }

    irBuilder.buildSimpleSwitch(join, cases, buildDefaultBody);
    irBuilder.state.breakCollectors.removeLast();
    irBuilder.state.continueCollectors.length -= continueTargets.length;
    if (continueTargets.isEmpty) return;

    // If there were recursive cases build a while loop whose body is a
    // switch containing (only) the recursive cases.  The condition is
    // 'state != initialValue' so the loop is not taken when the state variable
    // has not been assigned.
    //
    // 'loop' is the join-point of the exits from the inner switch which will
    // perform another iteration of the loop.  'exit' is the join-point of the
    // breaks from the switch, outside the loop.
    JumpCollector loop = new ForwardJumpCollector(irBuilder.environment);
    JumpCollector exit = new ForwardJumpCollector(irBuilder.environment,
        target: elements.getTargetDefinition(node));
    irBuilder.state.breakCollectors.add(exit);
    for (int i = 0; i < continueTargets.length; ++i) {
      irBuilder.state.continueCollectors.add(new GotoJumpCollector(
          continueTargets[i], stateIndex, i, loop));
    }
    cases.clear();
    for (int i = 0; i < continueTargets.length; ++i) {
      // The conditions compare to the recursive case index.
      ir.Primitive buildCondition(IrBuilder builder) {
        ir.Primitive constant = builder.buildIntegerConstant(i);
        return builder.buildIdentical(
            builder.environment.index2value[stateIndex], constant);
      }

      ir.Primitive buildBody(IrBuilder builder) {
        withBuilder(builder, () {
          ast.SwitchCase switchCase = continueTargets[i].statement;
          irBuilder.buildSequence(switchCase.statements, visit);
          if (irBuilder.isOpen) {
            if (switchCase == switchCases.last) {
              irBuilder.jumpTo(exit);
            } else {
              Element error = helpers.fallThroughError;
              ir.Primitive exception = irBuilder.buildInvokeStatic(
                  error,
                  new Selector.fromElement(error),
                  <ir.Primitive>[],
                  sourceInformationBuilder.buildGeneric(node));
              irBuilder.buildThrow(exception);
            }
          }
        });
        return null;
      }

      cases.add(new SwitchCaseInfo(buildCondition, buildBody));
    }

    // A loop with a simple switch in the body.
    IrBuilder whileBuilder = irBuilder.makeDelimitedBuilder();
    whileBuilder.buildWhile(
        buildCondition: (IrBuilder builder) {
          ir.Primitive condition = builder.buildIdentical(
              builder.environment.index2value[stateIndex], initial);
          return builder.buildNegation(condition);
        },
        buildBody: (IrBuilder builder) {
          builder.buildSimpleSwitch(loop, cases, null);
        });
    // Jump to the exit continuation.  This jump is the body of the loop exit
    // continuation, so the loop exit continuation can be eta-reduced.  The
    // jump is here for simplicity because `buildWhile` does not expose the
    // loop's exit continuation directly and has already emitted all jumps
    // to it anyway.
    whileBuilder.jumpTo(exit);
    irBuilder.add(new ir.LetCont(exit.continuation, whileBuilder.root));
    irBuilder.environment = exit.environment;
    irBuilder.environment.discard(1);  // Discard the state variable.
    irBuilder.state.breakCollectors.removeLast();
    irBuilder.state.continueCollectors.length -= continueTargets.length;
  }

  visitTryStatement(ast.TryStatement node) {
    List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[];
    for (ast.CatchBlock catchClause in node.catchBlocks.nodes) {
      LocalVariableElement exceptionVariable;
      if (catchClause.exception != null) {
        exceptionVariable = elements[catchClause.exception];
      }
      LocalVariableElement stackTraceVariable;
      if (catchClause.trace != null) {
        stackTraceVariable = elements[catchClause.trace];
      }
      DartType type;
      if (catchClause.onKeyword != null) {
        type = elements.getType(catchClause.type);
      }
      catchClauseInfos.add(new CatchClauseInfo(
          type: type,
          exceptionVariable: exceptionVariable,
          stackTraceVariable: stackTraceVariable,
          buildCatchBlock: subbuild(catchClause.block)));
    }

    assert(!node.catchBlocks.isEmpty || node.finallyBlock != null);
    if (!node.catchBlocks.isEmpty && node.finallyBlock != null) {
      // Try/catch/finally is encoded in terms of try/catch and try/finally:
      //
      // try tryBlock catch (ex, st) catchBlock finally finallyBlock
      // ==>
      // try { try tryBlock catch (ex, st) catchBlock } finally finallyBlock
      irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
          (IrBuilder inner) {
            inner.buildTryCatch(tryStatements[node.catchBlocks],
                subbuild(node.tryBlock),
                catchClauseInfos);
          },
          subbuild(node.finallyBlock));
    } else if (!node.catchBlocks.isEmpty) {
      irBuilder.buildTryCatch(tryStatements[node.catchBlocks],
          subbuild(node.tryBlock),
          catchClauseInfos);
    } else {
      irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
          subbuild(node.tryBlock),
          subbuild(node.finallyBlock));
    }
  }

  // ## Expressions ##
  ir.Primitive visitConditional(ast.Conditional node) {
    return irBuilder.buildConditional(
        build(node.condition),
        subbuild(node.thenExpression),
        subbuild(node.elseExpression));
  }

  // For all simple literals:
  // Build(Literal(c), C) = C[let val x = Constant(c) in [], x]
  ir.Primitive visitLiteralBool(ast.LiteralBool node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildBooleanConstant(node.value);
  }

  ir.Primitive visitLiteralDouble(ast.LiteralDouble node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildDoubleConstant(node.value);
  }

  ir.Primitive visitLiteralInt(ast.LiteralInt node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildIntegerConstant(node.value);
  }

  ir.Primitive visitLiteralNull(ast.LiteralNull node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildNullConstant();
  }

  ir.Primitive visitLiteralString(ast.LiteralString node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildDartStringConstant(node.dartString);
  }

  ConstantValue getConstantForNode(ast.Node node) {
    return irBuilder.state.constants.getConstantValueForNode(node, elements);
  }

  ConstantValue getConstantForVariable(VariableElement element) {
    return irBuilder.state.constants.getConstantValueForVariable(element);
  }

  ir.Primitive buildConstantExpression(ConstantExpression expression,
                                       SourceInformation sourceInformation) {
    return irBuilder.buildConstant(
        irBuilder.state.constants.getConstantValue(expression),
        sourceInformation: sourceInformation);
  }

  /// Returns the allocation site-specific type for a given allocation.
  ///
  /// Currently, it is an error to call this with anything that is not the
  /// allocation site for a List object (a literal list or a call to one
  /// of the List constructors).
  TypeMask getAllocationSiteType(ast.Node node) {
    return compiler.typesTask.getGuaranteedTypeOfNode(
        elements.analyzedElement, node);
  }

  ir.Primitive visitLiteralList(ast.LiteralList node) {
    if (node.isConst) {
      return translateConstant(node);
    }
    List<ir.Primitive> values = node.elements.nodes.mapToList(visit);
    InterfaceType type = elements.getType(node);
    TypeMask allocationSiteType = getAllocationSiteType(node);
    // TODO(sra): In checked mode, the elements must be checked as though
    // operator[]= is called.
    ir.Primitive list = irBuilder.buildListLiteral(type, values,
          allocationSiteType: allocationSiteType);
    if (type.treatAsRaw) return list;
    // Call JSArray<E>.typed(allocation) to install the reified type.
    ConstructorElement constructor = helpers.jsArrayTypedConstructor;
    ir.Primitive tagged = irBuilder.buildConstructorInvocation(
        constructor.effectiveTarget,
        CallStructure.ONE_ARG,
        constructor.computeEffectiveTargetType(type),
        <ir.Primitive>[list],
        sourceInformationBuilder.buildNew(node));

    if (allocationSiteType == null) return tagged;

    return irBuilder.addPrimitive(
        new ir.Refinement(tagged, allocationSiteType));
  }

  ir.Primitive visitLiteralMap(ast.LiteralMap node) {
    assert(irBuilder.isOpen);
    if (node.isConst) {
      return translateConstant(node);
    }

    InterfaceType type = elements.getType(node);

    if (node.entries.nodes.isEmpty) {
      if (type.treatAsRaw) {
        return irBuilder.buildStaticFunctionInvocation(
            helpers.mapLiteralUntypedEmptyMaker,
            <ir.Primitive>[],
            sourceInformation: sourceInformationBuilder.buildNew(node));
      } else {
        ConstructorElement constructor = helpers.mapLiteralConstructorEmpty;
        return irBuilder.buildConstructorInvocation(
            constructor.effectiveTarget,
            CallStructure.NO_ARGS,
            constructor.computeEffectiveTargetType(type),
            <ir.Primitive>[],
            sourceInformationBuilder.buildNew(node));
      }
    }

    List<ir.Primitive> keysAndValues = <ir.Primitive>[];
    for (ast.LiteralMapEntry entry in node.entries.nodes.toList()) {
      keysAndValues.add(visit(entry.key));
      keysAndValues.add(visit(entry.value));
    }
    ir.Primitive keysAndValuesList =
        irBuilder.buildListLiteral(null, keysAndValues);

    if (type.treatAsRaw) {
      return irBuilder.buildStaticFunctionInvocation(
          helpers.mapLiteralUntypedMaker,
          <ir.Primitive>[keysAndValuesList],
          sourceInformation: sourceInformationBuilder.buildNew(node));
    } else {
      ConstructorElement constructor = helpers.mapLiteralConstructor;
      return irBuilder.buildConstructorInvocation(
          constructor.effectiveTarget,
          CallStructure.ONE_ARG,
          constructor.computeEffectiveTargetType(type),
          <ir.Primitive>[keysAndValuesList],
          sourceInformationBuilder.buildNew(node));
    }
  }

  ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) {
    assert(irBuilder.isOpen);
    return translateConstant(node);
  }

  ir.Primitive visitParenthesizedExpression(
      ast.ParenthesizedExpression node) {
    assert(irBuilder.isOpen);
    return visit(node.expression);
  }

  // Stores the result of visiting a CascadeReceiver, so we can return it from
  // its enclosing Cascade.
  ir.Primitive _currentCascadeReceiver;

  ir.Primitive visitCascadeReceiver(ast.CascadeReceiver node) {
    assert(irBuilder.isOpen);
    return _currentCascadeReceiver = visit(node.expression);
  }

  ir.Primitive visitCascade(ast.Cascade node) {
    assert(irBuilder.isOpen);
    var oldCascadeReceiver = _currentCascadeReceiver;
    // Throw away the result of visiting the expression.
    // Instead we return the result of visiting the CascadeReceiver.
    visit(node.expression);
    ir.Primitive receiver = _currentCascadeReceiver;
    _currentCascadeReceiver = oldCascadeReceiver;
    return receiver;
  }

  @override
  ir.Primitive visitAssert(ast.Assert node) {
    assert(irBuilder.isOpen);
    if (compiler.enableUserAssertions) {
      return giveup(node, 'assert in checked mode not implemented');
    } else {
      // The call to assert and its argument expression must be ignored
      // in production mode.
      // Assertions can only occur in expression statements, so no value needs
      // to be returned.
      return null;
    }
  }

  // ## Sends ##
  @override
  void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) {
    if (prefix != null) buildCheckDeferredIsLoaded(prefix, node);
  }

  /// Create a call to check that a deferred import has already been loaded.
  ir.Primitive buildCheckDeferredIsLoaded(PrefixElement prefix, ast.Send node) {
    SourceInformation sourceInformation =
        sourceInformationBuilder.buildCall(node, node.selector);
    ir.Primitive name = irBuilder.buildStringConstant(
        compiler.deferredLoadTask.getImportDeferName(node, prefix));
    ir.Primitive uri =
        irBuilder.buildStringConstant('${prefix.deferredImport.uri}');
    return irBuilder.buildStaticFunctionInvocation(
        helpers.checkDeferredIsLoaded,
        <ir.Primitive>[name, uri],
        sourceInformation: sourceInformation);
  }

  ir.Primitive visitNamedArgument(ast.NamedArgument node) {
    assert(irBuilder.isOpen);
    return visit(node.expression);
  }

  @override
  ir.Primitive visitExpressionInvoke(ast.Send node,
                                     ast.Node expression,
                                     ast.NodeList argumentsNode,
                                     CallStructure callStructure, _) {
    ir.Primitive receiver = visit(expression);
    List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
    callStructure = normalizeDynamicArguments(callStructure, arguments);
    return irBuilder.buildCallInvocation(receiver, callStructure, arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  /// Returns `true` if [node] is a super call.
  // TODO(johnniwinther): Remove the need for this.
  bool isSuperCall(ast.Send node) {
    return node != null && node.receiver != null && node.receiver.isSuper();
  }

  @override
  ir.Primitive handleConstantGet(
      ast.Node node,
      ConstantExpression constant, _) {
    return buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
  }

  /// If [node] is null, returns this.
  /// Otherwise visits [node] and returns the result.
  ir.Primitive translateReceiver(ast.Expression node) {
    return node != null ? visit(node) : irBuilder.buildThis();
  }

  @override
  ir.Primitive handleDynamicGet(
      ast.Send node,
      ast.Node receiver,
      Name name,
      _) {
    return irBuilder.buildDynamicGet(
        translateReceiver(receiver),
        new Selector.getter(name),
        elements.getTypeMask(node),
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive visitIfNotNullDynamicPropertyGet(
      ast.Send node,
      ast.Node receiver,
      Name name,
      _) {
    ir.Primitive target = visit(receiver);
    return irBuilder.buildIfNotNullSend(
        target,
        nested(() => irBuilder.buildDynamicGet(
            target,
            new Selector.getter(name),
            elements.getTypeMask(node),
            sourceInformationBuilder.buildGet(node))));
  }

  @override
  ir.Primitive visitDynamicTypeLiteralGet(
      ast.Send node,
      ConstantExpression constant,
      _) {
    return buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive visitLocalVariableGet(
      ast.Send node,
      LocalVariableElement element,
      _) {
    return element.isConst
        ? irBuilder.buildConstant(getConstantForVariable(element),
            sourceInformation: sourceInformationBuilder.buildGet(node))
        : irBuilder.buildLocalGet(element);
  }

  ir.Primitive handleLocalGet(
      ast.Send node,
      LocalElement element,
      _) {
    return irBuilder.buildLocalGet(element);
  }

  @override
  ir.Primitive handleStaticFunctionGet(
      ast.Send node,
      MethodElement function,
      _) {
    return irBuilder.addPrimitive(new ir.GetStatic(function));
  }

  @override
  ir.Primitive handleStaticGetterGet(
      ast.Send node,
      FunctionElement getter,
      _) {
    return buildStaticGetterGet(getter, node);
  }

  /// Create a getter invocation of the static getter [getter]. This also
  /// handles the special case where [getter] is the `loadLibrary`
  /// pseudo-function on library prefixes of deferred imports.
  ir.Primitive buildStaticGetterGet(MethodElement getter, ast.Send node) {
    SourceInformation sourceInformation =
        sourceInformationBuilder.buildGet(node);
    if (getter.isDeferredLoaderGetter) {
      PrefixElement prefix = getter.enclosingElement;
      ir.Primitive loadId = irBuilder.buildStringConstant(
          compiler.deferredLoadTask.getImportDeferName(node, prefix));
      return irBuilder.buildStaticFunctionInvocation(
          compiler.loadLibraryFunction,
          <ir.Primitive>[loadId],
          sourceInformation: sourceInformation);
    } else {
      return irBuilder.buildStaticGetterGet(getter, sourceInformation);
    }
  }

  @override
  ir.Primitive visitSuperFieldGet(
      ast.Send node,
      FieldElement field,
      _) {
    return irBuilder.buildSuperFieldGet(field);
  }

  @override
  ir.Primitive visitSuperGetterGet(
      ast.Send node,
      FunctionElement getter,
      _) {
    return irBuilder.buildSuperGetterGet(
        getter, sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive visitSuperMethodGet(
      ast.Send node,
      MethodElement method,
      _) {
    return irBuilder.buildSuperMethodGet(method);
  }

  @override
  ir.Primitive visitUnresolvedSuperGet(
      ast.Send node,
      Element element, _) {
    return buildInstanceNoSuchMethod(
        elements.getSelector(node), elements.getTypeMask(node), []);
  }

  @override
  ir.Primitive visitThisGet(ast.Identifier node, _) {
    if (irBuilder.state.thisParameter == null) {
      // TODO(asgerf,johnniwinther): Should be in a visitInvalidThis method.
      // 'this' in static context. Just translate to null.
      assert(compiler.compilationFailed);
      return irBuilder.buildNullConstant();
    }
    return irBuilder.buildThis();
  }

  ir.Primitive translateTypeVariableTypeLiteral(
      TypeVariableElement element,
      SourceInformation sourceInformation) {
    return irBuilder.buildReifyTypeVariable(element.type, sourceInformation);
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralGet(ast.Send node,
                                               TypeVariableElement element, _) {
    return translateTypeVariableTypeLiteral(element,
        sourceInformationBuilder.buildGet(node));
  }

  ir.Primitive translateLogicalOperator(ast.Expression left,
                                        ast.Expression right,
                                        {bool isLazyOr}) {
    ir.Primitive leftValue = visit(left);

    ir.Primitive buildRightValue(IrBuilder rightBuilder) {
      return withBuilder(rightBuilder, () => visit(right));
    }

    return irBuilder.buildLogicalOperator(
        leftValue, buildRightValue, isLazyOr: isLazyOr);
  }

  @override
  ir.Primitive visitIfNull(
      ast.Send node, ast.Node left, ast.Node right, _) {
    return irBuilder.buildIfNull(build(left), subbuild(right));
  }

  @override
  ir.Primitive visitLogicalAnd(
      ast.Send node, ast.Node left, ast.Node right, _) {
    return translateLogicalOperator(left, right, isLazyOr: false);
  }

  @override
  ir.Primitive visitLogicalOr(
      ast.Send node, ast.Node left, ast.Node right, _) {
    return translateLogicalOperator(left, right, isLazyOr: true);
  }

  @override
  ir.Primitive visitAs(
      ast.Send node,
      ast.Node expression,
      DartType type,
      _) {
    ir.Primitive receiver = visit(expression);
    return irBuilder.buildTypeOperator(receiver, type, isTypeTest: false);
  }

  @override
  ir.Primitive visitIs(
      ast.Send node,
      ast.Node expression,
      DartType type,
      _) {
    ir.Primitive value = visit(expression);
    return irBuilder.buildTypeOperator(value, type, isTypeTest: true);
  }

  @override
  ir.Primitive visitIsNot(ast.Send node,
                          ast.Node expression, DartType type, _) {
    ir.Primitive value = visit(expression);
    ir.Primitive check = irBuilder.buildTypeOperator(
        value, type, isTypeTest: true);
    return irBuilder.buildNegation(check);
  }

  ir.Primitive translateBinary(ast.Send node,
                               ast.Node left,
                               op.BinaryOperator operator,
                               ast.Node right) {
    ir.Primitive receiver = visit(left);
    Selector selector = new Selector.binaryOperator(operator.selectorName);
    List<ir.Primitive> arguments = <ir.Primitive>[visit(right)];
    CallStructure callStructure =
        normalizeDynamicArguments(selector.callStructure, arguments);
    return irBuilder.buildDynamicInvocation(
        receiver,
        new Selector(selector.kind, selector.memberName, callStructure),
        elements.getTypeMask(node),
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, node.selector));
  }

  @override
  ir.Primitive visitBinary(ast.Send node,
                           ast.Node left,
                           op.BinaryOperator operator,
                           ast.Node right, _) {
    return translateBinary(node, left, operator, right);
  }

  @override
  ir.Primitive visitIndex(ast.Send node,
                          ast.Node receiver,
                          ast.Node index, _) {
    ir.Primitive target = visit(receiver);
    Selector selector = new Selector.index();
    List<ir.Primitive> arguments = <ir.Primitive>[visit(index)];
    CallStructure callStructure =
        normalizeDynamicArguments(selector.callStructure, arguments);
    return irBuilder.buildDynamicInvocation(
        target,
        new Selector(selector.kind, selector.memberName, callStructure),
        elements.getTypeMask(node),
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(receiver, node.selector));
  }

  ir.Primitive translateSuperBinary(FunctionElement function,
                                    op.BinaryOperator operator,
                                    ast.Node argument) {
    List<ir.Primitive> arguments = <ir.Primitive>[visit(argument)];
    return irBuilder.buildSuperMethodInvocation(function,
        CallStructure.ONE_ARG, arguments);
  }

  @override
  ir.Primitive visitSuperBinary(
      ast.Send node,
      FunctionElement function,
      op.BinaryOperator operator,
      ast.Node argument,
      _) {
    return translateSuperBinary(function, operator, argument);
  }

  @override
  ir.Primitive visitSuperIndex(
      ast.Send node,
      FunctionElement function,
      ast.Node index,
      _) {
    return irBuilder.buildSuperIndex(function, visit(index));
  }

  @override
  ir.Primitive visitEquals(
      ast.Send node,
      ast.Node left,
      ast.Node right,
      _) {
    return translateBinary(node, left, op.BinaryOperator.EQ, right);
  }

  @override
  ir.Primitive visitSuperEquals(
      ast.Send node,
      FunctionElement function,
      ast.Node argument,
      _) {
    return translateSuperBinary(function, op.BinaryOperator.EQ, argument);
  }

  @override
  ir.Primitive visitNot(
      ast.Send node,
      ast.Node expression,
      _) {
    return irBuilder.buildNegation(visit(expression));
  }

  @override
  ir.Primitive visitNotEquals(
      ast.Send node,
      ast.Node left,
      ast.Node right,
      _) {
    return irBuilder.buildNegation(
        translateBinary(node, left, op.BinaryOperator.NOT_EQ, right));
  }

  @override
  ir.Primitive visitSuperNotEquals(
      ast.Send node,
      FunctionElement function,
      ast.Node argument,
      _) {
    return irBuilder.buildNegation(
        translateSuperBinary(function, op.BinaryOperator.NOT_EQ, argument));
  }

  @override
  ir.Primitive visitUnary(ast.Send node,
                          op.UnaryOperator operator, ast.Node expression, _) {
    // TODO(johnniwinther): Clean up the creation of selectors.
    Selector selector = operator.selector;
    ir.Primitive receiver = translateReceiver(expression);
    return irBuilder.buildDynamicInvocation(
        receiver, selector, elements.getTypeMask(node), const [],
        sourceInformation: sourceInformationBuilder.buildCall(
            expression, node));
  }

  @override
  ir.Primitive visitSuperUnary(
      ast.Send node,
      op.UnaryOperator operator,
      FunctionElement function,
      _) {
    return irBuilder.buildSuperMethodInvocation(
        function, CallStructure.NO_ARGS, const []);
  }

  // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
  // semantic correlation between arguments and invocation.
  CallStructure translateDynamicArguments(ast.NodeList nodeList,
                                          CallStructure callStructure,
                                          List<ir.Primitive> arguments) {
    assert(arguments.isEmpty);
    for (ast.Node node in nodeList) arguments.add(visit(node));
    return normalizeDynamicArguments(callStructure, arguments);
  }

  // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
  // semantic correlation between arguments and invocation.
  CallStructure translateStaticArguments(ast.NodeList nodeList,
                                         Element element,
                                         CallStructure callStructure,
                                         List<ir.Primitive> arguments) {
    assert(arguments.isEmpty);
    for (ast.Node node in nodeList) arguments.add(visit(node));
    return normalizeStaticArguments(callStructure, element, arguments);
  }

  ir.Primitive translateCallInvoke(ir.Primitive target,
                                   ast.NodeList argumentsNode,
                                   CallStructure callStructure,
                                   SourceInformation sourceInformation) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(target, callStructure, arguments,
        sourceInformation: sourceInformation);
  }

  @override
  ir.Primitive handleConstantInvoke(
      ast.Send node,
      ConstantExpression constant,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    ir.Primitive target = buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
    return translateCallInvoke(target, arguments, callStructure,
        sourceInformationBuilder.buildCall(node, arguments));
  }

  @override
  ir.Primitive handleConstructorInvoke(
      ast.NewExpression node,
      ConstructorElement constructor,
      DartType type,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {

    // TODO(sigmund): move these checks down after visiting arguments
    // (see issue #25355)
    ast.Send send = node.send;
    // If an allocation refers to a type using a deferred import prefix (e.g.
    // `new lib.A()`), we must ensure that the deferred import has already been
    // loaded.
    var prefix = compiler.deferredLoadTask.deferredPrefixElement(
        send, elements);
    if (prefix != null) buildCheckDeferredIsLoaded(prefix, send);

    // We also emit deferred import checks when using redirecting factories that
    // refer to deferred prefixes.
    if (constructor.isRedirectingFactory && !constructor.isCyclicRedirection) {
      ConstructorElement current = constructor;
      while (current.isRedirectingFactory) {
        var prefix = current.redirectionDeferredPrefix;
        if (prefix != null) buildCheckDeferredIsLoaded(prefix, send);
        current = current.immediateRedirectionTarget;
      }
    }

    List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
    // Use default values from the effective target, not the immediate target.
    ConstructorElement target = constructor.implementation;
    while (target.isRedirectingFactory && !target.isCyclicRedirection) {
      target = target.effectiveTarget.implementation;
    }

    callStructure = normalizeStaticArguments(callStructure, target, arguments);
    TypeMask allocationSiteType;

    if (Elements.isFixedListConstructorCall(constructor, send, compiler) ||
        Elements.isGrowableListConstructorCall(constructor, send, compiler) ||
        Elements.isFilledListConstructorCall(constructor, send, compiler) ||
        Elements.isConstructorOfTypedArraySubclass(constructor, compiler)) {
      allocationSiteType = getAllocationSiteType(send);
    }
    ConstructorElement constructorImplementation = constructor.implementation;
    return irBuilder.buildConstructorInvocation(
        target,
        callStructure,
        constructorImplementation.computeEffectiveTargetType(type),
        arguments,
        sourceInformationBuilder.buildNew(node),
        allocationSiteType: allocationSiteType);
  }

  @override
  ir.Primitive handleDynamicInvoke(
      ast.Send node,
      ast.Node receiver,
      ast.NodeList argumentsNode,
      Selector selector,
      _) {
    ir.Primitive target = translateReceiver(receiver);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    CallStructure callStructure = translateDynamicArguments(
        argumentsNode, selector.callStructure, arguments);
    return irBuilder.buildDynamicInvocation(
        target,
        new Selector(selector.kind, selector.memberName, callStructure),
        elements.getTypeMask(node),
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, node.selector));
  }

  @override
  ir.Primitive visitIfNotNullDynamicPropertyInvoke(
      ast.Send node,
      ast.Node receiver,
      ast.NodeList argumentsNode,
      Selector selector,
      _) {
    ir.Primitive target = visit(receiver);
    return irBuilder.buildIfNotNullSend(
        target,
        nested(() {
          List<ir.Primitive> arguments = <ir.Primitive>[];
          CallStructure callStructure = translateDynamicArguments(
              argumentsNode, selector.callStructure, arguments);
          return irBuilder.buildDynamicInvocation(
              target,
              new Selector(selector.kind, selector.memberName, callStructure),
              elements.getTypeMask(node),
              arguments);
        }));
  }

  ir.Primitive handleLocalInvoke(
      ast.Send node,
      LocalElement element,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive function = irBuilder.buildLocalGet(element);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(function, callStructure, arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive handleStaticFieldGet(ast.Send node, FieldElement field, _) {
    return buildStaticFieldGet(field, sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive handleStaticFieldInvoke(
      ast.Send node,
      FieldElement field,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    SourceInformation src = sourceInformationBuilder.buildGet(node);
    ir.Primitive target = buildStaticFieldGet(field, src);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive handleStaticFunctionInvoke(ast.Send node,
      MethodElement function,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    if (compiler.backend.isForeign(function)) {
      return handleForeignCode(node, function, argumentsNode, callStructure);
    } else {
      List<ir.Primitive> arguments = <ir.Primitive>[];
      callStructure = translateStaticArguments(argumentsNode, function,
          callStructure, arguments);
      Selector selector = new Selector.call(function.memberName, callStructure);
      return irBuilder.buildInvokeStatic(function, selector, arguments,
          sourceInformationBuilder.buildCall(node, node.selector));
    }
  }

  @override
  ir.Primitive handleStaticFunctionIncompatibleInvoke(
      ast.Send node,
      MethodElement function,
      ast.NodeList arguments,
      CallStructure callStructure, _) {
    return irBuilder.buildStaticNoSuchMethod(
        elements.getSelector(node),
        arguments.nodes.mapToList(visit));
  }

  @override
  ir.Primitive handleStaticGetterInvoke(
      ast.Send node,
      FunctionElement getter,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive target = buildStaticGetterGet(getter, node);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive visitSuperFieldInvoke(
      ast.Send node,
      FieldElement field,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive target = irBuilder.buildSuperFieldGet(field);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive visitSuperGetterInvoke(
      ast.Send node,
      FunctionElement getter,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive target = irBuilder.buildSuperGetterGet(getter,
        sourceInformationBuilder.buildGet(node));
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive visitSuperMethodInvoke(
      ast.Send node,
      MethodElement method,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure = translateStaticArguments(argumentsNode, method,
        callStructure, arguments);
    return irBuilder.buildSuperMethodInvocation(
        method,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, node.selector));
  }

  @override
  ir.Primitive visitSuperMethodIncompatibleInvoke(
      ast.Send node,
      MethodElement method,
      ast.NodeList arguments,
      CallStructure callStructure, _) {
    List<ir.Primitive> normalizedArguments = <ir.Primitive>[];
    CallStructure normalizedCallStructure =
      translateDynamicArguments(arguments, callStructure, normalizedArguments);
    return buildInstanceNoSuchMethod(
        new Selector.call(method.memberName, normalizedCallStructure),
        elements.getTypeMask(node),
        normalizedArguments);
  }

  @override
  ir.Primitive visitUnresolvedSuperInvoke(
      ast.Send node,
      Element element,
      ast.NodeList argumentsNode,
      Selector selector, _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    CallStructure callStructure = translateDynamicArguments(
        argumentsNode, selector.callStructure, arguments);
    // TODO(johnniwinther): Supply a member name to the visit function instead
    // of looking it up in elements.
    return buildInstanceNoSuchMethod(
        new Selector.call(elements.getSelector(node).memberName, callStructure),
        elements.getTypeMask(node),
        arguments);
  }

  @override
  ir.Primitive visitThisInvoke(
      ast.Send node,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return translateCallInvoke(
        irBuilder.buildThis(),
        arguments,
        callStructure,
        sourceInformationBuilder.buildCall(node, arguments));
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralInvoke(
      ast.Send node,
      TypeVariableElement element,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return translateCallInvoke(
        translateTypeVariableTypeLiteral(
            element, sourceInformationBuilder.buildGet(node)),
        arguments,
        callStructure,
        sourceInformationBuilder.buildCall(node, arguments));
  }

  @override
  ir.Primitive visitIndexSet(
       ast.SendSet node,
       ast.Node receiver,
       ast.Node index,
       ast.Node rhs,
       _) {
    return irBuilder.buildDynamicIndexSet(
        visit(receiver), elements.getTypeMask(node), visit(index), visit(rhs));
  }

  @override
  ir.Primitive visitSuperIndexSet(
      ast.SendSet node,
      FunctionElement function,
      ast.Node index,
      ast.Node rhs,
      _) {
    return irBuilder.buildSuperIndexSet(function, visit(index), visit(rhs));
  }

  ir.Primitive translateCompounds(
      ast.SendSet node,
      ir.Primitive getValue(),
      CompoundRhs rhs,
      void setValue(ir.Primitive value)) {
    ir.Primitive value = getValue();
    op.BinaryOperator operator = rhs.operator;
    if (operator.kind == op.BinaryOperatorKind.IF_NULL) {
      // Unlike other compound operators if-null conditionally will not do the
      // assignment operation.
      return irBuilder.buildIfNull(value, nested(() {
        ir.Primitive newValue = build(rhs.rhs);
        setValue(newValue);
        return newValue;
      }));
    }

    Selector operatorSelector =
        new Selector.binaryOperator(operator.selectorName);
    ir.Primitive rhsValue;
    if (rhs.kind == CompoundKind.ASSIGNMENT) {
      rhsValue = visit(rhs.rhs);
    } else {
      rhsValue = irBuilder.buildIntegerConstant(1);
    }
    List<ir.Primitive> arguments = <ir.Primitive>[rhsValue];
    CallStructure callStructure =
        normalizeDynamicArguments(operatorSelector.callStructure, arguments);
    TypeMask operatorTypeMask =
        elements.getOperatorTypeMaskInComplexSendSet(node);
    SourceInformation operatorSourceInformation =
        sourceInformationBuilder.buildCall(node, node.assignmentOperator);
    ir.Primitive result = irBuilder.buildDynamicInvocation(
        value,
        new Selector(operatorSelector.kind, operatorSelector.memberName,
            callStructure),
        operatorTypeMask,
        arguments,
        sourceInformation: operatorSourceInformation);
    setValue(result);
    return rhs.kind == CompoundKind.POSTFIX ? value : result;
  }

  ir.Primitive translateSetIfNull(
      ast.SendSet node,
      ir.Primitive getValue(),
      ast.Node rhs,
      void setValue(ir.Primitive value)) {
    ir.Primitive value = getValue();
    // Unlike other compound operators if-null conditionally will not do the
    // assignment operation.
    return irBuilder.buildIfNull(value, nested(() {
      ir.Primitive newValue = build(rhs);
      setValue(newValue);
      return newValue;
    }));
  }

  @override
  ir.Primitive handleDynamicSet(
      ast.SendSet node,
      ast.Node receiver,
      Name name,
      ast.Node rhs,
      _) {
    return irBuilder.buildDynamicSet(
        translateReceiver(receiver),
        new Selector.setter(name),
        elements.getTypeMask(node),
        visit(rhs));
  }

  @override
  ir.Primitive visitIfNotNullDynamicPropertySet(
      ast.SendSet node,
      ast.Node receiver,
      Name name,
      ast.Node rhs,
      _) {
    ir.Primitive target = visit(receiver);
    return irBuilder.buildIfNotNullSend(
        target,
        nested(() => irBuilder.buildDynamicSet(
            target,
            new Selector.setter(name),
            elements.getTypeMask(node),
            visit(rhs))));
  }

  @override
  ir.Primitive handleLocalSet(
      ast.SendSet node,
      LocalElement element,
      ast.Node rhs,
      _) {
    ir.Primitive value = visit(rhs);
    value = checkTypeVsElement(value, element);
    return irBuilder.buildLocalVariableSet(element, value);
  }

  @override
  ir.Primitive handleStaticFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs,
      _) {
    ir.Primitive value = visit(rhs);
    irBuilder.addPrimitive(new ir.SetStatic(field, value));
    return value;
  }

  @override
  ir.Primitive visitSuperFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs,
      _) {
    return irBuilder.buildSuperFieldSet(field, visit(rhs));
  }

  @override
  ir.Primitive visitSuperSetterSet(
      ast.SendSet node,
      FunctionElement setter,
      ast.Node rhs,
      _) {
    return irBuilder.buildSuperSetterSet(setter, visit(rhs));
  }

  @override
  ir.Primitive visitUnresolvedSuperIndexSet(
      ast.Send node,
      Element element,
      ast.Node index,
      ast.Node rhs,
      arg) {
    return giveup(node, 'visitUnresolvedSuperIndexSet');
  }

  @override
  ir.Primitive handleStaticSetterSet(
      ast.SendSet node,
      FunctionElement setter,
      ast.Node rhs,
      _) {
    return irBuilder.buildStaticSetterSet(setter, visit(rhs));
  }

  @override
  ir.Primitive handleTypeLiteralConstantCompounds(
      ast.SendSet node,
      ConstantExpression constant,
      CompoundRhs rhs,
      arg) {
    SourceInformation src = sourceInformationBuilder.buildGet(node);
    return translateCompounds(node, () {
      return buildConstantExpression(constant, src);
    }, rhs, (ir.Primitive value) {
      // The binary operator will throw before this.
    });
  }

  @override
  ir.Primitive handleTypeLiteralConstantSetIfNulls(
      ast.SendSet node,
      ConstantExpression constant,
      ast.Node rhs,
      _) {
    // The type literal is never `null`.
    return buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive handleDynamicCompounds(
      ast.SendSet node,
      ast.Node receiver,
      Name name,
      CompoundRhs rhs,
      arg) {
    ir.Primitive target = translateReceiver(receiver);
    ir.Primitive helper() {
      return translateCompounds(node, () {
        return irBuilder.buildDynamicGet(
            target,
            new Selector.getter(name),
            elements.getGetterTypeMaskInComplexSendSet(node),
            sourceInformationBuilder.buildGet(node));
      }, rhs, (ir.Primitive result) {
        irBuilder.buildDynamicSet(
            target,
            new Selector.setter(name),
            elements.getTypeMask(node),
            result);
      });
    }
    return node.isConditional
        ? irBuilder.buildIfNotNullSend(target, nested(helper))
        : helper();
  }

  @override
  ir.Primitive handleDynamicSetIfNulls(
      ast.Send node,
      ast.Node receiver,
      Name name,
      ast.Node rhs,
      _) {
    ir.Primitive target = translateReceiver(receiver);
    ir.Primitive helper() {
      return translateSetIfNull(node, () {
        return irBuilder.buildDynamicGet(
            target,
            new Selector.getter(name),
            elements.getGetterTypeMaskInComplexSendSet(node),
            sourceInformationBuilder.buildGet(node));
      }, rhs, (ir.Primitive result) {
        irBuilder.buildDynamicSet(
            target,
            new Selector.setter(name),
            elements.getTypeMask(node),
            result);
      });
    }
    return node.isConditional
        ? irBuilder.buildIfNotNullSend(target, nested(helper))
        : helper();
  }

  ir.Primitive buildLocalNoSuchSetter(LocalElement local, ir.Primitive value) {
    Selector selector = new Selector.setter(
        new Name(local.name, local.library, isSetter: true));
    return irBuilder.buildStaticNoSuchMethod(selector, [value]);
  }

  @override
  ir.Primitive handleLocalCompounds(
      ast.SendSet node,
      LocalElement local,
      CompoundRhs rhs,
      arg,
      {bool isSetterValid}) {
    return translateCompounds(node, () {
      return irBuilder.buildLocalGet(local);
    }, rhs, (ir.Primitive result) {
      if (isSetterValid) {
        irBuilder.buildLocalVariableSet(local, result);
      } else {
        Selector selector = new Selector.setter(
            new Name(local.name, local.library, isSetter: true));
        irBuilder.buildStaticNoSuchMethod(selector, <ir.Primitive>[result]);
      }
    });
  }

  @override
  ir.Primitive handleLocalSetIfNulls(
      ast.SendSet node,
      LocalElement local,
      ast.Node rhs,
      _,
      {bool isSetterValid}) {
    return translateSetIfNull(node, () {
      return irBuilder.buildLocalGet(local);
    }, rhs, (ir.Primitive result) {
      if (isSetterValid) {
        irBuilder.buildLocalVariableSet(local, result);
      } else {
        Selector selector = new Selector.setter(
            new Name(local.name, local.library, isSetter: true));
        irBuilder.buildStaticNoSuchMethod(selector, <ir.Primitive>[result]);
      }
    });
  }

  @override
  ir.Primitive handleStaticCompounds(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      CompoundRhs rhs,
      arg) {
    return translateCompounds(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          SourceInformation src = sourceInformationBuilder.buildGet(node);
          return buildStaticFieldGet(getter, src);
        case CompoundGetter.GETTER:
          return buildStaticGetterGet(getter, node);
        case CompoundGetter.METHOD:
          return irBuilder.addPrimitive(new ir.GetStatic(getter));
        case CompoundGetter.UNRESOLVED:
          return irBuilder.buildStaticNoSuchMethod(
              new Selector.getter(new Name(getter.name, getter.library)),
              <ir.Primitive>[]);
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.addPrimitive(new ir.SetStatic(setter, result));
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildStaticSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          irBuilder.buildStaticNoSuchMethod(
              new Selector.setter(new Name(setter.name, setter.library)),
              <ir.Primitive>[result]);
          return;
      }
    });
  }

  @override
  ir.Primitive handleStaticSetIfNulls(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      ast.Node rhs,
      _) {
    return translateSetIfNull(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          SourceInformation src = sourceInformationBuilder.buildGet(node);
          return buildStaticFieldGet(getter, src);
        case CompoundGetter.GETTER:
          return buildStaticGetterGet(getter, node);
        case CompoundGetter.METHOD:
          return irBuilder.addPrimitive(new ir.GetStatic(getter));
        case CompoundGetter.UNRESOLVED:
          return irBuilder.buildStaticNoSuchMethod(
              new Selector.getter(new Name(getter.name, getter.library)),
              <ir.Primitive>[]);
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.addPrimitive(new ir.SetStatic(setter, result));
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildStaticSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          irBuilder.buildStaticNoSuchMethod(
              new Selector.setter(new Name(setter.name, setter.library)),
              <ir.Primitive>[result]);
          return;
      }
    });
  }

  ir.Primitive buildSuperNoSuchGetter(Element element, TypeMask mask) {
    return buildInstanceNoSuchMethod(
        new Selector.getter(new Name(element.name, element.library)),
        mask,
        const <ir.Primitive>[]);
  }

  ir.Primitive buildSuperNoSuchSetter(Element element,
                                      TypeMask mask,
                                      ir.Primitive value) {
    return buildInstanceNoSuchMethod(
        new Selector.setter(new Name(element.name, element.library)),
        mask,
        <ir.Primitive>[value]);
  }

  @override
  ir.Primitive handleSuperCompounds(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      CompoundRhs rhs,
      arg) {
    return translateCompounds(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          return irBuilder.buildSuperFieldGet(getter);
        case CompoundGetter.GETTER:
          return irBuilder.buildSuperGetterGet(
              getter, sourceInformationBuilder.buildGet(node));
        case CompoundGetter.METHOD:
          return irBuilder.buildSuperMethodGet(getter);
        case CompoundGetter.UNRESOLVED:
          return buildSuperNoSuchGetter(
              getter, elements.getGetterTypeMaskInComplexSendSet(node));
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.buildSuperFieldSet(setter, result);
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildSuperSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          buildSuperNoSuchSetter(
              setter, elements.getTypeMask(node), result);
          return;
      }
    });
  }

  @override
  ir.Primitive handleSuperSetIfNulls(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      ast.Node rhs,
      _) {
    return translateSetIfNull(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          return irBuilder.buildSuperFieldGet(getter);
        case CompoundGetter.GETTER:
          return irBuilder.buildSuperGetterGet(
              getter, sourceInformationBuilder.buildGet(node));
        case CompoundGetter.METHOD:
          return irBuilder.buildSuperMethodGet(getter);
        case CompoundGetter.UNRESOLVED:
          return buildSuperNoSuchGetter(
              getter,
              elements.getGetterTypeMaskInComplexSendSet(node));
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.buildSuperFieldSet(setter, result);
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildSuperSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          buildSuperNoSuchSetter(
              setter, elements.getTypeMask(node), result);
          return;
      }
    });
  }

  @override
  ir.Primitive handleTypeVariableTypeLiteralCompounds(
      ast.SendSet node,
      TypeVariableElement typeVariable,
      CompoundRhs rhs,
      arg) {
    return translateCompounds(node, () {
      return irBuilder.buildReifyTypeVariable(
          typeVariable.type,
          sourceInformationBuilder.buildGet(node));
    }, rhs, (ir.Primitive value) {
      // The binary operator will throw before this.
    });
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralSetIfNull(
      ast.Send node,
      TypeVariableElement element,
      ast.Node rhs,
      _) {
    // The type variable is never `null`.
    return translateTypeVariableTypeLiteral(element,
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive handleIndexCompounds(
      ast.SendSet node,
      ast.Node receiver,
      ast.Node index,
      CompoundRhs rhs,
      arg) {
    ir.Primitive target = visit(receiver);
    ir.Primitive indexValue = visit(index);
    return translateCompounds(node, () {
      Selector selector = new Selector.index();
      List<ir.Primitive> arguments = <ir.Primitive>[indexValue];
      CallStructure callStructure =
          normalizeDynamicArguments(selector.callStructure, arguments);
      return irBuilder.buildDynamicInvocation(
          target,
          new Selector(selector.kind, selector.memberName, callStructure),
          elements.getGetterTypeMaskInComplexSendSet(node),
          arguments,
          sourceInformation:
          sourceInformationBuilder.buildCall(receiver, node));
    }, rhs, (ir.Primitive result) {
      irBuilder.buildDynamicIndexSet(
          target,
          elements.getTypeMask(node),
          indexValue,
          result);
    });
  }

  @override
  ir.Primitive handleSuperIndexCompounds(
      ast.SendSet node,
      Element indexFunction,
      Element indexSetFunction,
      ast.Node index,
      CompoundRhs rhs,
      arg,
      {bool isGetterValid,
       bool isSetterValid}) {
    ir.Primitive indexValue = visit(index);
    return translateCompounds(node, () {
      return isGetterValid
          ? irBuilder.buildSuperIndex(indexFunction, indexValue)
          : buildInstanceNoSuchMethod(
              new Selector.index(),
              elements.getGetterTypeMaskInComplexSendSet(node),
              <ir.Primitive>[indexValue]);
    }, rhs, (ir.Primitive result) {
      if (isSetterValid) {
        irBuilder.buildSuperIndexSet(indexSetFunction, indexValue, result);
      } else {
        buildInstanceNoSuchMethod(
            new Selector.indexSet(),
            elements.getTypeMask(node),
            <ir.Primitive>[indexValue, result]);
      }
    });
  }

  /// Build code to handle foreign code, that is, native JavaScript code, or
  /// builtin values and operations of the backend.
  ir.Primitive handleForeignCode(ast.Send node,
      MethodElement function,
      ast.NodeList argumentList,
      CallStructure callStructure) {

    void validateArgumentCount({int minimum, int exactly}) {
      assert((minimum == null) != (exactly == null));
      int count = 0;
      int maximum;
      if (exactly != null) {
        minimum = exactly;
        maximum = exactly;
      }
      for (ast.Node argument in argumentList) {
        count++;
        if (maximum != null && count > maximum) {
          internalError(argument, 'Additional argument.');
        }
      }
      if (count < minimum) {
        internalError(node, 'Expected at least $minimum arguments.');
      }
    }

    /// Call a helper method from the isolate library. The isolate library uses
    /// its own isolate structure, that encapsulates dart2js's isolate.
    ir.Primitive buildIsolateHelperInvocation(MethodElement element,
        CallStructure callStructure) {
      if (element == null) {
        reporter.internalError(node,
            'Isolate library and compiler mismatch.');
      }
      List<ir.Primitive> arguments = <ir.Primitive>[];
      callStructure = translateStaticArguments(argumentList, element,
          callStructure, arguments);
      Selector selector = new Selector.call(element.memberName, callStructure);
      return irBuilder.buildInvokeStatic(element, selector, arguments,
          sourceInformationBuilder.buildCall(node, node.selector));
    }

    /// Lookup the value of the enum described by [node].
    getEnumValue(ast.Node node, EnumClassElement enumClass, List values) {
      Element element = elements[node];
      if (element is! FieldElement || element.enclosingClass != enumClass) {
        internalError(node, 'expected a JsBuiltin enum value');
      }

      int index = enumClass.enumValues.indexOf(element);
      return values[index];
    }

    /// Returns the String the node evaluates to, or throws an error if the
    /// result is not a string constant.
    String expectStringConstant(ast.Node node) {
      ir.Primitive nameValue = visit(node);
      if (nameValue is ir.Constant && nameValue.value.isString) {
        StringConstantValue constantValue = nameValue.value;
        return constantValue.primitiveValue.slowToString();
      } else {
        return internalError(node, 'expected a literal string');
      }
    }

    Link<ast.Node> argumentNodes  = argumentList.nodes;
    NativeBehavior behavior =
    compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
    switch (function.name) {
      case 'JS':
        validateArgumentCount(minimum: 2);
        // The first two arguments are the type and the foreign code template,
        // which already have been analyzed by the resolver and can be retrieved
        // using [NativeBehavior]. We can ignore these arguments in the backend.
        List<ir.Primitive> arguments =
        argumentNodes.skip(2).mapToList(visit, growable: false);
        if (behavior.codeTemplate.positionalArgumentCount != arguments.length) {
          reporter.reportErrorMessage(
              node, MessageKind.GENERIC,
              {'text':
              'Mismatch between number of placeholders'
                  ' and number of arguments.'});
          return irBuilder.buildNullConstant();
        }

        if (HasCapturedPlaceholders.check(behavior.codeTemplate.ast)) {
          reporter.reportErrorMessage(node, MessageKind.JS_PLACEHOLDER_CAPTURE);
          return irBuilder.buildNullConstant();
        }

        return irBuilder.buildForeignCode(behavior.codeTemplate, arguments,
            behavior);

      case 'DART_CLOSURE_TO_JS':
      // TODO(ahe): This should probably take care to wrap the closure in
      // another closure that saves the current isolate.
      case 'RAW_DART_FUNCTION_REF':
        validateArgumentCount(exactly: 1);

        ast.Node argument = node.arguments.single;
        FunctionElement closure = elements[argument].implementation;
        if (!Elements.isStaticOrTopLevelFunction(closure)) {
          internalError(argument,
              'only static or toplevel function supported');
        }
        if (closure.functionSignature.hasOptionalParameters) {
          internalError(argument,
              'closures with optional parameters not supported');
        }
        return irBuilder.buildForeignCode(
            js.js.expressionTemplateYielding(
                backend.emitter.staticFunctionAccess(closure)),
            <ir.Primitive>[],
            NativeBehavior.PURE,
            dependency: closure);

      case 'JS_BUILTIN':
      // The first argument is a description of the type and effect of the
      // builtin, which has already been analyzed in the frontend.  The second
      // argument must be a [JsBuiltin] value.  All other arguments are
      // values used by the JavaScript template that is associated with the
      // builtin.
        validateArgumentCount(minimum: 2);

        ast.Node builtin = argumentNodes.tail.head;
        JsBuiltin value = getEnumValue(builtin, helpers.jsBuiltinEnum,
            JsBuiltin.values);
        js.Template template = backend.emitter.builtinTemplateFor(value);
        List<ir.Primitive> arguments =
        argumentNodes.skip(2).mapToList(visit, growable: false);
        return irBuilder.buildForeignCode(template, arguments, behavior);

      case 'JS_EMBEDDED_GLOBAL':
        validateArgumentCount(exactly: 2);

        String name = expectStringConstant(argumentNodes.tail.head);
        js.Expression access =
        backend.emitter.generateEmbeddedGlobalAccess(name);
        js.Template template = js.js.expressionTemplateYielding(access);
        return irBuilder.buildForeignCode(template, <ir.Primitive>[], behavior);

      case 'JS_INTERCEPTOR_CONSTANT':
        validateArgumentCount(exactly: 1);

        ast.Node argument = argumentNodes.head;
        ir.Primitive argumentValue = visit(argument);
        if (argumentValue is ir.Constant && argumentValue.value.isType) {
          TypeConstantValue constant = argumentValue.value;
          ConstantValue interceptorValue =
          new InterceptorConstantValue(constant.representedType);
          return irBuilder.buildConstant(interceptorValue);
        }
        return internalError(argument, 'expected Type as argument');

      case 'JS_EFFECT':
        return irBuilder.buildNullConstant();

      case 'JS_GET_NAME':
        validateArgumentCount(exactly: 1);

        ast.Node argument = argumentNodes.head;
        JsGetName id = getEnumValue(argument, helpers.jsGetNameEnum,
            JsGetName.values);
        js.Name name = backend.namer.getNameForJsGetName(argument, id);
        ConstantValue nameConstant =
        new SyntheticConstantValue(SyntheticConstantKind.NAME,
            js.js.quoteName(name));

        return irBuilder.buildConstant(nameConstant);

      case 'JS_GET_FLAG':
        validateArgumentCount(exactly: 1);

        String name = expectStringConstant(argumentNodes.first);
        bool value = false;
        switch (name) {
          case 'MUST_RETAIN_METADATA':
            value = backend.mustRetainMetadata;
            break;
          case 'USE_CONTENT_SECURITY_POLICY':
            value = compiler.useContentSecurityPolicy;
            break;
          default:
            internalError(node, 'Unknown internal flag "$name".');
        }
        return irBuilder.buildBooleanConstant(value);

      case 'JS_STRING_CONCAT':
        validateArgumentCount(exactly: 2);
        List<ir.Primitive> arguments = argumentNodes.mapToList(visit);
        return irBuilder.buildStringConcatenation(arguments);

      case 'JS_CURRENT_ISOLATE_CONTEXT':
        validateArgumentCount(exactly: 0);

        if (!compiler.hasIsolateSupport) {
          // If the isolate library is not used, we just generate code
          // to fetch the current isolate.
          continue getStaticState;
        }
        return buildIsolateHelperInvocation(helpers.currentIsolate,
            CallStructure.NO_ARGS);

      getStaticState: case 'JS_GET_STATIC_STATE':
        validateArgumentCount(exactly: 0);

        return irBuilder.buildForeignCode(
            js.js.parseForeignJS(backend.namer.staticStateHolder),
            const <ir.Primitive>[],
            NativeBehavior.DEPENDS_OTHER);

      case 'JS_SET_STATIC_STATE':
        validateArgumentCount(exactly: 1);

        ir.Primitive value = visit(argumentNodes.single);
        String isolateName = backend.namer.staticStateHolder;
        return irBuilder.buildForeignCode(
            js.js.parseForeignJS("$isolateName = #"),
            <ir.Primitive>[value],
            NativeBehavior.CHANGES_OTHER);

      case 'JS_CALL_IN_ISOLATE':
        validateArgumentCount(exactly: 2);

        if (!compiler.hasIsolateSupport) {
          ir.Primitive closure = visit(argumentNodes.tail.head);
          return irBuilder.buildCallInvocation(closure, CallStructure.NO_ARGS,
              const <ir.Primitive>[]);
        }
        return buildIsolateHelperInvocation(helpers.callInIsolate,
            CallStructure.TWO_ARGS);

      default:
        return giveup(node, 'unplemented native construct: ${function.name}');
    }
  }

  /// Evaluates a string interpolation and appends each part to [accumulator]
  /// (after stringify conversion).
  void buildStringParts(ast.Node node, List<ir.Primitive> accumulator) {
    if (node is ast.StringJuxtaposition) {
      buildStringParts(node.first, accumulator);
      buildStringParts(node.second, accumulator);
    } else if (node is ast.StringInterpolation) {
      buildStringParts(node.string, accumulator);
      for (ast.StringInterpolationPart part in node.parts) {
        buildStringParts(part.expression, accumulator);
        buildStringParts(part.string, accumulator);
      }
    } else if (node is ast.LiteralString) {
      // Empty strings often occur at the end of a string interpolation,
      // do not bother to include them.
      if (!node.dartString.isEmpty) {
        accumulator.add(irBuilder.buildDartStringConstant(node.dartString));
      }
    } else if (node is ast.ParenthesizedExpression) {
      buildStringParts(node.expression, accumulator);
    } else {
      ir.Primitive value = visit(node);
      accumulator.add(irBuilder.buildStaticFunctionInvocation(
          helpers.stringInterpolationHelper,
          <ir.Primitive>[value]));
    }
  }

  ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
    assert(irBuilder.isOpen);
    List<ir.Primitive> parts = <ir.Primitive>[];
    buildStringParts(node, parts);
    return irBuilder.buildStringConcatenation(parts);
  }

  ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
    assert(irBuilder.isOpen);
    List<ir.Primitive> parts = <ir.Primitive>[];
    buildStringParts(node, parts);
    return irBuilder.buildStringConcatenation(parts);
  }

  ir.Primitive translateConstant(ast.Node node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildConstant(
        getConstantForNode(node),
        sourceInformation: sourceInformationBuilder.buildGet(node));
  }

  ir.Primitive visitThrow(ast.Throw node) {
    assert(irBuilder.isOpen);
    // This function is not called for throw expressions occurring as
    // statements.
    return irBuilder.buildNonTailThrow(visit(node.expression));
  }

  ir.Primitive buildInstanceNoSuchMethod(Selector selector,
      TypeMask mask,
      List<ir.Primitive> arguments) {
    return irBuilder.buildDynamicInvocation(
        irBuilder.buildThis(),
        Selectors.noSuchMethod_,
        mask,
        [irBuilder.buildInvocationMirror(selector, arguments)]);
  }

  @override
  ir.Primitive visitUnresolvedCompound(
      ast.Send node,
      Element element,
      op.AssignmentOperator operator,
      ast.Node rhs, _) {
    // TODO(asgerf): What is unresolved? The getter and/or the setter?
    //               If it was the setter, we must evaluate the right-hand side.
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node), []);
  }

  @override
  ir.Primitive visitUnresolvedClassConstructorInvoke(
      ast.NewExpression node,
      Element element,
      DartType type,
      ast.NodeList arguments,
      Selector selector, _) {
    // If the class is missing it's a runtime error.
    ir.Primitive message =
        irBuilder.buildStringConstant("Unresolved class: '${element.name}'");
    return irBuilder.buildStaticFunctionInvocation(
        helpers.throwRuntimeError,
        <ir.Primitive>[message]);
  }

  @override
  ir.Primitive visitUnresolvedConstructorInvoke(
      ast.NewExpression node,
      Element constructor,
      DartType type,
      ast.NodeList argumentsNode,
      Selector selector, _) {
    // If the class is there but the constructor is missing, it's an NSM error.
    List<ir.Primitive> arguments = <ir.Primitive>[];
    CallStructure callStructure = translateDynamicArguments(
        argumentsNode, selector.callStructure, arguments);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector(selector.kind, selector.memberName, callStructure),
        arguments);
  }

  @override
  ir.Primitive visitConstructorIncompatibleInvoke(
      ast.NewExpression node,
      ConstructorElement constructor,
      DartType type,
      ast.NodeList argumentsNode,
      CallStructure callStructure, _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.call(constructor.memberName, callStructure), arguments);
  }

  @override
  ir.Primitive visitUnresolvedGet(
      ast.Send node,
      Element element, _) {
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node), []);
  }

  @override
  ir.Primitive visitUnresolvedInvoke(
      ast.Send node,
      Element element,
      ast.NodeList arguments,
      Selector selector, _) {
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node),
        arguments.nodes.mapToList(visit));
  }

  @override
  ir.Primitive visitUnresolvedRedirectingFactoryConstructorInvoke(
       ast.NewExpression node,
       ConstructorElement constructor,
       InterfaceType type,
       ast.NodeList argumentsNode,
       CallStructure callStructure, _) {
    String nameString = Elements.reconstructConstructorName(constructor);
    Name name = new Name(nameString, constructor.library);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.call(name, callStructure),
        arguments);
  }

  @override
  ir.Primitive visitUnresolvedSet(
      ast.Send node,
      Element element,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitUnresolvedSuperIndex(
      ast.Send node,
      Element function,
      ast.Node index, _) {
    // Assume the index getter is missing.
    return buildInstanceNoSuchMethod(
        new Selector.index(), elements.getTypeMask(node), [visit(index)]);
  }

  @override
  ir.Primitive visitUnresolvedSuperBinary(
      ast.Send node,
      Element element,
      op.BinaryOperator operator,
      ast.Node argument, _) {
    return buildInstanceNoSuchMethod(
        elements.getSelector(node),
        elements.getTypeMask(node),
        [visit(argument)]);
  }

  @override
  ir.Primitive visitUnresolvedSuperUnary(
      ast.Send node,
      op.UnaryOperator operator,
      Element element, _) {
    return buildInstanceNoSuchMethod(
        elements.getSelector(node), elements.getTypeMask(node), []);
  }

  @override
  ir.Primitive bulkHandleNode(ast.Node node, String message, _) {
    return giveup(node, "Unhandled node: ${message.replaceAll('#', '$node')}");
  }

  @override
  ir.Primitive bulkHandleError(ast.Node node, ErroneousElement error, _) {
    return irBuilder.buildNullConstant();
  }

  @override
  ir.Primitive visitClassTypeLiteralSet(
      ast.SendSet node,
      TypeConstantExpression constant,
      ast.Node rhs, _) {
    InterfaceType type = constant.type;
    ClassElement element = type.element;
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(element.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitTypedefTypeLiteralSet(
      ast.SendSet node,
      TypeConstantExpression constant,
      ast.Node rhs, _) {
    TypedefType type = constant.type;
    TypedefElement element = type.element;
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(element.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralSet(
      ast.SendSet node,
      TypeVariableElement element,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(element.memberName), [visit(rhs)]);
  }

  @override
  ir.Primitive visitDynamicTypeLiteralSet(
      ast.SendSet node,
      ConstantExpression constant,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(Names.dynamic_), [visit(rhs)]);
  }

  @override
  ir.Primitive visitAbstractClassConstructorInvoke(
      ast.NewExpression node,
      ConstructorElement element,
      InterfaceType type,
      ast.NodeList arguments,
      CallStructure callStructure, _) {
    for (ast.Node argument in arguments) visit(argument);
    ir.Primitive name =
        irBuilder.buildStringConstant(element.enclosingClass.name);
    return irBuilder.buildStaticFunctionInvocation(
        helpers.throwAbstractClassInstantiationError,
        <ir.Primitive>[name]);
  }

  @override
  ir.Primitive handleFinalStaticFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs, _) {
    // TODO(asgerf): Include class name somehow for static class members?
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(field.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitFinalSuperFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs, _) {
    return buildInstanceNoSuchMethod(
        new Selector.setter(field.memberName),
        elements.getTypeMask(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleImmutableLocalSet(
      ast.SendSet node,
      LocalElement local,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(new Name(local.name, local.library)),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleStaticFunctionSet(
      ast.Send node,
      MethodElement function,
      ast.Node rhs,
      _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(function.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleStaticGetterSet(
      ast.SendSet node,
      GetterElement getter,
      ast.Node rhs,
      _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(getter.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleStaticSetterGet(
      ast.Send node,
      SetterElement setter,
      _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.getter(setter.memberName),
        []);
  }

  @override
  ir.Primitive handleStaticSetterInvoke(
      ast.Send node,
      SetterElement setter,
      ast.NodeList argumentsNode,
      CallStructure callStructure, _) {
    // Translate as a method call.
    List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.call(setter.memberName, callStructure),
        arguments);
  }

  @override
  ir.Primitive visitSuperGetterSet(
      ast.SendSet node,
      GetterElement getter,
      ast.Node rhs,
      _) {
    return buildInstanceNoSuchMethod(
        new Selector.setter(getter.memberName),
        elements.getTypeMask(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitSuperMethodSet(
      ast.Send node,
      MethodElement method,
      ast.Node rhs,
      _) {
    return buildInstanceNoSuchMethod(
        new Selector.setter(method.memberName),
        elements.getTypeMask(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitSuperSetterGet(
      ast.Send node,
      SetterElement setter, _) {
    return buildInstanceNoSuchMethod(
        new Selector.setter(setter.memberName),
        elements.getTypeMask(node),
        []);
  }

  @override
  ir.Primitive visitSuperSetterInvoke(
      ast.Send node,
      SetterElement setter,
      ast.NodeList argumentsNode,
      CallStructure callStructure, _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return buildInstanceNoSuchMethod(
        new Selector.call(setter.memberName, callStructure),
        elements.getTypeMask(node),
        arguments);
  }

  ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) {
    try {
      return action();
    } catch(e) {
      if (e == ABORT_IRNODE_BUILDER) {
        return null;
      }
      rethrow;
    }
  }

  internalError(ast.Node node, String message) {
    reporter.internalError(node, message);
  }

  @override
  visitNode(ast.Node node) {
    giveup(node, "Unhandled node");
  }

  dynamic giveup(ast.Node node, [String reason]) {
    bailoutMessage = '($node): $reason';
    throw ABORT_IRNODE_BUILDER;
  }
}

final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";

/// Determines which local variables should be boxed in a mutable variable
/// inside a given try block.
class TryBoxedVariables extends ast.Visitor {
  final TreeElements elements;
  TryBoxedVariables(this.elements);

  FunctionElement currentFunction;
  bool insideInitializer = false;
  Set<Local> capturedVariables = new Set<Local>();

  /// A map containing variables boxed inside try blocks.
  ///
  /// The map is keyed by the [NodeList] of catch clauses for try/catch and
  /// by the finally block for try/finally.  try/catch/finally is treated
  /// as a try/catch nested in the try block of a try/finally.
  Map<ast.Node, TryStatementInfo> tryStatements =
      <ast.Node, TryStatementInfo>{};

  List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
  bool get inTryStatement => tryNestingStack.isNotEmpty;

  String bailoutMessage = null;

  giveup(ast.Node node, [String reason]) {
    bailoutMessage = '($node): $reason';
    throw ABORT_IRNODE_BUILDER;
  }

  void markAsCaptured(Local local) {
    capturedVariables.add(local);
  }

  analyze(ast.Node node) {
    visit(node);
    // Variables that are captured by a closure are boxed for their entire
    // lifetime, so they never need to be boxed on entry to a try block.
    // They are not filtered out before this because we cannot identify all
    // of them in the same pass (they may be captured by a closure after the
    // try statement).
    for (TryStatementInfo info in tryStatements.values) {
      info.boxedOnEntry.removeAll(capturedVariables);
    }
  }

  visit(ast.Node node) => node.accept(this);

  visitNode(ast.Node node) {
    node.visitChildren(this);
  }

  void handleSend(ast.Send node) {
    Element element = elements[node];
    if (Elements.isLocal(element) &&
        !element.isConst &&
        element.enclosingElement != currentFunction) {
      LocalElement local = element;
      markAsCaptured(local);
    }
  }

  visitSend(ast.Send node) {
    handleSend(node);
    node.visitChildren(this);
  }

  visitSendSet(ast.SendSet node) {
    handleSend(node);
    Element element = elements[node];
    if (Elements.isLocal(element)) {
      LocalElement local = element;
      if (insideInitializer &&
          local.isParameter &&
          local.enclosingElement == currentFunction) {
        assert(local.enclosingElement.isConstructor);
        // Initializers in an initializer-list can communicate via parameters.
        // If a parameter is stored in an initializer list we box it.
        // TODO(sigurdm): Fix this.
        // Though these variables do not outlive the activation of the
        // function, they still need to be boxed.  As a simplification, we
        // treat them as if they are captured by a closure (i.e., they do
        // outlive the activation of the function).
        markAsCaptured(local);
      } else if (inTryStatement) {
        assert(local.isParameter || local.isVariable);
        // Search for the position of the try block containing the variable
        // declaration, or -1 if it is declared outside the outermost try.
        int i = tryNestingStack.length - 1;
        while (i >= 0 && !tryNestingStack[i].declared.contains(local)) {
          --i;
        }
        // If there is a next inner try, then the variable should be boxed on
        // entry to it.
        if (i + 1 < tryNestingStack.length) {
          tryNestingStack[i + 1].boxedOnEntry.add(local);
        }
      }
    }
    node.visitChildren(this);
  }

  visitFunctionExpression(ast.FunctionExpression node) {
    FunctionElement savedFunction = currentFunction;
    currentFunction = elements[node];

    if (currentFunction.asyncMarker != AsyncMarker.SYNC &&
        currentFunction.asyncMarker != AsyncMarker.SYNC_STAR &&
        currentFunction.asyncMarker != AsyncMarker.ASYNC) {
      giveup(node, "cannot handle async* functions");
    }

    if (node.initializers != null) {
      visit(node.initializers);
    }
    visit(node.body);
    currentFunction = savedFunction;
  }

  visitTryStatement(ast.TryStatement node) {
    // Try/catch/finally is treated as two simpler constructs: try/catch and
    // try/finally.  The encoding is:
    //
    // try S0 catch (ex, st) S1 finally S2
    // ==>
    // try { try S0 catch (ex, st) S1 } finally S2
    //
    // The analysis associates variables assigned in S0 with the catch clauses
    // and variables assigned in S0 and S1 with the finally block.
    TryStatementInfo enterTryFor(ast.Node node) {
      TryStatementInfo info = new TryStatementInfo();
      tryStatements[node] = info;
      tryNestingStack.add(info);
      return info;
    }
    void leaveTryFor(TryStatementInfo info) {
      assert(tryNestingStack.last == info);
      tryNestingStack.removeLast();
    }
    bool hasCatch = !node.catchBlocks.isEmpty;
    bool hasFinally = node.finallyBlock != null;
    TryStatementInfo catchInfo, finallyInfo;
    // There is a nesting stack of try blocks, so the outer try/finally block
    // is added first.
    if (hasFinally) finallyInfo = enterTryFor(node.finallyBlock);
    if (hasCatch) catchInfo = enterTryFor(node.catchBlocks);
    visit(node.tryBlock);

    if (hasCatch) {
      leaveTryFor(catchInfo);
      visit(node.catchBlocks);
    }
    if (hasFinally) {
      leaveTryFor(finallyInfo);
      visit(node.finallyBlock);
    }
  }

  visitVariableDefinitions(ast.VariableDefinitions node) {
    if (inTryStatement) {
      for (ast.Node definition in node.definitions.nodes) {
        LocalVariableElement local = elements[definition];
        assert(local != null);
        // In the closure conversion pass we check for isInitializingFormal,
        // but I'm not sure it can arise.
        assert(!local.isInitializingFormal);
        tryNestingStack.last.declared.add(local);
      }
    }
    node.visitChildren(this);
  }
}

/// The [IrBuilder]s view on the information about the program that has been
/// computed in resolution and and type interence.
class GlobalProgramInformation {
  final Compiler _compiler;
  JavaScriptBackend get _backend => _compiler.backend;

  GlobalProgramInformation(this._compiler);

  /// Returns [true], if the analysis could not determine that the type
  /// arguments for the class [cls] are never used in the program.
  bool requiresRuntimeTypesFor(ClassElement cls) {
    return cls.typeVariables.isNotEmpty && _backend.classNeedsRti(cls);
  }

  FunctionElement get throwTypeErrorHelper => _backend.helpers.throwTypeError;
  Element get throwNoSuchMethod => _backend.helpers.throwNoSuchMethod;

  ClassElement get nullClass => _compiler.coreClasses.nullClass;

  DartType unaliasType(DartType type) => type.unaliased;

  TypeMask getTypeMaskForForeign(NativeBehavior behavior) {
    if (behavior == null) {
      return _backend.dynamicType;
    }
    return TypeMaskFactory.fromNativeBehavior(behavior, _compiler);
  }

  bool isArrayType(TypeMask type) {
    return type.satisfies(_backend.helpers.jsArrayClass, _compiler.world);
  }

  TypeMask getTypeMaskForNativeFunction(FunctionElement function) {
    return  _compiler.typesTask.getGuaranteedReturnTypeOfElement(function);
  }

  FieldElement locateSingleField(Selector selector, TypeMask type) {
    return _compiler.world.locateSingleField(selector, type);
  }

  Element get closureConverter {
    return _backend.helpers.closureConverter;
  }

  void addNativeMethod(FunctionElement function) {
    _backend.emitter.nativeEmitter.nativeMethods.add(function);
  }
}
