Skip to content

Commit

Permalink
Merge pull request #4723 from WalterBright/pragmainline
Browse files Browse the repository at this point in the history
DIP56: add pragma(inline)
  • Loading branch information
andralex committed Jun 8, 2015
2 parents a606581 + 24e4d73 commit 4e5a31e
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 14 deletions.
61 changes: 54 additions & 7 deletions src/attrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "parse.h"
#include "template.h"
#include "utf.h"
#include "mtype.h"


/********************************* AttribDeclaration ****************************/
Expand Down Expand Up @@ -71,14 +72,15 @@ int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
*/
Scope *AttribDeclaration::createNewScope(Scope *sc,
StorageClass stc, LINK linkage, Prot protection, int explicitProtection,
structalign_t structalign)
structalign_t structalign, PINLINE inlining)
{
Scope *sc2 = sc;
if (stc != sc->stc ||
linkage != sc->linkage ||
!protection.isSubsetOf(sc->protection) ||
explicitProtection != sc->explicitProtection ||
structalign != sc->structalign)
structalign != sc->structalign ||
inlining != sc->inlining)
{
// create new one for changes
sc2 = sc->copy();
Expand All @@ -87,6 +89,7 @@ Scope *AttribDeclaration::createNewScope(Scope *sc,
sc2->protection = protection;
sc2->explicitProtection = explicitProtection;
sc2->structalign = structalign;
sc2->inlining = inlining;
}
return sc2;
}
Expand Down Expand Up @@ -388,7 +391,7 @@ Scope *StorageClassDeclaration::newScope(Scope *sc)
scstc |= stc;
//printf("scstc = x%llx\n", scstc);

return createNewScope(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
return createNewScope(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign, sc->inlining);
}

/*************************************************
Expand Down Expand Up @@ -527,7 +530,7 @@ Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)

Scope *LinkDeclaration::newScope(Scope *sc)
{
return createNewScope(sc, sc->stc, this->linkage, sc->protection, sc->explicitProtection, sc->structalign);
return createNewScope(sc, sc->stc, this->linkage, sc->protection, sc->explicitProtection, sc->structalign, sc->inlining);
}

char *LinkDeclaration::toChars()
Expand Down Expand Up @@ -580,7 +583,7 @@ Scope *ProtDeclaration::newScope(Scope *sc)
{
if (pkg_identifiers)
semantic(sc);
return createNewScope(sc, sc->stc, sc->linkage, this->protection, 1, sc->structalign);
return createNewScope(sc, sc->stc, sc->linkage, this->protection, 1, sc->structalign, sc->inlining);
}

void ProtDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
Expand Down Expand Up @@ -637,7 +640,7 @@ Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)

Scope *AlignDeclaration::newScope(Scope *sc)
{
return createNewScope(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, this->salign);
return createNewScope(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, this->salign, sc->inlining);
}

/********************************* AnonDeclaration ****************************/
Expand Down Expand Up @@ -786,8 +789,48 @@ Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
Dsymbol::arraySyntaxCopy(decl));
}

void PragmaDeclaration::setScope(Scope *sc)
Scope *PragmaDeclaration::newScope(Scope *sc)
{
if (ident == Id::Pinline)
{
PINLINE inlining = PINLINEdefault;
if (!args || args->dim == 0)
inlining = PINLINEdefault;
else if (args->dim != 1)
{
error("one boolean expression expected for pragma(inline), not %d", args->dim);
args->setDim(1);
(*args)[0] = new ErrorExp();
}
else
{
Expression *e = (*args)[0];

if (e->op != TOKint64 || !e->type->equals(Type::tbool))
{
if (e->op != TOKerror)
{
error("pragma(inline, true or false) expected, not %s", e->toChars());
(*args)[0] = new ErrorExp();
}
}
else if (e->isBool(true))
inlining = PINLINEalways;
else if (e->isBool(false))
inlining = PINLINEnever;
}

if (decl)
{
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = (*decl)[i];
s->semantic(sc);
}
}
return createNewScope(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign, inlining);
}
return sc;
}

