// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// 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 rr_LLVMReactorDebugInfo_hpp
#define rr_LLVMReactorDebugInfo_hpp

#include "Reactor.hpp"

#ifdef ENABLE_RR_DEBUG_INFO

#include <unordered_set>
#include <unordered_map>
#include <vector>
#include <memory>

// Forward declarations
namespace llvm
{
	class BasicBlock;
	class ConstantFolder;
	class DIBuilder;
	class DICompileUnit;
	class DIFile;
	class DILocation;
	class DIScope;
	class DISubprogram;
	class DIType;
	class Function;
	class Instruction;
	class IRBuilderDefaultInserter;
	class JITEventListener;
	class LLVMContext;
	class LoadedObjectInfo;
	class Module;
	class Type;
	class Value;

	namespace object
	{
		class ObjectFile;
	}

	template <typename T, typename Inserter> class IRBuilder;
} // namespace llvm

namespace rr
{
	class Type;
	class Value;

	// DebugInfo generates LLVM DebugInfo IR from the C++ source that calls
	// into Reactor functions. See docs/ReactorDebugInfo.mk for more information.
	class DebugInfo
	{
	public:
		using IRBuilder = llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>;

		DebugInfo(IRBuilder *builder,
				llvm::LLVMContext *context,
				llvm::Module *module,
				llvm::Function *function);

		~DebugInfo();

		// Finalize debug info generation. Must be called before the LLVM module
		// is built.
		void Finalize();

		// Updates the current source location.
		void EmitLocation();

		// Binds the value to its symbol in the source file.
		// See docs/ReactorDebugInfo.mk for more information.
		void EmitVariable(Value *value);

		// Forcefully flush the binding of the last variable name.
		// Used for binding the initializer of `For` loops.
		void Flush();

		// NotifyObjectEmitted informs any attached debuggers of the JIT'd
		// object.
		static void NotifyObjectEmitted(const llvm::object::ObjectFile &Obj, const llvm::LoadedObjectInfo &L);

		// NotifyFreeingObject informs any attached debuggers that the JIT'd
		// object is now invalid.
		static void NotifyFreeingObject(const llvm::object::ObjectFile &Obj);

	private:
		struct Token
		{
			enum Kind
			{
				Identifier,
				Return
			};
			Kind kind;
			std::string identifier;
		};

		using LineTokens = std::unordered_map<unsigned int, Token>;

		struct FunctionLocation
		{
			std::string name;
			std::string file;

			bool operator == (const FunctionLocation &rhs) const { return name == rhs.name && file == rhs.file; }
			bool operator != (const FunctionLocation &rhs) const { return !(*this == rhs); }

			struct Hash
			{
				std::size_t operator()(const FunctionLocation &l) const noexcept
				{
					return std::hash<std::string>()(l.file) * 31 +
							std::hash<std::string>()(l.name);
				}
			};
		};

		struct Location
		{
			FunctionLocation function;
			unsigned int line = 0;

			bool operator == (const Location &rhs) const { return function == rhs.function && line == rhs.line; }
			bool operator != (const Location &rhs) const { return !(*this == rhs); }

			struct Hash
			{
				std::size_t operator()(const Location &l) const noexcept
				{
					return FunctionLocation::Hash()(l.function) * 31 +
							std::hash<unsigned int>()(l.line);
				}
			};
		};

		using Backtrace = std::vector<Location>;

		struct Pending
		{
			std::string name;
			Location location;
			llvm::DILocation *diLocation = nullptr;
			llvm::Value *value = nullptr;
			llvm::Instruction *insertAfter = nullptr;
			llvm::BasicBlock *block = nullptr;
			llvm::DIScope *scope = nullptr;
			bool addNopOnNextLine = false;
		};

		struct Scope
		{
			Location location;
			llvm::DIScope *di;
			std::unordered_set<std::string> symbols;
			Pending pending;
		};

		void registerBasicTypes();

		void emitPending(Scope &scope, IRBuilder *builder);

		// Returns the source location of the non-Reactor calling function.
		Location getCallerLocation() const;

		// Returns the backtrace for the callstack, starting at the first
		// non-Reactor file. If limit is non-zero, then a maximum of limit
		// frames will be returned.
		Backtrace getCallerBacktrace(size_t limit = 0) const;

		llvm::DILocation* getLocation(const Backtrace &backtrace, size_t i);

		llvm::DIType *getOrCreateType(llvm::Type* type);
		llvm::DIFile *getOrCreateFile(const char* path);
		LineTokens const *getOrParseFileTokens(const char* path);

		// Synchronizes diScope with the current backtrace.
		void syncScope(Backtrace const& backtrace);

		IRBuilder *builder;
		llvm::LLVMContext *context;
		llvm::Module *module;
		llvm::Function *function;

		std::unique_ptr<llvm::DIBuilder> diBuilder;
		llvm::DICompileUnit *diCU;
		llvm::DISubprogram *diSubprogram;
		llvm::DILocation *diRootLocation;
		std::vector<Scope> diScope;
		std::unordered_map<std::string, llvm::DIFile*> diFiles;
		std::unordered_map<llvm::Type*, llvm::DIType*> diTypes;
		std::unordered_map<std::string, std::unique_ptr<LineTokens>> fileTokens;
		std::vector<void const*> pushed;
	};

} // namespace rr

#endif // ENABLE_RR_DEBUG_INFO

#endif // rr_LLVMReactorDebugInfo_hpp
