Example #1
0
    void visit(Dsymbol *s)
    {
    #if 0
        printf("Dsymbol::mangle() '%s'", s->toChars());
        if (s->parent)
            printf("  parent = %s %s", s->parent->kind(), s->parent->toChars());
        printf("\n");
    #endif

        char *id = s->ident ? s->ident->toChars() : s->toChars();
        OutBuffer buf;
        if (s->parent)
        {
            FuncDeclaration *f = s->parent->isFuncDeclaration();
            if (f)
                mangleExact(f);
            else
                s->parent->accept(this);
            if (result[0] == '_' && result[1] == 'D')
                result += 2;
            buf.writestring(result);
        }
        buf.printf("%llu%s", (ulonglong)strlen(id), id);
        id = buf.extractString();
        //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id);
        result = id;
    }
Example #2
0
 void visit(OverDeclaration *od)
 {
     if (od->overnext)
     {
         visit((Dsymbol *)od);
         return;
     }
 
     if (FuncDeclaration *fd = od->aliassym->isFuncDeclaration())
     {
         if (!od->hasOverloads || fd->isUnique())
         {
             mangleExact(fd);
             return;
         }
     }
     if (TemplateDeclaration *td = od->aliassym->isTemplateDeclaration())
     {
         if (!od->hasOverloads || td->overnext == NULL)
         {
             td->accept(this);
             return;
         }
     }
     visit((Dsymbol *)od);
 }
Example #3
0
 /******************************************************************************
  * Normally FuncDeclaration and FuncAliasDeclaration have overloads.
  * If and only if there is no overloads, mangle() could return
  * exact mangled name.
  *
  *      module test;
  *      void foo(long) {}           // _D4test3fooFlZv
  *      void foo(string) {}         // _D4test3fooFAyaZv
  *
  *      // from FuncDeclaration::mangle().
  *      pragma(msg, foo.mangleof);  // prints unexact mangled name "4test3foo"
  *                                  // by calling Dsymbol::mangle()
  *
  *      // from FuncAliasDeclaration::mangle()
  *      pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof);  // "_D4test3fooFlZv"
  *      pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof);  // "_D4test3fooFAyaZv"
  *
  * If a function has no overloads, .mangleof property still returns exact mangled name.
  *
  *      void bar() {}
  *      pragma(msg, bar.mangleof);  // still prints "_D4test3barFZv"
  *                                  // by calling FuncDeclaration::mangleExact().
  */
 void visit(FuncDeclaration *fd)
 {
     if (fd->isUnique())
         mangleExact(fd);
     else
         visit((Dsymbol *)fd);
 }
Example #4
0
    void visit(TemplateInstance *ti)
    {
        OutBuffer buf;

    #if 0
        printf("TemplateInstance::mangle() %p %s", ti, ti->toChars());
        if (ti->parent)
            printf("  parent = %s %s", ti->parent->kind(), ti->parent->toChars());
        printf("\n");
    #endif
        ti->getIdent();
        const char *id = ti->ident ? ti->ident->toChars() : ti->toChars();
        if (!ti->tempdecl)
            ti->error("is not defined");
        else
        {
            Dsymbol *par = ti->isTemplateMixin() ? ti->parent : ti->tempdecl->parent;
            if (par)
            {
                FuncDeclaration *f = par->isFuncDeclaration();
                if (f)
                    mangleExact(f);
                else
                    par->accept(this);
                if (result[0] == '_' && result[1] == 'D')
                    result += 2;
                buf.writestring(result);
            }
        }
        buf.printf("%llu%s", (ulonglong)strlen(id), id);
        id = buf.extractString();
        //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id);
        result = id;
    }
Example #5
0
/**
 * Replaces <<func>> with the name of the currently codegen'd function.
 *
 * This kludge is required to handle labels correctly, as the instruction
 * strings for jumps, … are generated during semantic3, but attribute inference
 * might change the function type (and hence the mangled name) right at the end
 * of semantic3.
 */
