// Copyright (c) 2019 Google LLC
//
// 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.

#include "source/fuzz/fuzzer_pass_add_useful_constructs.h"

#include "source/fuzz/transformation_add_constant_boolean.h"
#include "source/fuzz/transformation_add_constant_scalar.h"
#include "source/fuzz/transformation_add_type_boolean.h"
#include "source/fuzz/transformation_add_type_float.h"
#include "source/fuzz/transformation_add_type_int.h"
#include "source/fuzz/transformation_add_type_pointer.h"

namespace spvtools {
namespace fuzz {

FuzzerPassAddUsefulConstructs::FuzzerPassAddUsefulConstructs(
    opt::IRContext* ir_context, TransformationContext* transformation_context,
    FuzzerContext* fuzzer_context,
    protobufs::TransformationSequence* transformations)
    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
                 transformations) {}

FuzzerPassAddUsefulConstructs::~FuzzerPassAddUsefulConstructs() = default;

void FuzzerPassAddUsefulConstructs::MaybeAddIntConstant(
    uint32_t width, bool is_signed, std::vector<uint32_t> data) const {
  opt::analysis::Integer temp_int_type(width, is_signed);
  assert(GetIRContext()->get_type_mgr()->GetId(&temp_int_type) &&
         "int type should already be registered.");
  auto registered_int_type = GetIRContext()
                                 ->get_type_mgr()
                                 ->GetRegisteredType(&temp_int_type)
                                 ->AsInteger();
  auto int_type_id = GetIRContext()->get_type_mgr()->GetId(registered_int_type);
  assert(int_type_id &&
         "The relevant int type should have been added to the module already.");
  opt::analysis::IntConstant int_constant(registered_int_type, data);
  if (!GetIRContext()->get_constant_mgr()->FindConstant(&int_constant)) {
    TransformationAddConstantScalar add_constant_int =
        TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
                                        int_type_id, data);
    assert(add_constant_int.IsApplicable(GetIRContext(),
                                         *GetTransformationContext()) &&
           "Should be applicable by construction.");
    add_constant_int.Apply(GetIRContext(), GetTransformationContext());
    *GetTransformations()->add_transformation() = add_constant_int.ToMessage();
  }
}

void FuzzerPassAddUsefulConstructs::MaybeAddFloatConstant(
    uint32_t width, std::vector<uint32_t> data) const {
  opt::analysis::Float temp_float_type(width);
  assert(GetIRContext()->get_type_mgr()->GetId(&temp_float_type) &&
         "float type should already be registered.");
  auto registered_float_type = GetIRContext()
                                   ->get_type_mgr()
                                   ->GetRegisteredType(&temp_float_type)
                                   ->AsFloat();
  auto float_type_id =
      GetIRContext()->get_type_mgr()->GetId(registered_float_type);
  assert(
      float_type_id &&
      "The relevant float type should have been added to the module already.");
  opt::analysis::FloatConstant float_constant(registered_float_type, data);
  if (!GetIRContext()->get_constant_mgr()->FindConstant(&float_constant)) {
    TransformationAddConstantScalar add_constant_float =
        TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
                                        float_type_id, data);
    assert(add_constant_float.IsApplicable(GetIRContext(),
                                           *GetTransformationContext()) &&
           "Should be applicable by construction.");
    add_constant_float.Apply(GetIRContext(), GetTransformationContext());
    *GetTransformations()->add_transformation() =
        add_constant_float.ToMessage();
  }
}

