/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_DEX_TYPE_INFERENCE_H_
#define ART_COMPILER_DEX_TYPE_INFERENCE_H_

#include "base/logging.h"
#include "base/arena_object.h"
#include "base/scoped_arena_containers.h"

namespace art {

class ArenaBitVector;
class BasicBlock;
struct CompilationUnit;
class DexFile;
class MirFieldInfo;
class MirMethodInfo;
class MIR;
class MIRGraph;

/**
 * @brief Determine the type of SSA registers.
 *
 * @details
 * Because Dalvik's bytecode is not fully typed, we have to do some work to figure
 * out the sreg type.  For some operations it is clear based on the opcode (i.e.
 * ADD_FLOAT v0, v1, v2), but for others (MOVE), we may never know the "real" type.
 *
 * We perform the type inference operation in two phases:
 *   1. First, we make one pass over all insns in the topological sort order and
 *      extract known type information from all insns for their defs and uses.
 *   2. Then we repeatedly go through the graph to process insns that can propagate
 *      types from inputs to outputs and vice versa. These insns are just the MOVEs,
 *      AGET/APUTs, IF_ccs and Phis (including pseudo-Phis, see below).
 *
 * Since the main purpose is to determine the basic FP/core/reference type, we don't
 * need to record the precise reference type, we only record the array type to determine
 * the result types of agets and source type of aputs.
 *
 * One complication is the check-cast instruction that effectively defines a new
 * virtual register that has a different type than the original sreg. We need to
 * track these virtual sregs and insert pseudo-phis where they merge.
 *
 * Another problems is with null references. The same zero constant can be used
 * as differently typed null and moved around with move-object which would normally
 * be an ill-formed assignment. So we need to keep track of values that can be null
 * and values that cannot.
 *
 * Note that it's possible to have the same sreg show multiple defined types because dx
 * treats constants as untyped bit patterns. We disable register promotion in that case.
 */
class TypeInference : public DeletableArenaObject<kArenaAllocMisc> {
 public:
  TypeInference(MIRGraph* mir_graph, ScopedArenaAllocator* alloc);

  bool Apply(BasicBlock* bb);
  void Finish();

 private:
  struct Type {
    static Type Unknown() {
      return Type(0u);
    }

    static Type NonArrayRefType() {
      return Type(kFlagLowWord | kFlagNarrow | kFlagRef);
    }

    static Type ObjectArrayType() {
      return Type(kFlagNarrow | kFlagRef | kFlagLowWord |
                  (1u << kBitArrayDepthStart) | kFlagArrayNarrow | kFlagArrayRef);
    }

    static Type WideArrayType() {
      // Core or FP unknown.
      return Type(kFlagNarrow | kFlagRef | kFlagLowWord |
                  (1u << kBitArrayDepthStart) | kFlagArrayWide);
    }

    static Type NarrowArrayType() {
      // Core or FP unknown.
      return Type(kFlagNarrow | kFlagRef | kFlagLowWord |
                  (1u << kBitArrayDepthStart) | kFlagArrayNarrow);
    }

    static Type NarrowCoreArrayType() {
      return Type(kFlagNarrow | kFlagRef | kFlagLowWord |
                  (1u << kBitArrayDepthStart) | kFlagArrayNarrow | kFlagArrayCore);
    }

    static Type UnknownArrayType() {
      return Type(kFlagNarrow | kFlagRef | kFlagLowWord | (1u << kBitArrayDepthStart));
    }

    static Type ArrayType(uint32_t array_depth, Type nested_type);
    static Type ArrayTypeFromComponent(Type component_type);
    static Type ShortyType(char shorty);
    static Type DexType(const DexFile* dex_file, uint32_t type_idx);

    bool IsDefined() {
      return raw_bits_ != 0u;
    }

    bool SizeConflict() const {
      // NOTE: Ignore array element conflicts that don't propagate to direct conflicts.
      return (Wide() && Narrow()) || (HighWord() && LowWord());
    }

    bool TypeConflict() const {
      // NOTE: Ignore array element conflicts that don't propagate to direct conflicts.
      return (raw_bits_ & kMaskType) != 0u && !IsPowerOfTwo(raw_bits_ & kMaskType);  // 2+ bits.
    }