static unsigned setMangleOverride(Dsymbol *s, char *sym)
Expand Down Expand Up @@ -918,6 +961,10 @@ void PragmaDeclaration::semantic(Scope *sc)
}
goto Lnodecl;
}
else if (ident == Id::Pinline)
{
goto Ldecl;
}
else if (ident == Id::mangle)
{
if (!args)
Expand Down
4 changes: 2 additions & 2 deletions src/attrib.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class AttribDeclaration : public Dsymbol
int apply(Dsymbol_apply_ft_t fp, void *param);
static Scope *createNewScope(Scope *sc,
StorageClass newstc, LINK linkage, Prot protection, int explictProtection,
structalign_t structalign);
structalign_t structalign, PINLINE inlining);
virtual Scope *newScope(Scope *sc);
void addMember(Scope *sc, ScopeDsymbol *sds);
void setScope(Scope *sc);
Expand Down Expand Up @@ -147,7 +147,7 @@ class PragmaDeclaration : public AttribDeclaration
PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void setScope(Scope *sc);
Scope *newScope(Scope *sc);
const char *kind();
void accept(Visitor *v) { v->visit(this); }
};
Expand Down
4 changes: 3 additions & 1 deletion src/declaration.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/* Compiler implementation of the D programming language
* Copyright (c) 1999-2014 by Digital Mars
* Copyright (c) 1999-2015 by Digital Mars
* All Rights Reserved
* written by Walter Bright
* http://www.digitalmars.com
Expand Down Expand Up @@ -35,6 +35,7 @@ enum LINK;
enum TOK;
enum MATCH;
enum PURE;
enum PINLINE;

#define STCundefined 0LL
#define STCstatic 1LL
Expand Down Expand Up @@ -537,6 +538,7 @@ class FuncDeclaration : public Declaration
bool naked; // true if naked
ILS inlineStatusStmt;
ILS inlineStatusExp;
PINLINE inlining;

CompiledCtfeFunction *ctfeCode; // Compiled code for interpreter
int inlineNest; // !=0 if nested inline
Expand Down
2 changes: 2 additions & 0 deletions src/func.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
naked = false;
inlineStatusExp = ILSuninitialized;
inlineStatusStmt = ILSuninitialized;
inlining = PINLINEdefault;
inlineNest = 0;
ctfeCode = NULL;
isArrayOp = 0;
Expand Down Expand Up @@ -425,6 +426,7 @@ void FuncDeclaration::semantic(Scope *sc)
}
else
linkage = sc->linkage;
inlining = sc->inlining;
protection = sc->protection;
userAttribDecl = sc->userAttribDecl;

Expand Down
7 changes: 7 additions & 0 deletions src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,13 @@ enum MATCH
MATCHexact // exact match
};

enum PINLINE
{
PINLINEdefault, // as specified on the command line
PINLINEnever, // never inline
PINLINEalways // always inline
};

typedef uinteger_t StorageClass;

#endif /* DMD_GLOBALS_H */
3 changes: 2 additions & 1 deletion src/idgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,11 @@ Msgtable[] msgtable =
{ "_ArrayEq" },

// For pragma's
{ "Pinline", "inline" },
{ "lib" },
{ "mangle" },
{ "msg" },
{ "startaddress" },
{ "mangle" },

// For special functions
{ "tohash", "toHash" },
Expand Down
17 changes: 17 additions & 0 deletions src/inline.c
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,20 @@ bool canInline(FuncDeclaration *fd, int hasthis, int hdrscan, int statementsToo)
assert(0);
}

switch (fd->inlining)
{
case PINLINEdefault:
break;

case PINLINEalways:
break;

case PINLINEnever:
return false;
default:
assert(0);
}

