1 /**
2  * D binding to C++ <new>
3  *
4  * Copyright: Copyright (c) 2019 D Language Foundation
5  * License: Distributed under the
6  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7  *    (See accompanying file LICENSE)
8  * Authors:   Manu Evans
9  * Source:    $(DRUNTIMESRC core/stdcpp/new_.d)
10  */
11 
12 module core.stdcpp.new_;
13 
14 import core.stdcpp.xutility : __cpp_sized_deallocation, __cpp_aligned_new;
15 import core.stdcpp.exception : exception;
16 
17 // TODO: this really should come from __traits(getTargetInfo, "defaultNewAlignment")
18 version (D_LP64)
19     enum size_t __STDCPP_DEFAULT_NEW_ALIGNMENT__ = 16;
20 else
21     enum size_t __STDCPP_DEFAULT_NEW_ALIGNMENT__ = 8;
22 
23 extern (C++, "std")
24 {
25     ///
26     struct nothrow_t {}
27 
28     ///
29     enum align_val_t : size_t { defaultAlignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__ }
30 
31     ///
32     class bad_alloc : exception
33     {
34     @nogc:
35         ///
36         this() { super("bad allocation", 1); }
37     }
38 }
39 
40 
41 ///
42 T* cpp_new(T, Args...)(auto ref Args args) if (!is(T == class))
43 {
44     import core.lifetime : emplace, forward;
45 
46     T* mem = cast(T*)__cpp_new(T.sizeof);
47     return mem.emplace(forward!args);
48 }
49 
50 ///
51 T cpp_new(T, Args...)(auto ref Args args) if (is(T == class))
52 {
53     import core.lifetime : emplace, forward;
54 
55     T mem = cast(T)__cpp_new(__traits(classInstanceSize, T));
56     return mem.emplace(forward!args);
57 }
58 
59 ///
60 void cpp_delete(T)(T* ptr) if (!is(T == class))
61 {
62     destroy!false(*ptr);
63     __cpp_delete(ptr);
64 }
65 
66 ///
67 void cpp_delete(T)(T instance) if (is(T == class))
68 {
69     destroy!false(instance);
70     __cpp_delete(cast(void*) instance);
71 }
72 
73 
74 // raw C++ functions
75 extern(C++):
76 @nogc:
77 
78 /// Binding for ::operator new(std::size_t count)
79 pragma(mangle, __new_mangle)
80 void* __cpp_new(size_t count);
81 
82 /// Binding for ::operator new(std::size_t count, const std::nothrow_t&)
83 pragma(mangle, __new_nothrow_mangle)
84 void* __cpp_new_nothrow(size_t count, ref const(nothrow_t) = std_nothrow) nothrow;
85 
86 /// Binding for ::operator delete(void* ptr)
87 pragma(mangle, __delete_mangle)
88 void __cpp_delete(void* ptr);
89 
90 /// Binding for ::operator delete(void* ptr, const std::nothrow_t& tag)
91 pragma(mangle, __delete_nothrow_mangle)
92 void __cpp_delete_nothrow(void* ptr, ref const(nothrow_t) = std_nothrow) nothrow;
93 
94 static if (__cpp_sized_deallocation)
95 {
96     /// Binding for ::operator delete(void* ptr, size_t size)
97     pragma(mangle, __delete_size_mangle)
98     void __cpp_delete_size(void* ptr, size_t size);
99 }
100 static if (__cpp_aligned_new)
101 {
102     /// Binding for ::operator new(std::size_t count, std::align_val_t al)
103     pragma(mangle, __new_align_mangle)
104     void* __cpp_new_aligned(size_t count, align_val_t alignment);
105 
106     /// Binding for ::operator new(std::size_t count, std::align_val_t al, const std::nothrow_t&)
107     pragma(mangle, __new_aligned_nothrow_mangle)
108     void* __cpp_new_aligned_nothrow(size_t count, align_val_t alignment, ref const(nothrow_t) = std_nothrow) nothrow;
109 
110     /// Binding for ::operator delete(void* ptr, std::align_val_t al)
111     pragma(mangle, __delete_align_mangle)
112     void __cpp_delete_aligned(void* ptr, align_val_t alignment);
113 
114     /// Binding for ::operator delete(void* ptr, std::align_val_t al, const std::nothrow_t& tag)
115     pragma(mangle, __delete_align_nothrow_mangle)
116     void __cpp_delete_align_nothrow(void* ptr, align_val_t alignment, ref const(nothrow_t) = std_nothrow) nothrow;
117 
118     /// Binding for ::operator delete(void* ptr, size_t size, std::align_val_t al)
119     pragma(mangle, __delete_size_align_mangle)
120     void __cpp_delete_size_aligned(void* ptr, size_t size, align_val_t alignment);
121 }
122 
123 private:
124 extern (D):
125 
126 __gshared immutable nothrow_t std_nothrow;
127 
128 // we have to hard-code the mangling for the global new/delete operators
129 version (CppRuntime_Microsoft)
130 {
131     version (D_LP64)
132     {
133         enum __new_mangle                   = "??2@YAPEAX_K@Z";
134         enum __new_nothrow_mangle           = "??2@YAPEAX_KAEBUnothrow_t@std@@@Z";
135         enum __delete_mangle                = "??3@YAXPEAX@Z";
136         enum __delete_nothrow_mangle        = "??3@YAXPEAXAEBUnothrow_t@std@@@Z";
137         enum __delete_size_mangle           = "??3@YAXPEAX_K@Z";
138         enum __new_align_mangle             = "??2@YAPEAX_KW4align_val_t@std@@@Z";
139         enum __new_aligned_nothrow_mangle   = "??2@YAPEAX_KW4align_val_t@std@@AEBUnothrow_t@1@@Z";
140         enum __delete_align_mangle          = "??3@YAXPEAXW4align_val_t@std@@@Z";
141         enum __delete_align_nothrow_mangle  = "??3@YAXPEAXW4align_val_t@std@@AEBUnothrow_t@1@@Z";
142         enum __delete_size_align_mangle     = "??3@YAXPEAX_KW4align_val_t@std@@@Z";
143     }
144     else
145     {
146         enum __new_mangle                   = "??2@YAPAXI@Z";
147         enum __new_nothrow_mangle           = "??2@YAPAXIABUnothrow_t@std@@@Z";
148         enum __delete_mangle                = "??3@YAXPAX@Z";
149         enum __delete_nothrow_mangle        = "??3@YAXPAXABUnothrow_t@std@@@Z";
150         enum __delete_size_mangle           = "??3@YAXPAXI@Z";
151         enum __new_align_mangle             = "??2@YAPAXIW4align_val_t@std@@@Z";
152         enum __new_aligned_nothrow_mangle   = "??2@YAPAXIW4align_val_t@std@@ABUnothrow_t@1@@Z";
153         enum __delete_align_mangle          = "??3@YAXPAXW4align_val_t@std@@@Z";
154         enum __delete_align_nothrow_mangle  = "??3@YAXPAXW4align_val_t@std@@ABUnothrow_t@1@@Z";
155         enum __delete_size_align_mangle     = "??3@YAXPAXIW4align_val_t@std@@@Z";
156     }
157 }
158 else
159 {
160     version (D_LP64)
161     {
162         enum __new_mangle                   = "_Znwm";
163         enum __new_nothrow_mangle           = "_ZnwmRKSt9nothrow_t";
164         enum __delete_mangle                = "_ZdlPv";
165         enum __delete_nothrow_mangle        = "_ZdlPvRKSt9nothrow_t";
166         enum __delete_size_mangle           = "_ZdlPvm";
167         enum __new_align_mangle             = "_ZnwmSt11align_val_t";
168         enum __new_aligned_nothrow_mangle   = "_ZnwmSt11align_val_tRKSt9nothrow_t";
169         enum __delete_align_mangle          = "_ZdlPvSt11align_val_t";
170         enum __delete_align_nothrow_mangle  = "_ZdlPvSt11align_val_tRKSt9nothrow_t";
171         enum __delete_size_align_mangle     = "_ZdlPvmSt11align_val_t";
172     }
173     else
174     {
175         enum __new_mangle                   = "_Znwj";
176         enum __new_nothrow_mangle           = "_ZnwjRKSt9nothrow_t";
177         enum __delete_mangle                = "_ZdlPv";
178         enum __delete_nothrow_mangle        = "_ZdlPvRKSt9nothrow_t";
179         enum __delete_size_mangle           = "_ZdlPvj";
180         enum __new_align_mangle             = "_ZnwjSt11align_val_t";
181         enum __new_aligned_nothrow_mangle   = "_ZnwjSt11align_val_tRKSt9nothrow_t";
182         enum __delete_align_mangle          = "_ZdlPvSt11align_val_t";
183         enum __delete_align_nothrow_mangle  = "_ZdlPvSt11align_val_tRKSt9nothrow_t";
184         enum __delete_size_align_mangle     = "_ZdlPvjSt11align_val_t";
185     }
186 }