diff --git a/dmd/declaration.h b/dmd/declaration.h index 110a169b..1bbef094 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -853,6 +853,7 @@ struct FuncDeclaration : Declaration std::set nestedVars; std::string intrinsicName; + uint32_t priority; bool isIntrinsic(); bool isVaIntrinsic(); diff --git a/dmd/idgen.c b/dmd/idgen.c index dad04726..0374f425 100644 --- a/dmd/idgen.c +++ b/dmd/idgen.c @@ -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" }, diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 53fdfe96..7e63faa4 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -907,6 +907,7 @@ struct FuncDeclaration : Declaration std::set nestedVars; std::string intrinsicName; + uint32_t priority; bool isIntrinsic(); bool isVaIntrinsic(); diff --git a/dmd2/idgen.c b/dmd2/idgen.c index 80ad00c1..2fa2121a 100644 --- a/dmd2/idgen.c +++ b/dmd2/idgen.c @@ -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" }, diff --git a/gen/functions.cpp b/gen/functions.cpp index a0f505dc..f77bbaa6 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -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) diff --git a/gen/pragma.cpp b/gen/pragma.cpp index cff212a0..89b22ec5 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -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(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(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()) diff --git a/gen/pragma.h b/gen/pragma.h index a8b9631f..6da5dc65 100644 --- a/gen/pragma.h +++ b/gen/pragma.h @@ -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,