// 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,
                   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 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_;

  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 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_
