/*
 * Copyright (C) 2022 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.
 */

#include <inttypes.h>

#include <regex>

#include <sstream>

#include "common_runtime_test.h"
#include "disassembler_arm64.h"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#include "aarch64/disasm-aarch64.h"
#include "aarch64/macro-assembler-aarch64.h"
#pragma GCC diagnostic pop


using namespace vixl::aarch64;  // NOLINT(build/namespaces)

namespace art {
namespace arm64 {

/**
 * Fixture class for the ArtDisassemblerTest tests.
 */
class ArtDisassemblerTest : public CommonRuntimeTest {
 public:
  ArtDisassemblerTest() {
  }

  void SetupAssembly(uint64_t end_address) {
    masm.GetCPUFeatures()->Combine(vixl::CPUFeatures::All());

    disamOptions.reset(new DisassemblerOptions(/* absolute_addresses= */ true,
                                               reinterpret_cast<uint8_t*>(0x0),
                                               reinterpret_cast<uint8_t*>(end_address),
                                               /* can_read_literals_= */ true,
                                               &Thread::DumpThreadOffset<PointerSize::k64>));
    disasm.reset(new CustomDisassembler(&*disamOptions));
    decoder.AppendVisitor(disasm.get());
    masm.SetGenerateSimulatorCode(false);
  }

  static constexpr size_t kMaxSizeGenerated = 1024;

  template <typename LamdaType>
  void ImplantInstruction(LamdaType fn) {
    vixl::ExactAssemblyScope guard(&masm,
                                   kMaxSizeGenerated,
                                   vixl::ExactAssemblyScope::kMaximumSize);
    fn();
  }

  // Appends an instruction to the existing buffer and then
  // attempts to match the output of that instructions disassembly
  // against a regex expression. Fails if no match is found.
  template <typename LamdaType>
  void CompareInstruction(LamdaType fn, const char* EXP) {
    ImplantInstruction(fn);
    masm.FinalizeCode();

    // This gets the last instruction in the buffer.
    // The end address of the buffer is at the end of the last instruction.
    // sizeof(Instruction) is 1 byte as it in an empty class.
    // Therefore we need to go back kInstructionSize * sizeof(Instruction) bytes
    // in order to get to the start of the last instruction.
    const Instruction* targetInstruction =
        masm.GetBuffer()->GetEndAddress<Instruction*>()->
            GetInstructionAtOffset(-static_cast<signed>(kInstructionSize));

    decoder.Decode(targetInstruction);

    const char* disassembly = disasm->GetOutput();

    if (!std::regex_match(disassembly, std::regex(EXP))) {
      const uint32_t encoding = static_cast<uint32_t>(targetInstruction->GetInstructionBits());

      printf("\nEncoding: %08" PRIx32 "\nExpected: %s\nFound:    %s\n",
             encoding,
             EXP,
             disassembly);

      ADD_FAILURE();
    }
    printf("----\n%s\n", disassembly);
  }

  std::unique_ptr<CustomDisassembler> disasm;
  std::unique_ptr<DisassemblerOptions> disamOptions;
  Decoder decoder;
  MacroAssembler masm;
};

#define IMPLANT(fn)                                                          \
  do {                                                                       \
    ImplantInstruction([&]() { this->masm.fn; });                            \
  } while (0)

#define COMPARE(fn, output)                                                  \
  do {                                                                       \
    CompareInstruction([&]() { this->masm.fn; }, (output));                  \
  } while (0)

// These tests map onto the named per instruction instrumentation functions in:
// ART/art/disassembler/disassembler_arm.cc
// Context can be found in the logic conditional on incoming instruction types and sequences in the
// ART disassembler. As of writing the functionality we are testing for that of additional
// diagnostic info being appended to the end of the ART disassembly output.
TEST_F(ArtDisassemblerTest, LoadLiteralVisitBadAddress) {
  SetupAssembly(0xffffff);

  // Check we append an erroneous hint "(?)" for literal load instructions with
  // out of scope literal pool value addresses.
  COMPARE(ldr(x0, vixl::aarch64::Assembler::ImmLLiteral(1000)),
      "ldr x0, pc\\+128000 \\(addr -?0x[0-9a-fA-F]+\\) \\(\\?\\)");
}

TEST_F(ArtDisassemblerTest, LoadLiteralVisit) {
  SetupAssembly(0xffffffffffffffff);

  // Test that we do not append anything for ineligible instruction.
  COMPARE(ldr(x0, MemOperand(x18, 0)), "ldr x0, \\[x18\\]$");

  // Check we do append some extra info in the right text format for valid literal load instruction.
  COMPARE(ldr(x0, vixl::aarch64::Assembler::ImmLLiteral(0)),
      "ldr x0, pc\\+0 \\(addr -?0x[0-9a-f]+\\) \\(0x[0-9a-fA-F]+ / -?[0-9]+\\)");
  COMPARE(ldr(d0, vixl::aarch64::Assembler::ImmLLiteral(0)),
      "ldr d0, pc\\+0 \\(addr -?0x[0-9a-f]+\\) \\([0-9]+.[0-9]+e(\\+|-)[0-9]+\\)");
}

TEST_F(ArtDisassemblerTest, LoadStoreUnsignedOffsetVisit) {
  SetupAssembly(0xffffffffffffffff);

  // Test that we do not append anything for ineligible instruction.
  COMPARE(ldr(x0, MemOperand(x18, 8)), "ldr x0, \\[x18, #8\\]$");
  // Test that we do append the function name if the instruction is a load from the address
  // stored in the TR register.
  COMPARE(ldr(x0, MemOperand(x19, 8)), "ldr x0, \\[tr, #8\\] ; thin_lock_thread_id");
}

TEST_F(ArtDisassemblerTest, UnconditionalBranchNoAppendVisit) {
  SetupAssembly(0xffffffffffffffff);

  vixl::aarch64::Label destination;
  masm.Bind(&destination);

  IMPLANT(ldr(x16, MemOperand(x18, 0)));

  // Test that we do not append anything for ineligible instruction.
  COMPARE(bl(&destination),
      "bl #-0x4 \\(addr -?0x[0-9a-f]+\\)$");
}

TEST_F(ArtDisassemblerTest, UnconditionalBranchVisit) {
  SetupAssembly(0xffffffffffffffff);

  vixl::aarch64::Label destination;
  masm.Bind(&destination);

  IMPLANT(ldr(x16, MemOperand(x19, 0)));
  IMPLANT(br(x16));

  // Test that we do append the function name if the instruction is a branch
  // to a load that reads data from the address in the TR register, into the IPO register
  // followed by a BR branching using the IPO register.
  COMPARE(bl(&destination),
      "bl #-0x8 \\(addr -?0x[0-9a-f]+\\) ; state_and_flags");
}


}  // namespace arm64
}  // namespace art
