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

#ifndef RUNTIME_VM_FLOW_GRAPH_BUILDER_H_
#define RUNTIME_VM_FLOW_GRAPH_BUILDER_H_

#include "platform/assert.h"
#include "platform/globals.h"
#include "vm/allocation.h"
#include "vm/ast.h"
#include "vm/flow_graph.h"
#include "vm/growable_array.h"
#include "vm/intermediate_language.h"
#include "vm/raw_object.h"

namespace dart {

class AbstractType;
class Array;
class Class;
class Field;
class LocalVariable;
class ParsedFunction;
class String;
class TypeArguments;

class NestedStatement;
class TestGraphVisitor;

// A class to collect the exits from an inlined function during graph
// construction so they can be plugged into the caller's flow graph.
class InlineExitCollector : public ZoneAllocated {
 public:
  InlineExitCollector(FlowGraph* caller_graph, Definition* call)
      : caller_graph_(caller_graph), call_(call), exits_(4) {}

  void AddExit(ReturnInstr* exit);

  void Union(const InlineExitCollector* other);

  // Before replacing a call with a graph, the outer environment needs to be
  // attached to each instruction in the callee graph and the caller graph
  // needs to have its block and instruction ID state updated.
  // Additionally we need to remove all unreachable exits from the list of
  // collected exits.
  void PrepareGraphs(FlowGraph* callee_graph);

  // Inline a graph at a call site.
  //
  // Assumes the callee is in SSA with a correct dominator tree and use
  // lists.
  //
  // After inlining the caller graph will have correctly adjusted the use
  // lists.  The block orders will need to be recomputed.
  void ReplaceCall(TargetEntryInstr* callee_entry);

 private:
  struct Data {
    BlockEntryInstr* exit_block;
    ReturnInstr* exit_return;
  };

  BlockEntryInstr* ExitBlockAt(intptr_t i) const {
    ASSERT(exits_[i].exit_block != NULL);
    return exits_[i].exit_block;
  }

  Instruction* LastInstructionAt(intptr_t i) const {
    return ReturnAt(i)->previous();
  }

  Value* ValueAt(intptr_t i) const { return ReturnAt(i)->value(); }

  ReturnInstr* ReturnAt(intptr_t i) const { return exits_[i].exit_return; }

  static int LowestBlockIdFirst(const Data* a, const Data* b);
  void SortExits();
  void RemoveUnreachableExits(FlowGraph* callee_graph);

  Definition* JoinReturns(BlockEntryInstr** exit_block,
                          Instruction** last_instruction,
                          intptr_t try_index);

  Isolate* isolate() const { return caller_graph_->isolate(); }
  Zone* zone() const { return caller_graph_->zone(); }

  FlowGraph* caller_graph_;
  Definition* call_;
  GrowableArray<Data> exits_;
};


// Build a flow graph from a parsed function's AST.
class FlowGraphBuilder : public ValueObject {
 public:
  // The inlining context is NULL if not inlining.  The osr_id is the deopt
  // id of the OSR entry or Compiler::kNoOSRDeoptId if not compiling for OSR.
  FlowGraphBuilder(const ParsedFunction& parsed_function,
                   const ZoneGrowableArray<const ICData*>& ic_data_array,
                   ZoneGrowableArray<intptr_t>* context_level_array,
                   InlineExitCollector* exit_collector,
                   intptr_t osr_id);

  FlowGraph* BuildGraph();

  const ParsedFunction& parsed_function() const { return parsed_function_; }
  const Function& function() const { return parsed_function_.function(); }
  const ZoneGrowableArray<const ICData*>& ic_data_array() const {
    return ic_data_array_;
  }

  void Bailout(const char* reason) const;

  intptr_t AllocateBlockId() { return ++last_used_block_id_; }
  void SetInitialBlockId(intptr_t id) { last_used_block_id_ = id; }

  intptr_t GetNextDeoptId() const;

  intptr_t context_level() const;

  void IncrementLoopDepth() { ++loop_depth_; }
  void DecrementLoopDepth() { --loop_depth_; }
  intptr_t loop_depth() const { return loop_depth_; }

  // Manage the currently active try index.
  void set_try_index(intptr_t value) { try_index_ = value; }
  intptr_t try_index() const { return try_index_; }

  // Manage the currently active catch-handler try index.
  void set_catch_try_index(intptr_t value) { catch_try_index_ = value; }
  intptr_t catch_try_index() const { return catch_try_index_; }