    void MarkSizeConflict() {
      SetBits(kFlagLowWord | kFlagHighWord);
    }

    void MarkTypeConflict() {
      // Mark all three type bits so that merging any other type bits will not change this type.
      SetBits(kFlagFp | kFlagCore | kFlagRef);
    }

    void CheckPureRef() const {
      DCHECK_EQ(raw_bits_ & (kMaskWideAndType | kMaskWord), kFlagNarrow | kFlagRef | kFlagLowWord);
    }

    // If reference, don't treat as possible null and require precise type.
    //
    // References without this flag are allowed to have a type conflict and their
    // type will not be propagated down. However, for simplicity we allow propagation
    // of other flags up as it will affect only other null references; should those
    // references be marked non-null later, we would have to do it anyway.
    // NOTE: This is a negative "non-null" flag rather then a positive "is-null"
    // to simplify merging together with other non-array flags.
    bool NonNull() const {
      return IsBitSet(kFlagNonNull);
    }

    bool Wide() const {
      return IsBitSet(kFlagWide);
    }

    bool Narrow() const {
      return IsBitSet(kFlagNarrow);
    }

    bool Fp() const {
      return IsBitSet(kFlagFp);
    }

    bool Core() const {
      return IsBitSet(kFlagCore);
    }

    bool Ref() const {
      return IsBitSet(kFlagRef);
    }

    bool LowWord() const {
      return IsBitSet(kFlagLowWord);
    }

    bool HighWord() const {
      return IsBitSet(kFlagHighWord);
    }

    uint32_t ArrayDepth() const {
      return raw_bits_ >> kBitArrayDepthStart;
    }

    Type NestedType() const {
      DCHECK_NE(ArrayDepth(), 0u);
      return Type(kFlagLowWord | ((raw_bits_ & kMaskArrayWideAndType) >> kArrayTypeShift));
    }

    Type ComponentType() const {
      DCHECK_NE(ArrayDepth(), 0u);
      Type temp(raw_bits_ - (1u << kBitArrayDepthStart));  // array_depth - 1u;
      return (temp.ArrayDepth() != 0u) ? temp.AsNull() : NestedType();
    }

    void SetWide() {
      SetBits(kFlagWide);
    }

    void SetNarrow() {
      SetBits(kFlagNarrow);
    }

    void SetFp() {
      SetBits(kFlagFp);
    }

    void SetCore() {
      SetBits(kFlagCore);
    }

    void SetRef() {
      SetBits(kFlagRef);
    }

    void SetLowWord() {
      SetBits(kFlagLowWord);
    }

    void SetHighWord() {
      SetBits(kFlagHighWord);
    }

    Type ToHighWord() const {
      DCHECK_EQ(raw_bits_ & (kMaskWide | kMaskWord), kFlagWide | kFlagLowWord);
      return Type(raw_bits_ ^ (kFlagLowWord | kFlagHighWord));
    }

    bool MergeHighWord(Type low_word_type) {
      // NOTE: low_word_type may be also Narrow() or HighWord().
      DCHECK(low_word_type.Wide() && low_word_type.LowWord());
      return MergeBits(Type(low_word_type.raw_bits_ | kFlagHighWord),
                       kMaskWideAndType | kFlagHighWord);
    }

    bool Copy(Type type) {
      if (raw_bits_ != type.raw_bits_) {
        raw_bits_ = type.raw_bits_;
        return true;
      }
      return false;
    }

    // Merge non-array flags.
    bool MergeNonArrayFlags(Type src_type) {
      return MergeBits(src_type, kMaskNonArray);
    }

    // Merge array flags for conflict.
    bool MergeArrayConflict(Type src_type);

    // Merge all flags.
    bool MergeStrong(Type src_type);

    // Merge all flags.
    bool MergeWeak(Type src_type);

    // Get the same type but mark that it should not be treated as null.
    Type AsNonNull() const {
      return Type(raw_bits_ | kFlagNonNull);
    }

    // Get the same type but mark that it can be treated as null.
    Type AsNull() const {
      return Type(raw_bits_ & ~kFlagNonNull);
    }

