Example #1
0
File: mangle.c Project: smunix/ldc
char *mangle(Declaration *sthis)
{
    OutBuffer buf;
    char *id;
    Dsymbol *s;

    //printf("::mangle(%s)\n", sthis->toChars());
    s = sthis;
    do
    {
        //printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
        if (s->ident)
        {
            FuncDeclaration *fd = s->isFuncDeclaration();
            if (s != sthis && fd)
            {
                id = mangle(fd);
                buf.prependstring(id);
                goto L1;
            }
            else
            {
                id = s->ident->toChars();
                int len = strlen(id);
                char tmp[sizeof(len) * 3 + 1];
                buf.prependstring(id);
                sprintf(tmp, "%d", len);
                buf.prependstring(tmp);
            }
        }
        else
            buf.prependstring("0");
        s = s->parent;
    } while (s);

//    buf.prependstring("_D");
L1:
    //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
    //printf("sthis->type = %s\n", sthis->type->toChars());
    FuncDeclaration *fd = sthis->isFuncDeclaration();
    if (fd && (fd->needThis() || fd->isNested()))
        buf.writeByte(Type::needThisPrefix());
    if (sthis->type->deco)
        buf.writestring(sthis->type->deco);
    else
    {
#ifdef DEBUG
        if (!fd->inferRetType)
            printf("%s\n", fd->toChars());
#endif
        assert(fd && fd->inferRetType);
    }

    id = buf.toChars();
    buf.data = NULL;
    return id;
}
Example #2
0
LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
{
    // global/static variable
    if (VarDeclaration* vd = sym->isVarDeclaration())
    {
        IF_LOG Logger::println("Variable %savailable externally: %s",
            (vd->availableExternally ? "" : "not "), vd->toChars());

        // generated by inlining semantics run
        if (vd->availableExternally)
            return llvm::GlobalValue::AvailableExternallyLinkage;
        // template
        if (DtoIsTemplateInstance(sym))
            return templateLinkage;

        // Currently, we have to consider all variables, even function-local
        // statics, to be external, as CTFE might cause template functions
        // instances to be semantic3'd that occur within the body of a function
        // from an imported module. Consequently, a copy of them is codegen'd
        // in the importing module, even if they might reference a static in a
        // function in the imported module (e.g. via an alias parameter).
        //
        // A fix for this would be to track instantiations/semantic3 runs made
        // solely for CTFE purposes in a way similar to how the extra inlining
        // semantic runs are handled.
        //
        // LDC_FIXME: Can this also occur for functions? Find a better solution.
        if (true || vd->storage_class & STCextern)
            return llvm::GlobalValue::ExternalLinkage;

    }
    else if (FuncDeclaration* fdecl = sym->isFuncDeclaration())
    {
        IF_LOG Logger::println("Function %savailable externally: %s",
            (fdecl->availableExternally ? "" : "not "), fdecl->toChars());

        assert(fdecl->type->ty == Tfunction);
        TypeFunction* ft = static_cast<TypeFunction*>(fdecl->type);

        // intrinsics are always external
        if (fdecl->llvmInternal == LLVMintrinsic)
            return llvm::GlobalValue::ExternalLinkage;

        // Mark functions generated by an inlining semantic run as
        // available_externally. Naked functions are turned into module-level
        // inline asm and are thus declaration-only as far as the LLVM IR level
        // is concerned.
        if (fdecl->availableExternally && !fdecl->naked)
            return llvm::GlobalValue::AvailableExternallyLinkage;

        // array operations are always template linkage
        if (fdecl->isArrayOp == 1)
            return templateLinkage;

        // template instances should have weak linkage
        // but only if there's a body, and it's not naked
        // otherwise we make it external
        if (DtoIsTemplateInstance(fdecl) && fdecl->fbody && !fdecl->naked)
            return templateLinkage;

        // extern(C) functions are always external
        if (ft->linkage == LINKc)
            return llvm::GlobalValue::ExternalLinkage;

        // If a function without a body is nested in another
        // function, we cannot use internal linkage for that
        // function (see below about nested functions)
        // FIXME: maybe there is a better way without emission
        // of needless symbols?
        if (!fdecl->fbody)
            return llvm::GlobalValue::ExternalLinkage;
    }
    // class
    else if (ClassDeclaration* cd = sym->isClassDeclaration())
    {
        IF_LOG Logger::println("Class %savailable externally: %s",
            (cd->availableExternally ? "" : "not "), vd->toChars());

        // generated by inlining semantics run
        if (cd->availableExternally)
            return llvm::GlobalValue::AvailableExternallyLinkage;
        // template
        if (DtoIsTemplateInstance(cd))
            return templateLinkage;
    }
    else
    {
        llvm_unreachable("not global/function");
    }

    // The logic here should be sound in theory, but as long as the frontend
    // keeps inserting templates into wrong modules, this yields to linking
    // errors (see e.g. GitHub issue #558).
#if 0
    // Check if sym is a nested function and we can declare it as internal.
    //
    // Nested naked functions and the implicitly generated __require/__ensure
    // functions for in/out contracts cannot be internalized. The reason
    // for the latter is that contract functions, despite being nested, can be
    // referenced from other D modules e.g. in the case of contracts on
    // interface methods (where __require/__ensure are emitted to the module
    // where the interface is declared, but an actual interface implementation
    // can be in a completely different place).
    FuncDeclaration* fd = sym->isFuncDeclaration();
    if (!fd || (!fd->naked && fd->ident != Id::require && fd->ident != Id::ensure))
    {
        // Any symbol nested in a function that cannot be inlined can't be
        // referenced directly from outside that function, so we can give
        // such symbols internal linkage. This holds even if nested indirectly,
        // such as member functions of aggregates nested in functions.
        //
        // Note: This must be checked after things like template member-ness or
        // symbols nested in templates would get duplicated for each module,
        // breaking things like
        // ---
        // int counter(T)() { static int i; return i++; }"
        // ---
        // if instances get emitted in multiple object files because they'd use
        // different instances of 'i'.
        // TODO: Check if we are giving away too much inlining potential due to
        // canInline being overly conservative here.
        for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent)
        {
            FuncDeclaration *parentFd = parent->isFuncDeclaration();
            if (parentFd && !parentFd->canInline(parentFd->needThis(), false, false))
            {
                // We also cannot internalize nested functions which are
                // leaked to the outside via a templated return type, because
                // that type will also be codegen'd in any caller modules (see
                // GitHub issue #131).
                // Since we can't easily determine if this is really the case
                // here, just don't internalize it if the parent returns a
                // template at all, to be safe.
                TypeFunction* tf = static_cast<TypeFunction*>(parentFd->type);
                if (!DtoIsTemplateInstance(tf->next->toDsymbol(parentFd->scope)))
                    return llvm::GlobalValue::InternalLinkage;
            }
        }
    }