static void replace_func_name(IRState *p, std::string &insnt) {
  static const std::string needle("<<func>>");

  const char *mangle = mangleExact(p->func()->decl);

  size_t pos;
  while (std::string::npos != (pos = insnt.find(needle))) {
    // This will only happen for few instructions, and only once for those.
    insnt.replace(pos, needle.size(), mangle);
  }
}
Example #6
0
std::string getIRMangledName(FuncDeclaration *fdecl, LINK link) {
  std::string mangledName = mangleExact(fdecl);

  // Hash the name if necessary
  if (((link == LINKd) || (link == LINKdefault)) &&
      (global.params.hashThreshold != 0) &&
      (mangledName.length() > global.params.hashThreshold)) {

    auto hashedName = hashSymbolName(mangledName, fdecl);
    mangledName = "_D" + hashedName + "Z";
  }

  // TODO: Cache the result?

  return getIRMangledFuncName(std::move(mangledName), link);
}
Example #7
0
 // ditto
 void visit(FuncAliasDeclaration *fd)
 {
     FuncDeclaration *f = fd->toAliasFunc();
     FuncAliasDeclaration *fa = f->isFuncAliasDeclaration();
     if (!fd->hasOverloads && !fa)
     {
         mangleExact(f);
         return;
     }
     if (fa)
     {
         fa->accept(this);
         return;
     }
     visit((Dsymbol *)fd);
 }
Example #8
0
        void visit(FuncDeclaration *fd)
        {
            if (!fd->csym)
            {
                const char *id = mangleExact(fd);

                //printf("FuncDeclaration::toSymbol(%s %s)\n", fd->kind(), fd->toChars());
                //printf("\tid = '%s'\n", id);
                //printf("\ttype = %s\n", fd->type->toChars());
                Symbol *s = symbol_calloc(id);
                slist_add(s);

                s->prettyIdent = fd->toPrettyChars();
                s->Sclass = SCglobal;
                symbol_func(s);
                func_t *f = s->Sfunc;
                if (fd->isVirtual() && fd->vtblIndex != -1)
                    f->Fflags |= Fvirtual;
                else if (fd->isMember2() && fd->isStatic())
                    f->Fflags |= Fstatic;
                f->Fstartline.Slinnum = fd->loc.linnum;
                f->Fstartline.Scharnum = fd->loc.charnum;
                f->Fstartline.Sfilename = (char *)fd->loc.filename;
                if (fd->endloc.linnum)
                {
                    f->Fendline.Slinnum = fd->endloc.linnum;
                    f->Fendline.Scharnum = fd->endloc.charnum;
                    f->Fendline.Sfilename = (char *)fd->endloc.filename;
                }
                else
                {
                    f->Fendline.Slinnum = fd->loc.linnum;
                    f->Fendline.Scharnum = fd->loc.charnum;
                    f->Fendline.Sfilename = (char *)fd->loc.filename;
                }
                TYPE *t = Type_toCtype(fd->type);

                mangle_t msave = t->Tmangle;
                if (fd->isMain())
                {
                    t->Tty = TYnfunc;
                    t->Tmangle = mTYman_c;
                }
                else
                {
                    switch (fd->linkage)
                    {
                    case LINKwindows:
                        t->Tmangle = mTYman_std;
                        break;

                    case LINKpascal:
                        t->Tty = TYnpfunc;
                        t->Tmangle = mTYman_pas;
                        break;

                    case LINKc:
                        t->Tmangle = mTYman_c;
                        break;

                    case LINKd:
                        t->Tmangle = mTYman_d;
                        break;
                    case LINKcpp:
                        s->Sflags |= SFLpublic;
                        if (fd->isThis() && !global.params.is64bit && global.params.isWindows)
                        {
                            if (((TypeFunction *)fd->type)->varargs == 1)
                            {
                                t->Tty = TYnfunc;
                            }
                            else
                            {
                                t->Tty = TYmfunc;
                            }
                        }
                        t->Tmangle = mTYman_d;
                        break;
                    default:
                        printf("linkage = %d\n", fd->linkage);
                        assert(0);
                    }
                }

                if (msave)
                    assert(msave == t->Tmangle);
                //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
                t->Tcount++;
                s->Stype = t;
                //s->Sfielddef = this;

                fd->csym = s;
            }
            result = fd->csym;
        }
Example #9
0
/*******************************************
 * Convert intrinsic function to operator.
 * Returns that operator, -1 if not an intrinsic function.
 */
