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); }
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); }
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; }
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; }