#endif
    // default to external linkage
    return llvm::GlobalValue::ExternalLinkage;
}
Example #3
0
/******************************************************************************
 *  isv     : for the enclosing auto functions of an inner class/struct type.
 *            An aggregate type which defined inside auto function, it might
 *            become Voldemort Type so its object might be returned.
 *            This flag is necessary due to avoid mutual mangling
 *            between return type and enclosing scope. See bugzilla 8847.
 */
char *mangleDecl(Declaration *sthis, bool isv)
{
    OutBuffer buf;
    char *id;
    Dsymbol *s;

    //printf("::mangleDecl(%s)\n", sthis->toChars());
    s = sthis;
    do
    {
        //printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent);
        if (s->getIdent())
        {
            FuncDeclaration *fd = s->isFuncDeclaration();
            if (s != sthis && fd)
            {
                id = mangleDecl(fd, isv);
                buf.prependstring(id);
                goto L1;
            }
            else
            {
                id = s->ident->toChars();
                size_t len = strlen(id);
                char tmp[sizeof(len) * 3 + 1];
                buf.prependstring(id);
                sprintf(tmp, "%d", (int)len);
                buf.prependstring(tmp);
            }
        }
        else
            buf.prependstring("0");

        TemplateInstance *ti = s->isTemplateInstance();
        if (ti && !ti->isTemplateMixin())
            s = ti->tempdecl->parent;
        else
            s = s->parent;
    } while (s);

//    buf.prependstring("_D");
L1:
    //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null");
    //printf("sthis->type = %s\n", sthis->type->toChars());
    FuncDeclaration *fd = sthis->isFuncDeclaration();
    if (fd && (fd->needThis() || fd->isNested()))
        buf.writeByte(Type::needThisPrefix());
    if (isv && fd && (fd->inferRetType || getFuncTemplateDecl(fd)))
    {
#if DDMD
        TypeFunction *tfn = (TypeFunction *)sthis->type->copy();
        TypeFunction *tfo = (TypeFunction *)sthis->originalType;
        tfn->purity      = tfo->purity;
        tfn->isnothrow   = tfo->isnothrow;
        tfn->isproperty  = tfo->isproperty;
        tfn->isref       = fd->storage_class & STCauto ? false : tfo->isref;
        tfn->trust       = tfo->trust;
        tfn->next        = NULL;     // do not mangle return type
        tfn->toDecoBuffer(&buf, 0);
#else
        TypeFunction tfn = *(TypeFunction *)sthis->type;
        TypeFunction *tfo = (TypeFunction *)sthis->originalType;
        tfn.purity      = tfo->purity;
        tfn.isnothrow   = tfo->isnothrow;
        tfn.isproperty  = tfo->isproperty;
        tfn.isref       = fd->storage_class & STCauto ? false : tfo->isref;
        tfn.trust       = tfo->trust;
        tfn.next        = NULL;     // do not mangle return type
        tfn.toDecoBuffer(&buf, 0);
#endif
    }
    else if (sthis->type->deco)
        buf.writestring(sthis->type->deco);
    else
    {
#ifdef DEBUG
        if (!fd->inferRetType)
            printf("%s\n", fd->toChars());
#endif
        assert(fd && fd->inferRetType && fd->type->ty == Tfunction);
        TypeFunction *tf = (TypeFunction *)sthis->type;
        Type *tn = tf->next;
        tf->next = NULL;    // do not mangle undetermined return type
        tf->toDecoBuffer(&buf, 0);
        tf->next = tn;
    }

    id = buf.extractString();
    return id;
}
Example #4
0
File: cast.c Project: smunix/ldc
Expression *SymOffExp::castTo(Scope *sc, Type *t)
{
#if 0
    printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n",
        toChars(), type->toChars(), t->toChars());
#endif
    Expression *e = this;

    Type *tb = t->toBasetype();
    Type *typeb = type->toBasetype();
    if (tb != typeb)
    {
        // Look for pointers to functions where the functions are overloaded.
        FuncDeclaration *f;

        if (typeb->ty == Tpointer && typeb->next->ty == Tfunction &&
            tb->ty == Tpointer && tb->next->ty == Tfunction)
        {
            f = var->isFuncDeclaration();
            if (f)
            {
                f = f->overloadExactMatch(tb->next, m);
                if (f)
                {
#if DMDV2
                    if (tb->ty == Tdelegate)
                    {
                        if (f->needThis() && hasThis(sc))
                        {
                            e = new DelegateExp(loc, new ThisExp(loc), f);
                            e = e->semantic(sc);
                        }
                        else if (f->isNested())
                        {
                            e = new DelegateExp(loc, new IntegerExp(0), f);
                            e = e->semantic(sc);
                        }
                        else if (f->needThis())
                        {   error("no 'this' to create delegate for %s", f->toChars());
                            return new ErrorExp();
                        }
                        else
                        {   error("cannot cast from function pointer to delegate");
                            return new ErrorExp();
                        }
                    }
                    else
#endif
                    {
                        e = new SymOffExp(loc, f, 0);
                        e->type = t;
                    }
#if DMDV2
                    f->tookAddressOf++;
#endif
                    return e;
                }
            }
        }
        e = Expression::castTo(sc, t);
    }
    else
    {
        e->type = t;
    }
    return e;
}
Example #5
0
File: traits.c Project: nischu7/dmd
Expression *TraitsExp::semantic(Scope *sc)
{
#if LOGSEMANTIC
    printf("TraitsExp::semantic() %s\n", toChars());
#endif
    if (ident != Id::compiles && ident != Id::isSame &&
        ident != Id::identifier)
    {
        TemplateInstance::semanticTiargs(loc, sc, args, 1);
    }
    size_t dim = args ? args->dim : 0;
    Object *o;
    Declaration *d;
    FuncDeclaration *f;

#define ISTYPE(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Type *t = getType((Object *)args->data[i]); \
            if (!t)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;

#define ISDSYMBOL(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Dsymbol *s = getDsymbol((Object *)args->data[i]);   \
            if (!s)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;



    if (ident == Id::isArithmetic)
    {
        ISTYPE(t->isintegral() || t->isfloating())
    }
    else if (ident == Id::isFloating)
    {
        ISTYPE(t->isfloating())
    }
    else if (ident == Id::isIntegral)
    {
        ISTYPE(t->isintegral())
    }
    else if (ident == Id::isScalar)
    {
        ISTYPE(t->isscalar())
    }
    else if (ident == Id::isUnsigned)
    {
        ISTYPE(t->isunsigned())
    }
    else if (ident == Id::isAssociativeArray)
    {
        ISTYPE(t->toBasetype()->ty == Taarray)
    }
    else if (ident == Id::isStaticArray)
    {
        ISTYPE(t->toBasetype()->ty == Tsarray)
    }
    else if (ident == Id::isAbstractClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
    }
    else if (ident == Id::isFinalClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
    }
    else if (ident == Id::isAbstractFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
    }
    else if (ident == Id::isVirtualFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
    }
    else if (ident == Id::isFinalFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
    }
#if DMDV2
    else if (ident == Id::isStaticFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis())
    }
    else if (ident == Id::isRef)
    {
        ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isRef())
    }
    else if (ident == Id::isOut)
    {
        ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isOut())
    }
    else if (ident == Id::isLazy)
    {
        ISDSYMBOL((d = s->isDeclaration()) != NULL && d->storage_class & STClazy)
    }
    else if (ident == Id::identifier)
    {   // Get identifier for symbol as a string literal

        // Specify 0 for the flags argument to semanticTiargs() so that
        // a symbol should not be folded to a constant.
        TemplateInstance::semanticTiargs(loc, sc, args, 0);

        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        if (!s || !s->ident)
        {
            error("argument %s has no identifier", o->toChars());
            goto Lfalse;
        }
        StringExp *se = new StringExp(loc, s->ident->toChars());
        return se->semantic(sc);
    }
    else if (ident == Id::parent)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        if (s)
            s = s->toParent();
        if (!s)
        {
            error("argument %s has no parent", o->toChars());
            goto Lfalse;
        }
        return (new DsymbolExp(loc, s))->semantic(sc);
    }

#endif
    else if (ident == Id::hasMember ||
             ident == Id::getMember ||
             ident == Id::getOverloads ||
             ident == Id::getVirtualFunctions)
    {
        if (dim != 2)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Expression *e = isExpression((Object *)args->data[1]);
        if (!e)
        {   error("expression expected as second argument of __traits %s", ident->toChars());
            goto Lfalse;
        }
        e = e->optimize(WANTvalue | WANTinterpret);
        if (e->op != TOKstring)
        {   error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars());
            goto Lfalse;
        }
        StringExp *se = (StringExp *)e;
        se = se->toUTF8(sc);
        if (se->sz != 1)
        {   error("string must be chars");
            goto Lfalse;
        }
        Identifier *id = Lexer::idPool((char *)se->string);

        Type *t = isType(o);
        e = isExpression(o);
        Dsymbol *s = isDsymbol(o);
        if (t)
            e = typeDotIdExp(loc, t, id);
        else if (e)
            e = new DotIdExp(loc, e, id);
        else if (s)
        {   e = new DsymbolExp(loc, s);
            e = new DotIdExp(loc, e, id);
        }
        else
        {   error("invalid first argument");
            goto Lfalse;
        }

        if (ident == Id::hasMember)
        {   /* Take any errors as meaning it wasn't found
             */
            e = e->trySemantic(sc);
            if (!e)
            {   if (global.gag)
                    global.errors++;
                goto Lfalse;
            }
            else
                goto Ltrue;
        }
        else if (ident == Id::getMember)
        {
            e = e->semantic(sc);
            return e;
        }
        else if (ident == Id::getVirtualFunctions ||
                 ident == Id::getOverloads)
        {
            unsigned errors = global.errors;
            Expression *ex = e;
            e = e->semantic(sc);
            if (errors < global.errors)
                error("%s cannot be resolved", ex->toChars());

            /* Create tuple of functions of e
             */
            //e->dump(0);
            Expressions *exps = new Expressions();
            FuncDeclaration *f;
            if (e->op == TOKvar)
            {   VarExp *ve = (VarExp *)e;
                f = ve->var->isFuncDeclaration();
            }
            else if (e->op == TOKdotvar)
            {   DotVarExp *dve = (DotVarExp *)e;
                f = dve->var->isFuncDeclaration();
            }
            else
                f = NULL;
            Ptrait p;
            p.exps = exps;
            p.e1 = e;
            p.ident = ident;
            overloadApply(f, fptraits, &p);

            TupleExp *tup = new TupleExp(loc, exps);
            return tup->semantic(sc);
        }
        else
            assert(0);
    }
    else if (ident == Id::classInstanceSize)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        ClassDeclaration *cd;
        if (!s || (cd = s->isClassDeclaration()) == NULL)
        {
            error("first argument is not a class");
            goto Lfalse;
        }
        return new IntegerExp(loc, cd->structsize, Type::tsize_t);
    }
    else if (ident == Id::allMembers || ident == Id::derivedMembers)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        ScopeDsymbol *sd;
        if (!s)
        {
            error("argument has no members");
            goto Lfalse;
        }
        if ((sd = s->isScopeDsymbol()) == NULL)
        {
            error("%s %s has no members", s->kind(), s->toChars());
            goto Lfalse;
        }
        Expressions *exps = new Expressions;
        while (1)
        {   size_t dim = ScopeDsymbol::dim(sd->members);
            for (size_t i = 0; i < dim; i++)
            {
                Dsymbol *sm = ScopeDsymbol::getNth(sd->members, i);
                //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
                if (sm->ident)
                {
                    //printf("\t%s\n", sm->ident->toChars());
                    char *str = sm->ident->toChars();

                    /* Skip if already present in exps[]
                     */
                    for (size_t j = 0; j < exps->dim; j++)
                    {   StringExp *se2 = (StringExp *)exps->data[j];
                        if (strcmp(str, (char *)se2->string) == 0)
                            goto Lnext;
                    }

                    StringExp *se = new StringExp(loc, str);
                    exps->push(se);
                }
            Lnext:
                ;
            }
            ClassDeclaration *cd = sd->isClassDeclaration();
            if (cd && cd->baseClass && ident == Id::allMembers)
                sd = cd->baseClass;     // do again with base class
            else
                break;
        }
