Пример #1
0
TypeTuple *TypeDelegate::toArgTypes()
{
    /* Should be done as if it were:
     * struct S { size_t length; void* ptr; }
     */
    if (global.params.is64bit && !global.params.isLP64)
    {
        // For AMD64 ILP32 ABI, delegates fit into a single integer register.
        unsigned offset = Type::tsize_t->size(Loc());
        Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
        if (t)
            return new TypeTuple(t);
    }
    return new TypeTuple(Type::tvoidptr, Type::tvoidptr);
}
Пример #2
0
 void visit(TypeDArray *)
 {
     /* Should be done as if it were:
      * struct S { size_t length; void* ptr; }
      */
     if (global.params.is64bit && !global.params.isLP64)
     {
         // For AMD64 ILP32 ABI, D arrays fit into a single integer register.
         unsigned offset = (unsigned)Type::tsize_t->size(Loc());
         Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
         if (t)
         {
             result = new TypeTuple(t);
             return;
         }
     }
     result = new TypeTuple(Type::tsize_t, Type::tvoidptr);
 }
Пример #3
0
TypeTuple *TypeStruct::toArgTypes()
{
    //printf("TypeStruct::toArgTypes() %s\n", toChars());
    if (!sym->isPOD())
    {
     Lmemory:
        //printf("\ttoArgTypes() %s => [ ]\n", toChars());
        return new TypeTuple();         // pass on the stack
    }
    Type *t1 = NULL;
    Type *t2 = NULL;
    d_uns64 sz = size(Loc());
    assert(sz < 0xFFFFFFFF);
    switch ((unsigned)sz)
    {
        case 1:
            t1 = Type::tint8;
            break;
        case 2:
            t1 = Type::tint16;
            break;
        case 4:
            t1 = Type::tint32;
            break;
        case 8:
            t1 = Type::tint64;
            break;
        case 16:
            t1 = NULL;                   // could be a TypeVector
            break;
        default:
            goto Lmemory;
    }
    if (global.params.is64bit && sym->fields.dim)
    {
#if 1
        unsigned sz1 = 0;
        unsigned sz2 = 0;
        t1 = NULL;
        for (size_t i = 0; i < sym->fields.dim; i++)
        {   VarDeclaration *f = sym->fields[i];
            //printf("f->type = %s\n", f->type->toChars());

            TypeTuple *tup = f->type->toArgTypes();
            if (!tup)
                goto Lmemory;
            size_t dim = tup->arguments->dim;
            Type *ft1 = NULL;
            Type *ft2 = NULL;
            switch (dim)
            {
                case 2:
                    ft1 = (*tup->arguments)[0]->type;
                    ft2 = (*tup->arguments)[1]->type;
                    break;
                case 1:
                    if (f->offset < 8)
                        ft1 = (*tup->arguments)[0]->type;
                    else
                        ft2 = (*tup->arguments)[0]->type;
                    break;
                default:
                    goto Lmemory;
            }

            if (f->offset & 7)
            {
                // Misaligned fields goto Lmemory
                unsigned alignsz = f->type->alignsize();
                if (f->offset & (alignsz - 1))
                    goto Lmemory;

                // Fields that overlap the 8byte boundary goto Lmemory
                unsigned fieldsz = f->type->size(Loc());
                if (f->offset < 8 && (f->offset + fieldsz) > 8)
                    goto Lmemory;
            }

            // First field in 8byte must be at start of 8byte
            assert(t1 || f->offset == 0);

            if (ft1)
            {
                t1 = argtypemerge(t1, ft1, f->offset);
                if (!t1)
                    goto Lmemory;
            }

            if (ft2)
            {
                unsigned off2 = f->offset;
                if (ft1)
                    off2 = 8;
                if (!t2 && off2 != 8)
                    goto Lmemory;
                assert(t2 || off2 == 8);
                t2 = argtypemerge(t2, ft2, off2 - 8);
                if (!t2)
                    goto Lmemory;
            }
        }

        if (t2)
        {
            if (t1->isfloating() && t2->isfloating())
            {
                if (t1->ty == Tfloat64 && t2->ty == Tfloat64)
                    ;
                else
                    goto Lmemory;
            }
            else if (t1->isfloating())
                goto Lmemory;
            else if (t2->isfloating())
                goto Lmemory;
            else
                ;
        }
#else
        if (sym->fields.dim == 1)
        {   VarDeclaration *f = sym->fields[0];
            //printf("f->type = %s\n", f->type->toChars());
            TypeTuple *tup = f->type->toArgTypes();
            if (tup)
            {
                size_t dim = tup->arguments->dim;
                if (dim == 1)
                    t1 = (*tup->arguments)[0]->type;
            }
        }
#endif
    }

    //printf("\ttoArgTypes() %s => [%s,%s]\n", toChars(), t1 ? t1->toChars() : "", t2 ? t2->toChars() : "");

    TypeTuple *t;
    if (t1)
    {
        //if (t1) printf("test1: %s => %s\n", toChars(), t1->toChars());
        if (t2)
            t = new TypeTuple(t1, t2);
        else
            t = new TypeTuple(t1);
    }
    else
        goto Lmemory;
    return t;
}
Пример #4
0
        void visit(TypeStruct *t)
        {
            //printf("TypeStruct::toArgTypes() %s\n", t->toChars());
            if (!t->sym->isPOD() || t->sym->fields.dim == 0)
            {
            Lmemory:
                //printf("\ttoArgTypes() %s => [ ]\n", t->toChars());
                result = new TypeTuple();         // pass on the stack
                return;
            }
            Type *t1 = NULL;
            Type *t2 = NULL;
            const d_uns64 sz = t->size(Loc());
            assert(sz < 0xFFFFFFFF);
            switch ((unsigned)sz)
            {
                case 1:
                    t1 = Type::tint8;
                    break;
                case 2:
                    t1 = Type::tint16;
                    break;
                case 3:
                    if (!global.params.is64bit)
                        goto Lmemory;
                    /* fall through */
                case 4:
                    t1 = Type::tint32;
                    break;
                case 5:
                case 6:
                case 7:
                    if (!global.params.is64bit)
                        goto Lmemory;
                    /* fall through */
                case 8:
                    t1 = Type::tint64;
                    break;
                case 16:
                    t1 = NULL;                   // could be a TypeVector
                    break;
                case 9:
                case 10:
                case 11:
                case 12:
                case 13:
                case 14:
                case 15:
                    if (!global.params.is64bit)
                        goto Lmemory;
                    t1 = NULL;
                    break;
                default:
                    goto Lmemory;
            }
            if (global.params.is64bit && t->sym->fields.dim)
            {
                t1 = NULL;
                for (size_t i = 0; i < t->sym->fields.dim; i++)
                {
                    VarDeclaration *f = t->sym->fields[i];
                    //printf("  [%d] %s f->type = %s\n", (int)i, f->toChars(), f->type->toChars());

                    TypeTuple *tup = toArgTypes(f->type);
                    if (!tup)
                        goto Lmemory;
                    size_t dim = tup->arguments->dim;
                    Type *ft1 = NULL;
                    Type *ft2 = NULL;
                    switch (dim)
                    {
                        case 2:
                            ft1 = (*tup->arguments)[0]->type;
                            ft2 = (*tup->arguments)[1]->type;
                            break;
                        case 1:
                            if (f->offset < 8)
                                ft1 = (*tup->arguments)[0]->type;
                            else
                                ft2 = (*tup->arguments)[0]->type;
                            break;
                        default:
                            goto Lmemory;
                    }

                    if (f->offset & 7)
                    {
                        // Misaligned fields goto Lmemory
                        unsigned alignsz = f->type->alignsize();
                        if (f->offset & (alignsz - 1))
                            goto Lmemory;

                        // Fields that overlap the 8byte boundary goto Lmemory
                        const d_uns64 fieldsz = f->type->size(Loc());
                        assert(fieldsz != SIZE_INVALID && fieldsz < UINT64_MAX - UINT32_MAX);
                        if (f->offset < 8 && (f->offset + fieldsz) > 8)
                            goto Lmemory;
                    }

                    // First field in 8byte must be at start of 8byte
                    assert(t1 || f->offset == 0);
                    //printf("ft1 = %s\n", ft1 ? ft1->toChars() : "null");
                    //printf("ft2 = %s\n", ft2 ? ft2->toChars() : "null");
                    if (ft1)
                    {
                        t1 = argtypemerge(t1, ft1, f->offset);
                        if (!t1)
                            goto Lmemory;
                    }

                    if (ft2)
                    {
                        unsigned off2 = f->offset;
                        if (ft1)
                            off2 = 8;
                        if (!t2 && off2 != 8)
                            goto Lmemory;
                        assert(t2 || off2 == 8);
                        t2 = argtypemerge(t2, ft2, off2 - 8);
                        if (!t2)
                            goto Lmemory;
                    }
                }

                if (t2)
                {
                    if (t1->isfloating() && t2->isfloating())
                    {
                        if ((t1->ty == Tfloat32 || t1->ty == Tfloat64) &&
                            (t2->ty == Tfloat32 || t2->ty == Tfloat64))
                            ;
                        else
                            goto Lmemory;
                    }
                    else if (t1->isfloating())
                        goto Lmemory;
                    else if (t2->isfloating())
                        goto Lmemory;
                    else
                    {
                    }
                }
            }

            //printf("\ttoArgTypes() %s => [%s,%s]\n", t->toChars(), t1 ? t1->toChars() : "", t2 ? t2->toChars() : "");

            if (t1)
            {
                //if (t1) printf("test1: %s => %s\n", toChars(), t1->toChars());
                if (t2)
                    result = new TypeTuple(t1, t2);
                else
                    result = new TypeTuple(t1);
            }
            else
                goto Lmemory;
        }