Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.

Commit 9dce356

Browse files
committed
allow any exception to be caught in C++ by specific type
small refactorings preparing usage by x64
1 parent 7f5ba5e commit 9dce356

File tree

1 file changed

+55
-81
lines changed

1 file changed

+55
-81
lines changed

src/ldc/eh/win32.d

Lines changed: 55 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,25 @@ import core.sys.windows.windows;
1313
import core.exception : onOutOfMemoryError, OutOfMemoryError;
1414
import core.stdc.stdlib : malloc, free;
1515
import core.stdc.string : memcpy;
16+
import rt.util.container.common : xmalloc;
1617

1718
// pointers are image relative for Win64 versions
1819
version(Win64)
1920
alias ImgPtr(T) = uint; // offset into image
2021
else
21-
alias ImgPtr(T) = T;
22+
alias ImgPtr(T) = T*;
2223

2324
alias PMFN = ImgPtr!(void function(void*));
2425

25-
struct TypeDescriptor(int N)
26+
struct TypeDescriptor
2627
{
2728
version(_RTTI)
2829
const void * pVFTable; // Field overloaded by RTTI
2930
else
3031
uint hash; // Hash value computed from type's decorated name
3132

3233
void * spare; // reserved, possible for RTTI
33-
char[N+1] name; // variable size, zero terminated
34+
char[1] name; // variable size, zero terminated
3435
}
3536

