Exemple #1
0
type *type_static_array(targ_size_t dim, type *tnext)
{
    type *t = type_allocn(TYarray, tnext);
    t->Tdim = dim;
    t->Tcount++;
    return t;
}
Exemple #2
0
type *TypeFunction::toCtype()
{   type *t;

    if (ctype)
        return ctype;

    if (1)
    {
        param_t *paramtypes = NULL;
        size_t nparams = Parameter::dim(parameters);
        for (size_t i = 0; i < nparams; i++)
        {   Parameter *arg = Parameter::getNth(parameters, i);
            type *tp = arg->type->toCtype();
            if (arg->storageClass & (STCout | STCref))
            {   // C doesn't have reference types, so it's really a pointer
                // to the parameter type
                tp = type_allocn(TYref, tp);
            }
            param_append_type(&paramtypes,tp);
        }
        tym_t tyf = totym();
        t = type_alloc(tyf);
        t->Tflags |= TFprototype;
        if (varargs != 1)
            t->Tflags |= TFfixed;
        ctype = t;
        assert(next);           // function return type should exist
        t->Tnext = next->toCtype();
        t->Tnext->Tcount++;
        t->Tparamtypes = paramtypes;
    }
    ctype = t;
    return t;
}
Exemple #3
0
type *TypeFunction::toCtype()
{
    if (!ctype)
    {
        size_t nparams = Parameter::dim(parameters);

        type *tmp[10];
        type **ptypes = tmp;
        if (nparams > 10)
            ptypes = (type **)malloc(sizeof(type*) * nparams);

        for (size_t i = 0; i < nparams; i++)
        {   Parameter *arg = Parameter::getNth(parameters, i);
            type *tp = arg->type->toCtype();
            if (arg->storageClass & (STCout | STCref))
                tp = type_allocn(TYref, tp);
            ptypes[i] = tp;
        }

        type* tnext = next ? next->toCtype() : tsvoid;
        ctype = type_function(totym(), ptypes, nparams, varargs == 1, tnext);

        if (nparams > 10)
            free(ptypes);
    }
    return ctype;
}
Exemple #4
0
    void visit(TypeFunction *t)
    {
        size_t nparams = Parameter::dim(t->parameters);

        type *tmp[10];
        type **ptypes = tmp;
        if (nparams > 10)
            ptypes = (type **)malloc(sizeof(type*) * nparams);

        for (size_t i = 0; i < nparams; i++)
        {
            Parameter *p = Parameter::getNth(t->parameters, i);
            type *tp = Type_toCtype(p->type);
            if (p->storageClass & (STCout | STCref))
                tp = type_allocn(TYref, tp);
            else if (p->storageClass & STClazy)
            {
                // Mangle as delegate
                type *tf = type_function(TYnfunc, NULL, 0, false, tp);
                tp = type_delegate(tf);
            }
            ptypes[i] = tp;
        }

        t->ctype = type_function(totym(t), ptypes, nparams, t->varargs == 1, Type_toCtype(t->next));

        if (nparams > 10)
            free(ptypes);
    }