   private:
    enum FlagBits {
      kBitNonNull = 0,
      kBitWide,
      kBitNarrow,
      kBitFp,
      kBitCore,
      kBitRef,
      kBitLowWord,
      kBitHighWord,
      kBitArrayWide,
      kBitArrayNarrow,
      kBitArrayFp,
      kBitArrayCore,
      kBitArrayRef,
      kBitArrayDepthStart,
    };
    static constexpr size_t kArrayDepthBits = sizeof(uint32_t) * 8u - kBitArrayDepthStart;

    static constexpr uint32_t kFlagNonNull = 1u << kBitNonNull;
    static constexpr uint32_t kFlagWide = 1u << kBitWide;
    static constexpr uint32_t kFlagNarrow = 1u << kBitNarrow;
    static constexpr uint32_t kFlagFp = 1u << kBitFp;
    static constexpr uint32_t kFlagCore = 1u << kBitCore;
    static constexpr uint32_t kFlagRef = 1u << kBitRef;
    static constexpr uint32_t kFlagLowWord = 1u << kBitLowWord;
    static constexpr uint32_t kFlagHighWord = 1u << kBitHighWord;
    static constexpr uint32_t kFlagArrayWide = 1u << kBitArrayWide;
    static constexpr uint32_t kFlagArrayNarrow = 1u << kBitArrayNarrow;
    static constexpr uint32_t kFlagArrayFp = 1u << kBitArrayFp;
    static constexpr uint32_t kFlagArrayCore = 1u << kBitArrayCore;
    static constexpr uint32_t kFlagArrayRef = 1u << kBitArrayRef;

    static constexpr uint32_t kMaskWide = kFlagWide | kFlagNarrow;
    static constexpr uint32_t kMaskType = kFlagFp | kFlagCore | kFlagRef;
    static constexpr uint32_t kMaskWord = kFlagLowWord | kFlagHighWord;
    static constexpr uint32_t kMaskArrayWide = kFlagArrayWide | kFlagArrayNarrow;
    static constexpr uint32_t kMaskArrayType = kFlagArrayFp | kFlagArrayCore | kFlagArrayRef;
    static constexpr uint32_t kMaskWideAndType = kMaskWide | kMaskType;
    static constexpr uint32_t kMaskArrayWideAndType = kMaskArrayWide | kMaskArrayType;

    static constexpr size_t kArrayTypeShift = kBitArrayWide - kBitWide;
    static_assert(kArrayTypeShift == kBitArrayNarrow - kBitNarrow, "shift mismatch");
    static_assert(kArrayTypeShift == kBitArrayFp - kBitFp, "shift mismatch");
    static_assert(kArrayTypeShift == kBitArrayCore - kBitCore, "shift mismatch");
    static_assert(kArrayTypeShift == kBitArrayRef - kBitRef, "shift mismatch");
    static_assert((kMaskWide << kArrayTypeShift) == kMaskArrayWide, "shift mismatch");
    static_assert((kMaskType << kArrayTypeShift) == kMaskArrayType, "shift mismatch");
    static_assert((kMaskWideAndType << kArrayTypeShift) == kMaskArrayWideAndType, "shift mismatch");

    static constexpr uint32_t kMaskArrayDepth = static_cast<uint32_t>(-1) << kBitArrayDepthStart;
    static constexpr uint32_t kMaskNonArray = ~(kMaskArrayWideAndType | kMaskArrayDepth);

    // The maximum representable array depth. If we exceed the maximum (which can happen
    // only with an absurd nested array type in a dex file which would presumably cause
    // OOM while being resolved), we can report false conflicts.
    static constexpr uint32_t kMaxArrayDepth = static_cast<uint32_t>(-1) >> kBitArrayDepthStart;

    explicit Type(uint32_t raw_bits) : raw_bits_(raw_bits) { }

    bool IsBitSet(uint32_t flag) const {
      return (raw_bits_ & flag) != 0u;
    }

    void SetBits(uint32_t flags) {
      raw_bits_ |= flags;
    }

    bool MergeBits(Type src_type, uint32_t mask) {
      uint32_t new_bits = raw_bits_ | (src_type.raw_bits_ & mask);
      if (new_bits != raw_bits_) {
        raw_bits_ = new_bits;
        return true;
      }
      return false;
    }

    uint32_t raw_bits_;
  };

  struct MethodSignature {
    Type return_type;
    size_t num_params;
    Type* param_types;
  };

