/*
 * Copyright (C) 2011 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_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_
#define ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_

#include <iosfwd>
#include <memory>
#include <vector>

#include "arch/instruction_set.h"
#include "base/macros.h"

namespace art {

class ArmInstructionSetFeatures;
class Arm64InstructionSetFeatures;
class X86InstructionSetFeatures;
class X86_64InstructionSetFeatures;

// Abstraction used to describe features of a different instruction sets.
class InstructionSetFeatures {
 public:
  // Process a CPU variant string for the given ISA and create an InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromVariant(InstructionSet isa,
                                                                   const std::string& variant,
                                                                   std::string* error_msg);

  // Parse a bitmap for the given isa and create an InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromBitmap(InstructionSet isa,
                                                                  uint32_t bitmap);

  // Turn C pre-processor #defines into the equivalent instruction set features for kRuntimeISA.
  static std::unique_ptr<const InstructionSetFeatures> FromCppDefines();

  // Check if run-time detection of instruction set features is supported.
  //
  // Return: true - if run-time detection is supported on a target device.
  //         false - otherwise
  static bool IsRuntimeDetectionSupported() {
    return FromRuntimeDetection() != nullptr;
  }

  // Use run-time detection to get instruction set features.
  //
  // Return: a set of detected features or nullptr if runtime detection is not
  //         supported on a target.
  static std::unique_ptr<const InstructionSetFeatures> FromRuntimeDetection();

  // Process /proc/cpuinfo and use kRuntimeISA to produce InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromCpuInfo();

  // Process the auxiliary vector AT_HWCAP entry and use kRuntimeISA to produce
  // InstructionSetFeatures.
  static std::unique_ptr<const InstructionSetFeatures> FromHwcap();

  // Use assembly tests of the current runtime (ie kRuntimeISA) to determine the
  // InstructionSetFeatures. This works around kernel bugs in AT_HWCAP and /proc/cpuinfo.
  static std::unique_ptr<const InstructionSetFeatures> FromAssembly();

  // Parse a string of the form "div,-atomic_ldrd_strd" adding and removing these features to
  // create a new InstructionSetFeatures.
  std::unique_ptr<const InstructionSetFeatures> AddFeaturesFromString(
      const std::string& feature_list, std::string* error_msg) const WARN_UNUSED;

  // Are these features the same as the other given features?
  virtual bool Equals(const InstructionSetFeatures* other) const = 0;

  // For testing purposes we want to make sure that the system we run on has at
  // least the options we claim it has. In this cases Equals() does not
  // suffice and will cause the test to fail, since the runtime cpu feature
  // detection claims more capabilities then statically specified from the
  // build system.
  //
  // A good example of this is the armv8 ART test target that declares
  // "CPU_VARIANT=generic". If the generic target is specified and the code
  // is run on a platform with enhanced capabilities, the
  // instruction_set_features test will fail if we resort to using Equals()
  // between statically defined cpu features and runtime cpu features.
  //
  // For now we default this to Equals() in case the architecture does not
  // provide it.
  virtual bool HasAtLeast(const InstructionSetFeatures* other) const {
    return Equals(other);
  }

  // Return the ISA these features relate to.
  virtual InstructionSet GetInstructionSet() const = 0;

  // Return a bitmap that represents the features. ISA specific.
  virtual uint32_t AsBitmap() const = 0;

  // Return a string of the form "div,lpae" or "none".
  virtual std::string GetFeatureString() const = 0;

  // Down cast this ArmInstructionFeatures.
  const ArmInstructionSetFeatures* AsArmInstructionSetFeatures() const;

  // Down cast this Arm64InstructionFeatures.
  const Arm64InstructionSetFeatures* AsArm64InstructionSetFeatures() const;

  // Down cast this X86InstructionFeatures.
  const X86InstructionSetFeatures* AsX86InstructionSetFeatures() const;

  // Down cast this X86_64InstructionFeatures.
  const X86_64InstructionSetFeatures* AsX86_64InstructionSetFeatures() const;

  virtual ~InstructionSetFeatures() {}

 protected:
  InstructionSetFeatures() {}

  // Returns true if variant appears in the array variants.
  static bool FindVariantInArray(const char* const variants[], size_t num_variants,
                                 const std::string& variant);

  // Add architecture specific features in sub-classes.
  virtual std::unique_ptr<const InstructionSetFeatures>
      AddFeaturesFromSplitString(const std::vector<std::string>& features,
                                 std::string* error_msg) const = 0;

  // Add run-time detected architecture specific features in sub-classes.
  virtual std::unique_ptr<const InstructionSetFeatures>
      AddRuntimeDetectedFeatures(const InstructionSetFeatures *features ATTRIBUTE_UNUSED) const;

 private:
  DISALLOW_COPY_AND_ASSIGN(InstructionSetFeatures);
};
std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs);

}  // namespace art

#endif  // ART_RUNTIME_ARCH_INSTRUCTION_SET_FEATURES_H_