  intptr_t next_await_counter() { return jump_count_++; }

  ZoneGrowableArray<JoinEntryInstr*>* await_joins() const {
    return await_joins_;
  }

  void AddCatchEntry(CatchBlockEntryInstr* entry);

  GraphEntryInstr* graph_entry() const { return graph_entry_; }

  intptr_t num_copied_params() const { return num_copied_params_; }
  intptr_t num_non_copied_params() const { return num_non_copied_params_; }
  intptr_t num_stack_locals() const { return num_stack_locals_; }

  bool IsInlining() const { return (exit_collector_ != NULL); }
  InlineExitCollector* exit_collector() const { return exit_collector_; }

  ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const {
    return parsed_function_.deferred_prefixes();
  }

  intptr_t temp_count() const { return temp_count_; }
  intptr_t AllocateTemp() { return temp_count_++; }
  void DeallocateTemps(intptr_t count) {
    ASSERT(temp_count_ >= count);
    temp_count_ -= count;
  }

  intptr_t args_pushed() const { return args_pushed_; }
  void add_args_pushed(intptr_t n) { args_pushed_ += n; }

  NestedStatement* nesting_stack() const { return nesting_stack_; }

  // When compiling for OSR, remove blocks that are not reachable from the
  // OSR entry point.
  void PruneUnreachable();

  // Returns address where the constant 'value' is stored or 0 if not found.
  static uword FindDoubleConstant(double value);

  Thread* thread() const { return parsed_function().thread(); }
  Isolate* isolate() const { return parsed_function().isolate(); }
  Zone* zone() const { return parsed_function().zone(); }

  void AppendAwaitTokenPosition(TokenPosition token_pos);

  ZoneGrowableArray<TokenPosition>* await_token_positions() const {
    return await_token_positions_;
  }

  static bool SimpleInstanceOfType(const AbstractType& type);

 private:
  friend class NestedStatement;  // Explicit access to nesting_stack_.
  friend class Intrinsifier;

  intptr_t parameter_count() const {
    return num_copied_params_ + num_non_copied_params_;
  }
  intptr_t variable_count() const {
    return parameter_count() + num_stack_locals_;
  }

  const ParsedFunction& parsed_function_;
  const ZoneGrowableArray<const ICData*>& ic_data_array_;
  // Contains (deopt_id, context_level) pairs.
  ZoneGrowableArray<intptr_t>* context_level_array_;

  const intptr_t num_copied_params_;
  const intptr_t num_non_copied_params_;
  const intptr_t num_stack_locals_;  // Does not include any parameters.
  InlineExitCollector* const exit_collector_;

  intptr_t last_used_block_id_;
  intptr_t try_index_;
  intptr_t catch_try_index_;
  intptr_t loop_depth_;
  GraphEntryInstr* graph_entry_;

  // The expression stack height.
  intptr_t temp_count_;

  // Outgoing argument stack height.
  intptr_t args_pushed_;

  // A stack of enclosing nested statements.
  NestedStatement* nesting_stack_;

  // The deopt id of the OSR entry orCompiler::kNoOSRDeoptId if not compiling
  // for OSR.
  const intptr_t osr_id_;

  intptr_t jump_count_;
  ZoneGrowableArray<JoinEntryInstr*>* await_joins_;
  ZoneGrowableArray<TokenPosition>* await_token_positions_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(FlowGraphBuilder);
};


// Translate an AstNode to a control-flow graph fragment for its effects
// (e.g., a statement or an expression in an effect context).  Implements a
// function from an AstNode and next temporary index to a graph fragment
// with a single entry and at most one exit.  The fragment is represented by
// an (entry, exit) pair of Instruction pointers:
//
//   - (NULL, NULL): an empty and open graph fragment
//   - (i0, NULL): a closed graph fragment which has only non-local exits
//   - (i0, i1): an open graph fragment
class EffectGraphVisitor : public AstNodeVisitor {
 public:
  explicit EffectGraphVisitor(FlowGraphBuilder* owner)
      : owner_(owner), entry_(NULL), exit_(NULL) {}

#define DECLARE_VISIT(BaseName)                                                \
  virtual void Visit##BaseName##Node(BaseName##Node* node);

  FOR_EACH_NODE(DECLARE_VISIT)
#undef DECLARE_VISIT