Exemple #5
0
type *type_assoc_array(type *tkey, type *tvalue)
{
    type *t = type_allocn(TYaarray, tvalue);
    t->Tkey = tkey;
    tkey->Tcount++;
    t->Tcount++;
    return t;
}
Exemple #6
0
type *TypeAArray::toCtype()
{   type *t;

    if (ctype)
        return ctype;

    if (0 && global.params.symdebug)
    {
        /* An associative array is represented by:
         *      struct AArray { size_t length; void* ptr; }
         */

        static Symbol *s;

        if (!s)
        {
            s = symbol_calloc("_AArray");
            s->Sclass = SCstruct;
            s->Sstruct = struct_calloc();
            s->Sstruct->Sflags |= 0;
            s->Sstruct->Salignsize = alignsize();
            s->Sstruct->Sstructalign = global.structalign;
            s->Sstruct->Sstructsize = size(0);
            slist_add(s);

            Symbol *s1 = symbol_name("length", SCmember, Type::tsize_t->toCtype());
            list_append(&s->Sstruct->Sfldlst, s1);

            Symbol *s2 = symbol_name("data", SCmember, Type::tvoidptr->toCtype());
            s2->Smemoff = Type::tsize_t->size();
            list_append(&s->Sstruct->Sfldlst, s2);
        }

        t = type_alloc(TYstruct);
        t->Ttag = (Classsym *)s;                // structure tag name
        t->Tcount++;
        s->Stype = t;
    }
    else
    {
        if (global.params.symdebug == 1)
        {
            /* Generate D symbolic debug info, rather than C
             *   Tnext: element type
             *   Tkey: key type
             */
            t = type_allocn(TYaarray, next->toCtype());
            t->Tkey = index->toCtype();
            t->Tkey->Tcount++;
        }
        else
            t = type_fake(TYaarray);
    }
    t->Tcount++;
    ctype = t;
    return t;
}
Exemple #7
0
type *TypeSArray::toCtype()
{
    if (!ctype)
    {   type *tn;

        tn = next->toCtype();
        ctype = type_allocn(TYarray, tn);
        ctype->Tdim = dim->toInteger();
    }
    return ctype;
}
Exemple #8
0
type *type_allocmemptr(Classsym *stag,type *tn)
{   type *t;

    symbol_debug(stag);
    assert(stag->Sclass == SCstruct || tybasic(stag->Stype->Tty) == TYident);
    t = type_allocn(TYmemptr,tn);
    t->Ttag = stag;
    //printf("type_allocmemptr() = %p\n", t);
    //type_print(t);
    return t;
}
Exemple #9
0
type *TypeDelegate::toCtype()
{   type *t;

    if (ctype)
        return ctype;

    if (0 && global.params.symdebug)
    {
        /* A delegate consists of:
         *    _Delegate { void* frameptr; Function *funcptr; }
         */

        static Symbol *s;

        if (!s)
        {
            s = symbol_calloc("_Delegate");
            s->Sclass = SCstruct;
            s->Sstruct = struct_calloc();
            s->Sstruct->Sflags |= 0;
            s->Sstruct->Salignsize = alignsize();
            s->Sstruct->Sstructalign = global.structalign;
            s->Sstruct->Sstructsize = size(0);
            slist_add(s);

            Symbol *s1 = symbol_name("frameptr", SCmember, Type::tvoidptr->toCtype());
            list_append(&s->Sstruct->Sfldlst, s1);

            Symbol *s2 = symbol_name("funcptr", SCmember, Type::tvoidptr->toCtype());
            s2->Smemoff = Type::tvoidptr->size();
            list_append(&s->Sstruct->Sfldlst, s2);
        }

        t = type_alloc(TYstruct);
        t->Ttag = (Classsym *)s;                // structure tag name
        t->Tcount++;
        s->Stype = t;
    }
    else
    {
        if (global.params.symdebug == 1)
        {
            // Generate D symbolic debug info, rather than C
            t = type_allocn(TYdelegate, next->toCtype());
        }
        else
            t = type_fake(TYdelegate);
    }

    t->Tcount++;
    ctype = t;
    return t;
}
Exemple #10
0
type *TypeDArray::toCtype()
{   type *t;

    if (ctype)
        return ctype;

    if (0 && global.params.symdebug)
    {
        /* Create a C type out of:
         *      struct _Array_T { size_t length; T* data; }
         */
        Symbol *s;
        char *id;

        assert(next->deco);
        id = (char *) alloca(7 + strlen(next->deco) + 1);
        sprintf(id, "_Array_%s", next->deco);
        s = symbol_calloc(id);
        s->Sclass = SCstruct;
        s->Sstruct = struct_calloc();
        s->Sstruct->Sflags |= 0;
        s->Sstruct->Salignsize = alignsize();
        s->Sstruct->Sstructalign = global.structalign;
        s->Sstruct->Sstructsize = size(0);
        slist_add(s);

        Symbol *s1 = symbol_name("length", SCmember, Type::tsize_t->toCtype());
        list_append(&s->Sstruct->Sfldlst, s1);

        Symbol *s2 = symbol_name("data", SCmember, next->pointerTo()->toCtype());
        s2->Smemoff = Type::tsize_t->size();
        list_append(&s->Sstruct->Sfldlst, s2);

        t = type_alloc(TYstruct);
        t->Ttag = (Classsym *)s;                // structure tag name
        t->Tcount++;
        s->Stype = t;
    }
    else
    {
        if (global.params.symdebug == 1)
        {
            // Generate D symbolic debug info, rather than C
            t = type_allocn(TYdarray, next->toCtype());
        }
        else
            t = type_fake(TYdarray);
    }
    t->Tcount++;
    ctype = t;
    return t;
}
Exemple #11
0
/***************************************
 * Create an enum type.
 * Input:
 *      name    name of enum
 *      tbase   "base" type of enum
 * Returns:
 *      Tcount already incremented
 */