if (fd->type)
{
assert(fd->type->ty == Tfunction);
Expand Down Expand Up @@ -1786,6 +1800,9 @@ bool canInline(FuncDeclaration *fd, int hasthis, int hdrscan, int statementsToo)
return true;

Lno:
if (fd->inlining == PINLINEalways)
fd->error("cannot inline function");

if (!hdrscan) // Don't modify inlineStatus for header content scan
{
if (statementsToo)
Expand Down
3 changes: 3 additions & 0 deletions src/magicport.json
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,7 @@
"id",
"identifier",
"dinterpret",
"mtype",
"tokens",
"globals",
"mars",
Expand Down Expand Up @@ -2609,6 +2610,7 @@
"enum LINK",
"enum DYNCAST",
"enum MATCH",
"enum PINLINE",
"typedef StorageClass",
"variable global"
]
Expand Down Expand Up @@ -3288,6 +3290,7 @@
"OwnedBy",

"LINK",
"PINLINE",
"PREC",
"BUILTIN",
"PASS",
Expand Down
2 changes: 2 additions & 0 deletions src/scope.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Scope::Scope()
this->func = NULL;
this->slabel = NULL;
this->linkage = LINKd;
this->inlining = PINLINEdefault;
this->protection = Prot(PROTpublic);
this->explicitProtection = 0;
this->stc = 0;
Expand Down Expand Up @@ -108,6 +109,7 @@ Scope *Scope::createGlobal(Module *module)

sc->structalign = STRUCTALIGN_DEFAULT;
sc->linkage = LINKd;
sc->inlining = PINLINEdefault;
sc->protection = Prot(PROTpublic);

sc->module = module;
Expand Down
8 changes: 5 additions & 3 deletions src/scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class TemplateInstance;
#include "mars.h"
#else
enum LINK;
enum PINLINE;
#endif

#define CSXthis_ctor 1 // called this()
Expand Down Expand Up @@ -104,10 +105,11 @@ struct Scope
unsigned *fieldinit;
size_t fieldinit_dim;

structalign_t structalign; // alignment for struct members
LINK linkage; // linkage for external functions
structalign_t structalign; // alignment for struct members
LINK linkage; // linkage for external functions
PINLINE inlining; // inlining strategy for functions

Prot protection; // protection for class members
Prot protection; // protection for class members
int explicitProtection; // set if in an explicit protection attribute

StorageClass stc; // storage class
Expand Down
34 changes: 34 additions & 0 deletions src/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -3206,6 +3206,40 @@ Statement *PragmaStatement::semantic(Scope *sc)
return this;
}
}
else if (ident == Id::Pinline)
{
PINLINE inlining = PINLINEdefault;
if (!args || args->dim == 0)
inlining = PINLINEdefault;
else if (!args || args->dim != 1)
{
error("boolean expression expected for pragma(inline)");
goto Lerror;
}
else
{
Expression *e = (*args)[0];

if (e->op != TOKint64 || !e->type->equals(Type::tbool))
{
error("pragma(inline, true or false) expected, not %s", e->toChars());
goto Lerror;
}

if (e->isBool(true))
inlining = PINLINEalways;
else if (e->isBool(false))
inlining = PINLINEnever;

FuncDeclaration *fd = sc->func;
if (!fd)
{
error("pragma(inline) is not inside a function");
goto Lerror;
}
fd->inlining = inlining;
}
}
else
{
error("unrecognized pragma(%s)", ident->toChars());
Expand Down
11 changes: 11 additions & 0 deletions test/fail_compilation/pragmainline.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
TEST_OUTPUT:
---
fail_compilation/pragmainline.d(9): Error: pragma inline one boolean expression expected for pragma(inline), not 3
fail_compilation/pragmainline.d(10): Error: pragma inline pragma(inline, true or false) expected, not "string"
---
*/

pragma(inline, 1,2,3) void bar();
pragma(inline, "string") void baz();

24 changes: 24 additions & 0 deletions test/fail_compilation/pragmainline2.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
REQUIRED_ARGS: -inline
TEST_OUTPUT:
---
fail_compilation/pragmainline2.d(12): Error: function pragmainline2.foo cannot inline function
---
*/

pragma(inline, true):
pragma(inline, false):
pragma(inline)
void foo()
{
pragma(inline, false);
pragma(inline);
pragma(inline, true);
while (0) { }
}

void main()
{
foo();
}

0 comments on commit 4e5a31e

Please sign in to comment.