  FlowGraphBuilder* owner() const { return owner_; }
  Instruction* entry() const { return entry_; }
  Instruction* exit() const { return exit_; }

  bool is_empty() const { return entry_ == NULL; }
  bool is_open() const { return is_empty() || exit_ != NULL; }

  void Bailout(const char* reason) const;
  void InlineBailout(const char* reason) const;

  // Append a graph fragment to this graph.  Assumes this graph is open.
  void Append(const EffectGraphVisitor& other_fragment);
  // Append a definition that can have uses.  Assumes this graph is open.
  Value* Bind(Definition* definition);
  // Append a computation with no uses.  Assumes this graph is open.
  void Do(Definition* definition);
  // Append a single (non-Definition, non-Entry) instruction.  Assumes this
  // graph is open.
  void AddInstruction(Instruction* instruction);
  // Append a Goto (unconditional control flow) instruction and close
  // the graph fragment.  Assumes this graph fragment is open.
  void Goto(JoinEntryInstr* join);

  // Append a 'diamond' branch and join to this graph, depending on which
  // parts are reachable.  Assumes this graph is open.
  void Join(const TestGraphVisitor& test_fragment,
            const EffectGraphVisitor& true_fragment,
            const EffectGraphVisitor& false_fragment);

  // Append a 'while loop' test and back edge to this graph, depending on
  // which parts are reachable.  Afterward, the graph exit is the false
  // successor of the loop condition.
  void TieLoop(TokenPosition token_pos,
               const TestGraphVisitor& test_fragment,
               const EffectGraphVisitor& body_fragment,
               const EffectGraphVisitor& test_preamble_fragment);

  // Wraps a value in a push-argument instruction and adds the result to the
  // graph.
  PushArgumentInstr* PushArgument(Value* value);

  // This implementation shares state among visitors by using the builder.
  // The implementation is incorrect if a visitor that hits a return is not
  // actually added to the graph.
  void AddReturnExit(TokenPosition token_pos, Value* value);

 protected:
  Definition* BuildStoreTemp(const LocalVariable& local,
                             Value* value,
                             TokenPosition token_pos);
  Definition* BuildStoreExprTemp(Value* value, TokenPosition token_pos);
  Definition* BuildLoadExprTemp(TokenPosition token_pos);

  Definition* BuildStoreLocal(const LocalVariable& local,
                              Value* value,
                              TokenPosition token_pos);
  Definition* BuildLoadLocal(const LocalVariable& local,
                             TokenPosition token_pos);
  LoadLocalInstr* BuildLoadThisVar(LocalScope* scope, TokenPosition token_pos);
  LoadFieldInstr* BuildNativeGetter(NativeBodyNode* node,
                                    MethodRecognizer::Kind kind,
                                    intptr_t offset,
                                    const Type& type,
                                    intptr_t class_id);
  // Assumes setter parameter is named 'value'. Returns null constant.
  ConstantInstr* DoNativeSetterStoreValue(NativeBodyNode* node,
                                          intptr_t offset,
                                          StoreBarrierType emit_store_barrier);

  // Helpers for translating parts of the AST.
  void BuildPushTypeArguments(const ArgumentListNode& node,
                              ZoneGrowableArray<PushArgumentInstr*>* values);
  void BuildPushArguments(const ArgumentListNode& node,
                          ZoneGrowableArray<PushArgumentInstr*>* values);

  // Creates an instantiated type argument vector used in preparation of an
  // allocation call.
  // May be called only if allocating an object of a parameterized class.
  Value* BuildInstantiatedTypeArguments(TokenPosition token_pos,
                                        const TypeArguments& type_arguments);

  Value* BuildInstantiator(TokenPosition token_pos);
  Value* BuildInstantiatorTypeArguments(TokenPosition token_pos);
  Value* BuildFunctionTypeArguments(TokenPosition token_pos);
  PushArgumentInstr* PushInstantiatorTypeArguments(const AbstractType& type,
                                                   TokenPosition token_pos);
  PushArgumentInstr* PushFunctionTypeArguments(const AbstractType& type,
                                               TokenPosition token_pos);

  // Perform a type check on the given value.
  AssertAssignableInstr* BuildAssertAssignable(TokenPosition token_pos,
                                               Value* value,
                                               const AbstractType& dst_type,
                                               const String& dst_name);

  // Perform a type check on the given value and return it.
  Value* BuildAssignableValue(TokenPosition token_pos,
                              Value* value,
                              const AbstractType& dst_type,
                              const String& dst_name);

