// Copyright (c) 2016 Google Inc.
//
// 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 "gmock/gmock.h"

#include <initializer_list>

#include "module_utils.h"
#include "opt/make_unique.h"
#include "pass_fixture.h"

namespace {

using namespace spvtools;
using spvtest::GetIdBound;
using ::testing::Eq;

// A null pass whose construtors accept arguments
class NullPassWithArgs : public opt::NullPass {
 public:
  NullPassWithArgs(uint32_t) {}
  NullPassWithArgs(std::string) {}
  NullPassWithArgs(const std::vector<int>&) {}
  NullPassWithArgs(const std::vector<int>&, uint32_t) {}

  const char* name() const override { return "null-with-args"; }
};

TEST(PassManager, Interface) {
  opt::PassManager manager;
  EXPECT_EQ(0u, manager.NumPasses());

  manager.AddPass<opt::StripDebugInfoPass>();
  EXPECT_EQ(1u, manager.NumPasses());
  EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());

  manager.AddPass(MakeUnique<opt::NullPass>());
  EXPECT_EQ(2u, manager.NumPasses());
  EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());
  EXPECT_STREQ("null", manager.GetPass(1)->name());

  manager.AddPass<opt::StripDebugInfoPass>();
  EXPECT_EQ(3u, manager.NumPasses());
  EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());
  EXPECT_STREQ("null", manager.GetPass(1)->name());
  EXPECT_STREQ("strip-debug", manager.GetPass(2)->name());

  manager.AddPass<NullPassWithArgs>(1u);
  manager.AddPass<NullPassWithArgs>("null pass args");
  manager.AddPass<NullPassWithArgs>(std::initializer_list<int>{1, 2});
  manager.AddPass<NullPassWithArgs>(std::initializer_list<int>{1, 2}, 3);
  EXPECT_EQ(7u, manager.NumPasses());
  EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());
  EXPECT_STREQ("null", manager.GetPass(1)->name());
  EXPECT_STREQ("strip-debug", manager.GetPass(2)->name());
  EXPECT_STREQ("null-with-args", manager.GetPass(3)->name());
  EXPECT_STREQ("null-with-args", manager.GetPass(4)->name());
  EXPECT_STREQ("null-with-args", manager.GetPass(5)->name());
  EXPECT_STREQ("null-with-args", manager.GetPass(6)->name());
}

// A pass that appends an OpNop instruction to the debug1 section.
class AppendOpNopPass : public opt::Pass {
 public:
  const char* name() const override { return "AppendOpNop"; }
  Status Process(opt::IRContext* irContext) override {
    irContext->AddDebug1Inst(MakeUnique<opt::Instruction>(irContext));
    return Status::SuccessWithChange;
  }
};

// A pass that appends specified number of OpNop instructions to the debug1
// section.
class AppendMultipleOpNopPass : public opt::Pass {
 public:
  explicit AppendMultipleOpNopPass(uint32_t num_nop) : num_nop_(num_nop) {}

  const char* name() const override { return "AppendOpNop"; }
  Status Process(opt::IRContext* irContext) override {
    for (uint32_t i = 0; i < num_nop_; i++) {
      irContext->AddDebug1Inst(MakeUnique<opt::Instruction>(irContext));
    }
    return Status::SuccessWithChange;
  }

 private:
  uint32_t num_nop_;
};

// A pass that duplicates the last instruction in the debug1 section.
class DuplicateInstPass : public opt::Pass {
 public:
  const char* name() const override { return "DuplicateInst"; }
  Status Process(opt::IRContext* irContext) override {
    auto inst = MakeUnique<opt::Instruction>(
        *(--irContext->debug1_end())->Clone(irContext));
    irContext->AddDebug1Inst(std::move(inst));
    return Status::SuccessWithChange;
  }
};

using PassManagerTest = PassTest<::testing::Test>;

TEST_F(PassManagerTest, Run) {
  const std::string text = "OpMemoryModel Logical GLSL450\nOpSource ESSL 310\n";

  AddPass<AppendOpNopPass>();
  AddPass<AppendOpNopPass>();
  RunAndCheck(text.c_str(), (text + "OpNop\nOpNop\n").c_str());

  RenewPassManger();
  AddPass<AppendOpNopPass>();
  AddPass<DuplicateInstPass>();
  RunAndCheck(text.c_str(), (text + "OpNop\nOpNop\n").c_str());

  RenewPassManger();
  AddPass<DuplicateInstPass>();
  AddPass<AppendOpNopPass>();
  RunAndCheck(text.c_str(), (text + "OpSource ESSL 310\nOpNop\n").c_str());

  RenewPassManger();
  AddPass<AppendMultipleOpNopPass>(3);
  RunAndCheck(text.c_str(), (text + "OpNop\nOpNop\nOpNop\n").c_str());
}

// A pass that appends an OpTypeVoid instruction that uses a given id.
class AppendTypeVoidInstPass : public opt::Pass {
 public:
  explicit AppendTypeVoidInstPass(uint32_t result_id) : result_id_(result_id) {}

  const char* name() const override { return "AppendTypeVoidInstPass"; }
  Status Process(opt::IRContext* irContext) override {
    auto inst = MakeUnique<opt::Instruction>(
        irContext, SpvOpTypeVoid, 0, result_id_, std::vector<opt::Operand>{});
    irContext->AddType(std::move(inst));
    return Status::SuccessWithChange;
  }

 private:
  uint32_t result_id_;
};

TEST(PassManager, RecomputeIdBoundAutomatically) {
  opt::PassManager manager;
  std::unique_ptr<opt::Module> module(new opt::Module());
  opt::IRContext context(SPV_ENV_UNIVERSAL_1_2, std::move(module),
                         manager.consumer());
  EXPECT_THAT(GetIdBound(*context.module()), Eq(0u));

  manager.Run(&context);
  manager.AddPass<AppendOpNopPass>();
  // With no ID changes, the ID bound does not change.
  EXPECT_THAT(GetIdBound(*context.module()), Eq(0u));

  // Now we force an Id of 100 to be used.
  manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(100));
  EXPECT_THAT(GetIdBound(*context.module()), Eq(0u));
  manager.Run(&context);
  // The Id has been updated automatically, even though the pass
  // did not update it.
  EXPECT_THAT(GetIdBound(*context.module()), Eq(101u));

  // Try one more time!
  manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(200));
  manager.Run(&context);
  EXPECT_THAT(GetIdBound(*context.module()), Eq(201u));

  // Add another pass, but which uses a lower Id.
  manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(10));
  manager.Run(&context);
  // The Id stays high.
  EXPECT_THAT(GetIdBound(*context.module()), Eq(201u));
}

}  // anonymous namespace
