Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/core/cpuid.d
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ bool hasCPUID()
return true;
else version(LDC) {
size_t flags;
asm {
asm @nogc nothrow {
pushf;
pop EAX;
mov flags, EAX;
Expand Down
10 changes: 5 additions & 5 deletions src/ldc/eh/common.d
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extern(C) void fatalerror(in char* format, ...)
// Reading DWARF data
// ------------------------

version (Win64) {} else
version (CRuntime_Microsoft) {} else
{
extern(C)
{
Expand Down Expand Up @@ -195,15 +195,15 @@ ubyte* get_encoded_value(ubyte* addr, ref size_t res, ubyte encoding, void* cont
res += cast(size_t)old_addr;
break;
case _DW_EH_Format.DW_EH_PE_funcrel:
version(Win64) fatalerror("Not yet implemented."); else
version(CRuntime_Microsoft) fatalerror("Not yet implemented."); else
res += cast(size_t)_Unwind_GetRegionStart(context);
break;
case _DW_EH_Format.DW_EH_PE_textrel:
version(Win64) fatalerror("Not yet implemented."); else
version(CRuntime_Microsoft) fatalerror("Not yet implemented."); else
res += cast(size_t)_Unwind_GetTextRelBase(context);
break;
case _DW_EH_Format.DW_EH_PE_datarel:
version(Win64) fatalerror("Not yet implemented."); else
version(CRuntime_Microsoft) fatalerror("Not yet implemented."); else
res += cast(size_t)_Unwind_GetDataRelBase(context);
break;
default:
Expand Down Expand Up @@ -231,7 +231,7 @@ ptrdiff_t get_base_of_encoded_value(ubyte encoding, void* context)
case DW_EH_PE_aligned:
return 0;

version(Win64) {} else
version(CRuntime_Microsoft) {} else
{
case DW_EH_PE_textrel:
return _Unwind_GetTextRelBase (context);
Expand Down
232 changes: 232 additions & 0 deletions src/ldc/eh/win32.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/**
* This module implements the runtime-part of LDC exceptions
* on Windows win32.
*/
module ldc.eh.win32;

version(CRuntime_Microsoft):
version(Win32):

import ldc.eh.common;
import core.sys.windows.windows;
import core.exception : onOutOfMemoryError;
import core.stdc.stdlib : malloc;
import core.stdc.string : memcpy;

// pointers are image relative for Win64 versions
version(Win64)
alias ImgPtr(T) = uint; // offset into image
else
alias ImgPtr(T) = T;

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

struct TypeDescriptor(int N)
{
version(_RTTI)
const void * pVFTable; // Field overloaded by RTTI
else
uint hash; // Hash value computed from type's decorated name

void * spare; // reserved, possible for RTTI
char[N+1] name; // variable size, zero terminated
}

struct PMD
{
int mdisp; // Offset of intended data within base
int pdisp; // Displacement to virtual base pointer
int vdisp; // Index within vbTable to offset of base
}

struct CatchableType
{
uint properties; // Catchable Type properties (Bit field)
ImgPtr!(TypeDescriptor!1*) pType; // Pointer to TypeDescriptor
PMD thisDisplacement; // Pointer to instance of catch type within thrown object.
int sizeOrOffset; // Size of simple-type object or offset into buffer of 'this' pointer for catch object
PMFN copyFunction; // Copy constructor or CC-closure
}

enum CT_IsSimpleType = 0x00000001; // type is a simple type (includes pointers)
enum CT_ByReferenceOnly = 0x00000002; // type must be caught by reference
enum CT_HasVirtualBase = 0x00000004; // type is a class with virtual bases
enum CT_IsWinRTHandle = 0x00000008; // type is a winrt handle
enum CT_IsStdBadAlloc = 0x00000010; // type is a a std::bad_alloc

struct CatchableTypeArray
{
int nCatchableTypes;
ImgPtr!(CatchableType*)[2] arrayOfCatchableTypes;
}

struct _ThrowInfo
{
uint attributes; // Throw Info attributes (Bit field)
PMFN pmfnUnwind; // Destructor to call when exception has been handled or aborted.
PMFN pForwardCompat; // pointer to Forward compatibility frame handler
ImgPtr!(CatchableTypeArray*) pCatchableTypeArray; // pointer to CatchableTypeArray
}

enum TI_IsConst = 0x00000001; // thrown object has const qualifier
enum TI_IsVolatile = 0x00000002; // thrown object has volatile qualifier
enum TI_IsUnaligned = 0x00000004; // thrown object has unaligned qualifier
enum TI_IsPure = 0x00000008; // object thrown from a pure module
enum TI_IsWinRT = 0x00000010; // object thrown is a WinRT Exception

extern(Windows) void RaiseException(DWORD dwExceptionCode,
DWORD dwExceptionFlags,
DWORD nNumberOfArguments,
ULONG_PTR* lpArguments);

__gshared TypeDescriptor!16 tdObject = { 0, null, "_D6object6Object\0" };
__gshared TypeDescriptor!20 tdThrowable = { 0, null, "_D6object9Throwable\0" };
__gshared TypeDescriptor!12 tdException = { 0, null, "_D9Exception\0" };
version(none) {
__gshared CatchableType ctThrowable = { CT_IsSimpleType, cast(TypeDescriptor!1*) &tdThrowable, { 0, -1, 0 }, 4, null };
__gshared CatchableType ctException = { CT_IsSimpleType, cast(TypeDescriptor!1*) &tdException, { 0, -1, 0 }, 4, null };
__gshared CatchableTypeArray ctArray = { 2, [ &ctThrowable, &ctException ] };
__gshared _ThrowInfo objectThrowInfo = { 0, null, null, &ctArray };
}

enum int STATUS_MSC_EXCEPTION = 0xe0000000 | ('m' << 16) | ('s' << 8) | ('c' << 0);

enum EXCEPTION_NONCONTINUABLE = 0x01;
enum EXCEPTION_UNWINDING = 0x02;

enum EH_MAGIC_NUMBER1 = 0x19930520;

extern(C) void _d_throw_exception(Object e)
{
if (e is null)
fatalerror("Cannot throw null exception");
auto ti = typeid(e);
if (ti is null)
fatalerror("Cannot throw corrupt exception object with null classinfo");

ULONG_PTR[3] ExceptionInformation;
ExceptionInformation[0] = EH_MAGIC_NUMBER1;
ExceptionInformation[1] = cast(ULONG_PTR) cast(void*) &e;
ExceptionInformation[2] = cast(ULONG_PTR) getThrowInfo(ti);

RaiseException(STATUS_MSC_EXCEPTION, EXCEPTION_NONCONTINUABLE, 3, ExceptionInformation.ptr);
}

import rt.util.container.hashtab;
import core.sync.mutex;

__gshared HashTab!(TypeInfo_Class, _ThrowInfo) throwInfoHashtab;
__gshared HashTab!(TypeInfo_Class, CatchableType) catchableHashtab;
__gshared Mutex throwInfoMutex;

// create and cache throwinfo for ti
_ThrowInfo* getThrowInfo(TypeInfo_Class ti)
{
throwInfoMutex.lock();
if (auto p = ti in throwInfoHashtab)
{
throwInfoMutex.unlock();
return p;
}

size_t classes = 0;
for (TypeInfo_Class tic = ti; tic; tic = tic.base)
classes++;

size_t sz = int.sizeof + classes * ImgPtr!(CatchableType*).sizeof;
auto cta = cast(CatchableTypeArray*) malloc(sz);
if (!cta)
onOutOfMemoryError();
cta.nCatchableTypes = classes;

size_t c = 0;
for (TypeInfo_Class tic = ti; tic; tic = tic.base)
cta.arrayOfCatchableTypes.ptr[c++] = getCatchableType(tic);

_ThrowInfo tinf = { 0, null, null, cta };
throwInfoHashtab[ti] = tinf;
auto pti = ti in throwInfoHashtab;
throwInfoMutex.unlock();
return pti;
}

CatchableType* getCatchableType(TypeInfo_Class ti)
{
if (auto p = ti in catchableHashtab)
return p;

static size_t mangledNameLength(string s)
{
size_t len = 2 + s.length; // "_D" + identifier + 1 digit per dot
for (size_t q = 0; q < s.length; )
{
size_t p = q;
while (p < s.length && s.ptr[p] != '.')
p++;
for (size_t r = p - q; r >= 10; r /= 10) // add digits for length >= 10
len++;
q = p + 1;
}
return len;
}

static void mangleName(string s, char* buf)
{
*buf++ = '_';
*buf++ = 'D';
for (size_t q = 0; q < s.length; )
{
size_t p = q;
while (p < s.length && s.ptr[p] != '.')
p++;
size_t digits = 10;
size_t len = p - q;
for ( ; len >= digits; digits *= 10) {}
for (digits /= 10; digits > 1; digits /= 10)
{
size_t dig = len / digits;
*buf++ = cast(char)('0' + dig);
len -= dig * digits;
}
*buf++ = cast(char)('0' + len);
memcpy(buf, s.ptr + q, p - q);
buf += p - q;
q = p + 1;
}
*buf = 0;
}

size_t mangledLength = mangledNameLength(ti.name) + 1;
size_t sz = TypeDescriptor!1.sizeof + mangledLength;
auto td = cast(TypeDescriptor!1*) malloc(sz);
if (!td)
onOutOfMemoryError();

td.hash = 0;
td.spare = null;
mangleName(ti.name, td.name.ptr);

CatchableType ct = { CT_IsSimpleType, td, { 0, -1, 0 }, 4, null };
catchableHashtab[ti] = ct;
return ti in catchableHashtab;
}

void msvc_eh_init()
{
throwInfoMutex = new Mutex;

// Exception has a special mangling that's not reflected in the name

CatchableType ctObject = { CT_IsSimpleType, cast(TypeDescriptor!1*) &tdObject, { 0, -1, 0 }, 4, null };
catchableHashtab[typeid(Object)] = ctObject;
CatchableType ctThrowable = { CT_IsSimpleType, cast(TypeDescriptor!1*) &tdThrowable, { 0, -1, 0 }, 4, null };
catchableHashtab[typeid(Throwable)] = ctThrowable;
CatchableType ctException = { CT_IsSimpleType, cast(TypeDescriptor!1*) &tdException, { 0, -1, 0 }, 4, null };
catchableHashtab[typeid(Exception)] = ctException;
}

shared static this()
{
// should be called from rt_init
msvc_eh_init();
}
4 changes: 2 additions & 2 deletions src/rt/sections_ldc.d
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private
Section(SEG_DATA, SECT_COMMON)
];
}
else version (Win64)
else version (CRuntime_Microsoft)
{
extern extern (C) __gshared
{
Expand Down Expand Up @@ -371,7 +371,7 @@ void initSections()
}
_dyld_register_func_for_add_image(&scanSections);
}
else version (Win64)
else version (CRuntime_Microsoft)
{
pushRange(_data_start__, _data_end__);
if (_bss_start__ != null)
Expand Down
39 changes: 25 additions & 14 deletions src/rt/stdio_msvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,20 @@ int _set_output_format(int format); // VS2013-
//extern const char* __acrt_iob_func;
extern const char* _nullfunc = 0;

#pragma comment(linker, "/alternatename:__acrt_iob_func=_nullfunc")
#pragma comment(linker, "/alternatename:__iob_func=_nullfunc")
#pragma comment(linker, "/alternatename:_set_output_format=_nullfunc")
#if defined _M_IX86
#define C_PREFIX "_"
#elif defined _M_X64 || defined _M_ARM || defined _M_ARM64
#define C_PREFIX ""
#else
#error Unsupported architecture
#endif

#define DECLARE_ALTERNATE_NAME(name, alternate_name) \
__pragma(comment(linker, "/alternatename:" C_PREFIX #name "=" C_PREFIX #alternate_name))

DECLARE_ALTERNATE_NAME (__acrt_iob_func, _nullfunc);
DECLARE_ALTERNATE_NAME (__iob_func, _nullfunc);
DECLARE_ALTERNATE_NAME (_set_output_format, _nullfunc);

void init_msvc()
{
Expand All @@ -65,25 +76,25 @@ void init_msvc()
// VS2015+ provides C99-conformant (v)snprintf functions, so weakly
// link to legacy _(v)snprintf (not C99-conformant!) for VS2013- only

#pragma comment(linker, "/alternatename:snprintf=_snprintf")
#pragma comment(linker, "/alternatename:vsnprintf=_vsnprintf")
DECLARE_ALTERNATE_NAME (snprintf, _snprintf);
DECLARE_ALTERNATE_NAME (vsnprintf, _vsnprintf);

// VS2013- implements these functions as macros, VS2015+ provides symbols

#pragma comment(linker, "/alternatename:_fputc_nolock=_msvc_fputc_nolock")
#pragma comment(linker, "/alternatename:_fgetc_nolock=_msvc_fgetc_nolock")
#pragma comment(linker, "/alternatename:rewind=_msvc_rewind")
#pragma comment(linker, "/alternatename:clearerr=_msvc_clearerr")
#pragma comment(linker, "/alternatename:feof=_msvc_feof")
#pragma comment(linker, "/alternatename:ferror=_msvc_ferror")
#pragma comment(linker, "/alternatename:fileno=_msvc_fileno")
DECLARE_ALTERNATE_NAME (_fputc_nolock, _msvc_fputc_nolock);
DECLARE_ALTERNATE_NAME (_fgetc_nolock, _msvc_fgetc_nolock);
DECLARE_ALTERNATE_NAME (rewind, _msvc_rewind);
DECLARE_ALTERNATE_NAME (clearerr, _msvc_clearerr);
DECLARE_ALTERNATE_NAME (feof, _msvc_feof);
DECLARE_ALTERNATE_NAME (ferror, _msvc_ferror);
DECLARE_ALTERNATE_NAME (fileno, _msvc_fileno);

// VS2013- helper functions
int _filbuf(FILE* fp);
int _flsbuf(int c, FILE* fp);

#pragma comment(linker, "/alternatename:_filbuf=_nullfunc")
#pragma comment(linker, "/alternatename:_flsbuf=_nullfunc")
DECLARE_ALTERNATE_NAME(_filbuf, _nullfunc);
DECLARE_ALTERNATE_NAME(_flsbuf, _nullfunc);

int _msvc_fputc_nolock(int c, FILE* fp)
{
Expand Down