//
// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// Mangler.h --
//
// Author           : Richard C. Bilson
// Created On       : Sun May 17 21:44:03 2015
// Last Modified By : Peter A. Buhr
// Last Modified On : Sat Jul 22 09:45:30 2017
// Update Count     : 15
//

#include "Mangler.h"
#include "SynTree/Type.h"
#include "SynTree/Declaration.h"

namespace SymTab {
	namespace Mangler {
		namespace Encoding {
			const std::string manglePrefix = "_X";

			const std::string basicTypes[] = {
				"b",  // Bool
				"c",  // Char
				"a",  // SignedChar
				"h",  // UnsignedChar
				"s",  // ShortSignedInt
				"t",  // ShortUnsignedInt
				"i",  // SignedInt
				"j",  // UnsignedInt
				"l",  // LongSignedInt
				"m",  // LongUnsignedInt
				"x",  // LongLongSignedInt
				"y",  // LongLongUnsignedInt
				"f",  // Float
				"d",  // Double
				"e",  // LongDouble
				"Cf", // FloatComplex
				"Cd", // DoubleComplex
				"Ce", // LongDoubleComplex
				// Note: imaginary is not an overloadable type in C++
				"If", // FloatImaginary
				"Id", // DoubleImaginary
				"Ie", // LongDoubleImaginary
				"n",  // SignedInt128
				"o",  // UnsignedInt128
				"Dq",  // Float80 -- TODO: itanium says Float80 and LongDouble both encode to "e", but doing this causes problems with constructing long double, because the cost tables are incorrect
				"g",  // Float128
				// "z",	// ellipsis
				// "Dd" // # IEEE 754r decimal floating point (64 bits)
				// "De" // # IEEE 754r decimal floating point (128 bits)
				// "Df" // # IEEE 754r decimal floating point (32 bits)
				// "Dh" // # IEEE 754r half-precision floating point (16 bits)
				// "DF"N_ // # ISO/IEC TS 18661 binary floating point type _FloatN (N bits)
				// "Di" // char32_t
				// "Ds" // char16_t
			};
			static_assert(
				sizeof(basicTypes)/sizeof(basicTypes[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
				"Each basic type kind should have a corresponding mangler letter"
			);

			const std::map<int, std::string> qualifiers = {
				{ Type::Const, "K" },
				{ Type::Volatile, "V" },
				{ Type::Atomic, "DA" }, // A is array, so need something unique for atmoic. For now, go with multiletter DA
				{ Type::Mutex, "X" },
				{ Type::Lvalue, "L" },
			};

			const std::string void_t = "v";
			const std::string zero = "Z";
			const std::string one = "O";

			const std::string function = "F";
			const std::string tuple = "T";
			const std::string pointer = "P";
			const std::string array = "A";
			const std::string qualifiedTypeStart = "N";
			const std::string qualifiedTypeEnd = "E";

			const std::string forall = "Q";
			const std::string typeVariables[] = {
				"BD", // dtype
				"BF", // ftype
				"BT", // ttype
			};
			static_assert(
				sizeof(typeVariables)/sizeof(typeVariables[0]) == TypeDecl::NUMBER_OF_KINDS,
				"Each type variable kind should have a corresponding mangler prefix"
			);

			const std::string struct_t = "S";
			const std::string union_t = "U";
			const std::string enum_t = "M";
			const std::string type = "Y";

			const std::string autogen = "autogen__";
			const std::string intrinsic = "intrinsic__";
		} // namespace Encoding
	} // namespace Mangler
} // namespace SymTab
