diff --git a/dmd/attrib.c b/dmd/attrib.c index d839a671..c7f08770 100644 --- a/dmd/attrib.c +++ b/dmd/attrib.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -29,16 +29,8 @@ #if TARGET_NET #include "frontend.net/pragma.h" #endif - #if IN_LLVM -#include "../gen/enums.h" - -#include "llvm/Support/CommandLine.h" - -static llvm::cl::opt ignoreUnsupportedPragmas("ignore", - llvm::cl::desc("Ignore unsupported pragmas"), - llvm::cl::ZeroOrMore); - +#include "../gen/pragma.h" #endif @@ -51,13 +43,13 @@ void obj_startaddress(Symbol *s); /********************************* AttribDeclaration ****************************/ -AttribDeclaration::AttribDeclaration(Dsymbols *decl) +AttribDeclaration::AttribDeclaration(Dsymbols *decl) : Dsymbol() { this->decl = decl; } -Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) +Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) { return decl; } @@ -65,13 +57,13 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { int m = 0; - Dsymbols *d = include(sc, sd); + Dsymbols *d = include(sc, sd); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; - //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars()); + { Dsymbol *s = d->tdata()[i]; + //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars()); m |= s->addMember(sc, sd, m | memnum); } } @@ -101,7 +93,7 @@ void AttribDeclaration::setScopeNewSc(Scope *sc, newsc->structalign = structalign; } for (unsigned i = 0; i < decl->dim; i++) - { Dsymbol *s = decl->tdata()[i]; + { Dsymbol *s = decl->tdata()[i]; s->setScope(newsc); // yes, the only difference from semanticNewSc() } @@ -136,7 +128,7 @@ void AttribDeclaration::semanticNewSc(Scope *sc, newsc->structalign = structalign; } for (unsigned i = 0; i < decl->dim; i++) - { Dsymbol *s = decl->tdata()[i]; + { Dsymbol *s = decl->tdata()[i]; s->semantic(newsc); } @@ -150,14 +142,14 @@ void AttribDeclaration::semanticNewSc(Scope *sc, void AttribDeclaration::semantic(Scope *sc) { - Dsymbols *d = include(sc, NULL); + Dsymbols *d = include(sc, NULL); //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d); if (d) { - for (size_t i = 0; i < d->dim; i++) + for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = d->tdata()[i]; s->semantic(sc); } @@ -166,12 +158,12 @@ void AttribDeclaration::semantic(Scope *sc) void AttribDeclaration::semantic2(Scope *sc) { - Dsymbols *d = include(sc, NULL); + Dsymbols *d = include(sc, NULL); if (d) { - for (size_t i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = d->tdata()[i]; s->semantic2(sc); } } @@ -179,12 +171,12 @@ void AttribDeclaration::semantic2(Scope *sc) void AttribDeclaration::semantic3(Scope *sc) { - Dsymbols *d = include(sc, NULL); + Dsymbols *d = include(sc, NULL); if (d) { - for (size_t i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = d->tdata()[i]; s->semantic3(sc); } } @@ -192,12 +184,12 @@ void AttribDeclaration::semantic3(Scope *sc) void AttribDeclaration::inlineScan() { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; //printf("AttribDeclaration::inlineScan %s\n", s->toChars()); s->inlineScan(); } @@ -206,15 +198,15 @@ void AttribDeclaration::inlineScan() void AttribDeclaration::addComment(unsigned char *comment) { - //printf("AttribDeclaration::addComment %s\n", comment); + //printf("AttribDeclaration::addComment %s\n", comment); if (comment) { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; //printf("AttribDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } @@ -234,12 +226,12 @@ void AttribDeclaration::emitComment(Scope *sc) * Hence, Ddoc omits attributes from template members. */ - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; //printf("AttribDeclaration::emitComment %s\n", s->toChars()); s->emitComment(sc); } @@ -250,12 +242,12 @@ void AttribDeclaration::emitComment(Scope *sc) void AttribDeclaration::toObjFile(int multiobj) { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; s->toObjFile(multiobj); } } @@ -265,12 +257,12 @@ int AttribDeclaration::cvMember(unsigned char *p) { int nwritten = 0; int n; - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; n = s->cvMember(p); if (p) p += n; @@ -283,13 +275,13 @@ int AttribDeclaration::cvMember(unsigned char *p) int AttribDeclaration::hasPointers() { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = d->tdata()[i]; if (s->hasPointers()) return 1; } @@ -297,22 +289,22 @@ int AttribDeclaration::hasPointers() return 0; } -bool AttribDeclaration::hasStaticCtorOrDtor() -{ - Dsymbols *d = include(NULL, NULL); - - if (d) - { - for (size_t i = 0; i < d->dim; i++) - { - Dsymbol *s = (*d)[i]; - if (s->hasStaticCtorOrDtor()) - return TRUE; - } - } - return FALSE; -} - +bool AttribDeclaration::hasStaticCtorOrDtor() +{ + Dsymbols *d = include(NULL, NULL); + + if (d) + { + for (size_t i = 0; i < d->dim; i++) + { + Dsymbol *s = (*d)[i]; + if (s->hasStaticCtorOrDtor()) + return TRUE; + } + } + return FALSE; +} + const char *AttribDeclaration::kind() { return "attribute"; @@ -320,19 +312,19 @@ const char *AttribDeclaration::kind() int AttribDeclaration::oneMember(Dsymbol **ps) { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); return Dsymbol::oneMembers(d, ps); } void AttribDeclaration::checkCtorConstInit() { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; s->checkCtorConstInit(); } } @@ -343,12 +335,12 @@ void AttribDeclaration::checkCtorConstInit() void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses) { - Dsymbols *d = include(NULL, NULL); + Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; s->addLocalClass(aclasses); } } @@ -362,7 +354,7 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (decl->dim == 0) buf->writestring("{}"); else if (decl->dim == 1) - (decl->tdata()[0])->toCBuffer(buf, hgs); + (decl->tdata()[0])->toCBuffer(buf, hgs); else { buf->writenl(); @@ -370,7 +362,7 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); for (unsigned i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = decl->tdata()[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -385,7 +377,7 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /************************* StorageClassDeclaration ****************************/ -StorageClassDeclaration::StorageClassDeclaration(StorageClass stc, Dsymbols *decl) +StorageClassDeclaration::StorageClassDeclaration(StorageClass stc, Dsymbols *decl) : AttribDeclaration(decl) { this->stc = stc; @@ -527,7 +519,7 @@ void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /********************************* LinkDeclaration ****************************/ -LinkDeclaration::LinkDeclaration(enum LINK p, Dsymbols *decl) +LinkDeclaration::LinkDeclaration(enum LINK p, Dsymbols *decl) : AttribDeclaration(decl) { //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl); @@ -570,7 +562,7 @@ void LinkDeclaration::semantic3(Scope *sc) sc->linkage = linkage; for (unsigned i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = decl->tdata()[i]; s->semantic3(sc); } @@ -613,7 +605,7 @@ char *LinkDeclaration::toChars() /********************************* ProtDeclaration ****************************/ -ProtDeclaration::ProtDeclaration(enum PROT p, Dsymbols *decl) +ProtDeclaration::ProtDeclaration(enum PROT p, Dsymbols *decl) : AttribDeclaration(decl) { protection = p; @@ -650,9 +642,9 @@ void ProtDeclaration::importAll(Scope *sc) newsc->explicitProtection = 1; } - for (size_t i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = (*decl)[i]; + Dsymbol *s = (*decl)[i]; s->importAll(newsc); } @@ -695,7 +687,7 @@ void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /********************************* AlignDeclaration ****************************/ -AlignDeclaration::AlignDeclaration(Loc loc, unsigned sa, Dsymbols *decl) +AlignDeclaration::AlignDeclaration(Loc loc, unsigned sa, Dsymbols *decl) : AttribDeclaration(decl) { this->loc = loc; @@ -739,7 +731,7 @@ void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /********************************* AnonDeclaration ****************************/ -AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl) +AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl) : AttribDeclaration(decl) { this->loc = loc; @@ -760,12 +752,12 @@ void AnonDeclaration::semantic(Scope *sc) { //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); - if (sem == 1) - { //printf("already completed\n"); - scope = NULL; - return; // semantic() already completed - } - + if (sem == 1) + { //printf("already completed\n"); + scope = NULL; + return; // semantic() already completed + } + Scope *scx = NULL; if (scope) { sc = scope; @@ -813,7 +805,7 @@ void AnonDeclaration::semantic(Scope *sc) for (unsigned i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = decl->tdata()[i]; s->semantic(sc); if (isunion) @@ -906,7 +898,7 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { for (unsigned i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = decl->tdata()[i]; //buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -936,7 +928,7 @@ static bool parseStringExp(Expression* e, std::string& res) return false; } -PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl) +PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl) : AttribDeclaration(decl) { this->loc = loc; @@ -966,16 +958,16 @@ void PragmaDeclaration::setScope(Scope *sc) } else { - Expression *e = args->tdata()[0]; + Expression *e = args->tdata()[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->tdata()[0] = e; - StringExp* se = e->toString(); - if (!se) + args->tdata()[0] = e; + StringExp* se = e->toString(); + if (!se) { error("string expected, not '%s'", e->toChars()); } - PragmaScope* pragma = new PragmaScope(this, sc->parent, se); + PragmaScope* pragma = new PragmaScope(this, sc->parent, se); assert(sc); pragma->setScope(sc); @@ -993,9 +985,8 @@ void PragmaDeclaration::semantic(Scope *sc) { // Should be merged with PragmaStatement #if IN_LLVM - int llvm_internal = 0; + Pragma llvm_internal = LLVMnone; std::string arg1str; - #endif //printf("\tPragmaDeclaration::semantic '%s'\n",toChars()); @@ -1005,12 +996,12 @@ void PragmaDeclaration::semantic(Scope *sc) { for (size_t i = 0; i < args->dim; i++) { - Expression *e = args->tdata()[i]; + Expression *e = args->tdata()[i]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - StringExp *se = e->toString(); - if (se) + StringExp *se = e->toString(); + if (se) { fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); } @@ -1027,15 +1018,15 @@ void PragmaDeclaration::semantic(Scope *sc) error("string expected for library name"); else { - Expression *e = args->tdata()[0]; + Expression *e = args->tdata()[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->tdata()[0] = e; - if (e->op == TOKerror) - goto Lnodecl; - StringExp *se = e->toString(); - if (!se) + args->tdata()[0] = e; + if (e->op == TOKerror) + goto Lnodecl; + StringExp *se = e->toString(); + if (!se) error("string expected for library name, not '%s'", e->toChars()); else if (global.params.verbose) { @@ -1070,11 +1061,11 @@ void PragmaDeclaration::semantic(Scope *sc) if (!d) error("first argument of GNU_asm must be a function or variable declaration"); - e = args->tdata()[1]; + e = args->tdata()[1]; e = e->semantic(sc); e = e->optimize(WANTvalue); - e = e->toString(); - if (e && ((StringExp *)e)->sz == 1) + e = e->toString(); + if (e && ((StringExp *)e)->sz == 1) s = ((StringExp *)e); else error("second argument of GNU_asm must be a char string"); @@ -1108,193 +1099,13 @@ void PragmaDeclaration::semantic(Scope *sc) { } #endif // TARGET_NET - -// LDC #if IN_LLVM - - // pragma(intrinsic, "string") { funcdecl(s) } - else if (ident == Id::intrinsic) + else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone) { - Expression* expr = (Expression *)args->data[0]; - expr = expr->semantic(sc); - if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) - { - error("requires exactly 1 string literal parameter"); - fatal(); - } - llvm_internal = LLVMintrinsic; + // nothing to do anymore } - - // pragma(notypeinfo) { typedecl(s) } - else if (ident == Id::no_typeinfo) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMno_typeinfo; - } - - // pragma(nomoduleinfo) ; - else if (ident == Id::no_moduleinfo) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMno_moduleinfo; - } - - // pragma(alloca) { funcdecl(s) } - else if (ident == Id::Alloca) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMalloca; - } - - // pragma(va_start) { templdecl(s) } - else if (ident == Id::vastart) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_start; - } - - // pragma(va_copy) { funcdecl(s) } - else if (ident == Id::vacopy) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_copy; - } - - // pragma(va_end) { funcdecl(s) } - else if (ident == Id::vaend) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_end; - } - - // pragma(va_arg) { templdecl(s) } - else if (ident == Id::vaarg) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_arg; - } - - // pragma(fence) { templdecl(s) } - else if (ident == Id::fence) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMfence; - } - - // pragma(atomic_load) { templdecl(s) } - else if (ident == Id::atomic_load) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMatomic_load; - } - - // pragma(atomic_store) { templdecl(s) } - else if (ident == Id::atomic_store) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMatomic_store; - } - - // pragma(atomic_cmp_xchg) { templdecl(s) } - else if (ident == Id::atomic_cmp_xchg) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMatomic_cmp_xchg; - } - - // pragma(atomic_rmw, "string") { templdecl(s) } - else if (ident == Id::atomic_rmw) - { - Expression* expr = (Expression *)args->data[0]; - expr = expr->semantic(sc); - if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) - { - error("requires exactly 1 string literal parameter"); - fatal(); - } - llvm_internal = LLVMatomic_rmw; - } - - // pragma(ldc, "string") { templdecl(s) } - else if (ident == Id::ldc) - { - Expression* expr = (Expression *)args->data[0]; - expr = expr->semantic(sc); - if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) - { - error("requires exactly 1 string literal parameter"); - fatal(); - } - else if (arg1str == "verbose") - { - sc->module->llvmForceLogging = true; - } - else - { - error("command '%s' invalid", expr->toChars()); - fatal(); - } - } - - // pragma(llvm_inline_asm) { templdecl(s) } - else if (ident == Id::llvm_inline_asm) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMinline_asm; - } - -#endif // LDC - - - else if (ignoreUnsupportedPragmas) +#endif + else if (global.params.ignoreUnsupportedPragmas) { if (global.params.verbose) { @@ -1335,146 +1146,14 @@ void PragmaDeclaration::semantic(Scope *sc) { for (unsigned i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = decl->tdata()[i]; s->semantic(sc); -// LDC #if IN_LLVM - - if (llvm_internal) - { - if (s->llvmInternal) - { - error("multiple LDC specific pragmas not allowed not affect the same declaration ('%s' at '%s')", s->toChars(), s->loc.toChars()); - fatal(); + DtoCheckPragma(this, s, llvm_internal, arg1str); +#endif } - switch(llvm_internal) - { - case LLVMintrinsic: - if (FuncDeclaration* fd = s->isFuncDeclaration()) - { - fd->llvmInternal = llvm_internal; - fd->intrinsicName = arg1str; - fd->linkage = LINKintrinsic; - ((TypeFunction*)fd->type)->linkage = LINKintrinsic; - } - else if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - td->llvmInternal = llvm_internal; - td->intrinsicName = arg1str; - } - else - { - error("only allowed on function declarations"); - fatal(); - } - break; - - case LLVMatomic_rmw: - if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - td->llvmInternal = llvm_internal; - td->intrinsicName = arg1str; - } - else - { - error("the '%s' pragma is only allowed on template declarations", ident->toChars()); - fatal(); - } - break; - - case LLVMva_start: - case LLVMva_arg: - case LLVMatomic_load: - case LLVMatomic_store: - case LLVMatomic_cmp_xchg: - if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - if (td->parameters->dim != 1) - { - error("the '%s' pragma template must have exactly one template parameter", ident->toChars()); - fatal(); - } - else if (!td->onemember) - { - error("the '%s' pragma template must have exactly one member", ident->toChars()); - fatal(); - } - else if (td->overnext || td->overroot) - { - error("the '%s' pragma template must not be overloaded", ident->toChars()); - fatal(); - } - td->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma is only allowed on template declarations", ident->toChars()); - fatal(); - } - break; - - case LLVMva_copy: - case LLVMva_end: - case LLVMfence: - if (FuncDeclaration* fd = s->isFuncDeclaration()) - { - fd->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma is only allowed on function declarations", ident->toChars()); - fatal(); - } - break; - - case LLVMno_typeinfo: - s->llvmInternal = llvm_internal; - break; - - case LLVMalloca: - if (FuncDeclaration* fd = s->isFuncDeclaration()) - { - fd->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars()); - fatal(); - } - break; - - case LLVMinline_asm: - if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - if (td->parameters->dim > 1) - { - error("the '%s' pragma template must have exactly zero or one template parameters", ident->toChars()); - fatal(); - } - else if (!td->onemember) - { - error("the '%s' pragma template must have exactly one member", ident->toChars()); - fatal(); - } - td->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma is only allowed on template declarations", ident->toChars()); - fatal(); - } - break; - - default: - warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars()); - } - } - -#endif // LDC - - } } return; @@ -1520,7 +1199,7 @@ void PragmaDeclaration::toObjFile(int multiobj) * so instead append the library name to the list to be passed * to the linker. */ - global.params.libfiles->push(name); + global.params.libfiles->push(name); #else error("pragma lib not supported"); #endif @@ -1561,7 +1240,7 @@ void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /********************************* ConditionalDeclaration ****************************/ -ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl) +ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl) : AttribDeclaration(decl) { //printf("ConditionalDeclaration::ConditionalDeclaration()\n"); @@ -1586,7 +1265,7 @@ int ConditionalDeclaration::oneMember(Dsymbol **ps) //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc); if (condition->inc) { - Dsymbols *d = condition->include(NULL, NULL) ? decl : elsedecl; + Dsymbols *d = condition->include(NULL, NULL) ? decl : elsedecl; return Dsymbol::oneMembers(d, ps); } *ps = NULL; @@ -1605,9 +1284,9 @@ void ConditionalDeclaration::emitComment(Scope *sc) /* If generating doc comment, be careful because if we're inside * a template, then include(NULL, NULL) will fail. */ - Dsymbols *d = decl ? decl : elsedecl; + Dsymbols *d = decl ? decl : elsedecl; for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = d->tdata()[i]; s->emitComment(sc); } } @@ -1615,7 +1294,7 @@ void ConditionalDeclaration::emitComment(Scope *sc) // Decide if 'then' or 'else' code should be included -Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) +Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) { //printf("ConditionalDeclaration::include()\n"); assert(condition); @@ -1624,14 +1303,14 @@ Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) void ConditionalDeclaration::setScope(Scope *sc) { - Dsymbols *d = include(sc, NULL); + Dsymbols *d = include(sc, NULL); //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d); if (d) { for (unsigned i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = d->tdata()[i]; s->setScope(sc); } @@ -1640,14 +1319,14 @@ void ConditionalDeclaration::setScope(Scope *sc) void ConditionalDeclaration::importAll(Scope *sc) { - Dsymbols *d = include(sc, NULL); + Dsymbols *d = include(sc, NULL); //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d); if (d) { for (unsigned i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = d->tdata()[i]; s->importAll(sc); } @@ -1664,7 +1343,7 @@ void ConditionalDeclaration::addComment(unsigned char *comment) if (comment) { - Dsymbols *d = decl; + Dsymbols *d = decl; for (int j = 0; j < 2; j++) { @@ -1673,7 +1352,7 @@ void ConditionalDeclaration::addComment(unsigned char *comment) for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s; - s = d->tdata()[i]; + s = d->tdata()[i]; //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } @@ -1695,7 +1374,7 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { for (unsigned i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = decl->tdata()[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -1711,7 +1390,7 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); for (unsigned i = 0; i < elsedecl->dim; i++) { - Dsymbol *s = elsedecl->tdata()[i]; + Dsymbol *s = elsedecl->tdata()[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -1727,7 +1406,7 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /***************************** StaticIfDeclaration ****************************/ StaticIfDeclaration::StaticIfDeclaration(Condition *condition, - Dsymbols *decl, Dsymbols *elsedecl) + Dsymbols *decl, Dsymbols *elsedecl) : ConditionalDeclaration(condition, decl, elsedecl) { //printf("StaticIfDeclaration::StaticIfDeclaration()\n"); @@ -1785,7 +1464,7 @@ void StaticIfDeclaration::setScope(Scope *sc) void StaticIfDeclaration::semantic(Scope *sc) { - Dsymbols *d = include(sc, sd); + Dsymbols *d = include(sc, sd); //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); if (d) @@ -1797,7 +1476,7 @@ void StaticIfDeclaration::semantic(Scope *sc) for (unsigned i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = d->tdata()[i]; s->semantic(sc); } @@ -1849,8 +1528,8 @@ void CompileDeclaration::compileIt(Scope *sc) exp = exp->semantic(sc); exp = resolveProperties(sc, exp); exp = exp->optimize(WANTvalue | WANTinterpret); - StringExp *se = exp->toString(); - if (!se) + StringExp *se = exp->toString(); + if (!se) { exp->error("argument to mixin must be a string, not (%s)", exp->toChars()); } else diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index ac3ba4cc..2e4cc726 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -32,7 +32,7 @@ #include "template.h" #include "attrib.h" #if IN_LLVM -#include "../gen/enums.h" +#include "../gen/pragma.h" #endif /****************************** Dsymbol ******************************/ diff --git a/dmd/mars.h b/dmd/mars.h index f02a821a..2f2bd4f3 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -29,7 +29,7 @@ Macros defined by the compiler, not the code: __DMC__ Digital Mars compiler _MSC_VER Microsoft compiler __GNUC__ Gnu compiler - __clang__ Clang compiler + __clang__ Clang compiler Host operating system: _WIN32 Microsoft NT, Windows 95, Windows 98, Win32s, @@ -38,7 +38,7 @@ Macros defined by the compiler, not the code: linux Linux __APPLE__ Mac OSX __FreeBSD__ FreeBSD - __OpenBSD__ OpenBSD + __OpenBSD__ OpenBSD __sun&&__SVR4 Solaris, OpenSolaris (yes, both macros are necessary) For the target systems, there are the target operating system and @@ -49,7 +49,7 @@ the target object file format: TARGET_LINUX Covers 32 and 64 bit linux TARGET_OSX Covers 32 and 64 bit Mac OSX TARGET_FREEBSD Covers 32 and 64 bit FreeBSD - TARGET_OPENBSD Covers 32 and 64 bit OpenBSD + TARGET_OPENBSD Covers 32 and 64 bit OpenBSD TARGET_SOLARIS Covers 32 and 64 bit Solaris TARGET_NET Covers .Net @@ -58,7 +58,7 @@ the target object file format: Target object module format: OMFOBJ Intel Object Module Format, used on Windows - ELFOBJ Elf Object Module Format, used on linux, FreeBSD, OpenBSD and Solaris + ELFOBJ Elf Object Module Format, used on linux, FreeBSD, OpenBSD and Solaris MACHOBJ Mach-O Object Module Format, used on Mac OSX There are currently no macros for byte endianness order. @@ -84,20 +84,20 @@ the target object file format: #ifndef IS_PRINTF # ifdef __GNUC__ -# define IS_PRINTF(FMTARG) __attribute__((__format__ (__printf__, (FMTARG), (FMTARG)+1) )) +# define IS_PRINTF(FMTARG) __attribute__((__format__ (__printf__, (FMTARG), (FMTARG)+1) )) # else # define IS_PRINTF(FMTARG) # endif #endif -#ifndef IS_VPRINTF -# ifdef __GNUC__ -# define IS_VPRINTF(FMTARG) __attribute__((__format__ (__printf__, (FMTARG), 0) )) -# else -# define IS_VPRINTF(FMTARG) -# endif -#endif - +#ifndef IS_VPRINTF +# ifdef __GNUC__ +# define IS_VPRINTF(FMTARG) __attribute__((__format__ (__printf__, (FMTARG), 0) )) +# else +# define IS_VPRINTF(FMTARG) +# endif +#endif + #ifdef IN_GCC /* Changes for the GDC compiler by David Friedman */ #endif @@ -110,23 +110,23 @@ the target object file format: #define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class // Set if C++ mangling is done by the front end -#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS)) +#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS)) -/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD, TARGET_OPENBSD and +/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD, TARGET_OPENBSD and * TARGET_SOLARIS, which are * set on the command line via the compiler makefile. */ #if _WIN32 -#ifndef TARGET_WINDOS +#ifndef TARGET_WINDOS #define TARGET_WINDOS 1 // Windows dmd generates Windows targets -#endif -#ifndef OMFOBJ -#define OMFOBJ TARGET_WINDOS -#endif +#endif +#ifndef OMFOBJ +#define OMFOBJ TARGET_WINDOS +#endif #endif -#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS +#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS #ifndef ELFOBJ #define ELFOBJ 1 #endif @@ -172,11 +172,11 @@ enum OS typedef unsigned char ubyte; -// Can't include arraytypes.h here, need to declare these directly. -template struct ArrayBase; -//typedef ArrayBase Identifiers; -typedef ArrayBase Strings; - +// Can't include arraytypes.h here, need to declare these directly. +template struct ArrayBase; +//typedef ArrayBase Identifiers; +typedef ArrayBase Strings; + // Put command line switches in here struct Param { @@ -190,7 +190,7 @@ struct Param char optimizeLevel; // optimization level #endif char vtls; // identify thread local variables -// KN Start merge conflict +// KN Start merge conflict ARCH cpu; // target CPU OS os; // target OS bool is64bit; // generate 64 bit code @@ -205,52 +205,53 @@ struct Param bool useUnitTests; // generate unittest code bool useInline; // inline expand functions ubyte warnings; // enable warnings - ubyte Dversion; // D version number -// KN End merge conflict -#if 0 - char symdebug; // insert debug symbolic information - char alwaysframe; // always emit standard stack frame - char optimize; // run optimizer - char map; // generate linker .map file - char cpu; // target CPU - char is64bit; // generate 64 bit code - char isLinux; // generate code for linux - char isOSX; // generate code for Mac OSX - char isWindows; // generate code for Windows - char isFreeBSD; // generate code for FreeBSD - char isOPenBSD; // generate code for OpenBSD - char isSolaris; // generate code for Solaris - char scheduler; // which scheduler to use - char useDeprecated; // allow use of deprecated features - char useAssert; // generate runtime code for assert()'s - char useInvariants; // generate class invariant checks - char useIn; // generate precondition checks - char useOut; // generate postcondition checks - char useArrayBounds; // 0: no array bounds checks - // 1: array bounds checks for safe functions only - // 2: array bounds checks for all functions - char noboundscheck; // no array bounds checking at all - char useSwitchError; // check for switches without a default - char useUnitTests; // generate unittest code - char useInline; // inline expand functions - char release; // build release version - char preservePaths; // !=0 means don't strip path from source file - char warnings; // 0: enable warnings -#endif +// KN End merge conflict +#if 0 + char symdebug; // insert debug symbolic information + char alwaysframe; // always emit standard stack frame + char optimize; // run optimizer + char map; // generate linker .map file + char cpu; // target CPU + char is64bit; // generate 64 bit code + char isLinux; // generate code for linux + char isOSX; // generate code for Mac OSX + char isWindows; // generate code for Windows + char isFreeBSD; // generate code for FreeBSD + char isOPenBSD; // generate code for OpenBSD + char isSolaris; // generate code for Solaris + char scheduler; // which scheduler to use + char useDeprecated; // allow use of deprecated features + char useAssert; // generate runtime code for assert()'s + char useInvariants; // generate class invariant checks + char useIn; // generate precondition checks + char useOut; // generate postcondition checks + char useArrayBounds; // 0: no array bounds checks + // 1: array bounds checks for safe functions only + // 2: array bounds checks for all functions + char noboundscheck; // no array bounds checking at all + char useSwitchError; // check for switches without a default + char useUnitTests; // generate unittest code + char useInline; // inline expand functions + char release; // build release version + char preservePaths; // !=0 means don't strip path from source file + char warnings; // 0: enable warnings +#endif // 1: warnings as errors // 2: informational warnings (no errors) + ubyte Dversion; // D version number + bool ignoreUnsupportedPragmas; // rather than error on them char safe; // enforce safe memory model char *argv0; // program name - Strings *imppath; // array of char*'s of where to look for import modules - Strings *fileImppath; // array of char*'s of where to look for file import modules - char *objdir; // .obj/.lib file output directory + Strings *imppath; // array of char*'s of where to look for import modules + Strings *fileImppath; // array of char*'s of where to look for file import modules + char *objdir; // .obj/.lib file output directory char *objname; // .obj file output name bool doDocComments; // process embedded documentation comments char *docdir; // write documentation file to docdir directory char *docname; // write documentation file to docname - Strings *ddocfiles; // macro include files for Ddoc + Strings *ddocfiles; // macro include files for Ddoc bool doHdrGeneration; // process embedded documentation comments char *hdrdir; // write 'header' file to docdir directory @@ -260,15 +261,15 @@ struct Param char *xfilename; // write JSON file to xfilename unsigned debuglevel; // debug level - Strings *debugids; // debug identifiers + Strings *debugids; // debug identifiers unsigned versionlevel; // version level - Strings *versionids; // version identifiers + Strings *versionids; // version identifiers bool dump_source; - Strings *defaultlibnames; // default libraries for non-debug builds - Strings *debuglibnames; // default libraries for debug builds + Strings *defaultlibnames; // default libraries for non-debug builds + Strings *debuglibnames; // default libraries for debug builds char *moduleDepsFile; // filename for deps output OutBuffer *moduleDeps; // contents to be written to deps file @@ -286,9 +287,9 @@ struct Param bool run; // run resulting executable // Linker stuff - Strings *objfiles; - Strings *linkswitches; - Strings *libfiles; + Strings *objfiles; + Strings *linkswitches; + Strings *libfiles; char *deffile; char *resfile; char *exefile; @@ -332,8 +333,8 @@ struct Global const char *map_ext; // for .map files const char *copyright; const char *written; - Strings *path; // Array of char*'s which form the import lookup path - Strings *filePath; // Array of char*'s which form the file import lookup path + Strings *path; // Array of char*'s which form the import lookup path + Strings *filePath; // Array of char*'s which form the file import lookup path int structalign; const char *version; char *ldc_version; @@ -343,15 +344,15 @@ struct Global unsigned errors; // number of errors reported so far unsigned warnings; // number of warnings reported so far unsigned gag; // !=0 means gag reporting of errors & warnings - unsigned gaggedErrors; // number of errors reported while gagged - - // Start gagging. Return the current number of gagged errors - unsigned startGagging(); - - /* End gagging, restoring the old gagged state. - * Return true if errors occured while gagged. - */ - bool endGagging(unsigned oldGagged); + unsigned gaggedErrors; // number of errors reported while gagged + + // Start gagging. Return the current number of gagged errors + unsigned startGagging(); + + /* End gagging, restoring the old gagged state. + * Return true if errors occured while gagged. + */ + bool endGagging(unsigned oldGagged); Global(); }; diff --git a/dmd2/attrib.c b/dmd2/attrib.c index e3166823..c5fda17b 100644 --- a/dmd2/attrib.c +++ b/dmd2/attrib.c @@ -29,16 +29,8 @@ #if TARGET_NET #include "frontend.net/pragma.h" #endif - #if IN_LLVM -#include "../gen/enums.h" - -#include "llvm/Support/CommandLine.h" - -static llvm::cl::opt ignoreUnsupportedPragmas("ignore", - llvm::cl::desc("Ignore unsupported pragmas"), - llvm::cl::ZeroOrMore); - +#include "../gen/pragma.h" #endif @@ -944,20 +936,6 @@ const char *AnonDeclaration::kind() /********************************* PragmaDeclaration ****************************/ -static bool parseStringExp(Expression* e, std::string& res) -{ - StringExp *s = NULL; - - e = e->optimize(WANTvalue); - if (e->op == TOKstring && (s = (StringExp *)e)) - { - char* str = (char*)s->string; - res = str; - return true; - } - return false; -} - PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl) : AttribDeclaration(decl) { @@ -1015,7 +993,7 @@ void PragmaDeclaration::semantic(Scope *sc) { // Should be merged with PragmaStatement #if IN_LLVM - int llvm_internal = 0; + Pragma llvm_internal = LLVMnone; std::string arg1str; #endif @@ -1129,191 +1107,13 @@ void PragmaDeclaration::semantic(Scope *sc) { } #endif // TARGET_NET -// LDC #if IN_LLVM - - // pragma(intrinsic, "string") { funcdecl(s) } - else if (ident == Id::intrinsic) + else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone) { - Expression* expr = (Expression *)args->data[0]; - expr = expr->semantic(sc); - if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) - { - error("requires exactly 1 string literal parameter"); - fatal(); - } - llvm_internal = LLVMintrinsic; + // nothing to do anymore } - - // pragma(notypeinfo) { typedecl(s) } - else if (ident == Id::no_typeinfo) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMno_typeinfo; - } - - // pragma(nomoduleinfo) ; - else if (ident == Id::no_moduleinfo) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMno_moduleinfo; - } - - // pragma(alloca) { funcdecl(s) } - else if (ident == Id::Alloca) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMalloca; - } - - // pragma(va_start) { templdecl(s) } - else if (ident == Id::vastart) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_start; - } - - // pragma(va_copy) { funcdecl(s) } - else if (ident == Id::vacopy) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_copy; - } - - // pragma(va_end) { funcdecl(s) } - else if (ident == Id::vaend) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_end; - } - - // pragma(va_arg) { templdecl(s) } - else if (ident == Id::vaarg) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMva_arg; - } - - // pragma(fence) { templdecl(s) } - else if (ident == Id::fence) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMfence; - } - - // pragma(atomic_load) { templdecl(s) } - else if (ident == Id::atomic_load) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMatomic_load; - } - - // pragma(atomic_store) { templdecl(s) } - else if (ident == Id::atomic_store) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMatomic_store; - } - - // pragma(atomic_cmp_xchg) { templdecl(s) } - else if (ident == Id::atomic_cmp_xchg) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMatomic_cmp_xchg; - } - - // pragma(atomic_rmw, "string") { templdecl(s) } - else if (ident == Id::atomic_rmw) - { - Expression* expr = (Expression *)args->data[0]; - expr = expr->semantic(sc); - if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) - { - error("requires exactly 1 string literal parameter"); - fatal(); - } - llvm_internal = LLVMatomic_rmw; - } - - // pragma(ldc, "string") { templdecl(s) } - else if (ident == Id::ldc) - { - Expression* expr = (Expression *)args->data[0]; - expr = expr->semantic(sc); - if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) - { - error("requires exactly 1 string literal parameter"); - fatal(); - } - else if (arg1str == "verbose") - { - sc->module->llvmForceLogging = true; - } - else - { - error("command '%s' invalid", expr->toChars()); - fatal(); - } - } - - // pragma(llvm_inline_asm) { templdecl(s) } - else if (ident == Id::llvm_inline_asm) - { - if (args && args->dim > 0) - { - error("takes no parameters"); - fatal(); - } - llvm_internal = LLVMinline_asm; - } - -#endif // LDC - - else if (ignoreUnsupportedPragmas) +#endif + else if (global.params.ignoreUnsupportedPragmas) { if (global.params.verbose) { @@ -1358,142 +1158,10 @@ void PragmaDeclaration::semantic(Scope *sc) s->semantic(sc); -// LDC #if IN_LLVM - - if (llvm_internal) - { - if (s->llvmInternal) - { - error("multiple LDC specific pragmas not allowed not affect the same declaration ('%s' at '%s')", s->toChars(), s->loc.toChars()); - fatal(); + DtoCheckPragma(this, s, llvm_internal, arg1str); +#endif } - switch(llvm_internal) - { - case LLVMintrinsic: - if (FuncDeclaration* fd = s->isFuncDeclaration()) - { - fd->llvmInternal = llvm_internal; - fd->intrinsicName = arg1str; - fd->linkage = LINKintrinsic; - ((TypeFunction*)fd->type)->linkage = LINKintrinsic; - } - else if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - td->llvmInternal = llvm_internal; - td->intrinsicName = arg1str; - } - else - { - error("only allowed on function declarations"); - fatal(); - } - break; - - case LLVMatomic_rmw: - if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - td->llvmInternal = llvm_internal; - td->intrinsicName = arg1str; - } - else - { - error("the '%s' pragma is only allowed on template declarations", ident->toChars()); - fatal(); - } - break; - - case LLVMva_start: - case LLVMva_arg: - case LLVMatomic_load: - case LLVMatomic_store: - case LLVMatomic_cmp_xchg: - if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - if (td->parameters->dim != 1) - { - error("the '%s' pragma template must have exactly one template parameter", ident->toChars()); - fatal(); - } - else if (!td->onemember) - { - error("the '%s' pragma template must have exactly one member", ident->toChars()); - fatal(); - } - else if (td->overnext || td->overroot) - { - error("the '%s' pragma template must not be overloaded", ident->toChars()); - fatal(); - } - td->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma is only allowed on template declarations", ident->toChars()); - fatal(); - } - break; - - case LLVMva_copy: - case LLVMva_end: - case LLVMfence: - if (FuncDeclaration* fd = s->isFuncDeclaration()) - { - fd->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma is only allowed on function declarations", ident->toChars()); - fatal(); - } - break; - - case LLVMno_typeinfo: - s->llvmInternal = llvm_internal; - break; - - case LLVMalloca: - if (FuncDeclaration* fd = s->isFuncDeclaration()) - { - fd->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars()); - fatal(); - } - break; - - case LLVMinline_asm: - if (TemplateDeclaration* td = s->isTemplateDeclaration()) - { - if (td->parameters->dim > 1) - { - error("the '%s' pragma template must have exactly zero or one template parameters", ident->toChars()); - fatal(); - } - else if (!td->onemember) - { - error("the '%s' pragma template must have exactly one member", ident->toChars()); - fatal(); - } - td->llvmInternal = llvm_internal; - } - else - { - error("the '%s' pragma is only allowed on template declarations", ident->toChars()); - fatal(); - } - break; - - default: - warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars()); - } - } - -#endif // LDC - - } } return; diff --git a/dmd2/dsymbol.c b/dmd2/dsymbol.c index 704c7f88..f83d4f69 100644 --- a/dmd2/dsymbol.c +++ b/dmd2/dsymbol.c @@ -31,9 +31,8 @@ #include "import.h" #include "template.h" #include "attrib.h" - #if IN_LLVM -#include "../gen/enums.h" +#include "../gen/pragma.h" #endif /****************************** Dsymbol ******************************/ diff --git a/dmd2/mars.h b/dmd2/mars.h index 033a4763..9254d45c 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -206,6 +206,7 @@ struct Param bool useInline; // inline expand functions ubyte warnings; // enable warnings ubyte Dversion; // D version number + bool ignoreUnsupportedPragmas; // rather than error on them char enforcePropertySyntax; char *argv0; // program name diff --git a/gen/cl_options.cpp b/gen/cl_options.cpp index d3c0793f..6e0f6e93 100644 --- a/gen/cl_options.cpp +++ b/gen/cl_options.cpp @@ -73,6 +73,11 @@ static cl::opt warnings( cl::location(global.params.warnings), cl::init(0)); +static cl::opt ignoreUnsupportedPragmas("ignore", + cl::desc("Ignore unsupported pragmas"), + cl::ZeroOrMore, + cl::location(global.params.ignoreUnsupportedPragmas)); + static cl::opt debugInfo( cl::desc("Generating debug information:"), cl::ZeroOrMore, diff --git a/gen/enums.h b/gen/enums.h deleted file mode 100644 index 6d111c3c..00000000 --- a/gen/enums.h +++ /dev/null @@ -1,18 +0,0 @@ -enum -{ - LLVMnone, - LLVMintrinsic, - LLVMno_typeinfo, - LLVMno_moduleinfo, - LLVMalloca, - LLVMva_start, - LLVMva_copy, - LLVMva_end, - LLVMva_arg, - LLVMinline_asm, - LLVMfence, - LLVMatomic_store, - LLVMatomic_load, - LLVMatomic_cmp_xchg, - LLVMatomic_rmw -}; diff --git a/gen/functions.cpp b/gen/functions.cpp index fff942ad..72c4c342 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -24,6 +24,7 @@ #include "gen/abi.h" #include "gen/nested.h" #include "gen/cl_options.h" +#include "gen/pragma.h" using namespace llvm::Attribute; diff --git a/gen/pragma.cpp b/gen/pragma.cpp new file mode 100644 index 00000000..aacd5abe --- /dev/null +++ b/gen/pragma.cpp @@ -0,0 +1,347 @@ +#include "pragma.h" +#include "attrib.h" +#include "id.h" +#include "expression.h" +#include "scope.h" +#include "module.h" +#include "declaration.h" +#include "template.h" +#include "llvm/Support/CommandLine.h" + +static bool parseStringExp(Expression* e, std::string& res) +{ + StringExp *s = NULL; + + e = e->optimize(WANTvalue); + if (e->op == TOKstring && (s = (StringExp *)e)) + { + char* str = (char*)s->string; + res = str; + return true; + } + return false; +} + +Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str) +{ + Identifier *ident = decl->ident; + Expressions *args = decl->args; + + // pragma(intrinsic, "string") { funcdecl(s) } + if (ident == Id::intrinsic) + { + Expression* expr = (Expression *)args->data[0]; + expr = expr->semantic(sc); + if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) + { + error("requires exactly 1 string literal parameter"); + fatal(); + } + return LLVMintrinsic; + } + + // pragma(notypeinfo) { typedecl(s) } + else if (ident == Id::no_typeinfo) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMno_typeinfo; + } + + // pragma(nomoduleinfo) ; + else if (ident == Id::no_moduleinfo) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMno_moduleinfo; + } + + // pragma(alloca) { funcdecl(s) } + else if (ident == Id::Alloca) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMalloca; + } + + // pragma(va_start) { templdecl(s) } + else if (ident == Id::vastart) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMva_start; + } + + // pragma(va_copy) { funcdecl(s) } + else if (ident == Id::vacopy) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMva_copy; + } + + // pragma(va_end) { funcdecl(s) } + else if (ident == Id::vaend) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMva_end; + } + + // pragma(va_arg) { templdecl(s) } + else if (ident == Id::vaarg) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMva_arg; + } + + // pragma(fence) { funcdecl(s) } + else if (ident == Id::fence) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMfence; + } + + // pragma(atomic_load) { templdecl(s) } + else if (ident == Id::atomic_load) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMatomic_load; + } + + // pragma(atomic_store) { templdecl(s) } + else if (ident == Id::atomic_store) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMatomic_store; + } + + // pragma(atomic_cmp_xchg) { templdecl(s) } + else if (ident == Id::atomic_cmp_xchg) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMatomic_cmp_xchg; + } + + // pragma(atomic_rmw, "string") { templdecl(s) } + else if (ident == Id::atomic_rmw) + { + Expression* expr = (Expression *)args->data[0]; + expr = expr->semantic(sc); + if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) + { + error("requires exactly 1 string literal parameter"); + fatal(); + } + return LLVMatomic_rmw; + } + + // pragma(ldc, "string") { templdecl(s) } + else if (ident == Id::ldc) + { + Expression* expr = (Expression *)args->data[0]; + expr = expr->semantic(sc); + if (!args || args->dim != 1 || !parseStringExp(expr, arg1str)) + { + error("requires exactly 1 string literal parameter"); + fatal(); + } + else if (arg1str == "verbose") + { + sc->module->llvmForceLogging = true; + } + else + { + error("command '%s' invalid", expr->toChars()); + fatal(); + } + } + + // pragma(llvm_inline_asm) { templdecl(s) } + else if (ident == Id::llvm_inline_asm) + { + if (args && args->dim > 0) + { + error("takes no parameters"); + fatal(); + } + return LLVMinline_asm; + } + + return LLVMnone; +} + +void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s, + Pragma llvm_internal, const std::string &arg1str) +{ + if (llvm_internal == LLVMnone) + return; + + if (s->llvmInternal) + { + error("multiple LDC specific pragmas not allowed not affect the same declaration ('%s' at '%s')", s->toChars(), s->loc.toChars()); + fatal(); + } + + Identifier *ident = decl->ident; + + switch(llvm_internal) + { + case LLVMintrinsic: + if (FuncDeclaration* fd = s->isFuncDeclaration()) + { + fd->llvmInternal = llvm_internal; + fd->intrinsicName = arg1str; + fd->linkage = LINKintrinsic; + ((TypeFunction*)fd->type)->linkage = LINKintrinsic; + } + else if (TemplateDeclaration* td = s->isTemplateDeclaration()) + { + td->llvmInternal = llvm_internal; + td->intrinsicName = arg1str; + } + else + { + error("only allowed on function declarations"); + fatal(); + } + break; + + case LLVMatomic_rmw: + if (TemplateDeclaration* td = s->isTemplateDeclaration()) + { + td->llvmInternal = llvm_internal; + td->intrinsicName = arg1str; + } + else + { + error("the '%s' pragma is only allowed on template declarations", ident->toChars()); + fatal(); + } + break; + + case LLVMva_start: + case LLVMva_arg: + case LLVMatomic_load: + case LLVMatomic_store: + case LLVMatomic_cmp_xchg: + if (TemplateDeclaration* td = s->isTemplateDeclaration()) + { + if (td->parameters->dim != 1) + { + error("the '%s' pragma template must have exactly one template parameter", ident->toChars()); + fatal(); + } + else if (!td->onemember) + { + error("the '%s' pragma template must have exactly one member", ident->toChars()); + fatal(); + } + else if (td->overnext || td->overroot) + { + error("the '%s' pragma template must not be overloaded", ident->toChars()); + fatal(); + } + td->llvmInternal = llvm_internal; + } + else + { + error("the '%s' pragma is only allowed on template declarations", ident->toChars()); + fatal(); + } + break; + + case LLVMva_copy: + case LLVMva_end: + case LLVMfence: + if (FuncDeclaration* fd = s->isFuncDeclaration()) + { + fd->llvmInternal = llvm_internal; + } + else + { + error("the '%s' pragma is only allowed on function declarations", ident->toChars()); + fatal(); + } + break; + + case LLVMno_typeinfo: + s->llvmInternal = llvm_internal; + break; + + case LLVMalloca: + if (FuncDeclaration* fd = s->isFuncDeclaration()) + { + fd->llvmInternal = llvm_internal; + } + else + { + error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars()); + fatal(); + } + break; + + case LLVMinline_asm: + if (TemplateDeclaration* td = s->isTemplateDeclaration()) + { + if (td->parameters->dim > 1) + { + error("the '%s' pragma template must have exactly zero or one template parameters", ident->toChars()); + fatal(); + } + else if (!td->onemember) + { + error("the '%s' pragma template must have exactly one member", ident->toChars()); + fatal(); + } + td->llvmInternal = llvm_internal; + } + else + { + error("the '%s' pragma is only allowed on template declarations", ident->toChars()); + fatal(); + } + break; + + default: + warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars()); + } +} diff --git a/gen/pragma.h b/gen/pragma.h new file mode 100644 index 00000000..90119ef0 --- /dev/null +++ b/gen/pragma.h @@ -0,0 +1,33 @@ +#ifndef PRAGMA_H +#define PRAGMA_H + +#include + +struct PragmaDeclaration; +struct Dsymbol; +struct Scope; + +enum Pragma +{ + LLVMnone, + LLVMintrinsic, + LLVMno_typeinfo, + LLVMno_moduleinfo, + LLVMalloca, + LLVMva_start, + LLVMva_copy, + LLVMva_end, + LLVMva_arg, + LLVMinline_asm, + LLVMfence, + LLVMatomic_store, + LLVMatomic_load, + LLVMatomic_cmp_xchg, + LLVMatomic_rmw +}; + +Pragma DtoGetPragma(Scope *sc, PragmaDeclaration *decl, std::string &arg1str); +void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *sym, + Pragma llvm_internal, const std::string &arg1str); + +#endif // PRAGMA_H diff --git a/gen/toir.cpp b/gen/toir.cpp index 1f0d341b..cfdda25c 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -41,6 +41,7 @@ #include "gen/utils.h" #include "gen/warnings.h" #include "gen/optimizer.h" +#include "gen/pragma.h" #include "llvm/Support/ManagedStatic.h" diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 37f462b9..ed322a8b 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -20,6 +20,7 @@ #include "gen/complex.h" #include "gen/llvmhelpers.h" #include "gen/linkage.h" +#include "gen/pragma.h" #include "ir/irtype.h" #include "ir/irtypeclass.h" diff --git a/gen/tollvm.h b/gen/tollvm.h index 4826b161..2e197b3b 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -162,6 +162,4 @@ void DtoAggrCopy(LLValue* dst, LLValue* src); */ void DtoMemoryBarrier(bool ll, bool ls, bool sl, bool ss, bool device=false); -#include "enums.h" - #endif // LDC_GEN_TOLLVM_H