Refactoring: moved ldc specific code from dmd/attrib.c and dmd2/attrib.c into gen/pragma.cpp

This commit is contained in:
Alexey Prokhin
2012-02-04 14:35:12 +04:00
parent 72d510cb5e
commit 4d3ba3594c
14 changed files with 597 additions and 881 deletions

View File

@@ -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<bool> 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

View File

@@ -32,7 +32,7 @@
#include "template.h"
#include "attrib.h"
#if IN_LLVM
#include "../gen/enums.h"
#include "../gen/pragma.h"
#endif
/****************************** Dsymbol ******************************/

View File

@@ -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 <typename TYPE> struct ArrayBase;
//typedef ArrayBase<struct Identifier> Identifiers;
typedef ArrayBase<char> Strings;
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct ArrayBase;
//typedef ArrayBase<struct Identifier> Identifiers;
typedef ArrayBase<char> 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();
};

View File

@@ -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<bool> 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;

View File

@@ -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 ******************************/

View File

@@ -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

View File

@@ -73,6 +73,11 @@ static cl::opt<ubyte, true> warnings(
cl::location(global.params.warnings),
cl::init(0));
static cl::opt<bool, true> ignoreUnsupportedPragmas("ignore",
cl::desc("Ignore unsupported pragmas"),
cl::ZeroOrMore,
cl::location(global.params.ignoreUnsupportedPragmas));
static cl::opt<ubyte, true> debugInfo(
cl::desc("Generating debug information:"),
cl::ZeroOrMore,

View File

@@ -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
};

View File

@@ -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;

347
gen/pragma.cpp Normal file
View File

@@ -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());
}
}

33
gen/pragma.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef PRAGMA_H
#define PRAGMA_H
#include <string>
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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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