#if DMDV1
        Expression *e = new ArrayLiteralExp(loc, exps);
#endif
#if DMDV2
        /* Making this a tuple is more flexible, as it can be statically unrolled.
         * To make an array literal, enclose __traits in [ ]:
         *   [ __traits(allMembers, ...) ]
         */
        Expression *e = new TupleExp(loc, exps);
#endif
        e = e->semantic(sc);
        return e;
    }
    else if (ident == Id::compiles)
    {
        /* Determine if all the objects - types, expressions, or symbols -
         * compile without error
         */
        if (!dim)
            goto Lfalse;

        for (size_t i = 0; i < dim; i++)
        {   Object *o = (Object *)args->data[i];
            Expression *e;

            unsigned errors = global.errors;
            global.gag++;

            Type *t = isType(o);
            if (t)
            {   Dsymbol *s;
                t->resolve(loc, sc, &e, &t, &s);
                if (t)
                    t->semantic(loc, sc);
                else if (e)
                {   e = e->semantic(sc);
                    e = e->optimize(WANTvalue);
                }
            }
            else
            {   e = isExpression(o);
                if (e)
                {   e = e->semantic(sc);
                    e = e->optimize(WANTvalue);
                }
            }

            global.gag--;
            if (errors != global.errors)
            {
                global.errors = errors;
                goto Lfalse;
            }
        }
        goto Ltrue;
    }
    else if (ident == Id::isSame)
    {   /* Determine if two symbols are the same
         */
        if (dim != 2)
            goto Ldimerror;
        TemplateInstance::semanticTiargs(loc, sc, args, 0);
        Object *o1 = (Object *)args->data[0];
        Object *o2 = (Object *)args->data[1];
        Dsymbol *s1 = getDsymbol(o1);
        Dsymbol *s2 = getDsymbol(o2);

        //printf("isSame: %s, %s\n", o1->toChars(), o2->toChars());
#if 0
        printf("o1: %p\n", o1);
        printf("o2: %p\n", o2);
        if (!s1)
        {   Expression *ea = isExpression(o1);
            if (ea)
                printf("%s\n", ea->toChars());
            Type *ta = isType(o1);
            if (ta)
                printf("%s\n", ta->toChars());
            goto Lfalse;
        }
        else
            printf("%s %s\n", s1->kind(), s1->toChars());
#endif
        if (!s1 && !s2)
        {   Expression *ea1 = isExpression(o1);
            Expression *ea2 = isExpression(o2);
            if (ea1 && ea2)
            {
                if (ea1->equals(ea2))
                    goto Ltrue;
            }
        }

        if (!s1 || !s2)
            goto Lfalse;

        s1 = s1->toAlias();
        s2 = s2->toAlias();

        if (s1 == s2)
            goto Ltrue;
        else
            goto Lfalse;
    }
    else
    {   error("unrecognized trait %s", ident->toChars());
        goto Lfalse;
    }

    return NULL;

