Permalink
Browse files

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.
  • Loading branch information...
1 parent fd0021c commit 4ea7e8dbf8d9132b3c2a89cd2028eec66b1bac58 @redstar redstar committed Sep 12, 2012
Showing with 81 additions and 0 deletions.
  1. +1 −0 dmd/declaration.h
  2. +2 −0 dmd/idgen.c
  3. +1 −0 dmd2/declaration.h
  4. +2 −0 dmd2/idgen.c
  5. +5 −0 gen/functions.cpp
  6. +68 −0 gen/pragma.cpp
  7. +2 −0 gen/pragma.h
View
@@ -853,6 +853,7 @@ struct FuncDeclaration : Declaration
std::set<VarDeclaration*> nestedVars;
std::string intrinsicName;
+ uint32_t priority;
bool isIntrinsic();
bool isVaIntrinsic();
View
@@ -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" },
View
@@ -907,6 +907,7 @@ struct FuncDeclaration : Declaration
std::set<VarDeclaration*> nestedVars;
std::string intrinsicName;
+ uint32_t priority;
bool isIntrinsic();
bool isVaIntrinsic();
View
@@ -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" },
View
@@ -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)
View
@@ -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())
View
@@ -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,

0 comments on commit 4ea7e8d

Please sign in to comment.