Projet_SETI_RISC-V/riscv-gnu-toolchain/gcc/libphobos/libdruntime/core/stdcpp/xutility.d
2023-03-06 14:48:14 +01:00

428 lines
13 KiB
D

/**
* D header file for interaction with Microsoft C++ <xutility>
*
* Copyright: Copyright (c) 2018 D Language Foundation
* License: Distributed under the
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Manu Evans
* Source: $(DRUNTIMESRC core/stdcpp/xutility.d)
*/
module core.stdcpp.xutility;
@nogc:
version (CppRuntime_Clang)
{
import core.internal.traits : AliasSeq;
enum StdNamespace = AliasSeq!("std", "__1");
}
else
{
enum StdNamespace = "std";
}
enum CppStdRevision : uint
{
cpp98 = 199711,
cpp11 = 201103,
cpp14 = 201402,
cpp17 = 201703
}
enum __cplusplus = __traits(getTargetInfo, "cppStd");
// wrangle C++ features
enum __cpp_sized_deallocation = __cplusplus >= CppStdRevision.cpp14 || is(typeof(_MSC_VER)) ? 201309 : 0;
enum __cpp_aligned_new = __cplusplus >= CppStdRevision.cpp17 ? 201606 : 0;
version (CppRuntime_Microsoft)
{
import core.stdcpp.type_traits : is_empty;
version (_MSC_VER_1200)
enum _MSC_VER = 1200;
else version (_MSC_VER_1300)
enum _MSC_VER = 1300;
else version (_MSC_VER_1310)
enum _MSC_VER = 1310;
else version (_MSC_VER_1400)
enum _MSC_VER = 1400;
else version (_MSC_VER_1500)
enum _MSC_VER = 1500;
else version (_MSC_VER_1600)
enum _MSC_VER = 1600;
else version (_MSC_VER_1700)
enum _MSC_VER = 1700;
else version (_MSC_VER_1800)
enum _MSC_VER = 1800;
else version (_MSC_VER_1900)
enum _MSC_VER = 1900;
else version (_MSC_VER_1910)
enum _MSC_VER = 1910;
else version (_MSC_VER_1911)
enum _MSC_VER = 1911;
else version (_MSC_VER_1912)
enum _MSC_VER = 1912;
else version (_MSC_VER_1913)
enum _MSC_VER = 1913;
else version (_MSC_VER_1914)
enum _MSC_VER = 1914;
else version (_MSC_VER_1915)
enum _MSC_VER = 1915;
else version (_MSC_VER_1916)
enum _MSC_VER = 1916;
else version (_MSC_VER_1920)
enum _MSC_VER = 1920;
else version (_MSC_VER_1921)
enum _MSC_VER = 1921;
else version (_MSC_VER_1922)
enum _MSC_VER = 1922;
else version (_MSC_VER_1923)
enum _MSC_VER = 1923;
else
enum _MSC_VER = 1923; // assume most recent compiler version
// Client code can mixin the set of MSVC linker directives
mixin template MSVCLinkDirectives(bool failMismatch = false)
{
import core.stdcpp.xutility : __CXXLIB__, _ITERATOR_DEBUG_LEVEL;
static if (__CXXLIB__ == "libcmtd")
{
pragma(lib, "libcpmtd");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MTd_StaticDebug");
}
else static if (__CXXLIB__ == "msvcrtd")
{
pragma(lib, "msvcprtd");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug");
}
else static if (__CXXLIB__ == "libcmt")
{
pragma(lib, "libcpmt");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MT_StaticRelease");
}
else static if (__CXXLIB__ == "msvcrt")
{
pragma(lib, "msvcprt");
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:RuntimeLibrary=MD_DynamicRelease");
}
static if (failMismatch)
pragma(linkerDirective, "/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=" ~ ('0' + _ITERATOR_DEBUG_LEVEL));
}
// HACK: should we guess _DEBUG for `debug` builds?
version (NDEBUG) {}
else debug version = _DEBUG;
// By specific user request
version (_ITERATOR_DEBUG_LEVEL_0)
enum _ITERATOR_DEBUG_LEVEL = 0;
else version (_ITERATOR_DEBUG_LEVEL_1)
enum _ITERATOR_DEBUG_LEVEL = 1;
else version (_ITERATOR_DEBUG_LEVEL_2)
enum _ITERATOR_DEBUG_LEVEL = 2;
else
{
// Match the C Runtime
static if (__CXXLIB__ == "libcmtd" || __CXXLIB__ == "msvcrtd")
enum _ITERATOR_DEBUG_LEVEL = 2;
else static if (__CXXLIB__ == "libcmt" || __CXXLIB__ == "msvcrt" ||
__CXXLIB__ == "msvcrt100" || __CXXLIB__ == "msvcrt110" || __CXXLIB__ == "msvcrt120")
enum _ITERATOR_DEBUG_LEVEL = 0;
else
{
static if (__CXXLIB__.length > 0)
pragma(msg, "Unrecognised C++ runtime library '" ~ __CXXLIB__ ~ "'");
// No runtime specified; as a best-guess, -release will produce code that matches the MSVC release CRT
version (_DEBUG)
enum _ITERATOR_DEBUG_LEVEL = 2;
else
enum _ITERATOR_DEBUG_LEVEL = 0;
}
}
// convenient alias for the C++ std library name
enum __CXXLIB__ = __traits(getTargetInfo, "cppRuntimeLibrary");
extern(C++, "std"):
package:
enum _LOCK_DEBUG = 3;
extern(C++, class) struct _Lockit
{
this(int) nothrow @nogc @safe;
~this() nothrow @nogc @safe;
private:
int _Locktype;
}
void dummyDtor() { assert(false); }
pragma(linkerDirective, "/ALTERNATENAME:" ~ _Lockit.__dtor.mangleof ~ "=" ~ dummyDtor.mangleof);
struct _Container_base0
{
extern(D):
void _Orphan_all()() nothrow @nogc @safe {}
void _Swap_all()(ref _Container_base0) nothrow @nogc @safe {}
void _Swap_proxy_and_iterators()(ref _Container_base0) nothrow {}
}
struct _Iterator_base0
{
extern(D):
void _Adopt()(const(void)*) nothrow @nogc @safe {}
const(_Container_base0)* _Getcont()() const nothrow @nogc @safe { return null; }
enum bool _Unwrap_when_unverified = true;
}
struct _Container_proxy
{
const(_Container_base12)* _Mycont;
_Iterator_base12* _Myfirstiter;
}
struct _Container_base12
{
extern(D):
inout(_Iterator_base12*)*_Getpfirst()() inout nothrow @nogc @safe
{
return _Myproxy == null ? null : &_Myproxy._Myfirstiter;
}
void _Orphan_all()() nothrow @nogc @safe
{
static if (_ITERATOR_DEBUG_LEVEL == 2)
{
if (_Myproxy != null)
{
auto _Lock = _Lockit(_LOCK_DEBUG);
for (_Iterator_base12 **_Pnext = &_Myproxy._Myfirstiter; *_Pnext != null; *_Pnext = (*_Pnext)._Mynextiter)
(*_Pnext)._Myproxy = null;
_Myproxy._Myfirstiter = null;
}
}
}
// void _Swap_all()(ref _Container_base12) nothrow @nogc;
void _Swap_proxy_and_iterators()(ref _Container_base12 _Right) nothrow
{
static if (_ITERATOR_DEBUG_LEVEL == 2)
auto _Lock = _Lockit(_LOCK_DEBUG);
_Container_proxy* _Temp = _Myproxy;
_Myproxy = _Right._Myproxy;
_Right._Myproxy = _Temp;
if (_Myproxy)
_Myproxy._Mycont = &this;
if (_Right._Myproxy)
_Right._Myproxy._Mycont = &_Right;
}
_Container_proxy* _Myproxy;
}
struct _Iterator_base12
{
extern(D):
void _Adopt()(_Container_base12 *_Parent) nothrow @nogc @safe
{
if (_Parent == null)
{
static if (_ITERATOR_DEBUG_LEVEL == 2)
{
auto _Lock = _Lockit(_LOCK_DEBUG);
_Orphan_me();
}
}
else
{
_Container_proxy *_Parent_proxy = _Parent._Myproxy;
static if (_ITERATOR_DEBUG_LEVEL == 2)
{
if (_Myproxy != _Parent_proxy)
{
auto _Lock = _Lockit(_LOCK_DEBUG);
_Orphan_me();
_Mynextiter = _Parent_proxy._Myfirstiter;
_Parent_proxy._Myfirstiter = &this;
_Myproxy = _Parent_proxy;
}
}
else
_Myproxy = _Parent_proxy;
}
}
void _Clrcont()() nothrow @nogc @safe
{
_Myproxy = null;
}
const(_Container_base12)* _Getcont()() const nothrow @nogc @safe
{
return _Myproxy == null ? null : _Myproxy._Mycont;
}
inout(_Iterator_base12*)*_Getpnext()() inout nothrow @nogc @safe
{
return &_Mynextiter;
}
void _Orphan_me()() nothrow @nogc @safe
{
static if (_ITERATOR_DEBUG_LEVEL == 2)
{
if (_Myproxy != null)
{
_Iterator_base12 **_Pnext = &_Myproxy._Myfirstiter;
while (*_Pnext != null && *_Pnext != &this)
_Pnext = &(*_Pnext)._Mynextiter;
assert(*_Pnext, "ITERATOR LIST CORRUPTED!");
*_Pnext = _Mynextiter;
_Myproxy = null;
}
}
}
enum bool _Unwrap_when_unverified = _ITERATOR_DEBUG_LEVEL == 0;
_Container_proxy *_Myproxy;
_Iterator_base12 *_Mynextiter;
}
static if (_ITERATOR_DEBUG_LEVEL == 0)
{
alias _Container_base = _Container_base0;
alias _Iterator_base = _Iterator_base0;
}
else
{
alias _Container_base = _Container_base12;
alias _Iterator_base = _Iterator_base12;
}
extern (C++, class) struct _Compressed_pair(_Ty1, _Ty2, bool Ty1Empty = is_empty!_Ty1.value)
{
pragma (inline, true):
extern(D):
pure nothrow @nogc:
enum _HasFirst = !Ty1Empty;
ref inout(_Ty1) first() inout @safe { return _Myval1; }
ref inout(_Ty2) second() inout @safe { return _Myval2; }
static if (!Ty1Empty)
_Ty1 _Myval1;
else
{
@property ref inout(_Ty1) _Myval1() inout @trusted { return *_GetBase(); }
private inout(_Ty1)* _GetBase() inout @trusted { return cast(inout(_Ty1)*)&this; }
}
_Ty2 _Myval2;
}
// these are all [[noreturn]]
void _Xbad_alloc() nothrow;
void _Xinvalid_argument(const(char)* message) nothrow;
void _Xlength_error(const(char)* message) nothrow;
void _Xout_of_range(const(char)* message) nothrow;
void _Xoverflow_error(const(char)* message) nothrow;
void _Xruntime_error(const(char)* message) nothrow;
}
else version (CppRuntime_Clang)
{
import core.stdcpp.type_traits : is_empty;
extern(C++, "std"):
extern (C++, class) struct __compressed_pair(_T1, _T2)
{
pragma (inline, true):
extern(D):
enum Ty1Empty = is_empty!_T1.value;
enum Ty2Empty = is_empty!_T2.value;
ref inout(_T1) first() inout nothrow @safe @nogc { return __value1_; }
ref inout(_T2) second() inout nothrow @safe @nogc { return __value2_; }
private:
private inout(_T1)* __get_base1() inout { return cast(inout(_T1)*)&this; }
private inout(_T2)* __get_base2() inout { return cast(inout(_T2)*)&__get_base1()[Ty1Empty ? 0 : 1]; }
static if (!Ty1Empty)
_T1 __value1_;
else
@property ref inout(_T1) __value1_() inout nothrow @trusted @nogc { return *__get_base1(); }
static if (!Ty2Empty)
_T2 __value2_;
else
@property ref inout(_T2) __value2_() inout nothrow @trusted @nogc { return *__get_base2(); }
}
}
version (CppRuntime_Gcc)
{
import core.atomic;
alias _Atomic_word = int;
void __atomic_add_dispatch()(_Atomic_word* __mem, int __val) nothrow @nogc @safe
{
version (__GTHREADS)
{
// TODO: check __gthread_active_p()
// if (__gthread_active_p())
__atomic_add(__mem, __val);
// }
// else
// __atomic_add_single(__mem, __val);
}
else
__atomic_add_single(__mem, __val);
}
void __atomic_add()(_Atomic_word* __mem, int __val) nothrow @nogc @safe
{
atomicFetchAdd!(MemoryOrder.acq_rel)(*__mem, __val);
}
void __atomic_add_single()(_Atomic_word* __mem, int __val) nothrow @nogc @safe
{
*__mem += __val;
}
_Atomic_word __exchange_and_add_dispatch()(_Atomic_word* __mem, int __val) nothrow @nogc @safe
{
version (__GTHREADS)
{
// TODO: check __gthread_active_p()
return __exchange_and_add(__mem, __val);
// if (__gthread_active_p())
// return __exchange_and_add(__mem, __val);
// else
// return __exchange_and_add_single(__mem, __val);
}
else
return __exchange_and_add_single(__mem, __val);
}
_Atomic_word __exchange_and_add()(_Atomic_word* __mem, int __val) nothrow @nogc @safe
{
return atomicFetchAdd!(MemoryOrder.acq_rel)(*__mem, __val);
}
_Atomic_word __exchange_and_add_single()(_Atomic_word* __mem, int __val) nothrow @nogc @safe
{
_Atomic_word __result = *__mem;
*__mem += __val;
return __result;
}
}