// Copyright Microsoft and CHERIoT Contributors.
// SPDX-License-Identifier: MIT

#pragma once
#include <cheri.hh>
#include <compartment.h>
#include <platform-uart.hh>

#include <array>

namespace
{
	/**
	 * Is the loader being debugged?
	 */
	static constexpr bool DebugLoader = DEBUG_LOADER;

	namespace DebugConcepts
	{
		/// Helper concept for matching booleans
		template<typename T>
		concept IsBool = std::is_same_v<T, bool>;

		/// Helper concept for matching enumerations.
		template<typename T>
		concept IsEnum = std::is_enum_v<T>;

		/// Concept for something that can be lazily called to produce a bool.
		template<typename T>
		concept LazyAssertion = requires(T v)
		{
			{
				v()
				} -> IsBool;
		};
	} // namespace DebugConcepts

	/**
	 * Helper class for writing debug output to the UART.  This performs no
	 * internal buffering and assumes interrupts are disabled for the duration
	 * to avoid interference.
	 *
	 * This is based on snmalloc's class of the same name.
	 */
	class LoaderWriter
	{
		/**
		 * The capability to the UART device.
		 */
		static inline volatile Uart *uart16550;

		/**
		 * Append a character, delegating to `Output`.
		 */
		void append_char(char c)
		{
			uart16550->blocking_write(c);
		}

		/**
		 * Append a null-terminated C string.
		 */
		void append(const char *str)
		{
			for (; *str; ++str)
			{
				append_char(*str);
			}
		}

		/**
		 * Append a string view.
		 */
		void append(std::string_view str)
		{
			for (char c : str)
			{
				append_char(c);
			}
		}

		void append(char c)
		{
			append_char(c);
		}

		/**
		 * Outputs the permission set using the format G RWcgml Xa SU0 as
		 * described in [/docs/Debugging.md].
		 */
		void append(CHERI::PermissionSet permissions)
		{
			using namespace CHERI;
			auto perm = [&](Permission p, char c) -> char {
				if (permissions.contains(p))
				{
					return c;
				}
				return '-';
			};
			format("{} {}{}{}{}{}{} {}{} {}{}{}",
			       perm(Permission::Global, 'G'),
			       perm(Permission::Load, 'R'),
			       perm(Permission::Store, 'W'),
			       perm(Permission::LoadStoreCapability, 'c'),
			       perm(Permission::LoadGlobal, 'g'),
			       perm(Permission::LoadMutable, 'm'),
			       perm(Permission::StoreLocal, 'l'),
			       perm(Permission::Execute, 'X'),
			       perm(Permission::AccessSystemRegisters, 'a'),
			       perm(Permission::Seal, 'S'),
			       perm(Permission::Unseal, 'U'),
			       perm(Permission::User0, '0'));
		}

		/**
		 * Append a raw pointer as a hex string.
		 */
		__noinline void append(const void *ptr)
		{
			const CHERI::Capability C{ptr};

			format("{} (v:{} {}-{} l:{} o:{} p: {})",
			       C.address(),
			       C.is_valid(),
			       C.base(),
			       C.top(),
			       C.length(),
			       C.type(),
			       C.permissions());
		}

		/**
		 * Append a capability.
		 */
		template<typename T>
		__always_inline void append(CHERI::Capability<T> capability)
		{
			append(static_cast<const void *>(capability.get()));
		}

		/**
		 * Append a signed integer, as a decimal string.
		 */
		__noinline void append(int32_t s)
		{
			if (s < 0)
			{
				append_char('-');
				s = 0 - s;
			}
			std::array<char, 10> buf;
			const char           Digits[] = "0123456789";
			for (int i = int(buf.size() - 1); i >= 0; i--)
			{
				buf.at(static_cast<size_t>(i)) = Digits[s % 10];
				s /= 10;
			}
			bool skipZero = true;
			for (auto c : buf)
			{
				if (skipZero && (c == '0'))
				{
					continue;
				}
				skipZero = false;
				append_char(c);
			}
			if (skipZero)
			{
				append_char('0');
			}
		}

		/**
		 * Append a 32-bit unsigned integer to the buffer as hex with no prefix.
		 */
		__attribute__((noinline)) void append_hex_word(uint32_t s)
		{
			std::array<char, 8> buf;
			const char          Hexdigits[] = "0123456789abcdef";
			// Length of string including null terminator
			static_assert(sizeof(Hexdigits) == 0x11);
			for (long i = long(buf.size() - 1); i >= 0; i--)
			{
				buf.at(static_cast<size_t>(i)) = Hexdigits[s & 0xf];
				s >>= 4;
			}
			bool skipZero = true;
			for (auto c : buf)
			{
				if (skipZero && (c == '0'))
				{
					continue;
				}
				skipZero = false;
				append_char(c);
			}
			if (skipZero)
			{
				append_char('0');
			}
		}