void FuzzerPassAddUsefulConstructs::Apply() {
  {
    // Add boolean type if not present.
    opt::analysis::Bool temp_bool_type;
    if (!GetIRContext()->get_type_mgr()->GetId(&temp_bool_type)) {
      auto add_type_boolean =
          TransformationAddTypeBoolean(GetFuzzerContext()->GetFreshId());
      assert(add_type_boolean.IsApplicable(GetIRContext(),
                                           *GetTransformationContext()) &&
             "Should be applicable by construction.");
      add_type_boolean.Apply(GetIRContext(), GetTransformationContext());
      *GetTransformations()->add_transformation() =
          add_type_boolean.ToMessage();
    }
  }

  {
    // Add signed and unsigned 32-bit integer types if not present.
    for (auto is_signed : {true, false}) {
      opt::analysis::Integer temp_int_type(32, is_signed);
      if (!GetIRContext()->get_type_mgr()->GetId(&temp_int_type)) {
        TransformationAddTypeInt add_type_int = TransformationAddTypeInt(
            GetFuzzerContext()->GetFreshId(), 32, is_signed);
        assert(add_type_int.IsApplicable(GetIRContext(),
                                         *GetTransformationContext()) &&
               "Should be applicable by construction.");
        add_type_int.Apply(GetIRContext(), GetTransformationContext());
        *GetTransformations()->add_transformation() = add_type_int.ToMessage();
      }
    }
  }

  {
    // Add 32-bit float type if not present.
    opt::analysis::Float temp_float_type(32);
    if (!GetIRContext()->get_type_mgr()->GetId(&temp_float_type)) {
      TransformationAddTypeFloat add_type_float =
          TransformationAddTypeFloat(GetFuzzerContext()->GetFreshId(), 32);
      assert(add_type_float.IsApplicable(GetIRContext(),
                                         *GetTransformationContext()) &&
             "Should be applicable by construction.");
      add_type_float.Apply(GetIRContext(), GetTransformationContext());
      *GetTransformations()->add_transformation() = add_type_float.ToMessage();
    }
  }

  // Add boolean constants true and false if not present.
  opt::analysis::Bool temp_bool_type;
  auto bool_type = GetIRContext()
                       ->get_type_mgr()
                       ->GetRegisteredType(&temp_bool_type)
                       ->AsBool();
  for (auto boolean_value : {true, false}) {
    // Add OpConstantTrue/False if not already there.
    opt::analysis::BoolConstant bool_constant(bool_type, boolean_value);
    if (!GetIRContext()->get_constant_mgr()->FindConstant(&bool_constant)) {
      TransformationAddConstantBoolean add_constant_boolean(
          GetFuzzerContext()->GetFreshId(), boolean_value);
      assert(add_constant_boolean.IsApplicable(GetIRContext(),
                                               *GetTransformationContext()) &&
             "Should be applicable by construction.");
      add_constant_boolean.Apply(GetIRContext(), GetTransformationContext());
      *GetTransformations()->add_transformation() =
          add_constant_boolean.ToMessage();
    }
  }

  // Add signed and unsigned 32-bit integer constants 0 and 1 if not present.
  for (auto is_signed : {true, false}) {
    for (auto value : {0u, 1u}) {
      MaybeAddIntConstant(32, is_signed, {value});
    }
  }

  // Add 32-bit float constants 0.0 and 1.0 if not present.
  uint32_t uint_data[2];
  float float_data[2] = {0.0, 1.0};
  memcpy(uint_data, float_data, sizeof(float_data));
  for (unsigned int& datum : uint_data) {
    MaybeAddFloatConstant(32, {datum});
  }

  // For every known-to-be-constant uniform, make sure we have instructions
  // declaring:
  // - a pointer type with uniform storage class, whose pointee type is the type
  //   of the element
  // - a signed integer constant for each index required to access the element
  // - a constant for the constant value itself
  for (auto& fact_and_type_id : GetTransformationContext()
                                    ->GetFactManager()
                                    ->GetConstantUniformFactsAndTypes()) {
    uint32_t element_type_id = fact_and_type_id.second;
    assert(element_type_id);
    auto element_type =
        GetIRContext()->get_type_mgr()->GetType(element_type_id);
    assert(element_type &&
           "If the constant uniform fact is well-formed, the module must "
           "already have a declaration of the type for the uniform element.");
    opt::analysis::Pointer uniform_pointer(element_type,
                                           SpvStorageClassUniform);
    if (!GetIRContext()->get_type_mgr()->GetId(&uniform_pointer)) {
      auto add_pointer =
          TransformationAddTypePointer(GetFuzzerContext()->GetFreshId(),
                                       SpvStorageClassUniform, element_type_id);
      assert(add_pointer.IsApplicable(GetIRContext(),
                                      *GetTransformationContext()) &&
             "Should be applicable by construction.");
      add_pointer.Apply(GetIRContext(), GetTransformationContext());
      *GetTransformations()->add_transformation() = add_pointer.ToMessage();
    }
    std::vector<uint32_t> words;
    for (auto word : fact_and_type_id.first.constant_word()) {
      words.push_back(word);
    }
    // We get the element type again as the type manager may have been
    // invalidated since we last retrieved it.
    element_type = GetIRContext()->get_type_mgr()->GetType(element_type_id);
    if (element_type->AsInteger()) {
      MaybeAddIntConstant(element_type->AsInteger()->width(),
                          element_type->AsInteger()->IsSigned(), words);
    } else {
      assert(element_type->AsFloat() &&
             "Known uniform values must be integer or floating-point.");
      MaybeAddFloatConstant(element_type->AsFloat()->width(), words);
    }
    for (auto index :
         fact_and_type_id.first.uniform_buffer_element_descriptor().index()) {
      MaybeAddIntConstant(32, true, {index});
    }
  }
}

}  // namespace fuzz
}  // namespace spvtools
