mirror of
https://github.com/dlang/dmd.git
synced 2025-04-29 06:30:10 +03:00
Workaround for platforms lacking crt_destructor (#13364)
Workaround for platforms lacking crt_destructor Signed-off-by: Iain Buclaw <ibuclaw@users.noreply.github.com> Signed-off-by: Razvan Nitu <RazvanN7@users.noreply.github.com> Merged-on-behalf-of: Razvan Nitu <RazvanN7@users.noreply.github.com>
This commit is contained in:
parent
dba01aec93
commit
93108bb9ea
7 changed files with 102 additions and 5 deletions
16
.cirrus.yml
16
.cirrus.yml
|
@ -82,6 +82,22 @@ task:
|
||||||
<< : *COMMON_STEPS_TEMPLATE
|
<< : *COMMON_STEPS_TEMPLATE
|
||||||
|
|
||||||
# Mac
|
# Mac
|
||||||
|
task:
|
||||||
|
name: macOS 12.x x64, $TASK_NAME_SUFFIX
|
||||||
|
osx_instance:
|
||||||
|
image: monterey-xcode
|
||||||
|
timeout_in: 60m
|
||||||
|
environment:
|
||||||
|
OS_NAME: darwin
|
||||||
|
# override Cirrus default OS (`darwin`)
|
||||||
|
OS: osx
|
||||||
|
# 12 CPU cores and 24 GB of memory are available
|
||||||
|
N: 12
|
||||||
|
matrix:
|
||||||
|
- TASK_NAME_SUFFIX: DMD (latest)
|
||||||
|
- TASK_NAME_SUFFIX: DMD (coverage)
|
||||||
|
<< : *COVERAGE_ENVIRONMENT_TEMPLATE
|
||||||
|
<< : *COMMON_STEPS_TEMPLATE
|
||||||
task:
|
task:
|
||||||
name: macOS 11.x x64, $TASK_NAME_SUFFIX
|
name: macOS 11.x x64, $TASK_NAME_SUFFIX
|
||||||
osx_instance:
|
osx_instance:
|
||||||
|
|
|
@ -238,6 +238,7 @@ Symbol *getRtlsym(RTLSYM i)
|
||||||
case RTLSYM.C__ASSERT_FAIL: symbolz(ps,FLfunc,FREGSAVED,"__assert_fail", SFLexit, t); break;
|
case RTLSYM.C__ASSERT_FAIL: symbolz(ps,FLfunc,FREGSAVED,"__assert_fail", SFLexit, t); break;
|
||||||
case RTLSYM.C__ASSERT_RTN: symbolz(ps,FLfunc,FREGSAVED,"__assert_rtn", SFLexit, t); break;
|
case RTLSYM.C__ASSERT_RTN: symbolz(ps,FLfunc,FREGSAVED,"__assert_rtn", SFLexit, t); break;
|
||||||
|
|
||||||
|
case RTLSYM.CXA_ATEXIT: symbolz(ps,FLfunc,FREGSAVED,"__cxa_atexit", 0, t); break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,9 @@ enum RTLSYM
|
||||||
C_ASSERT,
|
C_ASSERT,
|
||||||
C__ASSERT,
|
C__ASSERT,
|
||||||
C__ASSERT_FAIL,
|
C__ASSERT_FAIL,
|
||||||
C__ASSERT_RTN
|
C__ASSERT_RTN,
|
||||||
|
|
||||||
|
CXA_ATEXIT
|
||||||
}
|
}
|
||||||
|
|
||||||
extern (C++):
|
extern (C++):
|
||||||
|
|
|
@ -5031,18 +5031,21 @@ struct TargetC final
|
||||||
Gcc_Clang = 3u,
|
Gcc_Clang = 3u,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool crtDestructorsSupported;
|
||||||
uint8_t longsize;
|
uint8_t longsize;
|
||||||
uint8_t long_doublesize;
|
uint8_t long_doublesize;
|
||||||
uint8_t wchar_tsize;
|
uint8_t wchar_tsize;
|
||||||
Runtime runtime;
|
Runtime runtime;
|
||||||
BitFieldStyle bitFieldStyle;
|
BitFieldStyle bitFieldStyle;
|
||||||
TargetC() :
|
TargetC() :
|
||||||
|
crtDestructorsSupported(true),
|
||||||
longsize(),
|
longsize(),
|
||||||
long_doublesize(),
|
long_doublesize(),
|
||||||
wchar_tsize()
|
wchar_tsize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
TargetC(uint8_t longsize, uint8_t long_doublesize = 0u, uint8_t wchar_tsize = 0u, Runtime runtime = (Runtime)0u, BitFieldStyle bitFieldStyle = (BitFieldStyle)0u) :
|
TargetC(bool crtDestructorsSupported, uint8_t longsize = 0u, uint8_t long_doublesize = 0u, uint8_t wchar_tsize = 0u, Runtime runtime = (Runtime)0u, BitFieldStyle bitFieldStyle = (BitFieldStyle)0u) :
|
||||||
|
crtDestructorsSupported(crtDestructorsSupported),
|
||||||
longsize(longsize),
|
longsize(longsize),
|
||||||
long_doublesize(long_doublesize),
|
long_doublesize(long_doublesize),
|
||||||
wchar_tsize(wchar_tsize),
|
wchar_tsize(wchar_tsize),
|
||||||
|
@ -7821,7 +7824,7 @@ public:
|
||||||
RealProperties()
|
RealProperties()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Target(OS os, uint8_t osMajor = 0u, uint8_t ptrsize = 0u, uint8_t realsize = 0u, uint8_t realpad = 0u, uint8_t realalignsize = 0u, uint8_t classinfosize = 0u, uint64_t maxStaticDataSize = 0LLU, TargetC c = TargetC(0u, 0u, 0u, (TargetC::Runtime)0u, (TargetC::BitFieldStyle)0u), TargetCPP cpp = TargetCPP(false, false, false, false, (TargetCPP::Runtime)0u), TargetObjC objc = TargetObjC(false), _d_dynamicArray< const char > architectureName = {}, CPU cpu = (CPU)11u, bool is64bit = true, bool isLP64 = false, _d_dynamicArray< const char > obj_ext = {}, _d_dynamicArray< const char > lib_ext = {}, _d_dynamicArray< const char > dll_ext = {}, bool run_noext = false, bool mscoff = false, FPTypeProperties<float > FloatProperties = FPTypeProperties<float >(NAN, NAN, NAN, NAN, NAN, 0LL, 0LL, 0LL, 0LL, 0LL, 0LL), FPTypeProperties<double > DoubleProperties = FPTypeProperties<double >(NAN, NAN, NAN, NAN, NAN, 0LL, 0LL, 0LL, 0LL, 0LL, 0LL), FPTypeProperties<_d_real > RealProperties = FPTypeProperties<_d_real >(NAN, NAN, NAN, NAN, NAN, 0LL, 0LL, 0LL, 0LL, 0LL, 0LL)) :
|
Target(OS os, uint8_t osMajor = 0u, uint8_t ptrsize = 0u, uint8_t realsize = 0u, uint8_t realpad = 0u, uint8_t realalignsize = 0u, uint8_t classinfosize = 0u, uint64_t maxStaticDataSize = 0LLU, TargetC c = TargetC(true, 0u, 0u, 0u, (TargetC::Runtime)0u, (TargetC::BitFieldStyle)0u), TargetCPP cpp = TargetCPP(false, false, false, false, (TargetCPP::Runtime)0u), TargetObjC objc = TargetObjC(false), _d_dynamicArray< const char > architectureName = {}, CPU cpu = (CPU)11u, bool is64bit = true, bool isLP64 = false, _d_dynamicArray< const char > obj_ext = {}, _d_dynamicArray< const char > lib_ext = {}, _d_dynamicArray< const char > dll_ext = {}, bool run_noext = false, bool mscoff = false, FPTypeProperties<float > FloatProperties = FPTypeProperties<float >(NAN, NAN, NAN, NAN, NAN, 0LL, 0LL, 0LL, 0LL, 0LL, 0LL), FPTypeProperties<double > DoubleProperties = FPTypeProperties<double >(NAN, NAN, NAN, NAN, NAN, 0LL, 0LL, 0LL, 0LL, 0LL, 0LL), FPTypeProperties<_d_real > RealProperties = FPTypeProperties<_d_real >(NAN, NAN, NAN, NAN, NAN, 0LL, 0LL, 0LL, 0LL, 0LL, 0LL)) :
|
||||||
os(os),
|
os(os),
|
||||||
osMajor(osMajor),
|
osMajor(osMajor),
|
||||||
ptrsize(ptrsize),
|
ptrsize(ptrsize),
|
||||||
|
|
|
@ -1170,8 +1170,75 @@ void FuncDeclaration_toObjFile(FuncDeclaration fd, bool multiobj)
|
||||||
|
|
||||||
if (fd.isCrtCtorDtor & 1)
|
if (fd.isCrtCtorDtor & 1)
|
||||||
objmod.setModuleCtorDtor(s, true);
|
objmod.setModuleCtorDtor(s, true);
|
||||||
|
|
||||||
if (fd.isCrtCtorDtor & 2)
|
if (fd.isCrtCtorDtor & 2)
|
||||||
objmod.setModuleCtorDtor(s, false);
|
{
|
||||||
|
//See TargetC.initialize
|
||||||
|
if(target.c.crtDestructorsSupported)
|
||||||
|
{
|
||||||
|
objmod.setModuleCtorDtor(s, false);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
https://issues.dlang.org/show_bug.cgi?id=22520
|
||||||
|
|
||||||
|
Apple radar: https://openradar.appspot.com/FB9733712
|
||||||
|
|
||||||
|
Apple deprecated the mechanism used to implement `crt_destructor`
|
||||||
|
on MacOS Monterey. This works around that by generating a new function
|
||||||
|
(crt_destructor_thunk_NNN, run as a constructor) which registers
|
||||||
|
the destructor-to-be using __cxa_atexit()
|
||||||
|
|
||||||
|
This workaround may need a further look at when it comes to
|
||||||
|
shared library support, however there is no bridge for
|
||||||
|
that spilt milk to flow under yet.
|
||||||
|
|
||||||
|
This relies on the Itanium ABI so is portable to any
|
||||||
|
platform it, if needed.
|
||||||
|
*/
|
||||||
|
__gshared uint nthDestructor = 0;
|
||||||
|
char* buf = cast(char*) calloc(50, 1);
|
||||||
|
assert(buf);
|
||||||
|
const ret = snprintf(buf, 100, "_dmd_crt_destructor_thunk.%u", nthDestructor++);
|
||||||
|
assert(ret >= 0 && ret < 100, "snprintf either failed or overran buffer");
|
||||||
|
//Function symbol
|
||||||
|
auto newConstructor = symbol_calloc(buf);
|
||||||
|
//Build type
|
||||||
|
newConstructor.Stype = type_function(TYnfunc, [], false, type_alloc(TYvoid));
|
||||||
|
//Tell it it's supposed to be a C function. Does it do anything? Not sure.
|
||||||
|
type_setmangle(&newConstructor.Stype, mTYman_c);
|
||||||
|
symbol_func(newConstructor);
|
||||||
|
//Global SC for now.
|
||||||
|
newConstructor.Sclass = SCstatic;
|
||||||
|
func_t* funcState = newConstructor.Sfunc;
|
||||||
|
//Init start block
|
||||||
|
funcState.Fstartblock = block_calloc();
|
||||||
|
block* startBlk = funcState.Fstartblock;
|
||||||
|
//Make that block run __cxa_atexit(&func);
|
||||||
|
auto atexitSym = getRtlsym(RTLSYM.CXA_ATEXIT);
|
||||||
|
Symbol* dso_handle = symbol_calloc("__dso_handle");
|
||||||
|
dso_handle.Stype = type_fake(TYint);
|
||||||
|
//Try to get MacOS _ prefix-ism right.
|
||||||
|
type_setmangle(&dso_handle.Stype, mTYman_c);
|
||||||
|
dso_handle.Sfl = FLextern;
|
||||||
|
dso_handle.Sclass = SCextern;
|
||||||
|
dso_handle.Stype.Tcount++;
|
||||||
|
auto handlePtr = el_ptr(dso_handle);
|
||||||
|
//Build parameter pack - __cxa_atexit(&func, null, null)
|
||||||
|
auto paramPack = el_params(handlePtr, el_long(TYnptr, 0), el_ptr(s), null);
|
||||||
|
auto exec = el_bin(OPcall, TYvoid, el_var(atexitSym), paramPack);
|
||||||
|
block_appendexp(startBlk, exec); //payload
|
||||||
|
startBlk.BC = BCgoto;
|
||||||
|
auto next = block_calloc();
|
||||||
|
startBlk.appendSucc(next);
|
||||||
|
startBlk.Bnext = next;
|
||||||
|
next.BC = BCret;
|
||||||
|
//Emit in binary
|
||||||
|
writefunc(newConstructor);
|
||||||
|
//Mark as a CONSTRUCTOR because our thunk implements the destructor
|
||||||
|
objmod.setModuleCtorDtor(newConstructor, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (sd; *irs.deferToObj)
|
foreach (sd; *irs.deferToObj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1192,7 +1192,7 @@ struct TargetC
|
||||||
/// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
|
/// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
|
||||||
Gcc_Clang, /// gcc and clang
|
Gcc_Clang, /// gcc and clang
|
||||||
}
|
}
|
||||||
|
bool crtDestructorsSupported = true; /// Not all platforms support crt_destructor
|
||||||
ubyte longsize; /// size of a C `long` or `unsigned long` type
|
ubyte longsize; /// size of a C `long` or `unsigned long` type
|
||||||
ubyte long_doublesize; /// size of a C `long double`
|
ubyte long_doublesize; /// size of a C `long double`
|
||||||
ubyte wchar_tsize; /// size of a C `wchar_t` type
|
ubyte wchar_tsize; /// size of a C `wchar_t` type
|
||||||
|
@ -1245,6 +1245,13 @@ struct TargetC
|
||||||
bitFieldStyle = BitFieldStyle.Gcc_Clang;
|
bitFieldStyle = BitFieldStyle.Gcc_Clang;
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
|
/*
|
||||||
|
MacOS Monterey (12) does not support C runtime destructors.
|
||||||
|
*/
|
||||||
|
if (os == Target.OS.OSX)
|
||||||
|
{
|
||||||
|
crtDestructorsSupported = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addRuntimePredefinedGlobalIdent() const
|
void addRuntimePredefinedGlobalIdent() const
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct TargetC
|
||||||
Gcc_Clang, // gcc and clang
|
Gcc_Clang, // gcc and clang
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint8_t crtDestructorsSupported; // Not all platforms support crt_destructor
|
||||||
uint8_t longsize; // size of a C 'long' or 'unsigned long' type
|
uint8_t longsize; // size of a C 'long' or 'unsigned long' type
|
||||||
uint8_t long_doublesize; // size of a C 'long double'
|
uint8_t long_doublesize; // size of a C 'long double'
|
||||||
uint8_t wchar_tsize; // size of a C 'wchar_t' type
|
uint8_t wchar_tsize; // size of a C 'wchar_t' type
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue