Showing with 205 additions and 27 deletions.
  1. +1 −1 dmd2/class.c
  2. +5 −0 dmd2/declaration.h
  3. +2 −0 dmd2/dsymbol.c
  4. +3 −0 dmd2/dsymbol.h
  5. +49 −1 dmd2/func.c
  6. +0 −1 dmd2/lexer.c
  7. +1 −0 dmd2/module.c
  8. +2 −0 dmd2/module.h
  9. +1 −1 dmd2/statement.c
  10. +8 −0 dmd2/template.c
  11. +13 −16 driver/main.cpp
  12. +3 −0 gen/declarations.cpp
  13. +105 −2 gen/functions.cpp
  14. +5 −0 gen/naked.cpp
  15. +6 −4 gen/tollvm.cpp
  16. +1 −1 runtime/druntime
2 changes: 1 addition & 1 deletion dmd2/class.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (!ident) // if anonymous class
{ const char *id = "__anonclass";

ident = Identifier::generateId(id);
ident = Identifier::generateId(id, sc->parent->getUniqueIdNumber());
}

if (!sc)
Expand Down
5 changes: 5 additions & 0 deletions dmd2/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ struct FuncDeclaration : Declaration
// function with contracts.
Expressions *fdrequireParams;
Expressions *fdensureParams;
ArrayBase<Expressions> ldcAttributes;
#endif

Identifier *outId; // identifier for out statement
Expand Down Expand Up @@ -943,6 +944,8 @@ struct FuncDeclaration : Declaration
// true if overridden with the pragma(LDC_allow_inline); stmt
bool allowInlining;

bool alwaysInline;

// true if set with the pragma(LDC_never_inline); stmt
bool neverInline;

Expand Down Expand Up @@ -999,6 +1002,8 @@ struct FuncLiteralDeclaration : FuncDeclaration
// TemplateInstance::semantic and the fact that importedFrom is only set
// once for the first module.
TemplateInstance *owningTemplate;
void initializeIdent(Scope* s);
const char* prefix;
#endif
};

Expand Down
2 changes: 2 additions & 0 deletions dmd2/dsymbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Dsymbol::Dsymbol()
this->unittest = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
this->uniqueIdNumber = 0;
#endif
}

Expand All @@ -80,6 +81,7 @@ Dsymbol::Dsymbol(Identifier *ident)
this->unittest = NULL;
#if IN_LLVM
this->llvmInternal = LLVMnone;
this->uniqueIdNumber = 0;
#endif
}

Expand Down
3 changes: 3 additions & 0 deletions dmd2/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ struct Dsymbol : Object
virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }

int uniqueIdNumber;
int getUniqueIdNumber(){ return uniqueIdNumber++; }

/// Codegen traversal
virtual void codegen(IRState* p);

Expand Down
50 changes: 49 additions & 1 deletion dmd2/func.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
// LDC
isArrayOp = false;
allowInlining = false;
alwaysInline = false;
neverInline = false;
availableExternally = true; // assume this unless proven otherwise
#endif
Expand Down Expand Up @@ -166,6 +167,9 @@ void FuncDeclaration::semantic(Scope *sc)
Dsymbol *pd;
bool doesoverride;

if(FuncLiteralDeclaration* fld = isFuncLiteralDeclaration())
fld->initializeIdent(sc);

#if 0
printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
if (isFuncLiteralDeclaration())
Expand Down Expand Up @@ -233,6 +237,44 @@ void FuncDeclaration::semantic(Scope *sc)
protection = sc->protection;
userAttributes = sc->userAttributes;

#if IN_LLVM
if(userAttributes)
{
assert(ldcAttributes.dim == 0);
expandTuples(userAttributes);
for (size_t i = 0; i < userAttributes->dim; i++)
{
Expression *attr = (*userAttributes)[i]->optimize(WANTvalue);
if (!attr || attr->op != TOKcall) continue;
if (attr->type->ty != Tstruct) continue;
TypeStruct *ts = static_cast<TypeStruct *>(attr->type);
StructDeclaration *sym = ts->sym;
if (strcmp("Attribute", sym->ident->string)) continue;
Module *module = sym->getModule();
if (strcmp("attribute", module->md->id->string)) continue;
if (module->md->packages->dim != 1 || strcmp("ldc", (*module->md->packages)[0]->string)) continue;

Expressions *exps = static_cast<CallExp *>(attr)->arguments;
assert(exps && exps->dim >= 1);

(*exps)[0] = (*exps)[0]->optimize(WANTvalue);
Expression* exp = (*exps)[0];
if (exp->op != TOKstring)
error(exp->loc, "First argument of @ldc.attribute must be of type string");

ldcAttributes.push(exps);

const char* name = (const char*)((StringExp*)exp)->string;
if(strcmp(name, "alwaysinline") == 0)
alwaysInline = true;
}

if(Module* mod = getModule())
if(mod != mod->importedFrom && alwaysInline)
mod->needExtraInliningSemantic = true;
}
#endif

if (!originalType)
originalType = type->syntaxCopy();
if (!type->deco)
Expand Down Expand Up @@ -4022,7 +4064,8 @@ FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
id = "__dgliteral";
else
id = "__funcliteral";
this->ident = Lexer::uniqueId(id);
this->ident = NULL;
this->prefix = id;
this->tok = tok;
this->fes = fes;
this->treq = NULL;
Expand All @@ -4033,6 +4076,11 @@ FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
#endif
}

void FuncLiteralDeclaration::initializeIdent(Scope* s)
{
if(!ident) ident = Lexer::uniqueId(prefix, s->parent->getUniqueIdNumber());
}

Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
{
FuncLiteralDeclaration *f;
Expand Down
1 change: 0 additions & 1 deletion dmd2/lexer.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
Expand Down
1 change: 1 addition & 0 deletions dmd2/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
this->doHdrGen = doHdrGen;
this->isRoot = false;
this->arrayfuncs = 0;
this->needExtraInliningSemantic = false;
#endif
}

Expand Down
2 changes: 2 additions & 0 deletions dmd2/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ struct Module : Package
void genmoduleinfo();

#if IN_LLVM
bool needExtraInliningSemantic;

// LDC
llvm::Module* genLLVMModule(llvm::LLVMContext& context);
void buildTargetFiles(bool singleObj);
Expand Down
2 changes: 1 addition & 1 deletion dmd2/statement.c
Original file line number Diff line number Diff line change
Expand Up @@ -4432,7 +4432,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
* _d_criticalenter(critsec.ptr);
* try { body } finally { _d_criticalexit(critsec.ptr); }
*/
Identifier *id = Lexer::uniqueId("__critsec");
Identifier *id = Lexer::uniqueId("__critsec", sc->parent->getUniqueIdNumber());
#if !IN_LLVM
Type *t = new TypeSArray(Type::tint8, new IntegerExp(Target::ptrsize + (global.params.is64bit ? os_critsecsize64() : os_critsecsize32())));
#else
Expand Down
8 changes: 8 additions & 0 deletions dmd2/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,14 @@ void TemplateDeclaration::semantic(Scope *sc)
return; // semantic() already run
semanticRun = PASSsemantic;

if(literal)
{
assert(onemember);
FuncLiteralDeclaration* fld = onemember->isFuncLiteralDeclaration();
fld->initializeIdent(sc);
ident = fld->ident;
}

// Remember templates defined in module object that we need to know about
if (sc->module && sc->module->ident == Id::object)
{
Expand Down
29 changes: 13 additions & 16 deletions driver/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@ int main(int argc, char **argv)
if (global.errors)
fatal();

// Do extra pass 3 semantic analysis for inlining
// This doesn't play nice with debug info at the moment.
//
// Also, don't run the additional semantic3 passes when building unit tests.
Expand All @@ -1035,25 +1036,21 @@ int main(int argc, char **argv)
// Alternatively, we could also amend the availableExternally detection
// logic (e.g. just codegen everything on -unittest builds), but the extra
// inlining is unlikely to be important for test builds anyway.
if (!global.params.symdebug && willInline() && !global.params.useUnitTests)
bool needExtraInliningSemantic =
!global.params.symdebug && willInline() && !global.params.useUnitTests;

Logger::println("Running some extra semantic3's for inlining purposes");
for (unsigned i = 0; i < Module::amodules.dim; i++)
{
global.inExtraInliningSemantic = true;
Logger::println("Running some extra semantic3's for inlining purposes");
Module *m = Module::amodules[i];
if(needExtraInliningSemantic || m->needExtraInliningSemantic)
{
// Do pass 3 semantic analysis on all imported modules,
// since otherwise functions in them cannot be inlined
for (unsigned i = 0; i < Module::amodules.dim; i++)
{
Module *m = Module::amodules[i];
if (global.params.verbose)
printf("semantic3 %s\n", m->toChars());
m->semantic2();
m->semantic3();
}
if (global.errors)
fatal();
global.inExtraInliningSemantic = true;
if (global.params.verbose) printf("semantic3 %s\n", m->toChars());
m->semantic2();
m->semantic3();
global.inExtraInliningSemantic = false;
}
global.inExtraInliningSemantic = false;
}
if (global.errors || global.warnings)
fatal();
Expand Down
3 changes: 3 additions & 0 deletions gen/declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ void ClassDeclaration::codegen(IRState *p)
IF_LOG Logger::println("ClassDeclaration::codegen: '%s'", toPrettyChars());
LOG_SCOPE

if(availableExternally)
return;

if (ir.defined) return;
ir.defined = true;

Expand Down
107 changes: 105 additions & 2 deletions gen/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//

#include "gen/functions.h"
#include "gen/utils.h"
#include "aggregate.h"
#include "declaration.h"
#include "id.h"
Expand Down Expand Up @@ -555,9 +556,7 @@ void DtoResolveFunction(FuncDeclaration* fdecl)

// queue declaration unless the function is abstract without body
if (!fdecl->isAbstract() || fdecl->fbody)
{
DtoDeclareFunction(fdecl);
}
}