int intrinsic_op(FuncDeclaration *fd)
{
    fd = fd->toAliasFunc();
    const char *name = mangleExact(fd);
    //printf("intrinsic_op(%s)\n", name);
    static const char *std_namearray[] =
    {
        /* The names are mangled differently because of the pure and
         * nothrow attributes.
         */
        "4math3cosFNaNbNiNfeZe",
        "4math3sinFNaNbNiNfeZe",
        "4math4fabsFNaNbNiNfeZe",
        "4math4rintFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNfdZd",
        "4math4sqrtFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNffZf",
        "4math4yl2xFNaNbNiNfeeZe",
        "4math5ldexpFNaNbNiNfeiZe",
        "4math6rndtolFNaNbNiNfeZl",
        "4math6yl2xp1FNaNbNiNfeeZe",
    };
    static const char *std_namearray64[] =
    {
        /* The names are mangled differently because of the pure and
         * nothrow attributes.
         */
        "4math3cosFNaNbNiNfeZe",
        "4math3sinFNaNbNiNfeZe",
        "4math4fabsFNaNbNiNfeZe",
        "4math4rintFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNfdZd",
        "4math4sqrtFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNffZf",
        "4math4yl2xFNaNbNiNfeeZe",
        "4math5ldexpFNaNbNiNfeiZe",
        "4math6rndtolFNaNbNiNfeZl",
        "4math6yl2xp1FNaNbNiNfeeZe",
    };
    static unsigned char std_ioptab[] =
    {
        OPcos,
        OPsin,
        OPabs,
        OPrint,
        OPsqrt,
        OPsqrt,
        OPsqrt,
        OPyl2x,
        OPscale,
        OPrndtol,
        OPyl2xp1,
    };

    static const char *core_namearray[] =
    {
        "4math3cosFNaNbNiNfeZe",
        "4math3sinFNaNbNiNfeZe",
        "4math4fabsFNaNbNiNfeZe",
        "4math4rintFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNfdZd",
        "4math4sqrtFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNffZf",
        "4math4yl2xFNaNbNiNfeeZe",
        "4math5ldexpFNaNbNiNfeiZe",
        "4math6rndtolFNaNbNiNfeZl",
        "4math6yl2xp1FNaNbNiNfeeZe",

        "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
        "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMdNhG16vZNhG16v",
        "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMfNhG16vZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vhZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMdZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMfZNhG16v",
        "4simd9__simd_ibFNaNbNiNfE4core4simd3XMMNhG16vhZNhG16v",

        "5bitop12volatileLoadFNbNiNfPhZh",
        "5bitop12volatileLoadFNbNiNfPkZk",
        "5bitop12volatileLoadFNbNiNfPmZm",
        "5bitop12volatileLoadFNbNiNfPtZt",

        "5bitop13volatileStoreFNbNiNfPhhZv",
        "5bitop13volatileStoreFNbNiNfPkkZv",
        "5bitop13volatileStoreFNbNiNfPmmZv",
        "5bitop13volatileStoreFNbNiNfPttZv",

        "5bitop3bsfFNaNbNiNfkZi",
        "5bitop3bsrFNaNbNiNfkZi",
        "5bitop3btcFNaNbNiPkkZi",
        "5bitop3btrFNaNbNiPkkZi",
        "5bitop3btsFNaNbNiPkkZi",
        "5bitop3inpFNbNikZh",
        "5bitop4inplFNbNikZk",
        "5bitop4inpwFNbNikZt",
        "5bitop4outpFNbNikhZh",
        "5bitop5bswapFNaNbNiNfkZk",
        "5bitop5outplFNbNikkZk",
        "5bitop5outpwFNbNiktZt",

        "5bitop7_popcntFNaNbNiNfkZi",
        "5bitop7_popcntFNaNbNiNfmxx", // don't find 64 bit version in 32 bit code
        "5bitop7_popcntFNaNbNiNftZt",
    };
    static const char *core_namearray64[] =
    {
        "4math3cosFNaNbNiNfeZe",
        "4math3sinFNaNbNiNfeZe",
        "4math4fabsFNaNbNiNfeZe",
        "4math4rintFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNfdZd",
        "4math4sqrtFNaNbNiNfeZe",
        "4math4sqrtFNaNbNiNffZf",
        "4math4yl2xFNaNbNiNfeeZe",
        "4math5ldexpFNaNbNiNfeiZe",
        "4math6rndtolFNaNbNiNfeZl",
        "4math6yl2xp1FNaNbNiNfeeZe",

        "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
        "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMdNhG16vZNhG16v",
        "4simd10__simd_stoFNaNbNiNfE4core4simd3XMMfNhG16vZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vNhG16vhZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMNhG16vZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMdZNhG16v",
        "4simd6__simdFNaNbNiNfE4core4simd3XMMfZNhG16v",
        "4simd9__simd_ibFNaNbNiNfE4core4simd3XMMNhG16vhZNhG16v",

        "5bitop12volatileLoadFNbNiNfPhZh",
        "5bitop12volatileLoadFNbNiNfPkZk",
        "5bitop12volatileLoadFNbNiNfPmZm",
        "5bitop12volatileLoadFNbNiNfPtZt",

        "5bitop13volatileStoreFNbNiNfPhhZv",
        "5bitop13volatileStoreFNbNiNfPkkZv",
        "5bitop13volatileStoreFNbNiNfPmmZv",
        "5bitop13volatileStoreFNbNiNfPttZv",

        "5bitop3bsfFNaNbNiNfmZi",
        "5bitop3bsrFNaNbNiNfmZi",
        "5bitop3btcFNaNbNiPmmZi",
        "5bitop3btrFNaNbNiPmmZi",
        "5bitop3btsFNaNbNiPmmZi",
        "5bitop3inpFNbNikZh",
        "5bitop4inplFNbNikZk",
        "5bitop4inpwFNbNikZt",
        "5bitop4outpFNbNikhZh",
        "5bitop5bswapFNaNbNiNfkZk",
        "5bitop5outplFNbNikkZk",
        "5bitop5outpwFNbNiktZt",

        "5bitop7_popcntFNaNbNiNfkZi",
        "5bitop7_popcntFNaNbNiNfmZi",
        "5bitop7_popcntFNaNbNiNftZt",
    };
    static unsigned char core_ioptab[] =
    {
        OPcos,
        OPsin,
        OPabs,
        OPrint,
        OPsqrt,
        OPsqrt,
        OPsqrt,
        OPyl2x,
        OPscale,
        OPrndtol,
        OPyl2xp1,

        OPvector,
        OPvector,
        OPvector,
        OPvector,
        OPvector,
        OPvector,
        OPvector,
        OPvector,
        OPvector,

        OPind,
        OPind,
        OPind,
        OPind,

        OPeq,
        OPeq,
        OPeq,
        OPeq,

        OPbsf,
        OPbsr,
        OPbtc,
        OPbtr,
        OPbts,
        OPinp,
        OPinp,
        OPinp,
        OPoutp,

        OPbswap,
        OPoutp,
        OPoutp,

        OPpopcnt,
        OPpopcnt,
        OPpopcnt,
    };

#ifdef DEBUG
    assert(sizeof(std_namearray) == sizeof(std_namearray64));
    assert(sizeof(std_namearray) / sizeof(char *) == sizeof(std_ioptab));
    for (size_t i = 0; i < sizeof(std_namearray) / sizeof(char *) - 1; i++)
    {
        if (strcmp(std_namearray[i], std_namearray[i + 1]) >= 0)
        {
            printf("std_namearray[%ld] = '%s'\n", (long)i, std_namearray[i]);
            assert(0);
        }
    }
    assert(sizeof(std_namearray64) / sizeof(char *) == sizeof(std_ioptab));
    for (size_t i = 0; i < sizeof(std_namearray64) / sizeof(char *) - 1; i++)
    {
        if (strcmp(std_namearray64[i], std_namearray64[i + 1]) >= 0)
        {
            printf("std_namearray64[%ld] = '%s'\n", (long)i, std_namearray64[i]);
            assert(0);
        }
    }
    assert(sizeof(core_namearray) == sizeof(core_namearray64));
    assert(sizeof(core_namearray) / sizeof(char *) == sizeof(core_ioptab));
    for (size_t i = 0; i < sizeof(core_namearray) / sizeof(char *) - 1; i++)
    {
        //printf("test1 %s %s %d\n", core_namearray[i], core_namearray[i + 1], strcmp(core_namearray[i], core_namearray[i + 1]));
        if (strcmp(core_namearray[i], core_namearray[i + 1]) >= 0)
        {
            printf("core_namearray[%ld] = '%s'\n", (long)i, core_namearray[i]);
            assert(0);
        }
    }
    assert(sizeof(core_namearray64) / sizeof(char *) == sizeof(core_ioptab));
    for (size_t i = 0; i < sizeof(core_namearray64) / sizeof(char *) - 1; i++)
    {
        if (strcmp(core_namearray64[i], core_namearray64[i + 1]) >= 0)
        {
            printf("core_namearray64[%ld] = '%s'\n", (long)i, core_namearray64[i]);
            assert(0);
        }
    }
#endif
    size_t length = strlen(name);

    if (length > 10 &&
        (name[7] == 'm' || name[7] == 'i') &&
        !memcmp(name, "_D3std", 6))
    {
        int i = binary(name + 6, I64 ? std_namearray64 : std_namearray, sizeof(std_namearray) / sizeof(char *));
        return (i == -1) ? i : std_ioptab[i];
    }
    if (length > 12 &&
        (name[8] == 'm' || name[8] == 'b' || name[8] == 's') &&
        !memcmp(name, "_D4core", 7))
    {
        int i = binary(name + 7, I64 ? core_namearray64 : core_namearray, sizeof(core_namearray) / sizeof(char *));
        if (i != -1)
            return core_ioptab[i];

        if (global.params.is64bit &&
            fd->toParent()->isTemplateInstance() &&
            !strcmp(mangle(fd->getModule()), "4core4stdc6stdarg") &&
            fd->ident == Id::va_start)
        {
            return OPva_start;
        }

        return -1;
    }

    return -1;
}
Example #10
0
Symbol *FuncDeclaration::toSymbol()
{
    if (!csym)
    {   Symbol *s;
        TYPE *t;
        const char *id;

#if 0
        id = ident->toChars();
#else
        id = mangleExact();
#endif
        //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
        //printf("\tid = '%s'\n", id);
        //printf("\ttype = %s\n", type->toChars());
        s = symbol_calloc(id);
        slist_add(s);

        {
            s->prettyIdent = toPrettyChars();
            s->Sclass = SCglobal;
            symbol_func(s);
            func_t *f = s->Sfunc;
            if (isVirtual() && vtblIndex != -1)
                f->Fflags |= Fvirtual;
            else if (isMember2() && isStatic())
                f->Fflags |= Fstatic;
            f->Fstartline.Slinnum = loc.linnum;
            f->Fstartline.Sfilename = (char *)loc.filename;
            if (endloc.linnum)
            {   f->Fendline.Slinnum = endloc.linnum;
                f->Fendline.Sfilename = (char *)endloc.filename;
            }
            else
            {   f->Fendline.Slinnum = loc.linnum;
                f->Fendline.Sfilename = (char *)loc.filename;
            }
            t = type->toCtype();
        }

        mangle_t msave = t->Tmangle;
        if (isMain())
        {
            t->Tty = TYnfunc;
            t->Tmangle = mTYman_c;
        }
        else
        {
            switch (linkage)
            {
                case LINKwindows:
                    t->Tmangle = mTYman_std;
                    break;

                case LINKpascal:
                    t->Tty = TYnpfunc;
                    t->Tmangle = mTYman_pas;
                    break;

                case LINKc:
                    t->Tmangle = mTYman_c;
                    break;

                case LINKd:
                    t->Tmangle = mTYman_d;
                    break;

                case LINKcpp:
                {   t->Tmangle = mTYman_cpp;
                    if (isThis() && !global.params.is64bit && global.params.isWindows)
                    {
                        if (((TypeFunction *)type)->varargs == 1)
                            t->Tty = TYnfunc;
                        else
                            t->Tty = TYmfunc;
                    }
                    s->Sflags |= SFLpublic;
                    Dsymbol *parent = toParent();
                    ClassDeclaration *cd = parent->isClassDeclaration();
                    if (cd)
                    {
                        ::type *tc = cd->type->toCtype();
                        s->Sscope = tc->Tnext->Ttag;
                    }
                    StructDeclaration *sd = parent->isStructDeclaration();
                    if (sd)
                    {
                        ::type *ts = sd->type->toCtype();
                        s->Sscope = ts->Ttag;
                    }
                    if (isCtorDeclaration())
                        s->Sfunc->Fflags |= Fctor;
                    if (isDtorDeclaration())
                        s->Sfunc->Fflags |= Fdtor;
                    break;
                }
                default:
                    printf("linkage = %d\n", linkage);
                    assert(0);
            }
        }
        if (msave)
            assert(msave == t->Tmangle);
        //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
        t->Tcount++;
        s->Stype = t;
        //s->Sfielddef = this;

        csym = s;
    }
    return csym;
}
Example #11
0
void DtoDeclareFunction(FuncDeclaration* fdecl)
{
    DtoResolveFunction(fdecl);

    if (fdecl->ir.isDeclared()) return;
    fdecl->ir.setDeclared();

    IF_LOG Logger::println("DtoDeclareFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars());
    LOG_SCOPE;

    if (fdecl->isUnitTestDeclaration() && !global.params.useUnitTests)
    {
        Logger::println("unit tests not enabled");
        return;
    }

    //printf("declare function: %s\n", fdecl->toPrettyChars());

    // intrinsic sanity check
    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
        error(fdecl->loc, "intrinsics cannot have function bodies");
        fatal();
    }

    // get TypeFunction*
    Type* t = fdecl->type->toBasetype();
    TypeFunction* f = static_cast<TypeFunction*>(t);

    // create IrFunction
    IrFunction *irFunc = getIrFunc(fdecl, true);

    LLFunction* vafunc = 0;
    if (DtoIsVaIntrinsic(fdecl))
        vafunc = DtoDeclareVaFunction(fdecl);

    // calling convention
    LINK link = f->linkage;
    if (vafunc || fdecl->llvmInternal == LLVMintrinsic
        // DMD treats _Dmain as having C calling convention and this has been
        // hardcoded into druntime, even if the frontend type has D linkage.
        // See Bugzilla issue 9028.
        || fdecl->isMain()
    )
    {
        link = LINKc;
    }

    // mangled name
    std::string mangledName(mangleExact(fdecl));
    mangledName = gABI->mangleForLLVM(mangledName, link);

    // construct function
    LLFunctionType* functype = DtoFunctionType(fdecl);
    LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName);
    if (!func) {
        if(fdecl->llvmInternal == LLVMinline_ir)
        {
            func = DtoInlineIRFunction(fdecl);
        }
        else
        {
            // All function declarations are "external" - any other linkage type
            // is set when actually defining the function.
            func = LLFunction::Create(functype,
                llvm::GlobalValue::ExternalLinkage, mangledName, gIR->module);
        }
    } else if (func->getFunctionType() != functype) {
        error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", mangleExact(fdecl));
        fatal();
    }

    func->setCallingConv(gABI->callingConv(link));

    IF_LOG Logger::cout() << "func = " << *func << std::endl;

    // add func to IRFunc
    irFunc->func = func;

    // parameter attributes
    if (!DtoIsIntrinsic(fdecl)) {
        set_param_attrs(f, func, fdecl);
        if (global.params.disableRedZone) {
            func->addFnAttr(LDC_ATTRIBUTE(NoRedZone));
        }
    }

    // main
    if (fdecl->isMain()) {
        // Detect multiple main functions, which is disallowed. DMD checks this
        // in the glue code, so we need to do it here as well.
        if (gIR->mainFunc) {
            error(fdecl->loc, "only one main function allowed");
        }
        gIR->mainFunc = func;
    }

    if (fdecl->neverInline)
    {
        irFunc->setNeverInline();
    }

    if (fdecl->llvmInternal == LLVMglobal_crt_ctor || fdecl->llvmInternal == LLVMglobal_crt_dtor)
    {
        AppendFunctionToLLVMGlobalCtorsDtors(func, fdecl->priority, fdecl->llvmInternal == LLVMglobal_crt_ctor);
    }

    IrFuncTy &irFty = irFunc->irFty;

    // if (!declareOnly)
    {
        // name parameters
        llvm::Function::arg_iterator iarg = func->arg_begin();

        if (irFty.arg_sret) {
            iarg->setName(".sret_arg");
            irFunc->retArg = iarg;
            ++iarg;
        }

        if (irFty.arg_this) {
            iarg->setName(".this_arg");
            irFunc->thisArg = iarg;

            VarDeclaration* v = fdecl->vthis;
            if (v) {
                // We already build the this argument here if we will need it
                // later for codegen'ing the function, just as normal
                // parameters below, because it can be referred to in nested
                // context types. Will be given storage in DtoDefineFunction.
                assert(!isIrParameterCreated(v));
                IrParameter *irParam = getIrParameter(v, true);
                irParam->value = iarg;
                irParam->arg = irFty.arg_this;
                irParam->isVthis = true;
            }

            ++iarg;
        }
        else if (irFty.arg_nest) {
            iarg->setName(".nest_arg");
            irFunc->nestArg = iarg;
            assert(irFunc->nestArg);
            ++iarg;
        }

        if (irFty.arg_arguments) {
            iarg->setName("._arguments");
            irFunc->_arguments = iarg;
            ++iarg;
        }

        // we never reference parameters of function prototypes
        unsigned int k = 0;
        for (; iarg != func->arg_end(); ++iarg)
        {
            if (fdecl->parameters && fdecl->parameters->dim > k)
            {
                int paramIndex = irFty.reverseParams ? fdecl->parameters->dim-k-1 : k;
                Dsymbol* argsym = static_cast<Dsymbol*>(fdecl->parameters->data[paramIndex]);

                VarDeclaration* argvd = argsym->isVarDeclaration();
                assert(argvd);
                assert(!isIrLocalCreated(argvd));
                std::string str(argvd->ident->toChars());
                str.append("_arg");
                iarg->setName(str);

                IrParameter *irParam = getIrParameter(argvd, true);
                irParam->value = iarg;
                irParam->arg = irFty.args[paramIndex];

                k++;
            }
            else
            {
                iarg->setName("unnamed");
            }
        }
    }
}
Example #12
0
LLFunction* DtoInlineIRFunction(FuncDeclaration* fdecl)
{
    const char* mangled_name = mangleExact(fdecl);
    TemplateInstance* tinst = fdecl->parent->isTemplateInstance();
    assert(tinst);

    Objects& objs = tinst->tdtypes;
    assert(objs.dim == 3);

    Expression* a0 = isExpression(objs[0]);
    assert(a0);
    StringExp* strexp = a0->toStringExp();
    assert(strexp);
    assert(strexp->sz == 1);
    std::string code(static_cast<char*>(strexp->string), strexp->len);

    Type* ret = isType(objs[1]);
    assert(ret);

    Tuple* a2 = isTuple(objs[2]);
    assert(a2);
    Objects& arg_types = a2->objects;

    std::string str;
    llvm::raw_string_ostream stream(str);
    stream << "define " << *DtoType(ret) << " @" << mangled_name << "(";

    for(size_t i = 0; ;)
    {
        Type* ty = isType(arg_types[i]);
        //assert(ty);
        if(!ty)
        {
            error(tinst->loc,
                "All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types");
            fatal();
        }
        stream << *DtoType(ty);

        i++;
        if(i >= arg_types.dim)
            break;

        stream << ", ";
    }

    if(ret->ty == Tvoid)
        code.append("\nret void");

    stream << ")\n{\n" << code <<  "\n}";

    llvm::SMDiagnostic err;

#if LDC_LLVM_VER >= 306
    std::unique_ptr<llvm::Module> m = llvm::parseAssemblyString(
        stream.str().c_str(), err, gIR->context());
#elif LDC_LLVM_VER >= 303
    llvm::Module* m = llvm::ParseAssemblyString(
        stream.str().c_str(), NULL, err, gIR->context());
#else
    llvm::ParseAssemblyString(
        stream.str().c_str(), gIR->module, err, gIR->context());
#endif

    std::string errstr = err.getMessage();
    if(errstr != "")
        error(tinst->loc,
            "can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s",
#if LDC_LLVM_VER >= 303
            err.getLineContents().str().c_str(),
#else
            err.getLineContents().c_str(),
#endif
            (std::string(err.getColumnNo(), ' ') + '^').c_str(),
            errstr.c_str(), stream.str().c_str());

#if LDC_LLVM_VER >= 306
    llvm::Linker(gIR->module).linkInModule(m.get());
#else
#if LDC_LLVM_VER >= 303
    std::string errstr2 = "";
#if LDC_LLVM_VER >= 306
    llvm::Linker(gIR->module).linkInModule(m.get(), &errstr2);
#else
    llvm::Linker(gIR->module).linkInModule(m, &errstr2);
#endif
    if(errstr2 != "")
        error(tinst->loc,
            "Error when linking in llvm inline ir: %s", errstr2.c_str());
#endif
#endif

    LLFunction* fun = gIR->module->getFunction(mangled_name);
    fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
    fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline));
    return fun;
}