  static const bool kResultNeeded = true;
  static const bool kResultNotNeeded = false;

  Definition* BuildStoreIndexedValues(StoreIndexedNode* node,
                                      bool result_is_needed);

  void BuildInstanceSetterArguments(
      InstanceSetterNode* node,
      ZoneGrowableArray<PushArgumentInstr*>* arguments,
      bool result_is_needed);

  StrictCompareInstr* BuildStrictCompare(AstNode* left,
                                         AstNode* right,
                                         Token::Kind kind,
                                         TokenPosition token_pos);

  virtual void BuildTypeTest(ComparisonNode* node);
  virtual void BuildTypeCast(ComparisonNode* node);

  bool HasContextScope() const;

  // Moves the nth parent context into the context register.
  void UnchainContexts(intptr_t n);

  // Unchain the current context until its level matches the context level
  // expected on entry at the target specified by its scope.
  void AdjustContextLevel(LocalScope* target_scope);

  void CloseFragment() { exit_ = NULL; }

  // Returns a local variable index for a temporary local that is
  // on top of the current expression stack.
  intptr_t GetCurrentTempLocalIndex() const;

  Value* BuildObjectAllocation(ConstructorCallNode* node);
  void BuildConstructorCall(ConstructorCallNode* node,
                            PushArgumentInstr* alloc_value);

  void BuildSaveContext(const LocalVariable& variable, TokenPosition token_pos);
  void BuildRestoreContext(const LocalVariable& variable,
                           TokenPosition token_pos);

  Definition* BuildStoreContext(Value* value, TokenPosition token_pos);
  Definition* BuildCurrentContext(TokenPosition token_pos);

  void BuildThrowNode(ThrowNode* node);

  StaticCallInstr* BuildStaticNoSuchMethodCall(
      const Class& target_class,
      AstNode* receiver,
      const String& method_name,
      ArgumentListNode* method_arguments,
      bool save_last_arg,
      bool is_super_invocation);

  StaticCallInstr* BuildThrowNoSuchMethodError(
      TokenPosition token_pos,
      const Class& function_class,
      const String& function_name,
      ArgumentListNode* function_arguments,
      int invocation_type);

  void BuildStaticSetter(StaticSetterNode* node, bool result_is_needed);
  Definition* BuildStoreStaticField(StoreStaticFieldNode* node,
                                    bool result_is_needed,
                                    TokenPosition token_pos);

  void BuildClosureCall(ClosureCallNode* node, bool result_needed);

  Value* BuildNullValue(TokenPosition token_pos);
  Value* BuildEmptyTypeArguments(TokenPosition token_pos);

  // Returns true if the run-time type check can be eliminated.
  bool CanSkipTypeCheck(TokenPosition token_pos,
                        Value* value,
                        const AbstractType& dst_type,
                        const String& dst_name);

  // Helpers for allocating and deallocating temporary locals on top of the
  // expression stack.
  LocalVariable* EnterTempLocalScope(Value* value);
  Definition* ExitTempLocalScope(Value* value);

  void BuildLetTempExpressions(LetNode* node);

  void BuildInstanceGetterConditional(InstanceGetterNode* node);
  void BuildInstanceCallConditional(InstanceCallNode* node);

  Thread* thread() const { return owner()->thread(); }
  Isolate* isolate() const { return owner()->isolate(); }
  Zone* zone() const { return owner()->zone(); }

 private:
  friend class TempLocalScope;  // For ReturnDefinition.

  // Helper to drop the result value.
  virtual void ReturnValue(Value* value) { Do(new DropTempsInstr(0, value)); }

  // Specify a definition of the final result.  Adds the definition to
  // the graph, but normally overridden in subclasses.
  virtual void ReturnDefinition(Definition* definition) {
    // Constants have no effect, do not add them to graph otherwise SSA
    // builder will get confused.
    if (!definition->IsConstant()) {
      Do(definition);
    }
  }

  // Shared global state.
  FlowGraphBuilder* owner_;

  // Output parameters.
  Instruction* entry_;
  Instruction* exit_;
};


// Translate an AstNode to a control-flow graph fragment for both its effects
// and value (e.g., for an expression in a value context).  Implements a
// function from an AstNode and next temporary index to a graph fragment (as
// in the EffectGraphVisitor), a next temporary index, and an intermediate
// language Value.
class ValueGraphVisitor : public EffectGraphVisitor {
 public:
  explicit ValueGraphVisitor(FlowGraphBuilder* owner)
      : EffectGraphVisitor(owner), value_(NULL) {}

