// 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_COMPILER_AOT_AOT_CALL_SPECIALIZER_H_
#define RUNTIME_VM_COMPILER_AOT_AOT_CALL_SPECIALIZER_H_

#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif  // defined(DART_PRECOMPILED_RUNTIME)

#include "vm/compiler/call_specializer.h"

namespace dart {

class Precompiler;

class AotCallSpecializer : public CallSpecializer {
 public:
  AotCallSpecializer(Precompiler* precompiler, FlowGraph* flow_graph);

  virtual ~AotCallSpecializer() {}

  virtual void VisitInstanceCall(InstanceCallInstr* instr);
  virtual void VisitStaticCall(StaticCallInstr* instr);
  virtual void VisitPolymorphicInstanceCall(
      PolymorphicInstanceCallInstr* instr);

  virtual bool TryReplaceInstanceOfWithRangeCheck(InstanceCallInstr* call,
                                                  const AbstractType& type);

 private:
  // Attempt to build ICData for call using propagated class-ids.
  virtual bool TryCreateICData(InstanceCallInstr* call);

  bool TryCreateICDataForUniqueTarget(InstanceCallInstr* call);

  bool RecognizeRuntimeTypeGetter(InstanceCallInstr* call);
  bool TryReplaceWithHaveSameRuntimeType(TemplateDartCall<0>* call);

  bool TryInlineFieldAccess(InstanceCallInstr* call);
  bool TryInlineFieldAccess(StaticCallInstr* call);

  bool IsSupportedIntOperandForStaticDoubleOp(CompileType* operand_type);
  Value* PrepareStaticOpInput(Value* input, intptr_t cid, Instruction* call);

  CompileType BuildStrengthenedReceiverType(Value* input, intptr_t cid);

  bool TryOptimizeInstanceCallUsingStaticTypes(InstanceCallInstr* instr);

  virtual bool TryOptimizeStaticCallUsingStaticTypes(StaticCallInstr* call);

  // If a call can be dispatched through the global dispatch table, replace
  // it by a dispatch table call.
  void TryReplaceWithDispatchTableCall(InstanceCallBaseInstr* call);
  const Function& InterfaceTargetForTableDispatch(InstanceCallBaseInstr* call);
  void ReplaceWithConditionalDispatchTableCall(
      InstanceCallBaseInstr* call,
      LoadClassIdInstr* load_cid,
      const Function& interface_target,
      const compiler::TableSelector* selector);

  // Try to replace a call with a more specialized instruction working on
  // integers (e.g. BinaryInt64OpInstr, EqualityCompareInstr,
  // RelationalOpInstr)
  bool TryOptimizeIntegerOperation(TemplateDartCall<0>* call, Token::Kind kind);

  // Try to replace a call with a more specialized instruction working on
  // doubles (e.g. BinaryDoubleOpInstr, EqualityCompareInstr,
  // RelationalOpInstr)
  bool TryOptimizeDoubleOperation(TemplateDartCall<0>* call, Token::Kind kind);

  // Check if o.m(...) [call] is actually an invocation through a getter
  // o.get:m().call(...) given that the receiver of the call is a subclass
  // of the [receiver_class]. If it is - then expand it into
  // o.get:m.call(...) to avoid hitting dispatch through noSuchMethod.
  bool TryExpandCallThroughGetter(const Class& receiver_class,
                                  InstanceCallInstr* call);

  Definition* TryOptimizeDivisionOperation(TemplateDartCall<0>* instr,
                                           Token::Kind op_kind,
                                           Value* left_value,
                                           Value* right_value);

  virtual void ReplaceInstanceCallsWithDispatchTableCalls();

  Precompiler* precompiler_;

  bool has_unique_no_such_method_;

  DISALLOW_COPY_AND_ASSIGN(AotCallSpecializer);
};

}  // namespace dart

#endif  // RUNTIME_VM_COMPILER_AOT_AOT_CALL_SPECIALIZER_H_