		/**
		 * Append a 32-bit unsigned integer to the buffer as hex.
		 */
		__attribute__((noinline)) void append(uint32_t s)
		{
			append_char('0');
			append_char('x');
			append_hex_word(s);
		}

		/**
		 * Append a 64-bit unsigned integer to the buffer as hex.
		 */
		__attribute__((noinline)) void append(uint64_t s)
		{
			append_char('0');
			append_char('x');
			uint32_t hi = static_cast<uint32_t>(s >> 32);
			uint32_t lo = static_cast<uint32_t>(s);
			if (hi != 0)
			{
				append_hex_word(hi);
			}
			append_hex_word(lo);
		}

		/**
		 * Append a 16-bit unsigned integer to the buffer as hex.
		 */
		__always_inline void append(uint16_t s)
		{
			append(static_cast<uint32_t>(s));
		}

		/**
		 * Append an 8-bit unsigned integer to the buffer as hex.
		 */
		__always_inline void append(uint8_t s)
		{
			append(static_cast<uint32_t>(s));
		}

		/**
		 * Append an enumerated type value.
		 */
		template<typename T>
		requires DebugConcepts::IsEnum<T>
		void append(T e)
		{
			// `magic_enum::enum_name` requires cap relocs, so don't use it in
			// components that want or need to avoid them.
			append(static_cast<int32_t>(e));
		}

		public:
		/**
		 * Base case for formatting: no format-string arguments.
		 */
		void format(const char *fmt)
		{
			append(fmt);
		}

		/**
		 * Inductive case for formatting.  Writes up to the instruction to
		 * output the first argument, writes that argument, and then recurses.
		 */
		template<typename T, typename... Args>
		void format(const char *fmt, T firstArg, Args... args)
		{
			for (const char *s = fmt; *s != 0; ++s)
			{
				if (s[0] == '{' && s[1] == '}')
				{
					append(firstArg);
					return format(s + 2, args...);
				}

				append_char(*s);
			}
		}

		/**
		 * Set the UART memory pointer.
		 */
		static void set_uart(volatile Uart *theUART)
		{
			uart16550 = theUART;
		}
	};

	/**
	 * Our libc++ does not currently provide source_location, but our clang
	 * provides the necessary builtins for one.
	 */
	struct SourceLocation
	{
		/**
		 * Explicitly construct a source location.
		 */
		constexpr SourceLocation(int         lineNumber,
		                         int         columnNumber,
		                         const char *fileName,
		                         const char *functionName)
		  : lineNumber(lineNumber),
		    columnNumber(columnNumber),
		    fileName(fileName),
		    functionName(functionName)
		{
		}

		/**
		 * Construct a source location for the caller.
		 */
		static constexpr SourceLocation __always_inline
		current(int         lineNumber   = __builtin_LINE(),
		        int         columnNumber = __builtin_COLUMN(),
		        const char *fileName     = __builtin_FILE(),
		        const char *functionName = __builtin_FUNCTION()) noexcept
		{
			return {lineNumber, columnNumber, fileName, functionName};
		}

		/// Returns the line number for this source location.
		[[nodiscard]] __always_inline constexpr int line() const noexcept
		{
			return lineNumber;
		}
		/// Returns the column number for this source location.
		[[nodiscard]] __always_inline constexpr int column() const noexcept
		{
			return columnNumber;
		}
		/// Returns the file name for this source location.
		[[nodiscard]] __always_inline constexpr const char *
		file_name() const noexcept
		{
			return fileName;
		}
		/// Returns the function name for this source location.
		[[nodiscard]] __always_inline constexpr const char *
		function_name() const noexcept
		{
			return functionName;
		}

		private:
		/// The line number of this source location.
		int lineNumber;
		/// The column number of this source location.
		int columnNumber;
		/// The file name of this source location.
		const char *fileName;
		/// The function name of this source location.
		const char *functionName;
	};

	/**
	 * Conditional debug class.  Used to control conditional output and
	 * assertion checking.  Enables debug log messages and assertions if
	 * `Enabled` is true.  Uses `Context` to print additional detail on debug
	 * lines.  Writes output using `Writer`.
	 *
	 * If `DisableInterrupts` is true then this disables interrupts while
	 * printing the message to avoid accidental interleaving.
	 *
	 * This class is expected to be used as a type alias, something like:
	 *
	 * ```c++
	 * constexpr bool DebugFoo = DEBUG_FOO;
	 * using Debug = ConditionalDebug<DebugFoo, "Foo">;
	 * ```
	 */
	template<bool Enabled>
	class LoaderDebug
	{
		public:
		/// The (singleton) writer used for output.
		static inline LoaderWriter writer;