Lnottype:
    error("%s is not a type", o->toChars());
    goto Lfalse;

Ldimerror:
    error("wrong number of arguments %d", dim);
    goto Lfalse;


Lfalse:
    return new IntegerExp(loc, 0, Type::tbool);

Ltrue:
    return new IntegerExp(loc, 1, Type::tbool);
}
Example #6
0
LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
{
    const bool mustDefine = mustDefineSymbol(sym);

    // global variable
    if (VarDeclaration* vd = sym->isVarDeclaration())
    {
        if (mustDefine)
        {
            IF_LOG Logger::println("Variable %savailable externally: %s",
                (vd->availableExternally ? "" : "not "), vd->toChars());
        }

        // generated by inlining semantics run
        if (vd->availableExternally && mustDefine)
            return llvm::GlobalValue::AvailableExternallyLinkage;
        // template
        if (needsTemplateLinkage(sym))
            return templateLinkage;
        // never use InternalLinkage for variables marked as "extern"
        if (vd->storage_class & STCextern)
            return llvm::GlobalValue::ExternalLinkage;
    }
    // function
    else if (FuncDeclaration* fdecl = sym->isFuncDeclaration())
    {
        if (mustDefine)
        {
            IF_LOG Logger::println("Function %savailable externally: %s",
                (fdecl->availableExternally ? "" : "not "), fdecl->toChars());
        }

        assert(fdecl->type->ty == Tfunction);
        TypeFunction* ft = static_cast<TypeFunction*>(fdecl->type);

        // intrinsics are always external
        if (fdecl->llvmInternal == LLVMintrinsic)
            return llvm::GlobalValue::ExternalLinkage;
        // generated by inlining semantics run
        if (fdecl->availableExternally && mustDefine)
            return llvm::GlobalValue::AvailableExternallyLinkage;
        // array operations are always template linkage
        if (fdecl->isArrayOp == 1)
            return templateLinkage;
        // template instances should have weak linkage
        // but only if there's a body, and it's not naked
        // otherwise we make it external
        else if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked)
            return templateLinkage;
        // extern(C) functions are always external
        else if (ft->linkage == LINKc)
            return llvm::GlobalValue::ExternalLinkage;
        // If a function without a body is nested in another
        // function, we cannot use internal linkage for that
        // function (see below about nested functions)
        // FIXME: maybe there is a better way without emission
        // of needless symbols?
        if (!fdecl->fbody)
            return llvm::GlobalValue::ExternalLinkage;
    }
    // class
    else if (ClassDeclaration* cd = sym->isClassDeclaration())
    {
        if (mustDefine)
        {
            IF_LOG Logger::println("Class %savailable externally: %s",
                (cd->availableExternally ? "" : "not "), vd->toChars());
        }
        // generated by inlining semantics run
        if (cd->availableExternally && mustDefine)
            return llvm::GlobalValue::AvailableExternallyLinkage;
        // template
        if (needsTemplateLinkage(cd))
            return templateLinkage;
    }
    else
    {
        assert(0 && "not global/function");
    }

    // If the function needs to be defined in the current module, check if it
    // is a nested function and we can declare it as internal.
    bool canInternalize = mustDefine;

    // Nested naked functions and the implicitly generated __require/__ensure
    // functions for in/out contracts cannot be internalized. The reason
    // for the latter is that contract functions, despite being nested, can be
    // referenced from other D modules e.g. in the case of contracts on
    // interface methods (where __require/__ensure are emitted to the module
    // where the interface is declared, but an actual interface implementation
    // can be in a completely different place).
    if (canInternalize)
    {
        if (FuncDeclaration* fd = sym->isFuncDeclaration())
        {
            if ((fd->naked != 0) ||
                (fd->ident == Id::require) || (fd->ident == Id::ensure))
            {
                canInternalize = false;
            }
        }
    }

    // Any symbol nested in a function that cannot be inlined can't be
    // referenced directly from outside that function, so we can give
    // such symbols internal linkage. This holds even if nested indirectly,
    // such as member functions of aggregates nested in functions.
    //
    // Note: This must be checked after things like template member-ness or
    // symbols nested in templates would get duplicated for each module,
    // breaking things like
    // ---
    // int counter(T)() { static int i; return i++; }"
    // ---
    // if instances get emitted in multiple object files because they'd use
    // different instances of 'i'.
    // TODO: Check if we are giving away too much inlining potential due to
    // canInline being overly conservative here.
    if (canInternalize)
    {
        for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent)
        {
            FuncDeclaration *fd = parent->isFuncDeclaration();
            if (fd && !fd->canInline(fd->needThis()))
            {
                // We also cannot internalize nested functions which are
                // leaked to the outside via a templated return type, because
                // that type will also be codegen'd in any caller modules (see
                // GitHub issue #131).
                // Since we can't easily determine if this is really the case
                // here, just don't internalize it if the parent returns a
                // template at all, to be safe.
                TypeFunction* tf = static_cast<TypeFunction*>(fd->type);
                if (!DtoIsTemplateInstance(tf->next->toDsymbol(fd->scope)))
                    return llvm::GlobalValue::InternalLinkage;
            }
        }
    }

    // default to external linkage
    return llvm::GlobalValue::ExternalLinkage;
}