  struct SplitSRegData {
    int32_t current_mod_s_reg;
    int32_t* starting_mod_s_reg;        // Indexed by BasicBlock::id.
    int32_t* ending_mod_s_reg;          // Indexed by BasicBlock::id.

    // NOTE: Before AddPseudoPhis(), def_phi_blocks_ marks the blocks
    // with check-casts and the block with the original SSA reg.
    // After AddPseudoPhis(), it marks blocks with pseudo-phis.
    ArenaBitVector* def_phi_blocks_;    // Indexed by BasicBlock::id.
  };

  class CheckCastData : public DeletableArenaObject<kArenaAllocMisc> {
   public:
    CheckCastData(MIRGraph* mir_graph, ScopedArenaAllocator* alloc);

    size_t NumSRegs() const {
      return num_sregs_;
    }

    void AddCheckCast(MIR* check_cast, Type type);
    void AddPseudoPhis();
    void InitializeCheckCastSRegs(Type* sregs) const;
    void MergeCheckCastConflicts(Type* sregs) const;
    void MarkPseudoPhiBlocks(uint64_t* bb_df_attrs) const;

    void Start(BasicBlock* bb);
    bool ProcessPseudoPhis(BasicBlock* bb, Type* sregs);
    void ProcessCheckCast(MIR* mir);

    SplitSRegData* GetSplitSRegData(int32_t s_reg);

   private:
    BasicBlock* FindDefBlock(MIR* check_cast);
    BasicBlock* FindTopologicallyEarliestPredecessor(BasicBlock* bb);
    bool IsSRegLiveAtStart(BasicBlock* bb, int v_reg, int32_t s_reg);

    MIRGraph* const mir_graph_;
    ScopedArenaAllocator* const alloc_;
    const size_t num_blocks_;
    size_t num_sregs_;

    // Map check-cast mir to special sreg and type.
    struct CheckCastMapValue {
      int32_t modified_s_reg;
      Type type;
    };
    ScopedArenaSafeMap<MIR*, CheckCastMapValue> check_cast_map_;
    ScopedArenaSafeMap<int32_t, SplitSRegData> split_sreg_data_;
  };

  static Type FieldType(const DexFile* dex_file, uint32_t field_idx);
  static Type* PrepareIFieldTypes(const DexFile* dex_file, MIRGraph* mir_graph,
                                  ScopedArenaAllocator* alloc);
  static Type* PrepareSFieldTypes(const DexFile* dex_file, MIRGraph* mir_graph,
                                  ScopedArenaAllocator* alloc);
  static MethodSignature Signature(const DexFile* dex_file, uint32_t method_idx, bool is_static,
                                   ScopedArenaAllocator* alloc);
  static MethodSignature* PrepareSignatures(const DexFile* dex_file, MIRGraph* mir_graph,
                                            ScopedArenaAllocator* alloc);
  static CheckCastData* InitializeCheckCastData(MIRGraph* mir_graph, ScopedArenaAllocator* alloc);

  void InitializeSRegs();

  int32_t ModifiedSReg(int32_t s_reg);
  int32_t PhiInputModifiedSReg(int32_t s_reg, BasicBlock* bb, size_t pred_idx);

  bool UpdateSRegFromLowWordType(int32_t mod_s_reg, Type low_word_type);

  MIRGraph* const mir_graph_;
  CompilationUnit* const cu_;

  // The type inference propagates types also backwards but this must not happen across
  // check-cast. So we need to effectively split an SSA reg into two at check-cast and
  // keep track of the types separately.
  std::unique_ptr<CheckCastData> check_cast_data_;

  size_t num_sregs_;      // Number of SSA regs or modified SSA regs, see check-cast.
  const Type* const ifields_;                 // Indexed by MIR::meta::ifield_lowering_info.
  const Type* const sfields_;                 // Indexed by MIR::meta::sfield_lowering_info.
  const MethodSignature* const signatures_;   // Indexed by MIR::meta::method_lowering_info.
  const MethodSignature current_method_signature_;
  Type* const sregs_;     // Indexed by SSA reg or modified SSA reg, see check-cast.
  uint64_t* const bb_df_attrs_;               // Indexed by BasicBlock::id.

  friend class TypeInferenceTest;
};

}  // namespace art

#endif  // ART_COMPILER_DEX_TYPE_INFERENCE_H_