//////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -706,6 +705,10 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati

//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////

bool willInline();

void DtoDeclareFunction(FuncDeclaration* fdecl)
{
DtoResolveFunction(fdecl);
Expand Down Expand Up @@ -817,6 +820,95 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
AppendFunctionToLLVMGlobalCtorsDtors(func, fdecl->priority, fdecl->llvmInternal == LLVMglobal_crt_ctor);
}

if (fdecl->userAttributes)
{
expandTuples(fdecl->userAttributes);
for (ArrayIter<Expressions> it(fdecl->ldcAttributes); !it.done(); it.next())
{
Expressions *exps = *it;
Expression *exp = (*exps)[0];
assert(exp->op == TOKstring);
std::string name(static_cast<const char*>(((StringExp*)exp)->string));

struct SimpleAttribute
{
std::string name;
#if LDC_LLVM_VER >= 303
llvm::Attribute::AttrKind attr;
#elif LDC_LLVM_VER == 302
llvm::Attributes::AttrVal attr;
#else
llvm::Attribute::AttrConst attr;
#endif
};
static SimpleAttribute simpleAttribute[] =
{
{ "alwaysinline", llvm::Attribute::AlwaysInline },
#if LDC_LLVM_VER >= 304
{ "builtin", llvm::Attribute::Builtin },
{ "cold", llvm::Attribute::Cold },
#endif
{ "inlinehint", llvm::Attribute::InlineHint },
#if LDC_LLVM_VER >= 302
{ "minsize", llvm::Attribute::MinSize },
#endif
{ "naked", llvm::Attribute::Naked },
#if LDC_LLVM_VER >= 304
{ "nobuiltin", llvm::Attribute::NoBuiltin },
{ "noduplicate", llvm::Attribute::NoDuplicate },
#endif
{ "noimplicitfloat", llvm::Attribute::NoImplicitFloat },
{ "noinline", llvm::Attribute::NoInline },
{ "nonlazybind", llvm::Attribute::NonLazyBind },
{ "noredzone", llvm::Attribute::NoRedZone },
{ "noreturn", llvm::Attribute::NoReturn },
{ "nounwind", llvm::Attribute::NoUnwind },
#if LDC_LLVM_VER >= 304
{ "optnone", llvm::Attribute::OptimizeNone },
#endif
{ "optsize", llvm::Attribute::OptimizeForSize },
{ "readnone", llvm::Attribute::ReadNone },
{ "readonly", llvm::Attribute::ReadOnly },
{ "returns_twice", llvm::Attribute::ReturnsTwice },
#if LDC_LLVM_VER >= 303
{ "sanitize_address", llvm::Attribute::SanitizeAddress },
{ "sanitize_memory", llvm::Attribute::SanitizeMemory },
{ "sanitize_thread", llvm::Attribute::SanitizeThread },
#else
{ "sanitize_address", llvm::Attribute::AddressSafety },
#endif
{ "ssp", llvm::Attribute::StackProtect },
{ "sspreq", llvm::Attribute::StackProtectReq },
#if LDC_LLVM_VER >= 303
{ "sspstrong", llvm::Attribute::StackProtectStrong },
#endif
{ "uwtable", llvm::Attribute::UWTable },
};

{
size_t i = 0, j = sizeof(simpleAttribute) / sizeof(simpleAttribute[0]);
do
{
size_t k = (i + j) / 2;
int cmp = name.compare(simpleAttribute[k].name);
if (!cmp)
{
func->addFnAttr(simpleAttribute[k].attr);
break;
}
else if (cmp < 0)
j = k;
else
i = k + 1;
}
while (i != j);

if (i == j)
error(exp->loc, "Unknown attribute %s\n", name.c_str());
}
}
}

IrFuncTy &irFty = fdecl->irFty;

// if (!declareOnly)
Expand Down Expand Up @@ -887,6 +979,17 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
}
}
}

bool inliningEnabled =
!global.params.symdebug && willInline() && !global.params.useUnitTests;

if(
(fdecl->alwaysInline || (inliningEnabled && fdecl->availableExternally)) &&
fdecl->semanticRun == PASSsemantic3done &&
fdecl->getModule())
{
DtoDefineFunction(fdecl);
}
}

//////////////////////////////////////////////////////////////////////////////////////////
Expand Down
Loading