Exemplo n.º 1
0
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym, bool checkInline)
{
    if (DtoIsTemplateInstance(sym))
        return templateLinkage;
    else if (checkInline && isAvailableExternally(sym))
        return llvm::GlobalValue::AvailableExternallyLinkage;
    else
        return llvm::GlobalValue::ExternalLinkage;
}
Exemplo n.º 2
0
llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
{
    if (DtoIsTemplateInstance(sym)) {
        if (isAvailableExternally(sym))
            return llvm::GlobalValue::AvailableExternallyLinkage;
        return templateLinkage;
    }
    else
        return llvm::GlobalValue::InternalLinkage;
}
Exemplo n.º 3
0
LinkageWithCOMDAT DtoLinkage(Dsymbol *sym) {
  auto linkage = (DtoIsTemplateInstance(sym) ? templateLinkage
                                             : LLGlobalValue::ExternalLinkage);

  // If @(ldc.attributes.weak) is applied, override the linkage to WeakAny
  if (hasWeakUDA(sym)) {
    linkage = LLGlobalValue::WeakAnyLinkage;
  }

  return {linkage, supportsCOMDAT()};
}
Exemplo n.º 4
0
LinkageWithCOMDAT DtoLinkage(Dsymbol* sym)
{
    if (DtoIsTemplateInstance(sym))
        return LinkageWithCOMDAT(templateLinkage, supportsCOMDAT());
    return LinkageWithCOMDAT(llvm::GlobalValue::ExternalLinkage, false);
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
void DtoDefineNakedFunction(FuncDeclaration* fd)
{
    Logger::println("DtoDefineNakedFunction(%s)", fd->mangle());
    LOG_SCOPE;

    assert(fd->ir.irFunc);
    gIR->functions.push_back(fd->ir.irFunc);

    // we need to do special processing on the body, since we only want
    // to allow actual inline asm blocks to reach the final asm output

    std::ostringstream& asmstr = gIR->nakedAsm;

    // build function header

    // FIXME: could we perhaps use llvm asmwriter to give us these details ?

    const char* mangle = fd->mangle();
    std::ostringstream tmpstr;

    bool const isWin = global.params.targetTriple.isOSWindows();
    bool const isOSX = (global.params.targetTriple.getOS() == llvm::Triple::Darwin ||
        global.params.targetTriple.getOS() == llvm::Triple::MacOSX);

    // osx is different
    // also mangling has an extra underscore prefixed
    if (isOSX)
    {
        std::string section = "text";
        bool weak = false;
        if (DtoIsTemplateInstance(fd))
        {
            tmpstr << "section\t__TEXT,__textcoal_nt,coalesced,pure_instructions";
            section = tmpstr.str();
            weak = true;
        }
        asmstr << "\t." << section << std::endl;
        asmstr << "\t.align\t4,0x90" << std::endl;
        asmstr << "\t.globl\t_" << mangle << std::endl;
        if (weak)
        {
            asmstr << "\t.weak_definition\t_" << mangle << std::endl;
        }
        asmstr << "_" << mangle << ":" << std::endl;
    }
    else
    {
        std::string fullMangle;
        if (global.params.targetTriple.getOS() == llvm::Triple::MinGW32 ||
            global.params.targetTriple.getOS() == llvm::Triple::Win32)
        {
            fullMangle = "_";
        }
        fullMangle += mangle;

        const char* linkage = "globl";
        std::string section = "text";
        if (DtoIsTemplateInstance(fd))
        {
            linkage = "weak";
            tmpstr << "section\t.gnu.linkonce.t." << fullMangle << ",\"ax\"";
            if (!isWin)
                tmpstr << ",@progbits";
            section = tmpstr.str();
        }
        asmstr << "\t." << section << std::endl;
        asmstr << "\t.align\t16" << std::endl;

        if (isWin)
        {
            asmstr << "\t.def\t" << fullMangle << ";";
            // hard code these two numbers for now since gas ignores .scl and llvm
            // is defaulting to .type 32 for everything I have seen
            asmstr << "\t.scl 2; .type 32;\t.endef" << std::endl;
        }
        else
        {
            asmstr << "\t.type\t" << fullMangle << ",@function" << std::endl;
        }

        asmstr << "\t." << linkage << "\t" << fullMangle << std::endl;
        asmstr << fullMangle << ":" << std::endl;

    }

    // emit body
    fd->fbody->toNakedIR(gIR);

    // We could have generated new errors in toNakedIR(), but we are in codegen
    // already so we have to abort here.
    if (global.errors)
        fatal();

    // emit size after body
    // llvm does this on linux, but not on osx or Win
    if (!(isWin || isOSX))
    {
        asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl << std::endl;
    }

    gIR->module->appendModuleInlineAsm(asmstr.str());
    asmstr.str("");

    gIR->functions.pop_back();
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
llvm::GlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
{
    if (DtoIsTemplateInstance(sym))
        return templateLinkage;
    return llvm::GlobalValue::ExternalLinkage;
}