mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Add pragma to install function as global C runtime ctor or dtor.
DMD has the obscure functionality to install functions starting with
_STI_ as global ctors and funtions starting with _STD_ as global
dtors. IMHO a pragma is a better way to specify the behaviour.
This commit adds pragma(LDC_global_crt_ctor) and
pragma(LDC_global_crt_dtor). If the pragma is specified on a function
or static method then an entry is made in the corresponding list. E.g.
in monitor_.d:
extern (C) {
#pragma(LDC_global_crt_ctor)
void _STI_monitor_staticctor()
{
// ...
}
}
This works on Linux without problems. On Windows with MS C Runtime
ctors work always but dtors are invoked only if linked against the
static C runtime. Dtors on Windows require at least LLVM 3.2.
This commit is contained in:
@@ -853,6 +853,7 @@ struct FuncDeclaration : Declaration
|
||||
std::set<VarDeclaration*> nestedVars;
|
||||
|
||||
std::string intrinsicName;
|
||||
uint32_t priority;
|
||||
|
||||
bool isIntrinsic();
|
||||
bool isVaIntrinsic();
|
||||
|
||||
@@ -241,6 +241,8 @@ Msgtable msgtable[] =
|
||||
{ "LDC_atomic_store" },
|
||||
{ "LDC_atomic_cmp_xchg" },
|
||||
{ "LDC_atomic_rmw" },
|
||||
{ "LDC_global_crt_ctor" },
|
||||
{ "LDC_global_crt_dtor" },
|
||||
|
||||
// Deprecated LDC pragmas lacking the vendor prefix.
|
||||
{ "intrinsic" },
|
||||
|
||||
@@ -907,6 +907,7 @@ struct FuncDeclaration : Declaration
|
||||
std::set<VarDeclaration*> nestedVars;
|
||||
|
||||
std::string intrinsicName;
|
||||
uint32_t priority;
|
||||
|
||||
bool isIntrinsic();
|
||||
bool isVaIntrinsic();
|
||||
|
||||
@@ -285,6 +285,8 @@ Msgtable msgtable[] =
|
||||
{ "LDC_atomic_store" },
|
||||
{ "LDC_atomic_cmp_xchg" },
|
||||
{ "LDC_atomic_rmw" },
|
||||
{ "LDC_global_crt_ctor" },
|
||||
{ "LDC_global_crt_dtor" },
|
||||
|
||||
// Deprecated LDC pragmas lacking the vendor prefix.
|
||||
{ "intrinsic" },
|
||||
|
||||
@@ -767,6 +767,11 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||
}
|
||||
}
|
||||
|
||||
if (fdecl->llvmInternal == LLVMglobal_crt_ctor || fdecl->llvmInternal == LLVMglobal_crt_dtor)
|
||||
{
|
||||
AppendFunctionToLLVMGlobalCtorsDtors(func, fdecl->priority, fdecl->llvmInternal == LLVMglobal_crt_ctor);
|
||||
}
|
||||
|
||||
// we never reference parameters of function prototypes
|
||||
std::string str;
|
||||
// if (!declareOnly)
|
||||
|
||||
@@ -31,6 +31,19 @@ static bool parseStringExp(Expression* e, std::string& res)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool parseIntExp(Expression* e, dinteger_t& res)
|
||||
{
|
||||
IntegerExp *i = NULL;
|
||||
|
||||
e = e->optimize(WANTvalue);
|
||||
if (e->op == TOKint64 && (i = static_cast<IntegerExp *>(e)))
|
||||
{
|
||||
res = i->value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pragmaDeprecated(Identifier* oldIdent, Identifier* newIdent)
|
||||
{
|
||||
#ifndef DMDV1
|
||||
@@ -104,6 +117,31 @@ Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str)
|
||||
return LLVMintrinsic;
|
||||
}
|
||||
|
||||
// pragma(ctor [, priority]) { funcdecl(s) }
|
||||
else if (ident == Id::LDC_global_crt_ctor || ident == Id::LDC_global_crt_dtor)
|
||||
{
|
||||
dinteger_t priority;
|
||||
if (args)
|
||||
{
|
||||
if (args->dim != 1 || !parseIntExp(expr, priority))
|
||||
{
|
||||
error("requires at most 1 integer literal parameter");
|
||||
fatal();
|
||||
}
|
||||
if (priority > 65535)
|
||||
{
|
||||
error("priority may not be greater then 65535");
|
||||
priority = 65535;
|
||||
}
|
||||
}
|
||||
else
|
||||
priority = 65535;
|
||||
char buf[8];
|
||||
sprintf(buf, "%lu", priority);
|
||||
arg1str = std::string(buf);
|
||||
return ident == Id::LDC_global_crt_ctor ? LLVMglobal_crt_ctor : LLVMglobal_crt_dtor;
|
||||
}
|
||||
|
||||
// pragma(notypeinfo) { typedecl(s) }
|
||||
else if (matchPragma(ident, Id::LDC_no_typeinfo, Id::no_typeinfo))
|
||||
{
|
||||
@@ -332,6 +370,36 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s,
|
||||
fatal();
|
||||
}
|
||||
break;
|
||||
case LLVMglobal_crt_ctor:
|
||||
case LLVMglobal_crt_dtor:
|
||||
if (FuncDeclaration* fd = s->isFuncDeclaration())
|
||||
{
|
||||
assert(fd->type->ty == Tfunction);
|
||||
TypeFunction* type = static_cast<TypeFunction*>(fd->type);
|
||||
Type* retType = type->next;
|
||||
if (retType->ty != Tvoid || type->parameters->dim > 0 || (
|
||||
#if DMDV2
|
||||
fd->isAggregateMember()
|
||||
#else
|
||||
fd->isThis()
|
||||
#endif
|
||||
&& !fd->isStatic())) {
|
||||
error(fd->loc, "the '%s' pragma is only allowed on void functions which take no arguments",
|
||||
ident->toChars());
|
||||
fd->llvmInternal = LLVMnone;
|
||||
break;
|
||||
}
|
||||
|
||||
fd->llvmInternal = llvm_internal;
|
||||
fd->priority = std::atoi(arg1str.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
error(s->loc, "the '%s' pragma is only allowed on function declarations",
|
||||
ident->toChars());
|
||||
s->llvmInternal = LLVMnone;
|
||||
}
|
||||
break;
|
||||
|
||||
case LLVMatomic_rmw:
|
||||
if (TemplateDeclaration* td = s->isTemplateDeclaration())
|
||||
|
||||
@@ -25,6 +25,8 @@ enum Pragma
|
||||
LLVMnone, // Not an LDC pragma.
|
||||
LLVMignore, // Pragma has already been processed in DtoGetPragma, ignore.
|
||||
LLVMintrinsic,
|
||||
LLVMglobal_crt_ctor,
|
||||
LLVMglobal_crt_dtor,
|
||||
LLVMno_typeinfo,
|
||||
LLVMno_moduleinfo,
|
||||
LLVMalloca,
|
||||
|
||||
Reference in New Issue
Block a user