type *type_enum(const char *name, type *tbase)
{
    Symbol *s = symbol_calloc(name);
    s->Sclass = SCenum;
    s->Senum = (enum_t *) MEM_PH_CALLOC(sizeof(enum_t));
    s->Senum->SEflags |= SENforward;        // forward reference

    type *t = type_allocn(TYenum, tbase);
    t->Ttag = (Classsym *)s;            // enum tag name
    t->Tcount++;
    s->Stype = t;
    t->Tcount++;
    return t;
}
Exemple #12
0
STATIC void cpp_this_type(type *tfunc,Classsym *stag)
{   type *t;

    type_debug(tfunc);
    symbol_debug(stag);
#if MARS
    t = type_allocn(TYnptr, stag->Stype);
    t->Tcount++;
#else
    t = cpp_thistype(tfunc,stag);
#endif
    //cpp_data_indirect_type(t);
    cpp_ecsu_data_indirect_type(t);
    type_free(t);
}
Exemple #13
0
type *type_function(tym_t tyf, type **ptypes, size_t nparams, bool variadic, type *tret)
{
    param_t *paramtypes = NULL;
    for (size_t i = 0; i < nparams; i++)
    {
        param_append_type(&paramtypes, ptypes[i]);
    }
    type *t = type_allocn(tyf, tret);
    t->Tflags |= TFprototype;
    if (!variadic)
        t->Tflags |= TFfixed;
    t->Tparamtypes = paramtypes;
    t->Tcount++;
    return t;
}
Exemple #14
0
Symbol *objc_getImageInfo()
{
    assert(!objc_simageInfo); // only allow once per object file
    objc_hasSymbols = true;

    dt_t *dt = NULL;
    dtdword(&dt, 0); // version
    dtdword(&dt, 0); // flags

    objc_simageInfo = symbol_name("L_OBJC_IMAGE_INFO", SCstatic, type_allocn(TYarray, tschar));
    objc_simageInfo->Sdt = dt;
    objc_simageInfo->Sseg = objc_getSegment(SEGimage_info);
    outdata(objc_simageInfo);

    return objc_simageInfo;
}
Exemple #15
0
Symbol *objc_getModuleInfo()
{
    assert(!objc_smoduleInfo); // only allow once per object file
    objc_hasSymbols = true;

    dt_t *dt = NULL;

    Symbol* symbol = symbol_name("L_OBJC_LABEL_CLASS_$", SCstatic, type_allocn(TYarray, tschar));
    symbol->Sdt = dt;
    symbol->Sseg = objc_getSegment(SEGmodule_info);
    outdata(symbol);

    objc_getImageInfo(); // make sure we also generate image info

    return objc_smoduleInfo;
}
Exemple #16
0
Symbol *toVtblSymbol(ClassDeclaration *cd)
{
    if (!cd->vtblsym)
    {
        if (!cd->csym)
            toSymbol(cd);

        TYPE *t = type_allocn(TYnptr | mTYconst, tsvoid);
        t->Tmangle = mTYman_d;
        Symbol *s = toSymbolX(cd, "__vtbl", SCextern, t, "Z");
        s->Sflags |= SFLnodebug;
        s->Sfl = FLextern;
        cd->vtblsym = s;
        slist_add(s);
    }
    return cd->vtblsym;
}
Exemple #17
0
type *TypeClass::toCtype()
{   type *t;
    Symbol *s;

    //printf("TypeClass::toCtype() %s\n", toChars());
    if (ctype)
        return ctype;

    /* Need this symbol to do C++ name mangling
     */
    const char *name = sym->isCPPinterface() ? sym->ident->toChars()
                                             : sym->toPrettyChars();
    s = symbol_calloc(name);
    s->Sclass = SCstruct;
    s->Sstruct = struct_calloc();
    s->Sstruct->Sflags |= STRclass;
    s->Sstruct->Salignsize = sym->alignsize;
    s->Sstruct->Sstructalign = sym->structalign;
    s->Sstruct->Sstructsize = sym->structsize;

    t = type_alloc(TYstruct);
    t->Ttag = (Classsym *)s;            // structure tag name
    t->Tcount++;
    s->Stype = t;
    slist_add(s);

    t = type_allocn(TYnptr, t);

    t->Tcount++;
    ctype = t;

    /* Add in fields of the class
     * (after setting ctype to avoid infinite recursion)
     */
    if (global.params.symdebug)
        for (int i = 0; i < sym->fields.dim; i++)
        {   VarDeclaration *v = sym->fields.tdata()[i];

            Symbol *s2 = symbol_name(v->ident->toChars(), SCmember, v->type->toCtype());
            s2->Smemoff = v->offset;
            list_append(&s->Sstruct->Sfldlst, s2);
        }

    return t;
}
Exemple #18
0
Symbol *objc_getCString(const char *str, size_t len, const char *symbolName, ObjcSegment segment)
{
    objc_hasSymbols = true;

    // create data
    dt_t *dt = NULL;
    dtnbytes(&dt, len + 1, str);

    // find segment
    int seg = objc_getSegment(segment);

    // create symbol
    Symbol *s;
    s = symbol_name(symbolName, SCstatic, type_allocn(TYarray, tschar));
    s->Sdt = dt;
    s->Sseg = seg;
    return s;
}
Exemple #19
0
Symbol *ClassDeclaration::toVtblSymbol()
{
    if (!vtblsym)
    {
        Symbol *s;
        TYPE *t;

        if (!csym)
            toSymbol();

        t = type_allocn(TYnptr | mTYconst, tsvoid);
        t->Tmangle = mTYman_d;
        s = toSymbolX("__vtbl", SCextern, t, "Z");
        s->Sflags |= SFLnodebug;
        s->Sfl = FLextern;
        vtblsym = s;
        slist_add(s);
    }
    return vtblsym;
}
Exemple #20
0
    void visit(TypeFunction *t)
    {
        size_t nparams = Parameter::dim(t->parameters);

        type *tmp[10];
        type **ptypes = tmp;
        if (nparams > 10)
            ptypes = (type **)malloc(sizeof(type*) * nparams);

        for (size_t i = 0; i < nparams; i++)
        {
            Parameter *arg = Parameter::getNth(t->parameters, i);
            type *tp = Type_toCtype(arg->type);
            if (arg->storageClass & (STCout | STCref))
                tp = type_allocn(TYref, tp);
            ptypes[i] = tp;
        }

        t->ctype = type_function(t->totym(), ptypes, nparams, t->varargs == 1, Type_toCtype(t->next));

        if (nparams > 10)
            free(ptypes);
    }