3637
struct PMD
@@ -43,7 +44,7 @@ struct PMD
4344
struct CatchableType
4445
{
4546
uint properties; // Catchable Type properties (Bit field)
46-
ImgPtr!(TypeDescriptor!1*) pType; // Pointer to TypeDescriptor
47+
ImgPtr!TypeDescriptor pType; // Pointer to TypeDescriptor
4748
PMD thisDisplacement; // Pointer to instance of catch type within thrown object.
4849
int sizeOrOffset; // Size of simple-type object or offset into buffer of 'this' pointer for catch object
4950
PMFN copyFunction; // Copy constructor or CC-closure
@@ -58,15 +59,15 @@ enum CT_IsStdBadAlloc = 0x00000010; // type is a a std::bad_alloc
5859
struct CatchableTypeArray
5960
{
6061
int nCatchableTypes;
61-
ImgPtr!(CatchableType*)[2] arrayOfCatchableTypes;
62+
ImgPtr!CatchableType[1] arrayOfCatchableTypes; // variable size
6263
}
6364

6465
struct _ThrowInfo
6566
{
6667
uint attributes; // Throw Info attributes (Bit field)
6768
PMFN pmfnUnwind; // Destructor to call when exception has been handled or aborted.
6869
PMFN pForwardCompat; // pointer to Forward compatibility frame handler
69-
ImgPtr!(CatchableTypeArray*) pCatchableTypeArray; // pointer to CatchableTypeArray
70+
ImgPtr!CatchableTypeArray pCatchableTypeArray; // pointer to CatchableTypeArray
7071
}
7172

7273
struct ExceptionRecord
@@ -142,96 +143,77 @@ extern(C) string _d_toString(Object o)
142143
import rt.util.container.hashtab;
143144
import core.sync.mutex;
144145

145-
__gshared HashTab!(TypeInfo_Class, _ThrowInfo) throwInfoHashtab;
146-
__gshared HashTab!(TypeInfo_Class, CatchableType) catchableHashtab;
146+
__gshared HashTab!(TypeInfo_Class, ImgPtr!_ThrowInfo) throwInfoHashtab;
147+
__gshared HashTab!(TypeInfo_Class, ImgPtr!CatchableType) catchableHashtab;
147148
__gshared Mutex throwInfoMutex;
148149

149150
// create and cache throwinfo for ti
150-
_ThrowInfo* getThrowInfo(TypeInfo_Class ti)
151+
ImgPtr!_ThrowInfo getThrowInfo(TypeInfo_Class ti)
151152
{
152153
throwInfoMutex.lock();
153154
if (auto p = ti in throwInfoHashtab)
154155
{
155156
throwInfoMutex.unlock();
156-
return p;
157+
return *p;
157158
}
158159

159-
bool isError = false;
160-
bool isException = false;
161160
size_t classes = 0;
162161
for (TypeInfo_Class tic = ti; tic; tic = tic.base)
163-
{
164-
classes++;
165-
if (tic == typeid(Exception))
166-
isException = true;
167-
if (tic == typeid(Error))
168-
isError = true;
169-
}
170-
if (isError || isException)
171-
classes += 2;
162+
classes += 2; // D and C++
172163

173-
size_t sz = int.sizeof + classes * ImgPtr!(CatchableType*).sizeof;
174-
auto cta = cast(CatchableTypeArray*) malloc(sz);
175-
if (!cta)
176-
onOutOfMemoryError();
164+
size_t sz = int.sizeof + classes * ImgPtr!(CatchableType).sizeof;
165+
auto cta = cast(CatchableTypeArray*) xmalloc(sz);
177166
cta.nCatchableTypes = classes;
178167

179168
size_t c = 0;
180-
for (TypeInfo_Class tic = ti; tic; tic = tic.base)
181-
cta.arrayOfCatchableTypes.ptr[c++] = getCatchableType(tic);
182-
if (isError || isException)
183-
cta.arrayOfCatchableTypes.ptr[c++] = ctCxxDThrowable;
184-
if (isException)
185-
cta.arrayOfCatchableTypes.ptr[c++] = ctCxxDException;
186-
if (isError)
187-
cta.arrayOfCatchableTypes.ptr[c++] = ctCxxDError;
188-
189-
_ThrowInfo tinf = { 0, null, null, cta };
169+
for (TypeInfo_Class tic = ti; tic; tic = tic.base, c += 2)
170+
{
171+
cta.arrayOfCatchableTypes.ptr[c] = getCatchableType(tic);
172+
cta.arrayOfCatchableTypes.ptr[c + 1] = cta.arrayOfCatchableTypes.ptr[c] + 1;
173+
}
174+
175+
auto tinf = cast(_ThrowInfo*) xmalloc(_ThrowInfo.sizeof);
176+
*tinf = _ThrowInfo(0, null, null, cta);
190177
throwInfoHashtab[ti] = tinf;
191-
auto pti = ti in throwInfoHashtab;
192178
throwInfoMutex.unlock();
193-
return pti;
179+
return tinf;
194180
}
195-
181+
182+
// returns pointer to array of 2 elements, one for D and one for C++
196183
CatchableType* getCatchableType(TypeInfo_Class ti)
197184
{
198185
if (auto p = ti in catchableHashtab)
199-
return p;
186+
return *p;
187+
188+
// generate catch types for both D (fully.qualified.name)
189+
// and C++ (D::name mangled to .PAVname@D@@)
190+
size_t p = ti.name.length;
191+
for ( ; p > 0 && ti.name[p-1] != '.'; p--) {}
192+
string name = ti.name[p .. $];
193+
194+
size_t szd = (TypeDescriptor.sizeof + ti.name.length + 3) & ~3;
195+
size_t szcpp = TypeDescriptor.sizeof + name.length + 8;
196+
auto tdd = cast(TypeDescriptor*) xmalloc(szd + szcpp);
197+
198+
tdd.hash = 0;
199+
tdd.spare = null;
200+
tdd.name.ptr[0] = 'D';
201+
memcpy(tdd.name.ptr + 1, ti.name.ptr, ti.name.length);
202+
tdd.name.ptr[ti.name.length + 1] = 0;
203+
204+
auto tdcpp = cast(TypeDescriptor*) (cast(char*)tdd + szd);
205+
tdcpp.hash = 0;
206+
tdcpp.spare = null;
207+
memcpy(tdcpp.name.ptr, ".PAV".ptr, 4);
208+
memcpy(tdcpp.name.ptr + 4, name.ptr, name.length);
209+
memcpy(tdcpp.name.ptr + 4 + name.length, "@D@@".ptr, 5);
210+
211+
auto ct = cast(CatchableType*) xmalloc(2 * CatchableType.sizeof);
212+
ct[0] = CatchableType(CT_IsSimpleType, tdd, PMD(0, -1, 0), 4, null);
213+
ct[1] = CatchableType(CT_IsSimpleType, tdcpp, PMD(0, -1, 0), 4, null);
200214

201-
size_t sz = TypeDescriptor!1.sizeof + ti.name.length;
202-
auto td = cast(TypeDescriptor!1*) malloc(sz);
203-
if (!td)
204-
onOutOfMemoryError();
205-
206-
td.hash = 0;
207-
td.spare = null;
208-
td.name.ptr[0] = 'D';
209-
memcpy(td.name.ptr + 1, ti.name.ptr, ti.name.length);
210-
td.name.ptr[ti.name.length + 1] = 0;
211-
212-
CatchableType ct = { CT_IsSimpleType, td, { 0, -1, 0 }, 4, null };
213215
catchableHashtab[ti] = ct;
214-
return ti in catchableHashtab;
215-
}
216-
217-
CatchableType* createCxxCatchableType(string cxxMangledName)
218-
{
219-
size_t sz = TypeDescriptor!1.sizeof + cxxMangledName.length;
220-
auto td = cast(TypeDescriptor!1*) malloc(sz);
221-
if (!td)
222-
onOutOfMemoryError();
223-
224-
td.hash = 0;
225-
td.spare = null;
226-
memcpy(td.name.ptr, cxxMangledName.ptr, cxxMangledName.length);
227-
td.name.ptr[cxxMangledName.length + 1] = 0;
228-
229-
CatchableType* pct = cast(CatchableType*) malloc(CatchableType.sizeof);
230-
if (!pct)
231-
onOutOfMemoryError();
232-
CatchableType ct = { CT_IsSimpleType, td, { 0, -1, 0 }, 4, null };
233-
*pct = ct;
234-
return pct;
216+
return ct;
235217
}
236218

237219
///////////////////////////////////////////////////////////////
@@ -338,9 +320,7 @@ private:
338320
{
339321
// alloc from GC? add array as a GC range?
340322
immutable ncap = _cap ? 2 * _cap : 64;
341-
auto p = cast(Throwable*)malloc(ncap * Throwable.sizeof);
342-
if (p is null)
343-
onOutOfMemoryError();
323+
auto p = cast(Throwable*)xmalloc(ncap * Throwable.sizeof);
344324
p[0 .. _length] = _p[0 .. _length];
345325
free(_p);
346326
_p = p;
@@ -530,7 +510,6 @@ extern(C) int* __processing_throw() nothrow;
530510

531511
extern(C) void* _d_eh_swapContext(FiberContext* newContext) nothrow
532512
{
533-
import rt.util.container.common : xmalloc;
534513
import core.stdc.string : memset;
535514
if (!fiberContext)
536515
{
@@ -577,11 +556,6 @@ void msvc_eh_init()
577556
{
578557
throwInfoMutex = new Mutex;
579558

580-
// predefine CatchableTypes for C++ interop
581-
ctCxxDThrowable = createCxxCatchableType(".PAVException@D@@");
582-
ctCxxDException = createCxxCatchableType(".PAVException@D@@");
583-
ctCxxDError = createCxxCatchableType(".PAVException@D@@");
584-
585559
// preallocate type descriptors likely to be needed
586560
getThrowInfo(typeid(Exception));
587561
// better not have to allocate when this is thrown:

0 commit comments

Comments
 (0)