#include "dmd/identifier.h"
#include "dmd/module.h"
#include "dmd/mtype.h"
+#include "dmd/target.h"
#include "tree.h"
#include "fold-const.h"
as casting from `C char' to `D char', which also means that `char *`
needs to be specially handled. */
-static Type *
+Type *
build_frontend_type (tree type)
{
Type *dtype;
}
}
- /* va_list should already be built, so no need to convert to D type again. */
- StructDeclaration *sd = (Type::tvalist->ty == Tstruct)
- ? ((TypeStruct *) Type::tvalist)->sym : NULL;
+ /* Expose target-specific va_list type. */
+ Type *tvalist = target.va_listType (Loc (), NULL);
+ StructDeclaration *sd = (tvalist->ty == Tstruct)
+ ? ((TypeStruct *) tvalist)->sym : NULL;
if (sd == NULL || !sd->isAnonymous ())
- {
- members->push (build_alias_declaration ("__builtin_va_list",
- Type::tvalist));
- }
+ members->push (build_alias_declaration ("__builtin_va_list", tvalist));
else
{
sd->ident = Identifier::idPool ("__builtin_va_list");
void
d_init_builtins (void)
{
- /* Build the "standard" abi va_list. */
- Type::tvalist = build_frontend_type (va_list_type_node);
- if (!Type::tvalist)
- sorry ("cannot represent built-in %<va_list%> type in D");
-
- /* Map the va_list type to the D frontend Type. This is to prevent both
- errors in gimplification or an ICE in targetm.canonical_va_list_type. */
- Type::tvalist->ctype = va_list_type_node;
- TYPE_LANG_SPECIFIC (va_list_type_node) = build_lang_type (Type::tvalist);
-
d_build_c_type_nodes ();
d_build_d_type_nodes ();
/* Want RECORD_TYPE, not POINTER_TYPE. */
BINFO_TYPE (binfo) = TREE_TYPE (ctype);
BINFO_INHERITANCE_CHAIN (binfo) = super;
- BINFO_OFFSET (binfo) = size_int (offset * Target::ptrsize);
+ BINFO_OFFSET (binfo) = size_int (offset * target.ptrsize);
BINFO_VIRTUAL_P (binfo) = 1;
for (size_t i = 0; i < cd->baseclasses->length; i++, offset++)
gcc_assert (POINTER_TYPE_P (fntype));
- return build_memref (fntype, result, size_int (Target::ptrsize * index));
+ return build_memref (fntype, result, size_int (target.ptrsize * index));
}
/* Return TRUE if EXP is a valid lvalue. Lvalue references cannot be
/* Check for types that may have padding. */
if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
- && Target::realpad != 0)
+ && target.realpad != 0)
return false;
if (offset <= vd->offset)
real_from_string3 (&r.rv (), buffer, TYPE_MODE (long_double_type_node));
/* Front-end checks overflow to see if the value is representable. */
- if (overflow && r == Target::RealProperties::infinity)
+ if (overflow && r == target.RealProperties.infinity)
*overflow = true;
return r;
/* This is the C main, not the D main. */
main_identifier_node = get_identifier ("main");
- Target::_init ();
+ target._init (global.params);
d_init_versions ();
/* Insert all library-configured identifiers and import paths. */
real_from_string3 (&r.rv (), buffer, TYPE_MODE (float_type_node));
- return r == Target::RealProperties::infinity;
+ return r == target.RealProperties.infinity;
}
/* Return true if the real_t value from string BUFFER overflows
real_from_string3 (&r.rv (), buffer, TYPE_MODE (double_type_node));
- return r == Target::RealProperties::infinity;
+ return r == target.RealProperties.infinity;
}
/* Fetch a little-endian 16-bit value from BUFFER. */
/* Implements the Target interface defined by the front end.
Used for retrieving target-specific information. */
-/* Type size information used by frontend. */
-int Target::ptrsize;
-int Target::c_longsize;
-int Target::realsize;
-int Target::realpad;
-int Target::realalignsize;
-bool Target::reverseCppOverloads;
-bool Target::cppExceptions;
-int Target::classinfosize;
-unsigned long long Target::maxStaticDataSize;
-
-/* Floating-point constants for .max, .min, and other properties. */
-template <typename T> real_t Target::FPTypeProperties<T>::max;
-template <typename T> real_t Target::FPTypeProperties<T>::min_normal;
-template <typename T> real_t Target::FPTypeProperties<T>::nan;
-template <typename T> real_t Target::FPTypeProperties<T>::snan;
-template <typename T> real_t Target::FPTypeProperties<T>::infinity;
-template <typename T> real_t Target::FPTypeProperties<T>::epsilon;
-template <typename T> d_int64 Target::FPTypeProperties<T>::dig;
-template <typename T> d_int64 Target::FPTypeProperties<T>::mant_dig;
-template <typename T> d_int64 Target::FPTypeProperties<T>::max_exp;
-template <typename T> d_int64 Target::FPTypeProperties<T>::min_exp;
-template <typename T> d_int64 Target::FPTypeProperties<T>::max_10_exp;
-template <typename T> d_int64 Target::FPTypeProperties<T>::min_10_exp;
+Target target;
/* Initialize the floating-point constants for TYPE. */
template <typename T>
static void
-define_float_constants (tree type)
+define_float_constants (T &f, tree type)
{
const double log10_2 = 0.30102999566398119521;
char buf[128];
/* The largest representable value that's not infinity. */
get_max_float (fmt, buf, sizeof (buf), false);
- real_from_string (&T::max.rv (), buf);
+ real_from_string (&f.max.rv (), buf);
/* The smallest representable normalized value that's not 0. */
snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - 1);
- real_from_string (&T::min_normal.rv (), buf);
+ real_from_string (&f.min_normal.rv (), buf);
/* Floating-point NaN. */
- real_nan (&T::nan.rv (), "", 1, mode);
+ real_nan (&f.nan.rv (), "", 1, mode);
/* Signalling floating-point NaN. */
- real_nan (&T::snan.rv (), "", 0, mode);
+ real_nan (&f.snan.rv (), "", 0, mode);
/* Floating-point +Infinity if the target supports infinities. */
- real_inf (&T::infinity.rv ());
+ real_inf (&f.infinity.rv ());
/* The smallest increment to the value 1. */
if (fmt->pnan < fmt->p)
snprintf (buf, sizeof (buf), "0x1p%d", fmt->emin - fmt->p);
else
snprintf (buf, sizeof (buf), "0x1p%d", 1 - fmt->p);
- real_from_string (&T::epsilon.rv (), buf);
+ real_from_string (&f.epsilon.rv (), buf);
/* The number of decimal digits of precision. */
- T::dig = (fmt->p - 1) * log10_2;
+ f.dig = (fmt->p - 1) * log10_2;
/* The number of bits in mantissa. */
- T::mant_dig = fmt->p;
+ f.mant_dig = fmt->p;
/* The maximum int value such that 2** (value-1) is representable. */
- T::max_exp = fmt->emax;
+ f.max_exp = fmt->emax;
/* The minimum int value such that 2** (value-1) is representable as a
normalized value. */
- T::min_exp = fmt->emin;
+ f.min_exp = fmt->emin;
/* The maximum int value such that 10**value is representable. */
- T::max_10_exp = fmt->emax * log10_2;
+ f.max_10_exp = fmt->emax * log10_2;
/* The minimum int value such that 10**value is representable as a
normalized value. */
- T::min_10_exp = (fmt->emin - 1) * log10_2;
+ f.min_10_exp = (fmt->emin - 1) * log10_2;
}
/* Initialize all variables of the Target structure. */
void
-Target::_init (void)
+Target::_init (const Param &)
{
/* Map D frontend type and sizes to GCC back-end types. */
- Target::ptrsize = (POINTER_SIZE / BITS_PER_UNIT);
- Target::realsize = int_size_in_bytes (long_double_type_node);
- Target::realpad = (Target::realsize -
- (TYPE_PRECISION (long_double_type_node) / BITS_PER_UNIT));
- Target::realalignsize = TYPE_ALIGN_UNIT (long_double_type_node);
+ this->ptrsize = (POINTER_SIZE / BITS_PER_UNIT);
+ this->realsize = int_size_in_bytes (long_double_type_node);
+ this->realpad = (this->realsize -
+ (TYPE_PRECISION (long_double_type_node) / BITS_PER_UNIT));
+ this->realalignsize = TYPE_ALIGN_UNIT (long_double_type_node);
/* Size of run-time TypeInfo object. */
- Target::classinfosize = 19 * Target::ptrsize;
+ this->classinfosize = 19 * this->ptrsize;
/* Much of the dmd front-end uses ints for sizes and offsets, and cannot
handle any larger data type without some pervasive rework. */
- Target::maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (integer_type_node));
+ this->maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (integer_type_node));
/* Define what type to use for size_t, ptrdiff_t. */
- if (Target::ptrsize == 8)
+ if (this->ptrsize == 8)
{
global.params.isLP64 = true;
- Tsize_t = Tuns64;
- Tptrdiff_t = Tint64;
+ Type::tsize_t = Type::basic[Tuns64];
+ Type::tptrdiff_t = Type::basic[Tint64];
}
- else if (Target::ptrsize == 4)
+ else if (this->ptrsize == 4)
{
- Tsize_t = Tuns32;
- Tptrdiff_t = Tint32;
+ Type::tsize_t = Type::basic[Tuns32];
+ Type::tptrdiff_t = Type::basic[Tint32];
}
- else if (Target::ptrsize == 2)
+ else if (this->ptrsize == 2)
{
- Tsize_t = Tuns16;
- Tptrdiff_t = Tint16;
+ Type::tsize_t = Type::basic[Tuns16];
+ Type::tptrdiff_t = Type::basic[Tint16];
}
else
sorry ("D does not support pointers on this target.");
- Type::tsize_t = Type::basic[Tsize_t];
- Type::tptrdiff_t = Type::basic[Tptrdiff_t];
Type::thash_t = Type::tsize_t;
/* Set-up target C ABI. */
- Target::c_longsize = int_size_in_bytes (long_integer_type_node);
+ this->c.longsize = int_size_in_bytes (long_integer_type_node);
+ this->c.long_doublesize = int_size_in_bytes (long_double_type_node);
/* Set-up target C++ ABI. */
- Target::reverseCppOverloads = false;
- Target::cppExceptions = true;
+ this->cpp.reverseOverloads = false;
+ this->cpp.exceptions = true;
+ this->cpp.twoDtorInVtable = true;
+
+ /* Set-up target Objective-C ABI. */
+ this->objc.supported = false;
/* Initialize all compile-time properties for floating-point types.
Should ensure that our real_t type is able to represent real_value. */
gcc_assert (sizeof (real_t) >= sizeof (real_value));
- define_float_constants <Target::FloatProperties> (float_type_node);
- define_float_constants <Target::DoubleProperties> (double_type_node);
- define_float_constants <Target::RealProperties> (long_double_type_node);
+ define_float_constants (this->FloatProperties, float_type_node);
+ define_float_constants (this->DoubleProperties, double_type_node);
+ define_float_constants (this->RealProperties, long_double_type_node);
/* Commonly used floating-point constants. */
const machine_mode mode = TYPE_MODE (long_double_type_node);
/* Returns a Type for the va_list type of the target. */
Type *
-Target::va_listType (void)
+Target::va_listType (const Loc &, Scope *)
{
- return Type::tvalist;
+ if (this->tvalist)
+ return this->tvalist;
+
+ /* Build the "standard" abi va_list. */
+ this->tvalist = build_frontend_type (va_list_type_node);
+ if (!this->tvalist)
+ sorry ("cannot represent built-in %<va_list%> type in D");
+
+ /* Map the va_list type to the D frontend Type. This is to prevent both
+ errors in gimplification or an ICE in targetm.canonical_va_list_type. */
+ this->tvalist->ctype = va_list_type_node;
+ TYPE_LANG_SPECIFIC (va_list_type_node) = build_lang_type (this->tvalist);
+
+ return this->tvalist;
}
/* Checks whether the target supports a vector type with total size SZ
/* Return the symbol mangling of S for C++ linkage. */
const char *
-Target::toCppMangle (Dsymbol *s)
+TargetCPP::toMangle (Dsymbol *s)
{
return toCppMangleItanium (s);
}
/* Return the symbol mangling of CD for C++ linkage. */
const char *
-Target::cppTypeInfoMangle (ClassDeclaration *cd)
+TargetCPP::typeInfoMangle (ClassDeclaration *cd)
{
return cppTypeInfoMangleItanium (cd);
}
In all other cases, return NULL. */
const char *
-Target::cppTypeMangle (Type *type)
+TargetCPP::typeMangle (Type *type)
{
if (type->isTypeBasic () || type->ty == Tvector || type->ty == Tstruct)
{
ARG to an extern(C++) function. */
Type *
-Target::cppParameterType (Parameter *arg)
+TargetCPP::parameterType (Parameter *arg)
{
Type *t = arg->type->merge2 ();
if (arg->storageClass & (STCout | STCref))
}
/* Could be a va_list, which we mangle as a pointer. */
- if (t->ty == Tsarray && Type::tvalist->ty == Tsarray)
+ Type *tvalist = target.va_listType (Loc (), NULL);
+ if (t->ty == Tsarray && tvalist->ty == Tsarray)
{
Type *tb = t->toBasetype ()->mutableOf ();
- if (tb == Type::tvalist)
+ if (tb == tvalist)
{
tb = t->nextOf ()->pointerTo ();
t = tb->castMod (t->mod);
in IS_FUNDAMENTAL and returns true if the parameter was set. */
bool
-Target::cppFundamentalType (const Type *, bool &)
+TargetCPP::fundamentalType (const Type *, bool &)
{
return false;
}
/* In d-builtins.cc. */
extern const attribute_spec d_langhook_attribute_table[];
extern const attribute_spec d_langhook_common_attribute_table[];
+extern Type *build_frontend_type (tree);
extern tree d_builtin_function (tree);
extern void d_init_builtins (void);
unsigned
base_vtable_offset (ClassDeclaration *cd, BaseClass *bc)
{
- unsigned csymoffset = Target::classinfosize;
+ unsigned csymoffset = target.classinfosize;
unsigned interfacesize = int_size_in_bytes (vtbl_interface_type_node);
csymoffset += cd->vtblInterfaces->length * interfacesize;
BaseClass *b = (*cd->vtblInterfaces)[i];
if (b == bc)
return csymoffset;
- csymoffset += b->sym->vtbl.length * Target::ptrsize;
+ csymoffset += b->sym->vtbl.length * target.ptrsize;
}
/* Check all overriding interface vtbl[]s. */
{
if (bc == bs)
return csymoffset;
- csymoffset += bs->sym->vtbl.length * Target::ptrsize;
+ csymoffset += bs->sym->vtbl.length * target.ptrsize;
}
}
}
-6d5bffa54f7da21d388d9999e586fd8a11ebcdb1
+56f0a65c493463633a293d71faf37cdf710041ef
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
: AttribDeclaration(decl)
{
//printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
- linkage = (p == LINKsystem) ? Target::systemLinkage() : p;
+ linkage = (p == LINKsystem) ? target.systemLinkage() : p;
}
LinkDeclaration *LinkDeclaration::create(LINK p, Dsymbols *decl)
// x ^^ y for x < 0 and y not an integer is not defined; so set result as NaN
if (e1->toReal() < CTFloat::zero)
{
- new(&ue) RealExp(loc, Target::RealProperties::nan, type);
+ new(&ue) RealExp(loc, target.RealProperties.nan, type);
}
else
new(&ue) CTFEExp(TOKcantexp);
{
// First check the target whether some specific ABI is being followed.
bool isFundamental;
- if (Target::cppFundamentalType(t, isFundamental))
+ if (target.cpp.fundamentalType(t, isFundamental))
return isFundamental;
if (t->ty == Tenum)
{
{
ParamsCppMangle *p = (ParamsCppMangle *)ctx;
CppMangleVisitor *mangler = p->mangler;
- Type *t = Target::cppParameterType(fparam);
+ Type *t = target.cpp.parameterType(fparam);
if (t->ty == Tsarray)
{
// Static arrays in D are passed by value; no counterpart in C++
return error(t);
// Handle any target-specific basic types.
- if (const char *tm = Target::cppTypeMangle(t))
+ if (const char *tm = target.cpp.typeMangle(t))
{
// Only do substitutions for non-fundamental types.
if (!isFundamentalType(t) || t->isConst())
case Tuns32: c = 'j'; break;
case Tfloat32: c = 'f'; break;
case Tint64:
- c = (Target::c_longsize == 8 ? 'l' : 'x');
+ c = (target.c.longsize == 8 ? 'l' : 'x');
break;
case Tuns64:
- c = (Target::c_longsize == 8 ? 'm' : 'y');
+ c = (target.c.longsize == 8 ? 'm' : 'y');
break;
case Tint128: c = 'n'; break;
case Tuns128: c = 'o'; break;
CV_qualifiers(t);
// Handle any target-specific vector types.
- if (const char *tm = Target::cppTypeMangle(t))
+ if (const char *tm = target.cpp.typeMangle(t))
{
buf->writestring(tm);
}
CV_qualifiers(t);
// Handle any target-specific struct types.
- if (const char *tm = Target::cppTypeMangle(t))
+ if (const char *tm = target.cpp.typeMangle(t))
{
buf->writestring(tm);
}
assert(b->sym->sizeok == SIZEOKdone);
if (!b->sym->alignsize)
- b->sym->alignsize = Target::ptrsize;
+ b->sym->alignsize = target.ptrsize;
cd->alignmember(b->sym->alignsize, b->sym->alignsize, &offset);
assert(bi < vtblInterfaces->length);
BaseClass *bv = (*vtblInterfaces)[bi];
{
if (interfaces.length == 0)
{
- alignsize = Target::ptrsize;
- structsize = Target::ptrsize; // allow room for __vptr
+ alignsize = target.ptrsize;
+ structsize = target.ptrsize; // allow room for __vptr
}
}
else
{
- alignsize = Target::ptrsize;
- structsize = Target::ptrsize; // allow room for __vptr
+ alignsize = target.ptrsize;
+ structsize = target.ptrsize; // allow room for __vptr
if (!isCPPclass())
- structsize += Target::ptrsize; // allow room for __monitor
+ structsize += target.ptrsize; // allow room for __monitor
}
//printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
const d_uns64 sz = t->size(loc);
assert(sz != SIZE_INVALID && sz < UINT32_MAX);
unsigned memsize = (unsigned)sz; // size of member
- unsigned memalignsize = Target::fieldalign(t); // size of member for alignment purposes
+ unsigned memalignsize = target.fieldalign(t); // size of member for alignment purposes
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment,
&ad->structsize, &ad->alignsize, isunion);
storage_class = STCstatic | STCgshared;
protection = Prot(PROTpublic);
linkage = LINKc;
- alignment = Target::ptrsize;
+ alignment = target.ptrsize;
}
TypeInfoDeclaration *TypeInfoDeclaration::create(Type *tinfo)
return;
case LINKcpp:
- buf->writestring(Target::toCppMangle(d));
+ buf->writestring(target.cpp.toMangle(d));
return;
case LINKdefault:
break;
case (structalign_t) STRUCTALIGN_DEFAULT:
- // Alignment in Target::fieldalignsize must match what the
+ // Alignment in target.fieldalignsize must match what the
// corresponding C compiler's default alignment behavior is.
assert(size > 0 && !(size & (size - 1)));
*poffset = (*poffset + size - 1) & ~(size - 1);
}
}
- TypeTuple *tt = Target::toArgTypes(type);
+ TypeTuple *tt = target.toArgTypes(type);
size_t dim = tt ? tt->arguments->length : 0;
if (dim >= 1)
{
case Tint64: value = (d_int64) value; break;
case Tuns64: value = (d_uns64) value; break;
case Tpointer:
- if (Target::ptrsize == 8)
+ if (target.ptrsize == 8)
value = (d_uns64) value;
- else if (Target::ptrsize == 4)
+ else if (target.ptrsize == 4)
value = (d_uns32) value;
- else if (Target::ptrsize == 2)
+ else if (target.ptrsize == 2)
value = (d_uns16) value;
else
assert(0);
* The results of this are highly platform dependent, and intended
* primarly for use in implementing va_arg().
*/
- tded = Target::toArgTypes(e->targ);
+ tded = target.toArgTypes(e->targ);
if (!tded)
goto Lno; // not valid for a parameter
break;
exp->e2 = exp->e2->castTo(sc, Type::tshiftcnt);
}
- if (!Target::isVectorOpSupported(exp->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(exp->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
return;
}
- if (!Target::isVectorOpSupported(tb, exp->op))
+ if (!target.isVectorOpSupported(tb, exp->op))
{
result = exp->incompatibleTypes();
return;
return;
}
- if (!Target::isVectorOpSupported(exp->e1->type->toBasetype(), exp->op))
+ if (!target.isVectorOpSupported(exp->e1->type->toBasetype(), exp->op))
{
result = exp->incompatibleTypes();
return;
return;
}
- if (!Target::isVectorOpSupported(tb, exp->op))
+ if (!target.isVectorOpSupported(tb, exp->op))
{
result = exp->incompatibleTypes();
return;
return;
}
- if (!Target::isVectorOpSupported(e->e1->type->toBasetype(), e->op))
+ if (!target.isVectorOpSupported(e->e1->type->toBasetype(), e->op))
{
result = e->incompatibleTypes();
return;
}
tb1 = exp->e1->type->toBasetype();
- if (!Target::isVectorOpSupported(tb1, exp->op, tb2))
+ if (!target.isVectorOpSupported(tb1, exp->op, tb2))
{
result = exp->incompatibleTypes();
return;
t1 = exp->e1->type->toBasetype();
t2 = exp->e2->type->toBasetype();
- if (!Target::isVectorOpSupported(t1, exp->op, t2))
+ if (!target.isVectorOpSupported(t1, exp->op, t2))
{
result = exp->incompatibleTypes();
return;
exp->type = t1; // t1 is complex
}
}
- else if (!Target::isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
+ else if (!target.isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
exp->type = t1; // t1 is complex
}
}
- else if (!Target::isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
+ else if (!target.isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
result = exp;
return;
}
- if (!Target::isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
if (exp->checkArithmeticBin())
return setError();
- if (!Target::isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
if (exp->checkIntegralBin())
return setError();
- if (!Target::isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
if (exp->checkIntegralBin())
return setError();
- if (!Target::isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
if (exp->checkIntegralBin())
return setError();
- if (!Target::isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(exp->e1->type->toBasetype(), exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
return;
}
- if (!Target::isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
return;
}
- if (!Target::isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
return;
}
- if (!Target::isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
+ if (!target.isVectorOpSupported(tb, exp->op, exp->e2->type->toBasetype()))
{
result = exp->incompatibleTypes();
return;
exp->error("%s is not defined for associative arrays", Token::toChars(exp->op));
return setError();
}
- else if (!Target::isVectorOpSupported(t1, exp->op, t2))
+ else if (!target.isVectorOpSupported(t1, exp->op, t2))
{
result = exp->incompatibleTypes();
return;
Type *t1 = exp->e1->type->toBasetype();
Type *t2 = exp->e2->type->toBasetype();
- if (!Target::isVectorOpSupported(t1, exp->op, t2))
+ if (!target.isVectorOpSupported(t1, exp->op, t2))
{
result = exp->incompatibleTypes();
return;
Type *tb1 = exp->e1->type->toBasetype();
Type *tb2 = exp->e2->type->toBasetype();
- if (!Target::isVectorOpSupported(tb1, exp->op, tb2))
+ if (!target.isVectorOpSupported(tb1, exp->op, tb2))
{
result = exp->incompatibleTypes();
return;
{
//printf("\tintroducing function %s\n", toChars());
introducing = 1;
- if (cd->isCPPclass() && Target::reverseCppOverloads)
+ if (cd->isCPPclass() && target.cpp.reverseOverloads)
{
// with dmc, overloaded functions are grouped and in reverse order
vtblIndex = (int)cd->vtbl.length;
if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
{
// Declare _argptr
- Type *t = Type::tvalist;
+ Type *t = target.va_listType(loc, sc);
v_argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
v_argptr->storage_class |= STCtemp;
v_argptr->semantic(sc2);
if ((sinteger_t)uval >= 0)
{
dinteger_t sizemax;
- if (Target::ptrsize == 8)
+ if (target.ptrsize == 8)
sizemax = 0xFFFFFFFFFFFFFFFFULL;
- else if (Target::ptrsize == 4)
+ else if (target.ptrsize == 4)
sizemax = 0xFFFFFFFFUL;
- else if (Target::ptrsize == 2)
+ else if (target.ptrsize == 2)
sizemax = 0xFFFFUL;
else
assert(0);
buf->writestring("cast(");
buf->writestring(t->toChars());
buf->writeByte(')');
- if (Target::ptrsize == 8)
+ if (target.ptrsize == 8)
goto L4;
else
goto L3;
Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
-int Tsize_t = Tuns32;
-int Tptrdiff_t = Tint32;
-
/***************************** Type *****************************/
ClassDeclaration *Type::dtypeinfo;
Type *Type::tstring;
Type *Type::twstring;
Type *Type::tdstring;
-Type *Type::tvalist;
Type *Type::basic[TMAX];
unsigned char Type::sizeTy[TMAX];
StringTable Type::stringtable;
tstring = tchar->immutableOf()->arrayOf();
twstring = twchar->immutableOf()->arrayOf();
tdstring = tdchar->immutableOf()->arrayOf();
- tvalist = Target::va_listType();
- if (global.params.isLP64)
- {
- Tsize_t = Tuns64;
- Tptrdiff_t = Tint64;
- }
- else
- {
- Tsize_t = Tuns32;
- Tptrdiff_t = Tint32;
- }
+ const bool isLP64 = global.params.isLP64;
- tsize_t = basic[Tsize_t];
- tptrdiff_t = basic[Tptrdiff_t];
+ tsize_t = basic[isLP64 ? Tuns64 : Tuns32];
+ tptrdiff_t = basic[isLP64 ? Tint64 : Tint32];
thash_t = tsize_t;
}
size = 8; break;
case Tfloat80:
case Timaginary80:
- size = Target::realsize; break;
+ size = target.realsize; break;
case Tcomplex32:
size = 8; break;
case Tcomplex64:
case Tuns128:
size = 16; break;
case Tcomplex80:
- size = Target::realsize * 2; break;
+ size = target.realsize * 2; break;
case Tvoid:
//size = Type::size(); // error message
unsigned TypeBasic::alignsize()
{
- return Target::alignsize(this);
+ return target.alignsize(this);
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- fvalue = Target::FloatProperties::max;
+ fvalue = target.FloatProperties.max;
goto Lfvalue;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- fvalue = Target::DoubleProperties::max;
+ fvalue = target.DoubleProperties.max;
goto Lfvalue;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- fvalue = Target::RealProperties::max;
+ fvalue = target.RealProperties.max;
goto Lfvalue;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- fvalue = Target::FloatProperties::min_normal;
+ fvalue = target.FloatProperties.min_normal;
goto Lfvalue;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- fvalue = Target::DoubleProperties::min_normal;
+ fvalue = target.DoubleProperties.min_normal;
goto Lfvalue;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- fvalue = Target::RealProperties::min_normal;
+ fvalue = target.RealProperties.min_normal;
goto Lfvalue;
}
}
case Tfloat32:
case Tfloat64:
case Tfloat80:
- fvalue = Target::RealProperties::nan;
+ fvalue = target.RealProperties.nan;
goto Lfvalue;
}
}
case Tfloat32:
case Tfloat64:
case Tfloat80:
- fvalue = Target::RealProperties::infinity;
+ fvalue = target.RealProperties.infinity;
goto Lfvalue;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- ivalue = Target::FloatProperties::dig;
+ ivalue = target.FloatProperties.dig;
goto Lint;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- ivalue = Target::DoubleProperties::dig;
+ ivalue = target.DoubleProperties.dig;
goto Lint;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- ivalue = Target::RealProperties::dig;
+ ivalue = target.RealProperties.dig;
goto Lint;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- fvalue = Target::FloatProperties::epsilon;
+ fvalue = target.FloatProperties.epsilon;
goto Lfvalue;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- fvalue = Target::DoubleProperties::epsilon;
+ fvalue = target.DoubleProperties.epsilon;
goto Lfvalue;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- fvalue = Target::RealProperties::epsilon;
+ fvalue = target.RealProperties.epsilon;
goto Lfvalue;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- ivalue = Target::FloatProperties::mant_dig;
+ ivalue = target.FloatProperties.mant_dig;
goto Lint;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- ivalue = Target::DoubleProperties::mant_dig;
+ ivalue = target.DoubleProperties.mant_dig;
goto Lint;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- ivalue = Target::RealProperties::mant_dig;
+ ivalue = target.RealProperties.mant_dig;
goto Lint;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- ivalue = Target::FloatProperties::max_10_exp;
+ ivalue = target.FloatProperties.max_10_exp;
goto Lint;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- ivalue = Target::DoubleProperties::max_10_exp;
+ ivalue = target.DoubleProperties.max_10_exp;
goto Lint;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- ivalue = Target::RealProperties::max_10_exp;
+ ivalue = target.RealProperties.max_10_exp;
goto Lint;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- ivalue = Target::FloatProperties::max_exp;
+ ivalue = target.FloatProperties.max_exp;
goto Lint;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- ivalue = Target::DoubleProperties::max_exp;
+ ivalue = target.DoubleProperties.max_exp;
goto Lint;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- ivalue = Target::RealProperties::max_exp;
+ ivalue = target.RealProperties.max_exp;
goto Lint;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- ivalue = Target::FloatProperties::min_10_exp;
+ ivalue = target.FloatProperties.min_10_exp;
goto Lint;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- ivalue = Target::DoubleProperties::min_10_exp;
+ ivalue = target.DoubleProperties.min_10_exp;
goto Lint;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- ivalue = Target::RealProperties::min_10_exp;
+ ivalue = target.RealProperties.min_10_exp;
goto Lint;
}
}
case Tcomplex32:
case Timaginary32:
case Tfloat32:
- ivalue = Target::FloatProperties::min_exp;
+ ivalue = target.FloatProperties.min_exp;
goto Lint;
case Tcomplex64:
case Timaginary64:
case Tfloat64:
- ivalue = Target::DoubleProperties::min_exp;
+ ivalue = target.DoubleProperties.min_exp;
goto Lint;
case Tcomplex80:
case Timaginary80:
case Tfloat80:
- ivalue = Target::RealProperties::min_exp;
+ ivalue = target.RealProperties.min_exp;
goto Lint;
}
}
case Tfloat32:
case Tfloat64:
case Tfloat80:
- return new RealExp(loc, Target::RealProperties::snan, this);
+ return new RealExp(loc, target.RealProperties.snan, this);
case Tcomplex32:
case Tcomplex64:
case Tcomplex80:
{ // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
- complex_t cvalue = complex_t(Target::RealProperties::snan, Target::RealProperties::snan);
+ complex_t cvalue = complex_t(target.RealProperties.snan, target.RealProperties.snan);
return new ComplexExp(loc, cvalue, this);
}
}
TypeSArray *t = (TypeSArray *)basetype;
int sz = (int)t->size(loc);
- switch (Target::isVectorTypeSupported(sz, t->nextOf()))
+ switch (target.isVectorTypeSupported(sz, t->nextOf()))
{
case 0: // valid
break;
{
Loverflow:
error(loc, "%s size %llu * %llu exceeds 0x%llx size limit for static array",
- toChars(), (unsigned long long)tbn->size(loc), (unsigned long long)d1, Target::maxStaticDataSize);
+ toChars(), (unsigned long long)tbn->size(loc), (unsigned long long)d1, target.maxStaticDataSize);
goto Lerror;
}
* run on them for the size, since they may be forward referenced.
*/
bool overflow = false;
- if (mulu(tbn->size(loc), d2, overflow) >= Target::maxStaticDataSize || overflow)
+ if (mulu(tbn->size(loc), d2, overflow) >= target.maxStaticDataSize || overflow)
goto Loverflow;
}
}
d_uns64 TypeDArray::size(Loc)
{
//printf("TypeDArray::size()\n");
- return Target::ptrsize * 2;
+ return target.ptrsize * 2;
}
unsigned TypeDArray::alignsize()
{
// A DArray consists of two ptr-sized values, so align it on pointer size
// boundary
- return Target::ptrsize;
+ return target.ptrsize;
}
Type *TypeDArray::semantic(Loc loc, Scope *sc)
d_uns64 TypeAArray::size(Loc)
{
- return Target::ptrsize;
+ return target.ptrsize;
}
Type *TypeAArray::semantic(Loc loc, Scope *sc)
d_uns64 TypePointer::size(Loc)
{
- return Target::ptrsize;
+ return target.ptrsize;
}
MATCH TypePointer::implicitConvTo(Type *to)
d_uns64 TypeReference::size(Loc)
{
- return Target::ptrsize;
+ return target.ptrsize;
}
Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
d_uns64 TypeDelegate::size(Loc)
{
- return Target::ptrsize * 2;
+ return target.ptrsize * 2;
}
unsigned TypeDelegate::alignsize()
{
- return Target::ptrsize;
+ return target.ptrsize;
}
MATCH TypeDelegate::implicitConvTo(Type *to)
/* Copy from the initializer symbol for larger symbols,
* otherwise the literals expressed as code get excessively large.
*/
- if (size(loc) > Target::ptrsize * 4U && !needsNested())
+ if (size(loc) > target.ptrsize * 4U && !needsNested())
structinit->useStaticInit = true;
structinit->type = this;
d_uns64 TypeClass::size(Loc)
{
- return Target::ptrsize;
+ return target.ptrsize;
}
Dsymbol *TypeClass::toDsymbol(Scope *)
};
typedef unsigned char TY; // ENUMTY
-extern int Tsize_t;
-extern int Tptrdiff_t;
-
#define SIZE_INVALID (~(d_uns64)0) // error return from size() functions
static Type *tstring; // immutable(char)[]
static Type *twstring; // immutable(wchar)[]
static Type *tdstring; // immutable(dchar)[]
- static Type *tvalist; // va_list alias
static Type *terror; // for error recovery
static Type *tnull; // for null type
if (v->type->hasPointers() && v->type->toBasetype()->ty != Tstruct)
{
- if ((ad->type->alignment() < (unsigned)Target::ptrsize ||
- (v->offset & (Target::ptrsize - 1))) &&
+ if ((ad->type->alignment() < target.ptrsize ||
+ (v->offset & (target.ptrsize - 1))) &&
sc->func->setUnsafe())
{
if (printmsg)
fs->key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL);
fs->key->storage_class |= STCtemp;
}
- else if (fs->key->type->ty != Tsize_t)
+ else if (fs->key->type->ty != Type::tsize_t->ty)
{
tmp_length = new CastExp(loc, tmp_length, fs->key->type);
}
d_uns64 keysize = taa->index->size();
if (keysize == SIZE_INVALID)
goto Lerror2;
- assert(keysize < UINT64_MAX - Target::ptrsize);
- keysize = (keysize + (Target::ptrsize- 1)) & ~(Target::ptrsize - 1);
+ assert(keysize < UINT64_MAX - target.ptrsize);
+ keysize = (keysize + (target.ptrsize - 1)) & ~(target.ptrsize - 1);
// paint delegate argument to the type runtime expects
if (!fldeTy[i]->equals(flde->type))
{
* try { body } finally { _d_criticalexit(critsec.ptr); }
*/
Identifier *id = Identifier::generateId("__critsec");
- Type *t = Type::tint8->sarrayOf(Target::ptrsize + Target::critsecsize());
+ Type *t = Type::tint8->sarrayOf(target.ptrsize + target.critsecsize());
VarDeclaration *tmp = new VarDeclaration(ss->loc, t, id, NULL);
tmp->storage_class |= STCtemp | STCgshared | STCstatic;
}
else if (cd->isCPPclass())
{
- if (!Target::cppExceptions)
+ if (!target.cpp.exceptions)
{
error(c->loc, "catching C++ class objects not supported for this target");
c->errors = true;
class TypeTuple;
struct OutBuffer;
+struct TargetC
+{
+ unsigned longsize; // size of a C 'long' or 'unsigned long' type
+ unsigned long_doublesize; // size of a C 'long double'
+ unsigned criticalSectionSize; // size of os critical section
+};
+
+struct TargetCPP
+{
+ bool reverseOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order
+ bool exceptions; // set if catching C++ exceptions is supported
+ bool twoDtorInVtable; // target C++ ABI puts deleting and non-deleting destructor into vtable
+
+ const char *toMangle(Dsymbol *s);
+ const char *typeInfoMangle(ClassDeclaration *cd);
+ const char *typeMangle(Type *t);
+ Type *parameterType(Parameter *p);
+ bool fundamentalType(const Type *t, bool& isFundamental);
+};
+
+struct TargetObjC
+{
+ bool supported; // set if compiler can interface with Objective-C
+};
+
struct Target
{
- static int ptrsize;
- static int realsize; // size a real consumes in memory
- static int realpad; // 'padding' added to the CPU real size to bring it up to realsize
- static int realalignsize; // alignment for reals
- static bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order
- static bool cppExceptions; // set if catching C++ exceptions is supported
- static int c_longsize; // size of a C 'long' or 'unsigned long' type
- static int c_long_doublesize; // size of a C 'long double'
- static int classinfosize; // size of 'ClassInfo'
- static unsigned long long maxStaticDataSize; // maximum size of static data
+ // D ABI
+ unsigned ptrsize;
+ unsigned realsize; // size a real consumes in memory
+ unsigned realpad; // 'padding' added to the CPU real size to bring it up to realsize
+ unsigned realalignsize; // alignment for reals
+ unsigned classinfosize; // size of 'ClassInfo'
+ unsigned long long maxStaticDataSize; // maximum size of static data
+
+ // C ABI
+ TargetC c;
+
+ // C++ ABI
+ TargetCPP cpp;
+
+ // Objective-C ABI
+ TargetObjC objc;
template <typename T>
struct FPTypeProperties
{
- static real_t max;
- static real_t min_normal;
- static real_t nan;
- static real_t snan;
- static real_t infinity;
- static real_t epsilon;
-
- static d_int64 dig;
- static d_int64 mant_dig;
- static d_int64 max_exp;
- static d_int64 min_exp;
- static d_int64 max_10_exp;
- static d_int64 min_10_exp;
+ real_t max;
+ real_t min_normal;
+ real_t nan;
+ real_t snan;
+ real_t infinity;
+ real_t epsilon;
+
+ d_int64 dig;
+ d_int64 mant_dig;
+ d_int64 max_exp;
+ d_int64 min_exp;
+ d_int64 max_10_exp;
+ d_int64 min_10_exp;
};
- typedef FPTypeProperties<float> FloatProperties;
- typedef FPTypeProperties<double> DoubleProperties;
- typedef FPTypeProperties<real_t> RealProperties;
+ FPTypeProperties<float> FloatProperties;
+ FPTypeProperties<double> DoubleProperties;
+ FPTypeProperties<real_t> RealProperties;
- static void _init();
+private:
+ Type *tvalist;
+
+public:
+ void _init(const Param& params);
// Type sizes and support.
- static unsigned alignsize(Type* type);
- static unsigned fieldalign(Type* type);
- static unsigned critsecsize();
- static Type *va_listType(); // get type of va_list
- static int isVectorTypeSupported(int sz, Type *type);
- static bool isVectorOpSupported(Type *type, TOK op, Type *t2 = NULL);
+ unsigned alignsize(Type *type);
+ unsigned fieldalign(Type *type);
+ unsigned critsecsize();
+ Type *va_listType(const Loc &loc, Scope *sc); // get type of va_list
+ int isVectorTypeSupported(int sz, Type *type);
+ bool isVectorOpSupported(Type *type, TOK op, Type *t2 = NULL);
// ABI and backend.
- static const char *toCppMangle(Dsymbol *s);
- static const char *cppTypeInfoMangle(ClassDeclaration *cd);
- static const char *cppTypeMangle(Type *t);
- static Type *cppParameterType(Parameter *p);
- static bool cppFundamentalType(const Type *t, bool& isFundamental);
- static LINK systemLinkage();
- static TypeTuple *toArgTypes(Type *t);
+ LINK systemLinkage();
+ TypeTuple *toArgTypes(Type *t);
};
+
+extern Target target;
field = create_field_decl (vtbltype, NULL, 1, 1);
insert_aggregate_field (type, field, offset);
- structsize += id->vtbl.length * Target::ptrsize;
+ structsize += id->vtbl.length * target.ptrsize;
}
}
}
tree field = create_field_decl (vtbltype, NULL, 1, 1);
insert_aggregate_field (type, field, offset);
- structsize += id->vtbl.length * Target::ptrsize;
+ structsize += id->vtbl.length * target.ptrsize;
}
}
}
/* Let C++ do the RTTI generation, and just reference the symbol as
extern, knowing the underlying type is not required. */
- const char *ident = Target::cppTypeInfoMangle (cd);
+ const char *ident = target.cpp.typeInfoMangle (cd);
tree typeinfo = declare_extern_var (get_identifier (ident),
unknown_type_node);
TREE_READONLY (typeinfo) = 1;
bool
valist_array_p (Type *type)
{
- if (Type::tvalist->ty == Tsarray)
+ Type *tvalist = target.va_listType (Loc (), NULL);
+ if (tvalist->ty == Tsarray)
{
Type *tb = type->toBasetype ();
- if (same_type_p (tb, Type::tvalist))
+ if (same_type_p (tb, tvalist))
return true;
}
{
tree field = create_field_decl (ptr_type_node, "__monitor", 1,
inherited_p);
- insert_aggregate_field (type, field, Target::ptrsize);
+ insert_aggregate_field (type, field, target.ptrsize);
}
}