Exemple #21
0
void type_init()
{   int i;

    tsbool    = type_allocbasic(TYbool);
    tswchar_t = type_allocbasic(TYwchar_t);
    tsdchar   = type_allocbasic(TYdchar);
    tsvoid    = type_allocbasic(TYvoid);
    tsnullptr = type_allocbasic(TYnullptr);
    tschar16  = type_allocbasic(TYchar16);
    tsuchar   = type_allocbasic(TYuchar);
    tsschar   = type_allocbasic(TYschar);
    tschar    = type_allocbasic(TYchar);
    tsshort   = type_allocbasic(TYshort);
    tsushort  = type_allocbasic(TYushort);
    tsint     = type_allocbasic(TYint);
    tsuns     = type_allocbasic(TYuint);
    tslong    = type_allocbasic(TYlong);
    tsulong   = type_allocbasic(TYulong);
    tsllong   = type_allocbasic(TYllong);
    tsullong  = type_allocbasic(TYullong);
    tsfloat   = type_allocbasic(TYfloat);
    tsdouble  = type_allocbasic(TYdouble);
    tsifloat   = type_allocbasic(TYifloat);
    tsidouble  = type_allocbasic(TYidouble);
    tscfloat   = type_allocbasic(TYcfloat);
    tscdouble  = type_allocbasic(TYcdouble);
#if TX86
    tsreal64  = type_allocbasic(TYdouble_alias);
    tsldouble  = type_allocbasic(TYldouble);
    tsildouble  = type_allocbasic(TYildouble);
    tscldouble  = type_allocbasic(TYcldouble);
#else
    tsldouble = type_allocbasic(TYldouble);
    tscomp = type_allocbasic(TYcomp);
    chartype = tschar;                          /* default is signed chars */
#endif
    if (I64)
    {
        TYptrdiff = TYllong;
        TYsize = TYullong;
        tsptrdiff = tsllong;
        tssize = tsullong;
    }
    else
    {
        TYptrdiff = TYint;
        TYsize = TYuint;
        tsptrdiff = tsint;
        tssize = tsuns;
    }

#if TX86
    chartype = (config.flags3 & CFG3ju) ? tsuchar : tschar;

    // Type of far library function
    tsclib =    type_fake(LARGECODE ? TYfpfunc : TYnpfunc);
    tsclib->Tmangle = mTYman_c;
    tsclib->Tcount++;

    // Type of trace function
    tstrace =   type_fake(I16 ? TYffunc : TYnfunc);
    tstrace->Tmangle = mTYman_c;
    tstrace->Tcount++;

    tspvoid = type_allocn(pointertype,tsvoid);
    tspvoid->Tmangle = mTYman_c;
    tspvoid->Tcount++;

    // Type of far library function
    tsjlib =    type_fake(TYjfunc);
    tsjlib->Tmangle = mTYman_c;
    tsjlib->Tcount++;

    tsdlib = tsjlib;

#if SCPP
    tspcvoid = type_alloc(mTYconst | TYvoid);
    tspcvoid = newpointer(tspcvoid);
    tspcvoid->Tmangle = mTYman_c;
    tspcvoid->Tcount++;
#endif

    // Type of logical expression
    tslogical = (config.flags4 & CFG4bool) ? tsbool : tsint;

    for (i = 0; i < TYMAX; i++)
    {
        if (tstypes[i])
        {   tsptr2types[i] = type_allocn(pointertype,tstypes[i]);
            tsptr2types[i]->Tcount++;
        }
    }
#else
    type_list = NULL;
    tsclib = type_fake( TYffunc );
    tsclib->Tmangle = mTYman_c;
    tsclib->Tcount++;
#ifdef DEBUG
    type_num = 0;
    type_max = 0;
#endif /* DEBUG */
#endif /* TX86 */
}
Exemple #22
0
type *type_delegate(type *tnext)
{
    type *t = type_allocn(TYdelegate, tnext);
    t->Tcount++;
    return t;
}
Exemple #23
0
type *type_dyn_array(type *tnext)
{
    type *t = type_allocn(TYdarray, tnext);
    t->Tcount++;
    return t;
}
Exemple #24
0
type *type_pointer(type *tnext)
{
    type *t = type_allocn(TYnptr, tnext);
    t->Tcount++;
    return t;
}
Exemple #25
0
void cv8_func_term(Symbol *sfunc)
{
    //printf("cv8_func_term(%s)\n", sfunc->Sident);

    assert(currentfuncdata.sfunc == sfunc);
    currentfuncdata.section_length = retoffset + retsize;

    funcdata->write(&currentfuncdata, sizeof(currentfuncdata));

    // Write function symbol
    assert(tyfunc(sfunc->ty()));
    idx_t typidx;
    func_t* fn = sfunc->Sfunc;
    if(fn->Fclass)
    {
        // generate member function type info
        // it would be nicer if this could be in cv4_typidx, but the function info is not available there
        unsigned nparam;
        unsigned char call = cv4_callconv(sfunc->Stype);
        idx_t paramidx = cv4_arglist(sfunc->Stype,&nparam);
        unsigned next = cv4_typidx(sfunc->Stype->Tnext);

        type* classtype = (type*)fn->Fclass;
        unsigned classidx = cv4_typidx(classtype);
        type *tp = type_allocn(TYnptr, classtype);
        unsigned thisidx = cv4_typidx(tp);  // TODO
        debtyp_t *d = debtyp_alloc(2 + 4 + 4 + 4 + 1 + 1 + 2 + 4 + 4);
        TOWORD(d->data,LF_MFUNCTION_V2);
        TOLONG(d->data + 2,next);       // return type
        TOLONG(d->data + 6,classidx);   // class type
        TOLONG(d->data + 10,thisidx);   // this type
        d->data[14] = call;
        d->data[15] = 0;                // reserved
        TOWORD(d->data + 16,nparam);
        TOLONG(d->data + 18,paramidx);
        TOLONG(d->data + 22,0);  // this adjust
        typidx = cv_debtyp(d);
    }
    else
        typidx = cv_typidx(sfunc->Stype);

    const char *id = sfunc->prettyIdent ? sfunc->prettyIdent : prettyident(sfunc);
    size_t len = strlen(id);
    if(len > CV8_MAX_SYMBOL_LENGTH)
        len = CV8_MAX_SYMBOL_LENGTH;
    /*
     *  2       length (not including these 2 bytes)
     *  2       S_GPROC_V3
     *  4       parent
     *  4       pend
     *  4       pnext
     *  4       size of function
     *  4       size of function prolog
     *  4       offset to function epilog
     *  4       type index
     *  6       seg:offset of function start
     *  1       flags
     *  n       0 terminated name string
     */
    Outbuffer *buf = currentfuncdata.f1buf;
    buf->reserve(2 + 2 + 4 * 7 + 6 + 1 + len + 1);
    buf->writeWordn( 2 + 4 * 7 + 6 + 1 + len + 1);
    buf->writeWordn(sfunc->Sclass == SCstatic ? S_LPROC_V3 : S_GPROC_V3);
    buf->write32(0);            // parent
    buf->write32(0);            // pend
    buf->write32(0);            // pnext
    buf->write32(currentfuncdata.section_length);       // size of function
    buf->write32(startoffset);          // size of prolog
    buf->write32(retoffset);                    // offset to epilog
    buf->write32(typidx);

    F1_Fixups f1f;
    f1f.s = sfunc;
    f1f.offset = buf->size();
    currentfuncdata.f1fixup->write(&f1f, sizeof(f1f));
    buf->write32(0);
    buf->writeWordn(0);

    buf->writeByte(0);
    buf->writen(id, len);
    buf->writeByte(0);

    // Write local symbol table
    bool endarg = false;
    for (SYMIDX si = 0; si < globsym.top; si++)
    {   //printf("globsym.tab[%d] = %p\n",si,globsym.tab[si]);
        symbol *sa = globsym.tab[si];
        if (endarg == false &&
            sa->Sclass != SCparameter &&
            sa->Sclass != SCfastpar &&
            sa->Sclass != SCshadowreg)
        {
            buf->writeWord(2);
            buf->writeWord(S_ENDARG);
            endarg = true;
        }
        cv8_outsym(sa);
    }

    /* Put out function return record S_RETURN
     * (VC doesn't, so we won't bother, either.)
     */

    // Write function end symbol
    buf->writeWord(2);
    buf->writeWord(S_END);

    currentfuncdata.f1buf = F1_buf;
    currentfuncdata.f1fixup = F1fixup;
}
Exemple #26
0
        void visit(VarDeclaration *vd)
        {
            //printf("VarDeclaration::toSymbol(%s)\n", vd->toChars());
            assert(!vd->needThis());
            if (!vd->csym)
            {
                const char *id;
                if (vd->isDataseg())
                    id = mangle(vd);
                else
                    id = vd->ident->toChars();
                Symbol *s = symbol_calloc(id);
                s->Salignment = vd->alignment;
                if (vd->storage_class & STCtemp)
                    s->Sflags |= SFLartifical;

                TYPE *t;
                if (vd->storage_class & (STCout | STCref))
                {
                    t = type_allocn(TYnref, Type_toCtype(vd->type));
                    t->Tcount++;
                }
                else if (vd->storage_class & STClazy)
                {
                    if (config.exe == EX_WIN64 && vd->isParameter())
                        t = type_fake(TYnptr);
                    else
                        t = type_fake(TYdelegate);          // Tdelegate as C type
                    t->Tcount++;
                }
                else if (vd->isParameter())
                {
                    if (config.exe == EX_WIN64 && vd->type->size(Loc()) > REGSIZE)
                    {
                        t = type_allocn(TYnref, Type_toCtype(vd->type));
                        t->Tcount++;
                    }
                    else
                    {
                        t = Type_toCtype(vd->type);
                        t->Tcount++;
                    }
                }
                else
                {
                    t = Type_toCtype(vd->type);
                    t->Tcount++;
                }

                if (vd->isDataseg())
                {
                    if (vd->isThreadlocal())
                    {
                        /* Thread local storage
                         */
                        TYPE *ts = t;
                        ts->Tcount++;   // make sure a different t is allocated
                        type_setty(&t, t->Tty | mTYthread);
                        ts->Tcount--;

                        if (global.params.vtls)
                        {
                            char *p = vd->loc.toChars();
                            fprintf(global.stdmsg, "%s: %s is thread local\n", p ? p : "", vd->toChars());
                            if (p)
                                mem.xfree(p);
                        }
                    }
                    s->Sclass = SCextern;
                    s->Sfl = FLextern;
                    slist_add(s);
                    /* if it's global or static, then it needs to have a qualified but unmangled name.
                     * This gives some explanation of the separation in treating name mangling.
                     * It applies to PDB format, but should apply to CV as PDB derives from CV.
                     *    http://msdn.microsoft.com/en-us/library/ff553493(VS.85).aspx
                     */
                    s->prettyIdent = vd->toPrettyChars(true);
                }
                else
                {
                    s->Sclass = SCauto;
                    s->Sfl = FLauto;

                    if (vd->nestedrefs.dim)
                    {
                        /* Symbol is accessed by a nested function. Make sure
                         * it is not put in a register, and that the optimizer
                         * assumes it is modified across function calls and pointer
                         * dereferences.
                         */
                        //printf("\tnested ref, not register\n");
                        type_setcv(&t, t->Tty | mTYvolatile);
                    }
                }

                if (vd->ident == Id::va_argsave || vd->storage_class & STCvolatile)
                {
                    /* __va_argsave is set outside of the realm of the optimizer,
                     * so we tell the optimizer to leave it alone
                     */
                    type_setcv(&t, t->Tty | mTYvolatile);
                }

                mangle_t m = 0;
                switch (vd->linkage)
                {
                    case LINKwindows:
                        m = global.params.is64bit ? mTYman_c : mTYman_std;
                        break;

                    case LINKpascal:
                        m = mTYman_pas;
                        break;

                    case LINKc:
                        m = mTYman_c;
                        break;

                    case LINKd:
                        m = mTYman_d;
                        break;
                    case LINKcpp:
                        s->Sflags |= SFLpublic;
                        m = mTYman_d;
                        break;
                    default:
                        printf("linkage = %d\n", vd->linkage);
                        assert(0);
                }

                type_setmangle(&t, m);
                s->Stype = t;

                vd->csym = s;
            }
            result = vd->csym;
        }