/*
 * 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_CFI_TEST_H_
#define ART_COMPILER_CFI_TEST_H_

#include <vector>
#include <memory>
#include <sstream>

#include "arch/instruction_set.h"
#include "dwarf/dwarf_test.h"
#include "dwarf/headers.h"
#include "disassembler/disassembler.h"
#include "gtest/gtest.h"

namespace art {

class CFITest : public dwarf::DwarfTest {
 public:
  void GenerateExpected(FILE* f, InstructionSet isa, const char* isa_str,
                        const std::vector<uint8_t>& actual_asm,
                        const std::vector<uint8_t>& actual_cfi) {
    std::vector<std::string> lines;
    // Print the raw bytes.
    fprintf(f, "static constexpr uint8_t expected_asm_%s[] = {", isa_str);
    HexDump(f, actual_asm);
    fprintf(f, "\n};\n");
    fprintf(f, "static constexpr uint8_t expected_cfi_%s[] = {", isa_str);
    HexDump(f, actual_cfi);
    fprintf(f, "\n};\n");
    // Pretty-print CFI opcodes.
    constexpr bool is64bit = false;
    dwarf::DebugFrameOpCodeWriter<> initial_opcodes;
    dwarf::WriteEhFrameCIE(is64bit, dwarf::Reg(8), initial_opcodes, &eh_frame_data_);
    std::vector<uintptr_t> eh_frame_patches;
    dwarf::WriteEhFrameFDE(is64bit, 0, 0, actual_asm.size(), &actual_cfi,
                           &eh_frame_data_, &eh_frame_patches);
    ReformatCfi(Objdump(false, "-W"), &lines);
    // Pretty-print assembly.
    auto* opts = new DisassemblerOptions(false, actual_asm.data(), true);
    std::unique_ptr<Disassembler> disasm(Disassembler::Create(isa, opts));
    std::stringstream stream;
    const uint8_t* base = actual_asm.data() + (isa == kThumb2 ? 1 : 0);
    disasm->Dump(stream, base, base + actual_asm.size());
    ReformatAsm(&stream, &lines);
    // Print CFI and assembly interleaved.
    std::stable_sort(lines.begin(), lines.end(), CompareByAddress);
    for (const std::string& line : lines) {
      fprintf(f, "// %s\n", line.c_str());
    }
    fprintf(f, "\n");
  }

 private:
  // Helper - get offset just past the end of given string.
  static size_t FindEndOf(const std::string& str, const char* substr) {
    size_t pos = str.find(substr);
    CHECK_NE(std::string::npos, pos);
    return pos + strlen(substr);
  }

  // Spit to lines and remove raw instruction bytes.
  static void ReformatAsm(std::stringstream* stream,
                          std::vector<std::string>* output) {
    std::string line;
    while (std::getline(*stream, line)) {
      line = line.substr(0, FindEndOf(line, ": ")) +
             line.substr(FindEndOf(line, "\t"));
      size_t pos;
      while ((pos = line.find("  ")) != std::string::npos) {
        line = line.replace(pos, 2, " ");
      }
      while (!line.empty() && line.back() == ' ') {
        line.pop_back();
      }
      output->push_back(line);
    }
  }

  // Find interesting parts of objdump output and prefix the lines with address.
  static void ReformatCfi(const std::vector<std::string>& lines,
                          std::vector<std::string>* output) {
    std::string address;
    for (const std::string& line : lines) {
      if (line.find("DW_CFA_nop") != std::string::npos) {
        // Ignore.
      } else if (line.find("DW_CFA_advance_loc") != std::string::npos) {
        // The last 8 characters are the address.
        address = "0x" + line.substr(line.size() - 8);
      } else if (line.find("DW_CFA_") != std::string::npos) {
        std::string new_line(line);
        // "bad register" warning is caused by always using host (x86) objdump.
        const char* bad_reg = "bad register: ";
        size_t pos;
        if ((pos = new_line.find(bad_reg)) != std::string::npos) {
          new_line = new_line.replace(pos, strlen(bad_reg), "");
        }
        // Remove register names in parentheses since they have x86 names.
        if ((pos = new_line.find(" (")) != std::string::npos) {
          new_line = new_line.replace(pos, FindEndOf(new_line, ")") - pos, "");
        }
        // Use the .cfi_ prefix.
        new_line = ".cfi_" + new_line.substr(FindEndOf(new_line, "DW_CFA_"));
        output->push_back(address + ": " + new_line);
      }
    }
  }

  // Compare strings by the address prefix.
  static bool CompareByAddress(const std::string& lhs, const std::string& rhs) {
    EXPECT_EQ(lhs[10], ':');
    EXPECT_EQ(rhs[10], ':');
    return strncmp(lhs.c_str(), rhs.c_str(), 10) < 0;
  }

  // Pretty-print byte array.  12 bytes per line.
  static void HexDump(FILE* f, const std::vector<uint8_t>& data) {
    for (size_t i = 0; i < data.size(); i++) {
      fprintf(f, i % 12 == 0 ? "\n    " : " ");  // Whitespace.
      fprintf(f, "0x%02X,", data[i]);
    }
  }
};

}  // namespace art

#endif  // ART_COMPILER_CFI_TEST_H_