  // Visit functions overridden by this class.
  virtual void VisitAssignableNode(AssignableNode* node);
  virtual void VisitConstructorCallNode(ConstructorCallNode* node);
  virtual void VisitBinaryOpNode(BinaryOpNode* node);
  virtual void VisitConditionalExprNode(ConditionalExprNode* node);
  virtual void VisitLoadLocalNode(LoadLocalNode* node);
  virtual void VisitStoreIndexedNode(StoreIndexedNode* node);
  virtual void VisitInstanceSetterNode(InstanceSetterNode* node);
  virtual void VisitInstanceGetterNode(InstanceGetterNode* node);
  virtual void VisitThrowNode(ThrowNode* node);
  virtual void VisitClosureCallNode(ClosureCallNode* node);
  virtual void VisitStaticSetterNode(StaticSetterNode* node);
  virtual void VisitStoreStaticFieldNode(StoreStaticFieldNode* node);
  virtual void VisitTypeNode(TypeNode* node);
  virtual void VisitLetNode(LetNode* node);
  virtual void VisitInstanceCallNode(InstanceCallNode* node);

  Value* value() const { return value_; }

 protected:
  // Output parameters.
  Value* value_;

 private:
  // Helper to set the output state to return a Value.
  virtual void ReturnValue(Value* value) { value_ = value; }

  // Specify a definition of the final result.  Adds the definition to
  // the graph and returns a use of it (i.e., set the visitor's output
  // parameters).
  virtual void ReturnDefinition(Definition* definition) {
    ReturnValue(Bind(definition));
  }
};


// Translate an AstNode to a control-flow graph fragment for both its
// effects and true/false control flow (e.g., for an expression in a test
// context).  The resulting graph is always closed (even if it is empty)
// Successor control flow is explicitly set by a pair of pointers to
// TargetEntryInstr*.
//
// To distinguish between the graphs with only nonlocal exits and graphs
// with both true and false exits, there are a pair of TargetEntryInstr**:
//
//   - Both NULL: only non-local exits, truly closed
//   - Neither NULL: true and false successors at the given addresses
//
// We expect that AstNode in test contexts either have only nonlocal exits
// or else control flow has both true and false successors.
//
// The cis and token_pos are used in checked mode to verify that the
// condition of the test is of type bool.
class TestGraphVisitor : public ValueGraphVisitor {
 public:
  TestGraphVisitor(FlowGraphBuilder* owner, TokenPosition condition_token_pos)
      : ValueGraphVisitor(owner),
        true_successor_addresses_(1),
        false_successor_addresses_(1),
        condition_token_pos_(condition_token_pos) {}

  void IfFalseGoto(JoinEntryInstr* join) const;
  void IfTrueGoto(JoinEntryInstr* join) const;

  BlockEntryInstr* CreateTrueSuccessor() const;
  BlockEntryInstr* CreateFalseSuccessor() const;

  virtual void VisitBinaryOpNode(BinaryOpNode* node);

  TokenPosition condition_token_pos() const { return condition_token_pos_; }

 private:
  // Construct and concatenate a Branch instruction to this graph fragment.
  // Closes the fragment and sets the output parameters.
  virtual void ReturnValue(Value* value);

  // Either merges the definition into a BranchInstr (Comparison, BooleanNegate)
  // or adds the definition to the graph and returns a use of its value.
  virtual void ReturnDefinition(Definition* definition);

  void MergeBranchWithStrictCompare(StrictCompareInstr* comp);
  void MergeBranchWithNegate(BooleanNegateInstr* comp);

  BlockEntryInstr* CreateSuccessorFor(
      const GrowableArray<TargetEntryInstr**>& branches) const;

  void ConnectBranchesTo(const GrowableArray<TargetEntryInstr**>& branches,
                         JoinEntryInstr* join) const;

  // Output parameters.
  GrowableArray<TargetEntryInstr**> true_successor_addresses_;
  GrowableArray<TargetEntryInstr**> false_successor_addresses_;

  TokenPosition condition_token_pos_;
};

}  // namespace dart

#endif  // RUNTIME_VM_FLOW_GRAPH_BUILDER_H_