		/**
		 * Log a message.
		 *
		 * This function does nothing if the `Enabled` condition is false.
		 */
		template<typename... Args>
		static void log(const char *fmt, Args... args)
		{
			if constexpr (Enabled)
			{
				// Ensure that the compiler does not reorder messages.
				asm volatile("" ::: "memory");
				writer.format("\x1b[35mloader\033[0m");
				writer.format(": ");
				writer.format(fmt, args...);
				writer.format("\n");
				asm volatile("" ::: "memory");
			}
		}

		/**
		 * Helper to report failure.
		 *
		 * This must not take the `SourceLocation` directly because doing so
		 * prevents the compiler from decomposing and subsequently
		 * constant-propagating its fields in the caller, resulting in 24 bytes
		 * of stack space consumed for every assert or invariant.
		 */
		template<typename... Args>
		__noinline static void report_failure(const char *kind,
		                                      const char *file,
		                                      const char *function,
		                                      int         line,
		                                      const char *fmt,
		                                      Args... args)
		{
			// Ensure that the compiler does not reorder messages.
			asm volatile("" ::: "memory");
			writer.format(
			  "\x1b[35m{}:{} \x1b[31m{} failure\x1b[35m in {}\x1b[36m\n",
			  file,
			  line,
			  kind,
			  function);
			writer.format(fmt, args...);
			writer.format("\033[0m\n");
			asm volatile("" ::: "memory");
		}

		/**
		 * Function-like class for invariants that is expected to be used via
		 * the deduction guide as:
		 *
		 * ConditionalDebug::Invariant(someCondition, "A message...", ...);
		 *
		 * Invariants are checked unconditionally but will log a verbose
		 * message only if `Enabled` is true.
		 */
		template<typename... Args>
		struct Invariant
		{
			/**
			 * Constructor, performs the invariant check.
			 */
			__always_inline
			Invariant(bool        condition,
			          const char *fmt,
			          Args... args,
			          SourceLocation loc = SourceLocation::current())
			{
				if (!condition)
				{
					if constexpr (Enabled)
					{
						report_failure("Invariant",
						               loc.file_name(),
						               loc.function_name(),
						               loc.line(),
						               fmt,
						               std::forward<Args>(args)...);
					}
					__builtin_trap();
				}
			}
		};
		/**
		 * Function-like class for assertions that is expected to be used via
		 * the deduction guide as:
		 *
		 * ConditionalDebug::Assert(someCondition, "A message...", ...);
		 *
		 * Assertions are checked only if `Enabled` is true.
		 */
		template<typename... Args>
		struct Assert
		{
			/**
			 * Constructor, performs the assertion check.
			 */
			template<typename T>
			requires DebugConcepts::IsBool<T> __always_inline
			Assert(T           condition,
			       const char *fmt,
			       Args... args,
			       SourceLocation loc = SourceLocation::current())
			{
				if constexpr (Enabled)
				{
					if (!condition)
					{
						report_failure("Assertion",
						               loc.file_name(),
						               loc.function_name(),
						               loc.line(),
						               fmt,
						               std::forward<Args>(args)...);
						__builtin_trap();
					}
				}
			}

			/**
			 * Constructor, performs an assertion check.
			 *
			 * This version is passed a lambda that returns a bool, rather than
			 * a boolean condition.  This allows the compiler to completely
			 * elide the contents of the lambda in builds where this component
			 * is not being debugged.  This version should be used for places
			 * where the assertion condition has side effects.
			 */
			template<typename T>
			requires DebugConcepts::LazyAssertion<T> __always_inline
			Assert(T         &&condition,
			       const char *fmt,
			       Args... args,
			       SourceLocation loc = SourceLocation::current())
			{
				if constexpr (Enabled)
				{
					if (!condition())
					{
						report_failure("Assertion",
						               loc.file_name(),
						               loc.function_name(),
						               loc.line(),
						               fmt,
						               std::forward<Args>(args)...);
						__builtin_trap();
					}
				}
			}
		};

		/**
		 * Deduction guide, allows `Invariant` to be used as if it were a
		 * function.
		 */
		template<typename T, typename... Ts>
		Invariant(T, const char *, Ts &&...) -> Invariant<Ts...>;

		/**
		 * Deduction guide, allows `Assert` to be used as if it were a
		 * function.
		 */
		template<typename... Ts>
		Assert(bool, const char *, Ts &&...) -> Assert<Ts...>;

		/**
		 * Deduction guide, allows `Assert` to be used as if it were a
		 * function with a lambda argument.
		 */
		template<typename... Ts>
		Assert(auto, const char *, Ts &&...) -> Assert<Ts...>;
	};

	/**
	 * Debug interface for the loader.  Enables verbose debugging if
	 * `DebugLoader` is true and requires that the loader explicitly
	 * initialises the UART.
	 */
	using Debug = LoaderDebug<DebugLoader>;
} // namespace
