diff --git a/dmd2/access.c b/dmd2/access.c index ef16f226..69f527ef 100644 --- a/dmd2/access.c +++ b/dmd2/access.c @@ -253,7 +253,6 @@ void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) if (!result) { error(loc, "member %s is not accessible", smember->toChars()); -halt(); } } diff --git a/dmd2/arrayop.c b/dmd2/arrayop.c index 15cfcc04..b399fa97 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -91,7 +91,9 @@ bool isArrayOpValid(Expression *e) Expression *BinExp::arrayOp(Scope *sc) { - if (type->toBasetype()->nextOf()->toBasetype()->ty == Tvoid) + Type *tb = type->toBasetype(); + assert(tb->ty == Tarray || tb->ty == Tsarray); + if (tb->nextOf()->toBasetype()->ty == Tvoid) { error("Cannot perform array operations on void[] arrays"); return new ErrorExp(); diff --git a/dmd2/cast.c b/dmd2/cast.c index 1e0c6ddd..bf0fffe2 100644 --- a/dmd2/cast.c +++ b/dmd2/cast.c @@ -449,8 +449,6 @@ MATCH StringExp::implicitConvTo(Type *t) printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", toChars(), committed, type->toChars(), t->toChars()); #endif - if (!committed) - { if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid) { return MATCHnomatch; @@ -471,7 +469,9 @@ MATCH StringExp::implicitConvTo(Type *t) ((TypeSArray *)t)->dim->toInteger()) return MATCHnomatch; TY tynto = t->nextOf()->ty; - if (tynto == Tchar || tynto == Twchar || tynto == Tdchar) + if (tynto == tyn) + return MATCHexact; + if (!committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar)) return MATCHexact; } else if (type->ty == Tarray) @@ -480,7 +480,9 @@ MATCH StringExp::implicitConvTo(Type *t) ((TypeSArray *)t)->dim->toInteger()) return MATCHnomatch; TY tynto = t->nextOf()->ty; - if (tynto == Tchar || tynto == Twchar || tynto == Tdchar) + if (tynto == tyn) + return MATCHexact; + if (!committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar)) return MATCHexact; } case Tarray: @@ -497,13 +499,14 @@ MATCH StringExp::implicitConvTo(Type *t) case Tchar: case Twchar: case Tdchar: - return m; + if (!committed) + return m; + break; } break; } } } - } return Expression::implicitConvTo(t); #if 0 m = (MATCH)type->implicitConvTo(t); @@ -2002,6 +2005,28 @@ int arrayTypeCompatible(Loc loc, Type *t1, Type *t2) return 0; } +/*********************************** + * See if both types are arrays that can be compared + * for equality without any casting. Return !=0 if so. + * This is to enable comparing things like an immutable + * array with a mutable one. + */ +int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2) +{ + t1 = t1->toBasetype(); + t2 = t2->toBasetype(); + + if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) && + t2->ty == t1->ty) + { + if (t1->nextOf()->implicitConvTo(t2->nextOf()) >= MATCHconst || + t2->nextOf()->implicitConvTo(t1->nextOf()) >= MATCHconst) + return 1; + } + return 0; +} + + /******************************************************************/ /* Determine the integral ranges of an expression. diff --git a/dmd2/class.c b/dmd2/class.c index 059b89ac..e1a4e4bd 100644 --- a/dmd2/class.c +++ b/dmd2/class.c @@ -573,17 +573,18 @@ void ClassDeclaration::semantic(Scope *sc) isscope = 1; if (storage_class & STCabstract) isabstract = 1; + if (storage_class & STCimmutable) - type = type->invariantOf(); - else if (storage_class & STCconst) - type = type->constOf(); - else if (storage_class & STCshared) - type = type->sharedOf(); + type = type->addMod(MODimmutable); + if (storage_class & STCconst) + type = type->addMod(MODconst); + if (storage_class & STCshared) + type = type->addMod(MODshared); sc = sc->push(this); - sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | - STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared); - sc->stc |= storage_class & STC_TYPECTOR; + //sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared); + //sc->stc |= storage_class & STC_TYPECTOR; + sc->stc &= STCsafe | STCtrusted | STCsystem; sc->parent = this; sc->inunion = 0; diff --git a/dmd2/cppmangle.c b/dmd2/cppmangle.c index cd34c708..f6f436cc 100644 --- a/dmd2/cppmangle.c +++ b/dmd2/cppmangle.c @@ -43,6 +43,8 @@ struct CppMangleState static Array components; int substitute(OutBuffer *buf, void *p); + int exist(void *p); + void store(void *p); }; Array CppMangleState::components; @@ -82,6 +84,23 @@ int CppMangleState::substitute(OutBuffer *buf, void *p) return 0; } +int CppMangleState::exist(void *p) +{ + for (size_t i = 0; i < components.dim; i++) + { + if (p == components.data[i]) + { + return 1; + } + } + return 0; +} + +void CppMangleState::store(void *p) +{ + components.push(p); +} + void source_name(OutBuffer *buf, Dsymbol *s) { char *name = s->ident->toChars(); @@ -203,9 +222,6 @@ void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms) * u # vendor extended type */ - if (isConst()) - buf->writeByte('K'); - switch (ty) { case Tvoid: c = 'v'; break; @@ -234,12 +250,18 @@ void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms) default: assert(0); } - if (p) + if (p || isConst()) { if (cms->substitute(buf, this)) return; - buf->writeByte(p); } + + if (isConst()) + buf->writeByte('K'); + + if (p) + buf->writeByte(p); + buf->writeByte(c); } @@ -266,19 +288,25 @@ void TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms) void TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms) { - if (!cms->substitute(buf, this)) + if (!cms->exist(this)) { buf->writeByte('P'); next->toCppMangle(buf, cms); + cms->store(this); } + else + cms->substitute(buf, this); } void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms) { - if (!cms->substitute(buf, this)) + if (!cms->exist(this)) { buf->writeByte('R'); next->toCppMangle(buf, cms); + cms->store(this); } + else + cms->substitute(buf, this); } @@ -325,15 +353,37 @@ void TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms) void TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms) { - if (!cms->substitute(buf, sym)) - cpp_mangle_name(buf, cms, sym); + if (!cms->exist(this)) + { + if (isConst()) + buf->writeByte('K'); + + if (!cms->substitute(buf, sym)) + cpp_mangle_name(buf, cms, sym); + + if (isConst()) + cms->store(this); + } + else + cms->substitute(buf, this); } void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms) { - if (!cms->substitute(buf, sym)) - cpp_mangle_name(buf, cms, sym); + if (!cms->exist(this)) + { + if (isConst()) + buf->writeByte('K'); + + if (!cms->substitute(buf, sym)) + cpp_mangle_name(buf, cms, sym); + + if (isConst()) + cms->store(this); + } + else + cms->substitute(buf, this); } @@ -373,7 +423,14 @@ void Parameter::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *a { // Mangle static arrays as pointers t = t->pointerTo(); } - t->toCppMangle(buf, cms); + + /* If it is a basic, enum or struct type, + * then don't mark it const + */ + if ((t->ty == Tenum || t->ty == Tstruct || t->isTypeBasic()) && t->isConst()) + t->mutableOf()->toCppMangle(buf, cms); + else + t->toCppMangle(buf, cms); n++; } diff --git a/dmd2/declaration.c b/dmd2/declaration.c index 282e768e..622975cb 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -154,6 +154,7 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t) TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects) : Declaration(id) { + this->loc = loc; this->type = NULL; this->objects = objects; this->isexp = 0; @@ -776,6 +777,10 @@ void VarDeclaration::semantic(Scope *sc) if (storage_class & STCextern && init) error("extern symbols cannot have initializers"); + AggregateDeclaration *ad = isThis(); + if (ad) + storage_class |= ad->storage_class & STC_TYPECTOR; + /* If auto type inference, do the inference */ int inferred = 0; @@ -789,6 +794,11 @@ void VarDeclaration::semantic(Scope *sc) e = ai->toAssocArrayLiteral(); else e = init->toExpression(); + if (!e) + { + error("cannot infer type from initializer"); + e = new ErrorExp(); + } init = new ExpInitializer(e->loc, e); type = init->inferType(sc); if (type->ty == Tsarray) @@ -1446,6 +1456,27 @@ void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); } +AggregateDeclaration *VarDeclaration::isThis() +{ + AggregateDeclaration *ad = NULL; + + if (!(storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | + STCtls | STCgshared | STCctfe))) + { + if ((storage_class & (STCconst | STCimmutable | STCwild)) && init) + return NULL; + + for (Dsymbol *s = this; s; s = s->parent) + { + ad = s->isMember(); + if (ad) + break; + if (!s->parent || !s->parent->isTemplateMixin()) break; + } + } + return ad; +} + int VarDeclaration::needThis() { //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); diff --git a/dmd2/declaration.h b/dmd2/declaration.h index e56d441d..fef50a80 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -304,6 +304,7 @@ struct VarDeclaration : Declaration Type *htype; Initializer *hinit; #endif + AggregateDeclaration *isThis(); int needThis(); int isImportedSymbol(); int isDataseg(); @@ -757,6 +758,7 @@ struct FuncDeclaration : Declaration void semantic3(Scope *sc); // called from semantic3 void varArgs(Scope *sc, TypeFunction*, VarDeclaration *&, VarDeclaration *&); + int equals(Object *o); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -899,7 +901,6 @@ struct CtorDeclaration : FuncDeclaration int isVirtual(); int addPreInvariant(); int addPostInvariant(); - void toDocBuffer(OutBuffer *buf); CtorDeclaration *isCtorDeclaration() { return this; } }; diff --git a/dmd2/doc.c b/dmd2/doc.c index 2a373744..3e4e0c11 100644 --- a/dmd2/doc.c +++ b/dmd2/doc.c @@ -131,6 +131,8 @@ SMALL = $0\n\ BR =
\n\ LINK = $0\n\ LINK2 = $+\n\ +LPAREN= (\n\ +RPAREN= )\n\ \n\ RED = $0\n\ BLUE = $0\n\ @@ -833,7 +835,8 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf) hgs.ddoc = 1; prefix(buf, td); - tf->next->toCBuffer(buf, NULL, &hgs); + if (tf) + tf->next->toCBuffer(buf, NULL, &hgs); buf->writeByte(' '); buf->writestring(ident->toChars()); buf->writeByte('('); @@ -845,7 +848,7 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf) tp->toCBuffer(buf, &hgs); } buf->writeByte(')'); - Parameter::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs); + Parameter::argsToCBuffer(buf, &hgs, tf ? tf->parameters : NULL, tf ? tf->varargs : 0); buf->writestring(";\n"); highlightCode(NULL, this, buf, o); @@ -857,16 +860,6 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf) } } -void CtorDeclaration::toDocBuffer(OutBuffer *buf) -{ - HdrGenState hgs; - - buf->writestring("this"); - Parameter::argsToCBuffer(buf, &hgs, arguments, varargs); - buf->writestring(";\n"); -} - - void AggregateDeclaration::toDocBuffer(OutBuffer *buf) { if (ident) diff --git a/dmd2/expression.c b/dmd2/expression.c index 05f425b7..513e7b1f 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -280,13 +280,13 @@ Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc) */ #if DMDV2 -int arrayExpressionCanThrow(Expressions *exps) +int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow) { if (exps) { for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)exps->data[i]; - if (e && e->canThrow()) + if (e && e->canThrow(mustNotThrow)) return 1; } } @@ -1321,6 +1321,15 @@ Expression *Expression::checkToBoolean(Scope *sc) e = e->semantic(sc); return e; } + + // Forward to aliasthis. + if (ad->aliasthis) + { + Expression *e = new DotIdExp(loc, this, ad->aliasthis->ident); + e = e->semantic(sc); + e = e->checkToBoolean(sc); + return e; + } } if (!type->checkBoolean()) @@ -1407,9 +1416,11 @@ int Expression::isBit() /******************************** * Can this expression throw an exception? * Valid only after semantic() pass. + * + * If 'mustNotThrow' is true, generate an error if it throws */ -int Expression::canThrow() +int Expression::canThrow(bool mustNotThrow) { #if DMDV2 return FALSE; @@ -2353,7 +2364,7 @@ Lagain: { //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); if (!type) - { if (!v->type && v->scope) + { if ((!v->type || !v->type->deco) && v->scope) v->semantic(v->scope); type = v->type; if (!v->type) @@ -2390,6 +2401,11 @@ Lagain: if (!f->originalType && f->scope) // semantic not yet run f->semantic(f->scope); + if (f->isUnitTestDeclaration()) + { + error("cannot call unittest function %s", toChars()); + return new ErrorExp(); + } if (!f->type->deco) { error("forward reference to %s", toChars()); @@ -2772,7 +2788,7 @@ Expression *StringExp::syntaxCopy() int StringExp::equals(Object *o) { - //printf("StringExp::equals('%s')\n", o->toChars()); + //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars()); if (o && o->dyncast() == DYNCAST_EXPRESSION) { Expression *e = (Expression *)o; @@ -2941,6 +2957,7 @@ StringExp *StringExp::toUTF8(Scope *sc) int StringExp::compare(Object *obj) { + //printf("StringExp::compare()\n"); // Used to sort case statement expressions so we can do an efficient lookup StringExp *se2 = (StringExp *)(obj); @@ -2954,12 +2971,13 @@ int StringExp::compare(Object *obj) int len1 = len; int len2 = se2->len; + //printf("sz = %d, len1 = %d, len2 = %d\n", sz, len1, len2); if (len1 == len2) { switch (sz) { case 1: - return strcmp((char *)string, (char *)se2->string); + return memcmp((char *)string, (char *)se2->string, len1); case 2: { unsigned u; @@ -3184,7 +3202,7 @@ int ArrayLiteralExp::isBool(int result) } #if DMDV2 -int ArrayLiteralExp::canThrow() +int ArrayLiteralExp::canThrow(bool mustNotThrow) { return 1; // because it can fail allocating memory } @@ -3279,7 +3297,7 @@ int AssocArrayLiteralExp::isBool(int result) } #if DMDV2 -int AssocArrayLiteralExp::canThrow() +int AssocArrayLiteralExp::canThrow(bool mustNotThrow) { return 1; } @@ -3530,9 +3548,9 @@ int StructLiteralExp::checkSideEffect(int flag) } #if DMDV2 -int StructLiteralExp::canThrow() +int StructLiteralExp::canThrow(bool mustNotThrow) { - return arrayExpressionCanThrow(elements); + return arrayExpressionCanThrow(elements, mustNotThrow); } #endif @@ -4068,9 +4086,9 @@ int NewExp::checkSideEffect(int flag) } #if DMDV2 -int NewExp::canThrow() +int NewExp::canThrow(bool mustNotThrow) { - return 1; + return 0; // regard storage allocation failures as not recoverable } #endif @@ -4142,7 +4160,7 @@ int NewAnonClassExp::checkSideEffect(int flag) } #if DMDV2 -int NewAnonClassExp::canThrow() +int NewAnonClassExp::canThrow(bool mustNotThrow) { return 1; } @@ -4618,9 +4636,9 @@ int TupleExp::checkSideEffect(int flag) } #if DMDV2 -int TupleExp::canThrow() +int TupleExp::canThrow(bool mustNotThrow) { - return arrayExpressionCanThrow(exps); + return arrayExpressionCanThrow(exps, mustNotThrow); } #endif @@ -4806,12 +4824,12 @@ int DeclarationExp::checkSideEffect(int flag) } #if DMDV2 -int DeclarationExp::canThrow() +int DeclarationExp::canThrow(bool mustNotThrow) { VarDeclaration *v = declaration->isVarDeclaration(); if (v && v->init) { ExpInitializer *ie = v->init->isExpInitializer(); - return ie && ie->exp->canThrow(); + return ie && ie->exp->canThrow(mustNotThrow); } return 0; } @@ -5159,6 +5177,17 @@ Expression *IsExp::semantic(Scope *sc) goto Lno; break; + case TOKargTypes: + /* Generate a type tuple of the equivalent types used to determine if a + * function argument of this type can be passed in registers. + * The results of this are highly platform dependent, and intended + * primarly for use in implementing va_arg(). + */ + tded = targ->toArgTypes(); + if (!tded) + goto Lno; // not valid for a parameter + break; + default: assert(0); } @@ -5189,7 +5218,7 @@ Expression *IsExp::semantic(Scope *sc) tded = (Type *)dedtypes.data[0]; if (!tded) tded = targ; - +#if DMDV2 Objects tiargs; tiargs.setDim(1); tiargs.data[0] = (void *)targ; @@ -5204,16 +5233,16 @@ Expression *IsExp::semantic(Scope *sc) if (m == MATCHnomatch) goto Lno; s->semantic(sc); - if (!sc->insert(s)) - error("declaration %s is already defined", s->toChars()); #if 0 Object *o = (Object *)dedtypes.data[i]; Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o); #endif if (sc->sd) s->addMember(sc, sc->sd, 1); + else if (!sc->insert(s)) + error("declaration %s is already defined", s->toChars()); } - +#endif goto Lyes; } } @@ -5327,9 +5356,9 @@ Expression *UnaExp::semantic(Scope *sc) } #if DMDV2 -int UnaExp::canThrow() +int UnaExp::canThrow(bool mustNotThrow) { - return e1->canThrow(); + return e1->canThrow(mustNotThrow); } #endif @@ -5473,9 +5502,9 @@ int BinExp::isunsigned() } #if DMDV2 -int BinExp::canThrow() +int BinExp::canThrow(bool mustNotThrow) { - return e1->canThrow() || e2->canThrow(); + return e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow); } #endif @@ -5509,7 +5538,9 @@ Expression *BinAssignExp::commonSemanticAssign(Scope *sc) if (e1->op == TOKslice) { // T[] op= ... - typeCombine(sc); + e = typeCombine(sc); + if (e->op == TOKerror) + return e; type = e1->type; return arrayOp(sc); } @@ -5552,7 +5583,9 @@ Expression *BinAssignExp::commonSemanticAssignIntegral(Scope *sc) if (e1->op == TOKslice) { // T[] op= ... - typeCombine(sc); + e = typeCombine(sc); + if (e->op == TOKerror) + return e; type = e1->type; return arrayOp(sc); } @@ -5791,7 +5824,7 @@ int AssertExp::checkSideEffect(int flag) } #if DMDV2 -int AssertExp::canThrow() +int AssertExp::canThrow(bool mustNotThrow) { /* assert()s are non-recoverable errors, so functions that * use them can be considered "nothrow" @@ -7305,10 +7338,10 @@ int CallExp::checkSideEffect(int flag) } #if DMDV2 -int CallExp::canThrow() +int CallExp::canThrow(bool mustNotThrow) { //printf("CallExp::canThrow() %s\n", toChars()); - if (e1->canThrow()) + if (e1->canThrow(mustNotThrow)) return 1; /* If any of the arguments can throw, then this expression can throw @@ -7316,7 +7349,7 @@ int CallExp::canThrow() for (size_t i = 0; i < arguments->dim; i++) { Expression *e = (Expression *)arguments->data[i]; - if (e && e->canThrow()) + if (e && e->canThrow(mustNotThrow)) return 1; } @@ -7332,7 +7365,8 @@ int CallExp::canThrow() return 0; if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow) return 0; - + if (mustNotThrow) + error("%s is not nothrow", e1->toChars()); return 1; } #endif @@ -8681,7 +8715,10 @@ Expression *IndexExp::semantic(Scope *sc) case Taarray: { TypeAArray *taa = (TypeAArray *)t1; - if (!arrayTypeCompatible(e2->loc, e2->type, taa->index)) + /* We can skip the implicit conversion if they differ only by + * constness (Bugzilla 2684, see also bug 2954b) + */ + if (!arrayTypeCompatibleWithoutCasting(e2->loc, e2->type, taa->index)) { e2 = e2->implicitCastTo(sc, taa->index); // type checking } @@ -8761,8 +8798,14 @@ Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) error("string literals are immutable"); if (type && !type->isMutable()) error("%s isn't mutable", e->toChars()); - if (e1->type->toBasetype()->ty == Taarray) + Type *t1 = e1->type->toBasetype(); + if (t1->ty == Taarray) + { TypeAArray *taa = (TypeAArray *)t1; + Type *t2b = e2->type->toBasetype(); + if (t2b->ty == Tarray && t2b->nextOf()->isMutable()) + error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars()); e1 = e1->modifiableLvalue(sc, e1); + } return toLvalue(sc, e); } @@ -9079,9 +9122,10 @@ Expression *AssignExp::semantic(Scope *sc) { // Deal with AAs (Bugzilla 2451) // Rewrite as: - // e1 = (typeof(e2) tmp = void, tmp = e2, tmp); + // e1 = (typeof(aa.value) tmp = void, tmp = e2, tmp); + Type * aaValueType = ((TypeAArray *)((IndexExp*)e1)->e1->type->toBasetype())->next; Identifier *id = Lexer::uniqueId("__aatmp"); - VarDeclaration *v = new VarDeclaration(loc, e2->type, + VarDeclaration *v = new VarDeclaration(loc, aaValueType, id, new VoidInitializer(NULL)); v->storage_class |= STCctfe; @@ -9264,7 +9308,9 @@ Expression *AddAssignExp::semantic(Scope *sc) if (e1->op == TOKslice) { - typeCombine(sc); + e = typeCombine(sc); + if (e->op == TOKerror) + return e; type = e1->type; return arrayOp(sc); } @@ -9375,7 +9421,9 @@ Expression *MinAssignExp::semantic(Scope *sc) if (e1->op == TOKslice) { // T[] -= ... - typeCombine(sc); + e = typeCombine(sc); + if (e->op == TOKerror) + return e; type = e1->type; return arrayOp(sc); } @@ -9505,9 +9553,10 @@ Expression *MulAssignExp::semantic(Scope *sc) #endif if (e1->op == TOKslice) - { // T[] -= ... - typeCombine(sc); - type = e1->type; + { // T[] *= ... + e = typeCombine(sc); + if (e->op == TOKerror) + return e; return arrayOp(sc); } @@ -9578,8 +9627,10 @@ Expression *DivAssignExp::semantic(Scope *sc) #endif if (e1->op == TOKslice) - { // T[] -= ... - typeCombine(sc); + { // T[] /= ... + e = typeCombine(sc); + if (e->op == TOKerror) + return e; type = e1->type; return arrayOp(sc); } @@ -11238,9 +11289,9 @@ int CondExp::checkSideEffect(int flag) } #if DMDV2 -int CondExp::canThrow() +int CondExp::canThrow(bool mustNotThrow) { - return econd->canThrow() || e1->canThrow() || e2->canThrow(); + return econd->canThrow(mustNotThrow) || e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow); } #endif diff --git a/dmd2/expression.h b/dmd2/expression.h index 381d7716..474bcfed 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -86,7 +86,7 @@ void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs); void expandTuples(Expressions *exps); FuncDeclaration *hasThis(Scope *sc); Expression *fromConstInitializer(int result, Expression *e); -int arrayExpressionCanThrow(Expressions *exps); +int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow); struct IntRange { uinteger_t imin; @@ -163,7 +163,7 @@ struct Expression : Object virtual int isBool(int result); virtual int isBit(); virtual int checkSideEffect(int flag); - virtual int canThrow(); + virtual int canThrow(bool mustNotThrow); virtual int inlineCost(InlineCostState *ics); virtual Expression *doInline(InlineDoState *ids); @@ -448,7 +448,7 @@ struct TupleExp : Expression #if IN_DMD elem *toElem(IRState *irs); #endif - int canThrow(); + int canThrow(bool mustNotThrow); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -477,7 +477,7 @@ struct ArrayLiteralExp : Expression Expression *interpret(InterState *istate); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - int canThrow(); + int canThrow(bool mustNotThrow); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -513,7 +513,7 @@ struct AssocArrayLiteralExp : Expression Expression *interpret(InterState *istate); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - int canThrow(); + int canThrow(bool mustNotThrow); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -552,7 +552,7 @@ struct StructLiteralExp : Expression Expression *interpret(InterState *istate); int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); - int canThrow(); + int canThrow(bool mustNotThrow); MATCH implicitConvTo(Type *t); int inlineCost(InlineCostState *ics); @@ -644,7 +644,7 @@ struct NewExp : Expression int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void scanForNestedRef(Scope *sc); - int canThrow(); + int canThrow(bool mustNotThrow); //int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -670,7 +670,7 @@ struct NewAnonClassExp : Expression Expression *semantic(Scope *sc); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int canThrow(); + int canThrow(bool mustNotThrow); }; #if DMDV2 @@ -808,7 +808,7 @@ struct DeclarationExp : Expression elem *toElem(IRState *irs); #endif void scanForNestedRef(Scope *sc); - int canThrow(); + int canThrow(bool mustNotThrow); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -891,7 +891,7 @@ struct UnaExp : Expression void dump(int indent); void scanForNestedRef(Scope *sc); Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *)); - int canThrow(); + int canThrow(bool mustNotThrow); Expression *resolveLoc(Loc loc, Scope *sc); int inlineCost(InlineCostState *ics); @@ -924,7 +924,7 @@ struct BinExp : Expression Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *)); Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *)); Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0); - int canThrow(); + int canThrow(bool mustNotThrow); Expression *arrayOp(Scope *sc); int inlineCost(InlineCostState *ics); @@ -981,7 +981,7 @@ struct AssertExp : UnaExp Expression *semantic(Scope *sc); Expression *interpret(InterState *istate); int checkSideEffect(int flag); - int canThrow(); + int canThrow(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int inlineCost(InlineCostState *ics); @@ -1114,7 +1114,7 @@ struct CallExp : UnaExp void scanForNestedRef(Scope *sc); int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); - int canThrow(); + int canThrow(bool mustNotThrow); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -1985,7 +1985,7 @@ struct CondExp : BinExp MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); void scanForNestedRef(Scope *sc); - int canThrow(); + int canThrow(bool mustNotThrow); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); diff --git a/dmd2/func.c b/dmd2/func.c index 27806134..15295a3f 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -142,6 +142,7 @@ Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s) void FuncDeclaration::semantic(Scope *sc) { TypeFunction *f; + AggregateDeclaration *ad; StructDeclaration *sd; ClassDeclaration *cd; InterfaceDeclaration *id; @@ -187,6 +188,10 @@ void FuncDeclaration::semantic(Scope *sc) foverrides.setDim(0); // reset in case semantic() is being retried for this function storage_class |= sc->stc & ~STCref; + ad = isThis(); + if (ad) + storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized); + //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal()); if (!originalType) @@ -194,7 +199,9 @@ void FuncDeclaration::semantic(Scope *sc) if (!type->deco) { sc = sc->push(); - sc->stc |= storage_class & STCref; // forward to function type + sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCdisable + | STCsafe | STCtrusted | STCsystem); // forward to function type + if (isCtorDeclaration()) sc->flags |= SCOPEctor; type = type->semantic(loc, sc); @@ -302,11 +309,11 @@ void FuncDeclaration::semantic(Scope *sc) #endif #ifdef IN_GCC - AggregateDeclaration *ad; - - ad = parent->isAggregateDeclaration(); - if (ad) - ad->methods.push(this); + { + AggregateDeclaration *ad = parent->isAggregateDeclaration(); + if (ad) + ad->methods.push(this); + } #endif sd = parent->isStructDeclaration(); if (sd) @@ -1381,8 +1388,10 @@ void FuncDeclaration::semantic3(Scope *sc) else if (!inlineAsm) { #if DMDV2 - int blockexit = fbody ? fbody->blockExit() : BEfallthru; - if (f->isnothrow && blockexit & BEthrow) + // Check for errors related to 'nothrow'. + int nothrowErrors = global.errors; + int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru; + if (f->isnothrow && (global.errors != nothrowErrors) ) error("'%s' is nothrow yet may throw", toChars()); int offend = blockexit & BEfallthru; @@ -1680,7 +1689,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (e) { Statement *s = new ExpStatement(0, e); s = s->semantic(sc2); - if (fbody->blockExit() == BEfallthru) + if (fbody->blockExit(f->isnothrow) == BEfallthru) fbody = new CompoundStatement(0, fbody, s); else fbody = new TryFinallyStatement(0, fbody, s); @@ -1737,6 +1746,8 @@ void FuncDeclaration::semantic3(Scope *sc) semanticRun = PASSsemanticdone; // Ensure errors get reported again else semanticRun = PASSsemantic3done; + //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); + //fflush(stdout); } void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -1748,6 +1759,23 @@ void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) bodyToCBuffer(buf, hgs); } +int FuncDeclaration::equals(Object *o) +{ + if (this == o) + return TRUE; + + Dsymbol *s = isDsymbol(o); + if (s) + { + FuncDeclaration *fd = s->isFuncDeclaration(); + if (fd) + { + return toParent()->equals(fd->toParent()) && + ident->equals(fd->ident) && type->equals(fd->type); + } + } + return FALSE; +} void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs) { @@ -1825,7 +1853,10 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf) if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done) { assert(fdv->scope); - fdv->semantic3(fdv->scope); + Scope *sc = fdv->scope->push(); + sc->stc &= ~STCoverride; + fdv->semantic3(sc); + sc->pop(); } sf = fdv->mergeFrequire(sf); @@ -1872,6 +1903,19 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf) for (int i = 0; i < foverrides.dim; i++) { FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i]; + + /* The semantic pass on the contracts of the overridden functions must + * be completed before code generation occurs (bug 3602 and 5230). + */ + if (fdv->fdensure && fdv->fdensure->semanticRun != PASSsemantic3done) + { + assert(fdv->scope); + Scope *sc = fdv->scope->push(); + sc->stc &= ~STCoverride; + fdv->semantic3(sc); + sc->pop(); + } + sf = fdv->mergeFensure(sf); if (fdv->fdensure) { @@ -3046,7 +3090,11 @@ void CtorDeclaration::semantic(Scope *sc) #if STRUCTTHISREF if (ad && ad->isStructDeclaration()) - ((TypeFunction *)type)->isref = 1; + { ((TypeFunction *)type)->isref = 1; + if (!originalType) + // Leave off the "ref" + originalType = new TypeFunction(arguments, tret, varargs, LINKd, storage_class | sc->stc); + } #endif if (!originalType) originalType = type; @@ -3104,6 +3152,8 @@ int CtorDeclaration::addPostInvariant() void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { + if (originalType && originalType->ty == Tfunction) + ((TypeFunction *)originalType)->attributesToCBuffer(buf, 0); buf->writestring("this"); Parameter::argsToCBuffer(buf, hgs, arguments, varargs); bodyToCBuffer(buf, hgs); @@ -3628,6 +3678,8 @@ void UnitTestDeclaration::semantic(Scope *sc) if (!type) type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); Scope *sc2 = sc->push(); + // It makes no sense for unit tests to be pure or nothrow. + sc2->stc &= ~(STCnothrow | STCpure); sc2->linkage = LINKd; FuncDeclaration::semantic(sc2); sc2->pop(); diff --git a/dmd2/imphint.c b/dmd2/imphint.c index 4e631304..50db4b75 100644 --- a/dmd2/imphint.c +++ b/dmd2/imphint.c @@ -15,6 +15,8 @@ #include #include +#include "mars.h" + /****************************************** * Looks for undefined identifier s to see * if it might be undefined because an import @@ -30,24 +32,28 @@ const char *importHint(const char *s) { "std.c.stdio", "std.stdio", "std.math", + "std.c.stdarg", }; static const char *names[] = { "printf", NULL, "writefln", NULL, "sin", "cos", "sqrt", "fabs", NULL, + "__va_argsave_t", NULL, }; #else static const char *modules[] = { "core.stdc.stdio", "std.stdio", "std.math", + "std.c.stdarg", }; static const char *names[] = { "printf", NULL, "writeln", NULL, "sin", "cos", "sqrt", "fabs", NULL, + "__va_argsave_t", NULL, }; #endif int m = 0; diff --git a/dmd2/interpret.c b/dmd2/interpret.c index df35ad9b..e6f0be2a 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -55,6 +55,7 @@ Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclarati ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim); Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference = NULL); Expression *getVarExp(Loc loc, InterState *istate, Declaration *d); +VarDeclaration *findParentVar(Expression *e, Expression *thisval); /************************************* * Attempt to interpret a function given the arguments. @@ -220,9 +221,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument } } // Don't restore the value of 'this' upon function return - if (needThis() && thisarg->op == TOKvar && istate) + if (needThis() && istate) { - VarDeclaration *thisvar = ((VarExp *)(thisarg))->var->isVarDeclaration(); + VarDeclaration *thisvar = findParentVar(thisarg, istate->localThis); + if (!thisvar) // it's a reference. Find which variable it refers to. + thisvar = findParentVar(thisarg->interpret(istate), istate->localThis); for (size_t i = 0; i < istate->vars.dim; i++) { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; if (v == thisvar) @@ -1354,6 +1357,11 @@ Expression *DeclarationExp::interpret(InterState *istate) e = ie->exp->interpret(istate); else if (v->init->isVoidInitializer()) e = NULL; + else + { + error("Declaration %s is not yet implemented in CTFE", toChars()); + e = EXP_CANT_INTERPRET; + } } #if DMDV2 else if (s == v && (v->isConst() || v->isImmutable()) && v->init) @@ -1366,13 +1374,19 @@ Expression *DeclarationExp::interpret(InterState *istate) else if (!e->type) e->type = v->type; } + else if (s->isTupleDeclaration() && !v->init) + e = NULL; + else + { + error("Declaration %s is not yet implemented in CTFE", toChars()); + e = EXP_CANT_INTERPRET; + } } else if (declaration->isAttribDeclaration() || declaration->isTemplateMixin() || declaration->isTupleDeclaration()) { // These can be made to work, too lazy now - error("Declaration %s is not yet implemented in CTFE", toChars()); - + error("Declaration %s is not yet implemented in CTFE", toChars()); e = EXP_CANT_INTERPRET; } else @@ -2731,8 +2745,12 @@ Expression *CallExp::interpret(InterState *istate) VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration(); if (vd && vd->value && vd->value->op == TOKsymoff) fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration(); - else { - ecall = vd->value->interpret(istate); + else + { + ecall = getVarExp(loc, istate, vd); + if (ecall == EXP_CANT_INTERPRET) + return ecall; + #if IN_LLVM if (ecall->op == TOKaddress) { AddrExp *e = (AddrExp*)ecall; @@ -2741,7 +2759,7 @@ Expression *CallExp::interpret(InterState *istate) } #else if (ecall->op == TOKsymoff) - fd = ((SymOffExp *)ecall)->var->isFuncDeclaration(); + fd = ((SymOffExp *)ecall)->var->isFuncDeclaration(); #endif } } diff --git a/dmd2/lexer.c b/dmd2/lexer.c index 3f41618e..fd5733d7 100644 --- a/dmd2/lexer.c +++ b/dmd2/lexer.c @@ -3002,6 +3002,7 @@ static Keyword keywords[] = //{ "manifest", TOKmanifest }, // Added after 1.0 + { "__argTypes", TOKargTypes }, { "ref", TOKref }, { "macro", TOKmacro }, #if DMDV2 diff --git a/dmd2/lexer.h b/dmd2/lexer.h index 3c0cd040..d5da99e0 100644 --- a/dmd2/lexer.h +++ b/dmd2/lexer.h @@ -152,6 +152,7 @@ enum TOK TOKunittest, // Added after 1.0 + TOKargTypes, TOKref, TOKmacro, #if DMDV2 diff --git a/dmd2/mangle.c b/dmd2/mangle.c index e6429a9a..a6d8d34d 100644 --- a/dmd2/mangle.c +++ b/dmd2/mangle.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2010 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -218,23 +218,26 @@ char *ClassDeclaration::mangle() char *TemplateInstance::mangle() { OutBuffer buf; - char *id; #if 0 - printf("TemplateInstance::mangle() %s", toChars()); + printf("TemplateInstance::mangle() %p %s", this, toChars()); if (parent) printf(" parent = %s %s", parent->kind(), parent->toChars()); printf("\n"); #endif - id = ident ? ident->toChars() : toChars(); + char *id = ident ? ident->toChars() : toChars(); if (!tempdecl) error("is not defined"); - else if (tempdecl->parent) + else { - char *p = tempdecl->parent->mangle(); - if (p[0] == '_' && p[1] == 'D') - p += 2; - buf.writestring(p); + Dsymbol *par = isnested || isTemplateMixin() ? parent : tempdecl->parent; + if (par) + { + char *p = par->mangle(); + if (p[0] == '_' && p[1] == 'D') + p += 2; + buf.writestring(p); + } } buf.printf("%zu%s", strlen(id), id); id = buf.toChars(); diff --git a/dmd2/mars.c b/dmd2/mars.c index a9908b5e..cccbafd2 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -100,7 +100,7 @@ Global::Global() "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; #endif ; - version = "v2.050"; + version = "v2.051"; #if IN_LLVM ldc_version = "LDC trunk"; llvm_version = "LLVM 2.8"; diff --git a/dmd2/mtype.c b/dmd2/mtype.c index 2fd0090d..04a60f10 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -1223,10 +1223,10 @@ Type *Type::addStorageClass(StorageClass stc) else { if (stc & (STCconst | STCin)) mod = MODconst; + else if (stc & STCwild) // const takes precedence over wild + mod |= MODwild; if (stc & STCshared) mod |= MODshared; - if (stc & STCwild) - mod |= MODwild; } return addMod(mod); } @@ -2198,7 +2198,7 @@ Type *TypeNext::makeConst() } TypeNext *t = (TypeNext *)Type::makeConst(); if (ty != Tfunction && ty != Tdelegate && - (next->deco || next->ty == Tfunction) && + //(next->deco || next->ty == Tfunction) && !next->isImmutable() && !next->isConst()) { if (next->isShared()) t->next = next->sharedConstOf(); @@ -2222,7 +2222,7 @@ Type *TypeNext::makeInvariant() } TypeNext *t = (TypeNext *)Type::makeInvariant(); if (ty != Tfunction && ty != Tdelegate && - (next->deco || next->ty == Tfunction) && + //(next->deco || next->ty == Tfunction) && !next->isImmutable()) { t->next = next->invariantOf(); } @@ -2242,7 +2242,7 @@ Type *TypeNext::makeShared() } TypeNext *t = (TypeNext *)Type::makeShared(); if (ty != Tfunction && ty != Tdelegate && - (next->deco || next->ty == Tfunction) && + //(next->deco || next->ty == Tfunction) && !next->isImmutable() && !next->isShared()) { if (next->isConst() || next->isWild()) @@ -2267,7 +2267,7 @@ Type *TypeNext::makeSharedConst() } TypeNext *t = (TypeNext *)Type::makeSharedConst(); if (ty != Tfunction && ty != Tdelegate && - (next->deco || next->ty == Tfunction) && + //(next->deco || next->ty == Tfunction) && !next->isImmutable() && !next->isSharedConst()) { t->next = next->sharedConstOf(); @@ -2289,7 +2289,7 @@ Type *TypeNext::makeWild() } TypeNext *t = (TypeNext *)Type::makeWild(); if (ty != Tfunction && ty != Tdelegate && - (next->deco || next->ty == Tfunction) && + //(next->deco || next->ty == Tfunction) && !next->isImmutable() && !next->isConst() && !next->isWild()) { if (next->isShared()) @@ -2314,7 +2314,7 @@ Type *TypeNext::makeSharedWild() } TypeNext *t = (TypeNext *)Type::makeSharedWild(); if (ty != Tfunction && ty != Tdelegate && - (next->deco || next->ty == Tfunction) && + //(next->deco || next->ty == Tfunction) && !next->isImmutable() && !next->isSharedConst()) { t->next = next->sharedWildOf(); @@ -2331,9 +2331,9 @@ Type *TypeNext::makeMutable() { //printf("TypeNext::makeMutable() %p, %s\n", this, toChars()); TypeNext *t = (TypeNext *)Type::makeMutable(); - if (ty != Tfunction && ty != Tdelegate && - (next->deco || next->ty == Tfunction) && - next->isWild()) + if ((ty != Tfunction && ty != Tdelegate && + //(next->deco || next->ty == Tfunction) && + next->isWild()) || ty == Tsarray) { t->next = next->mutableOf(); } @@ -3509,7 +3509,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) { Loverflow: error(loc, "index %jd overflow for static array", d1); - dim = new IntegerExp(0, 1, tsize_t); + goto Lerror; } } } @@ -3523,7 +3523,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) if (d >= tt->arguments->dim) { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim); - return Type::terror; + goto Lerror; } Parameter *arg = (Parameter *)tt->arguments->data[(size_t)d]; return arg->type; @@ -3531,18 +3531,30 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) case Tstruct: { TypeStruct *ts = (TypeStruct *)tbn; if (ts->sym->isnested) - error(loc, "cannot have array of inner structs %s", ts->toChars()); + { error(loc, "cannot have array of inner structs %s", ts->toChars()); + goto Lerror; + } break; } case Tfunction: case Tnone: error(loc, "can't have array of %s", tbn->toChars()); - tbn = next = tint32; - break; + goto Lerror; } if (tbn->isscope()) - error(loc, "cannot have array of scope %s", tbn->toChars()); - return merge(); + { error(loc, "cannot have array of scope %s", tbn->toChars()); + goto Lerror; + } + + /* Ensure things like const(immutable(T)[3]) become immutable(T[3]) + * and const(T)[3] become const(T[3]) + */ + t = addMod(next->mod); + + return t->merge(); + +Lerror: + return Type::terror; } void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) @@ -4096,6 +4108,7 @@ printf("index->ito->ito = x%x\n", index->ito->ito); switch (next->toBasetype()->ty) { case Tfunction: + case Tvoid: case Tnone: error(loc, "can't have associative array of %s", next->toChars()); return Type::terror; @@ -5882,7 +5895,19 @@ L1: } if (!s) { - error(loc, "identifier '%s' is not defined", toChars()); + const char *p = toChars(); + const char *n = importHint(p); + if (n) + error(loc, "'%s' is not defined, perhaps you need to import %s; ?", p, n); + else + { + Identifier *id = new Identifier(p, TOKidentifier); + s = sc->search_correct(id); + if (s) + error(loc, "undefined identifier %s, did you mean %s %s?", p, s->kind(), s->toChars()); + else + error(loc, "undefined identifier %s", p); + } } } @@ -6197,7 +6222,7 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) { Expression *e; Type *t; - //printf("TypeTypeof::semantic() %p\n", this); + //printf("TypeTypeof::semantic() %s\n", toChars()); //static int nest; if (++nest == 50) *(char*)0=0; @@ -6248,14 +6273,15 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) else #endif { - sc->intypeof++; - exp = exp->semantic(sc); + Scope *sc2 = sc->push(); + sc2->intypeof++; + exp = exp->semantic(sc2); #if DMDV2 if (exp->type && exp->type->ty == Tfunction && ((TypeFunction *)exp->type)->isproperty) - exp = resolveProperties(sc, exp); + exp = resolveProperties(sc2, exp); #endif - sc->intypeof--; + sc2->pop(); if (exp->op == TOKtype) { error(loc, "argument %s to typeof is not an expression", exp->toChars()); @@ -6304,7 +6330,7 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) return t; Lerr: - return tvoid; + return terror; } d_uns64 TypeTypeof::size(Loc loc) @@ -7290,6 +7316,30 @@ int TypeStruct::hasPointers() return FALSE; } +static MATCH aliasthisConvTo(AggregateDeclaration *ad, Type *from, Type *to) +{ + assert(ad->aliasthis); + Declaration *d = ad->aliasthis->isDeclaration(); + if (d) + { assert(d->type); + Type *t = d->type; + if (d->isVarDeclaration() && d->needThis()) + { + t = t->addMod(from->mod); + } + else if (d->isFuncDeclaration()) + { + FuncDeclaration *fd = (FuncDeclaration *)d; + Expression *ethis = from->defaultInit(0); + fd = fd->overloadResolve(0, ethis, NULL); + if (fd) + t = ((TypeFunction *)fd->type)->next; + } + return t->implicitConvTo(to); + } + return MATCHnomatch; +} + MATCH TypeStruct::implicitConvTo(Type *to) { MATCH m; @@ -7304,7 +7354,8 @@ MATCH TypeStruct::implicitConvTo(Type *to) to = ((TypeAArray*)to)->getImpl()->type; --global.gag; if (errs != global.errors) - { global.errors = errs; + { + global.errors = errs; return MATCHnomatch; } } @@ -7339,15 +7390,7 @@ MATCH TypeStruct::implicitConvTo(Type *to) } } else if (sym->aliasthis) - { - m = MATCHnomatch; - Declaration *d = sym->aliasthis->isDeclaration(); - if (d) - { assert(d->type); - Type *t = d->type->addMod(mod); - m = t->implicitConvTo(to); - } - } + m = aliasthisConvTo(sym, this, to); else m = MATCHnomatch; // no match return m; @@ -7812,14 +7855,7 @@ MATCH TypeClass::implicitConvTo(Type *to) m = MATCHnomatch; if (sym->aliasthis) - { - Declaration *d = sym->aliasthis->isDeclaration(); - if (d) - { assert(d->type); - Type *t = d->type->addMod(mod); - m = t->implicitConvTo(to); - } - } + m = aliasthisConvTo(sym, this, to); return m; } @@ -7906,6 +7942,30 @@ TypeTuple::TypeTuple(Expressions *exps) //printf("TypeTuple() %p, %s\n", this, toChars()); } +/******************************************* + * Type tuple with 0, 1 or 2 types in it. + */ +TypeTuple::TypeTuple() + : Type(Ttuple) +{ + arguments = new Parameters(); +} + +TypeTuple::TypeTuple(Type *t1) + : Type(Ttuple) +{ + arguments = new Parameters(); + arguments->push(new Parameter(0, t1, NULL, NULL)); +} + +TypeTuple::TypeTuple(Type *t1, Type *t2) + : Type(Ttuple) +{ + arguments = new Parameters(); + arguments->push(new Parameter(0, t1, NULL, NULL)); + arguments->push(new Parameter(0, t2, NULL, NULL)); +} + Type *TypeTuple::syntaxCopy() { Parameters *args = Parameter::arraySyntaxCopy(arguments); diff --git a/dmd2/mtype.h b/dmd2/mtype.h index d1d337fd..4de1769b 100644 --- a/dmd2/mtype.h +++ b/dmd2/mtype.h @@ -54,10 +54,10 @@ typedef TYPE type; #endif #if IN_DMD -typedef struct TYPE type; struct Symbol; #endif +struct TypeTuple; enum ENUMTY { @@ -185,7 +185,7 @@ struct Type : Object #define tshiftcnt tint32 // right side of shift expression // #define tboolean tint32 // result of boolean expression #define tboolean tbool // result of boolean expression - #define tindex tint32 // array/ptr index + #define tindex tsize_t // array/ptr index static Type *tvoidptr; // void* static Type *tstring; // immutable(char)[] #define terror basic[Terror] // for error recovery @@ -331,7 +331,7 @@ struct Type : Object virtual unsigned wildMatch(Type *targ); virtual Expression *toExpression(); virtual int hasPointers(); - //Type *next; + virtual TypeTuple *toArgTypes(); virtual Type *nextOf(); uinteger_t sizemask(); @@ -419,6 +419,7 @@ struct TypeBasic : Type Expression *defaultInit(Loc loc); int isZeroInit(Loc loc); int builtinTypeInfo(); + TypeTuple *toArgTypes(); // For eliminating dynamic_cast TypeBasic *isTypeBasic(); @@ -459,6 +460,7 @@ struct TypeSArray : TypeArray TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *toExpression(); int hasPointers(); + TypeTuple *toArgTypes(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -489,6 +491,7 @@ struct TypeDArray : TypeArray MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -521,6 +524,7 @@ struct TypeAArray : TypeArray int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); MATCH implicitConvTo(Type *to); MATCH constConv(Type *to); #if CPP_MANGLE @@ -550,7 +554,7 @@ struct TypePointer : TypeNext int isZeroInit(Loc loc); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); - + TypeTuple *toArgTypes(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -665,6 +669,7 @@ struct TypeDelegate : TypeNext TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); int hasPointers(); + TypeTuple *toArgTypes(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -769,6 +774,7 @@ struct TypeStruct : Type MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); MATCH implicitConvTo(Type *to); MATCH constConv(Type *to); Type *toHeadMutable(); @@ -818,6 +824,7 @@ struct TypeEnum : Type MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -864,6 +871,7 @@ struct TypeTypedef : Type MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); int hasWild(); Type *toHeadMutable(); #if CPP_MANGLE @@ -899,6 +907,7 @@ struct TypeClass : Type int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); int hasPointers(); + TypeTuple *toArgTypes(); int builtinTypeInfo(); #if DMDV2 Type *toHeadMutable(); @@ -921,6 +930,9 @@ struct TypeTuple : Type TypeTuple(Parameters *arguments); TypeTuple(Expressions *exps); + TypeTuple(); + TypeTuple(Type *t1); + TypeTuple(Type *t1, Type *t2); Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); int equals(Object *o); @@ -982,6 +994,7 @@ extern int Tsize_t; extern int Tptrdiff_t; int arrayTypeCompatible(Loc loc, Type *t1, Type *t2); +int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2); void MODtoBuffer(OutBuffer *buf, unsigned char mod); int MODimplicitConv(unsigned char modfrom, unsigned char modto); int MODmerge(unsigned char mod1, unsigned char mod2); diff --git a/dmd2/parse.c b/dmd2/parse.c index 712dc95f..da1375c7 100644 --- a/dmd2/parse.c +++ b/dmd2/parse.c @@ -3785,7 +3785,10 @@ Statement *Parser::parseStatement(int flags) } else elsebody = NULL; - s = new IfStatement(loc, arg, condition, ifbody, elsebody); + if (condition && ifbody) + s = new IfStatement(loc, arg, condition, ifbody, elsebody); + else + s = NULL; // don't propagate parsing errors break; } @@ -5175,6 +5178,7 @@ Expression *Parser::parsePrimaryExp() token.value == TOKsuper || token.value == TOKenum || token.value == TOKinterface || + token.value == TOKargTypes || #if DMDV2 token.value == TOKconst && peek(&token)->value == TOKrparen || token.value == TOKinvariant && peek(&token)->value == TOKrparen || diff --git a/dmd2/root/aav.c b/dmd2/root/aav.c index a4873bc7..ca685d42 100644 --- a/dmd2/root/aav.c +++ b/dmd2/root/aav.c @@ -161,7 +161,7 @@ void _aaRehash(AA** paa) } } if (aa->b != aa->binit) - delete aa->b; + delete[] aa->b; newb.nodes = aa->nodes; } diff --git a/dmd2/root/array.c b/dmd2/root/array.c index affdcff5..e1828598 100644 --- a/dmd2/root/array.c +++ b/dmd2/root/array.c @@ -177,7 +177,8 @@ void Array::append(Array *a) void Array::remove(unsigned i) { - memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0])); + if (dim - i - 1) + memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0])); dim--; } diff --git a/dmd2/statement.c b/dmd2/statement.c index f7db947b..f29202e2 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -149,8 +149,9 @@ int Statement::usesEH() } /* Only valid after semantic analysis + * If 'mustNotThrow' is true, generate an error if it throws */ -int Statement::blockExit() +int Statement::blockExit(bool mustNotThrow) { printf("Statement::blockExit(%p)\n", this); printf("%s\n", toChars()); @@ -278,7 +279,7 @@ Statement *ExpStatement::semantic(Scope *sc) return this; } -int ExpStatement::blockExit() +int ExpStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; if (exp) @@ -291,7 +292,7 @@ int ExpStatement::blockExit() if (a->e1->isBool(FALSE)) // if it's an assert(0) return BEhalt; } - if (exp->canThrow()) + if (exp->canThrow(mustNotThrow)) result |= BEthrow; } return result; @@ -347,7 +348,8 @@ Statements *CompileStatement::flatten(Scope *sc) while (p.token.value != TOKeof) { Statement *s = p.parseStatement(PSsemi | PScurlyscope); - a->push(s); + if (s) // if no parsing errors + a->push(s); } return a; } @@ -640,7 +642,7 @@ int CompoundStatement::usesEH() return FALSE; } -int CompoundStatement::blockExit() +int CompoundStatement::blockExit(bool mustNotThrow) { //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); int result = BEfallthru; @@ -652,13 +654,13 @@ int CompoundStatement::blockExit() //printf("%s\n", s->toChars()); if (!(result & BEfallthru) && !s->comeFrom()) { - if (s->blockExit() != BEhalt && !s->isEmpty()) + if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty()) s->warning("statement is not reachable"); } else { result &= ~BEfallthru; - result |= s->blockExit(); + result |= s->blockExit(mustNotThrow); } } } @@ -852,14 +854,14 @@ int UnrolledLoopStatement::usesEH() return FALSE; } -int UnrolledLoopStatement::blockExit() +int UnrolledLoopStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; for (size_t i = 0; i < statements->dim; i++) { Statement *s = (Statement *) statements->data[i]; if (s) { - int r = s->blockExit(); + int r = s->blockExit(mustNotThrow); result |= r & ~(BEbreak | BEcontinue); } } @@ -955,10 +957,10 @@ int ScopeStatement::usesEH() return statement ? statement->usesEH() : FALSE; } -int ScopeStatement::blockExit() +int ScopeStatement::blockExit(bool mustNotThrow) { //printf("ScopeStatement::blockExit(%p)\n", statement); - return statement ? statement->blockExit() : BEfallthru; + return statement ? statement->blockExit(mustNotThrow) : BEfallthru; } @@ -1028,18 +1030,18 @@ int WhileStatement::usesEH() return body ? body->usesEH() : 0; } -int WhileStatement::blockExit() +int WhileStatement::blockExit(bool mustNotThrow) { assert(0); //printf("WhileStatement::blockExit(%p)\n", this); int result = BEnone; - if (condition->canThrow()) + if (condition->canThrow(mustNotThrow)) result |= BEthrow; if (condition->isBool(TRUE)) { if (body) - { result |= body->blockExit(); + { result |= body->blockExit(mustNotThrow); if (result & BEbreak) result |= BEfallthru; } @@ -1051,7 +1053,7 @@ int WhileStatement::blockExit() else { if (body) - result |= body->blockExit(); + result |= body->blockExit(mustNotThrow); result |= BEfallthru; } result &= ~(BEbreak | BEcontinue); @@ -1123,11 +1125,11 @@ int DoStatement::usesEH() return body ? body->usesEH() : 0; } -int DoStatement::blockExit() +int DoStatement::blockExit(bool mustNotThrow) { int result; if (body) - { result = body->blockExit(); + { result = body->blockExit(mustNotThrow); if (result == BEbreak) return BEfallthru; if (result & BEcontinue) @@ -1137,7 +1139,7 @@ int DoStatement::blockExit() result = BEfallthru; if (result & BEfallthru) { - if (condition->canThrow()) + if (condition->canThrow(mustNotThrow)) result |= BEthrow; if (!(result & BEbreak) && condition->isBool(TRUE)) result &= ~BEfallthru; @@ -1248,16 +1250,16 @@ int ForStatement::usesEH() return (init && init->usesEH()) || body->usesEH(); } -int ForStatement::blockExit() +int ForStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; if (init) - { result = init->blockExit(); + { result = init->blockExit(mustNotThrow); if (!(result & BEfallthru)) return result; } if (condition) - { if (condition->canThrow()) + { if (condition->canThrow(mustNotThrow)) result |= BEthrow; if (condition->isBool(TRUE)) result &= ~BEfallthru; @@ -1267,12 +1269,12 @@ int ForStatement::blockExit() else result &= ~BEfallthru; // the body must do the exiting if (body) - { int r = body->blockExit(); + { int r = body->blockExit(mustNotThrow); if (r & (BEbreak | BEgoto)) result |= BEfallthru; result |= r & ~(BEfallthru | BEbreak | BEcontinue); } - if (increment && increment->canThrow()) + if (increment && increment->canThrow(mustNotThrow)) result |= BEthrow; return result; } @@ -2086,15 +2088,15 @@ int ForeachStatement::usesEH() return body->usesEH(); } -int ForeachStatement::blockExit() +int ForeachStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; - if (aggr->canThrow()) + if (aggr->canThrow(mustNotThrow)) result |= BEthrow; if (body) { - result |= body->blockExit() & ~(BEbreak | BEcontinue); + result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); } return result; } @@ -2316,19 +2318,19 @@ int ForeachRangeStatement::usesEH() return body->usesEH(); } -int ForeachRangeStatement::blockExit() +int ForeachRangeStatement::blockExit(bool mustNotThrow) { assert(0); int result = BEfallthru; - if (lwr && lwr->canThrow()) + if (lwr && lwr->canThrow(mustNotThrow)) result |= BEthrow; - else if (upr && upr->canThrow()) + else if (upr && upr->canThrow(mustNotThrow)) result |= BEthrow; if (body) { - result |= body->blockExit() & ~(BEbreak | BEcontinue); + result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); } return result; } @@ -2454,35 +2456,35 @@ int IfStatement::usesEH() return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); } -int IfStatement::blockExit() +int IfStatement::blockExit(bool mustNotThrow) { //printf("IfStatement::blockExit(%p)\n", this); int result = BEnone; - if (condition->canThrow()) + if (condition->canThrow(mustNotThrow)) result |= BEthrow; if (condition->isBool(TRUE)) { if (ifbody) - result |= ifbody->blockExit(); + result |= ifbody->blockExit(mustNotThrow); else result |= BEfallthru; } else if (condition->isBool(FALSE)) { if (elsebody) - result |= elsebody->blockExit(); + result |= elsebody->blockExit(mustNotThrow); else result |= BEfallthru; } else { if (ifbody) - result |= ifbody->blockExit(); + result |= ifbody->blockExit(mustNotThrow); else result |= BEfallthru; if (elsebody) - result |= elsebody->blockExit(); + result |= elsebody->blockExit(mustNotThrow); else result |= BEfallthru; } @@ -2574,11 +2576,11 @@ int ConditionalStatement::usesEH() return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); } -int ConditionalStatement::blockExit() +int ConditionalStatement::blockExit(bool mustNotThrow) { - int result = ifbody->blockExit(); + int result = ifbody->blockExit(mustNotThrow); if (elsebody) - result |= elsebody->blockExit(); + result |= elsebody->blockExit(mustNotThrow); return result; } @@ -2724,14 +2726,14 @@ int PragmaStatement::usesEH() return body && body->usesEH(); } -int PragmaStatement::blockExit() +int PragmaStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; #if 0 // currently, no code is generated for Pragma's, so it's just fallthru if (arrayExpressionCanThrow(args)) result |= BEthrow; if (body) - result |= body->blockExit(); + result |= body->blockExit(mustNotThrow); #endif return result; } @@ -2786,7 +2788,7 @@ Statement *StaticAssertStatement::semantic(Scope *sc) return NULL; } -int StaticAssertStatement::blockExit() +int StaticAssertStatement::blockExit(bool mustNotThrow) { return BEfallthru; } @@ -2964,13 +2966,13 @@ int SwitchStatement::usesEH() return body ? body->usesEH() : 0; } -int SwitchStatement::blockExit() +int SwitchStatement::blockExit(bool mustNotThrow) { int result = BEnone; - if (condition->canThrow()) + if (condition->canThrow(mustNotThrow)) result |= BEthrow; if (body) - { result |= body->blockExit(); + { result |= body->blockExit(mustNotThrow); if (result & BEbreak) { result |= BEfallthru; result &= ~BEbreak; @@ -3115,9 +3117,9 @@ int CaseStatement::usesEH() return statement->usesEH(); } -int CaseStatement::blockExit() +int CaseStatement::blockExit(bool mustNotThrow) { - return statement->blockExit(); + return statement->blockExit(mustNotThrow); } @@ -3278,9 +3280,9 @@ int DefaultStatement::usesEH() return statement->usesEH(); } -int DefaultStatement::blockExit() +int DefaultStatement::blockExit(bool mustNotThrow) { - return statement->blockExit(); + return statement->blockExit(mustNotThrow); } @@ -3317,7 +3319,7 @@ Statement *GotoDefaultStatement::semantic(Scope *sc) return this; } -int GotoDefaultStatement::blockExit() +int GotoDefaultStatement::blockExit(bool mustNotThrow) { return BEgoto; } @@ -3365,7 +3367,7 @@ Statement *GotoCaseStatement::semantic(Scope *sc) return this; } -int GotoCaseStatement::blockExit() +int GotoCaseStatement::blockExit(bool mustNotThrow) { return BEgoto; } @@ -3389,9 +3391,10 @@ SwitchErrorStatement::SwitchErrorStatement(Loc loc) { } -int SwitchErrorStatement::blockExit() +int SwitchErrorStatement::blockExit(bool mustNotThrow) { - return BEthrow; + // Switch errors are non-recoverable + return BEhalt; } @@ -3713,10 +3716,10 @@ Statement *ReturnStatement::semantic(Scope *sc) return this; } -int ReturnStatement::blockExit() +int ReturnStatement::blockExit(bool mustNotThrow) { int result = BEreturn; - if (exp && exp->canThrow()) + if (exp && exp->canThrow(mustNotThrow)) result |= BEthrow; return result; } @@ -3808,7 +3811,7 @@ Statement *BreakStatement::semantic(Scope *sc) return this; } -int BreakStatement::blockExit() +int BreakStatement::blockExit(bool mustNotThrow) { //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); return ident ? BEgoto : BEbreak; @@ -3911,7 +3914,7 @@ Statement *ContinueStatement::semantic(Scope *sc) return this; } -int ContinueStatement::blockExit() +int ContinueStatement::blockExit(bool mustNotThrow) { return ident ? BEgoto : BEcontinue; } @@ -4089,9 +4092,9 @@ int SynchronizedStatement::usesEH() return TRUE; } -int SynchronizedStatement::blockExit() +int SynchronizedStatement::blockExit(bool mustNotThrow) { - return body ? body->blockExit() : BEfallthru; + return body ? body->blockExit(mustNotThrow) : BEfallthru; } @@ -4202,13 +4205,13 @@ int WithStatement::usesEH() return body ? body->usesEH() : 0; } -int WithStatement::blockExit() +int WithStatement::blockExit(bool mustNotThrow) { int result = BEnone; - if (exp->canThrow()) + if (exp->canThrow(mustNotThrow)) result = BEthrow; if (body) - result |= body->blockExit(); + result |= body->blockExit(mustNotThrow); else result |= BEfallthru; return result; @@ -4277,10 +4280,10 @@ int TryCatchStatement::usesEH() return TRUE; } -int TryCatchStatement::blockExit() +int TryCatchStatement::blockExit(bool mustNotThrow) { assert(body); - int result = body->blockExit(); + int result = body->blockExit(false); int catchresult = 0; for (size_t i = 0; i < catches->dim; i++) @@ -4289,7 +4292,7 @@ int TryCatchStatement::blockExit() if (c->type == Type::terror) continue; - catchresult |= c->blockExit(); + catchresult |= c->blockExit(mustNotThrow); /* If we're catching Object, then there is no throwing */ @@ -4300,6 +4303,10 @@ int TryCatchStatement::blockExit() result &= ~BEthrow; } } + if (mustNotThrow && (result & BEthrow)) + { + body->blockExit(mustNotThrow); // now explain why this is nothrow + } return result | catchresult; } @@ -4381,9 +4388,9 @@ void Catch::semantic(Scope *sc) sc->pop(); } -int Catch::blockExit() +int Catch::blockExit(bool mustNotThrow) { - return handler ? handler->blockExit() : BEfallthru; + return handler ? handler->blockExit(mustNotThrow) : BEfallthru; } void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -4438,7 +4445,7 @@ Statement *TryFinallyStatement::semantic(Scope *sc) return finalbody; if (!finalbody) return body; - if (body->blockExit() == BEfallthru) + if (body->blockExit(false) == BEfallthru) { Statement *s = new CompoundStatement(loc, body, finalbody); return s; } @@ -4470,10 +4477,10 @@ int TryFinallyStatement::usesEH() return TRUE; } -int TryFinallyStatement::blockExit() +int TryFinallyStatement::blockExit(bool mustNotThrow) { if (body) - return body->blockExit(); + return body->blockExit(mustNotThrow); return BEfallthru; } @@ -4500,7 +4507,7 @@ Statement *OnScopeStatement::semantic(Scope *sc) return this; } -int OnScopeStatement::blockExit() +int OnScopeStatement::blockExit(bool mustNotThrow) { // At this point, this statement is just an empty placeholder return BEfallthru; } @@ -4596,8 +4603,10 @@ Statement *ThrowStatement::semantic(Scope *sc) return this; } -int ThrowStatement::blockExit() +int ThrowStatement::blockExit(bool mustNotThrow) { + if (mustNotThrow) + error("%s is thrown but not caught", exp->type->toChars()); return BEthrow; // obviously } @@ -4654,9 +4663,9 @@ Statements *VolatileStatement::flatten(Scope *sc) return a; } -int VolatileStatement::blockExit() +int VolatileStatement::blockExit(bool mustNotThrow) { - return statement ? statement->blockExit() : BEfallthru; + return statement ? statement->blockExit(mustNotThrow) : BEfallthru; } @@ -4719,7 +4728,7 @@ Statement *GotoStatement::semantic(Scope *sc) return this; } -int GotoStatement::blockExit() +int GotoStatement::blockExit(bool mustNotThrow) { //printf("GotoStatement::blockExit(%p)\n", this); return BEgoto; @@ -4811,10 +4820,10 @@ int LabelStatement::usesEH() return statement ? statement->usesEH() : FALSE; } -int LabelStatement::blockExit() +int LabelStatement::blockExit(bool mustNotThrow) { //printf("LabelStatement::blockExit(%p)\n", this); - return statement ? statement->blockExit() : BEfallthru; + return statement ? statement->blockExit(mustNotThrow) : BEfallthru; } @@ -4849,3 +4858,68 @@ LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? { return this; } + +#if !IN_LLVM + +/************************ AsmStatement ***************************************/ + +AsmStatement::AsmStatement(Loc loc, Token *tokens) + : Statement(loc) +{ + this->tokens = tokens; + asmcode = NULL; + asmalign = 0; + refparam = FALSE; + naked = FALSE; + regs = 0; +} + +Statement *AsmStatement::syntaxCopy() +{ + return new AsmStatement(loc, tokens); +} + + + +int AsmStatement::comeFrom() +{ + return TRUE; +} + +int AsmStatement::blockExit(bool mustNotThrow) +{ + if (mustNotThrow) + error("asm statements are assumed to throw", toChars()); + // Assume the worst + return BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt; +} + +void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("asm { "); + Token *t = tokens; + while (t) + { + buf->writestring(t->toChars()); + if (t->next && + t->value != TOKmin && + t->value != TOKcomma && + t->next->value != TOKcomma && + t->value != TOKlbracket && + t->next->value != TOKlbracket && + t->next->value != TOKrbracket && + t->value != TOKlparen && + t->next->value != TOKlparen && + t->next->value != TOKrparen && + t->value != TOKdot && + t->next->value != TOKdot) + { + buf->writebyte(' '); + } + t = t->next; + } + buf->writestring("; }"); + buf->writenl(); +} + +#endif diff --git a/dmd2/statement.h b/dmd2/statement.h index 9ea2c6ee..c8b7be52 100644 --- a/dmd2/statement.h +++ b/dmd2/statement.h @@ -130,7 +130,7 @@ struct Statement : Object virtual int hasBreak(); virtual int hasContinue(); virtual int usesEH(); - virtual int blockExit(); + virtual int blockExit(bool mustNotThrow); virtual int comeFrom(); virtual int isEmpty(); virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); @@ -174,7 +174,7 @@ struct ExpStatement : Statement void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(); + int blockExit(bool mustNotThrow); int isEmpty(); int inlineCost(InlineCostState *ics); @@ -224,7 +224,7 @@ struct CompoundStatement : Statement void toCBuffer(OutBuffer *buf, HdrGenState *hgs); virtual Statement *semantic(Scope *sc); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); int isEmpty(); virtual Statements *flatten(Scope *sc); @@ -265,7 +265,7 @@ struct UnrolledLoopStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -289,7 +289,7 @@ struct ScopeStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); int isEmpty(); Expression *interpret(InterState *istate); @@ -310,7 +310,7 @@ struct WhileStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -331,7 +331,7 @@ struct DoStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -355,7 +355,7 @@ struct ForStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -387,7 +387,7 @@ struct ForeachStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -415,7 +415,7 @@ struct ForeachRangeStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -441,7 +441,7 @@ struct IfStatement : Statement Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); IfStatement *isIfStatement() { return this; } int inlineCost(InlineCostState *ics); @@ -462,7 +462,7 @@ struct ConditionalStatement : Statement Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -477,7 +477,7 @@ struct PragmaStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -491,7 +491,7 @@ struct StaticAssertStatement : Statement StaticAssertStatement(StaticAssert *sa); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -518,7 +518,7 @@ struct SwitchStatement : Statement Statement *semantic(Scope *sc); int hasBreak(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -544,7 +544,7 @@ struct CaseStatement : Statement Statement *semantic(Scope *sc); int compare(Object *obj); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -592,7 +592,7 @@ struct DefaultStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -614,7 +614,7 @@ struct GotoDefaultStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -630,7 +630,7 @@ struct GotoCaseStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -639,7 +639,7 @@ struct GotoCaseStatement : Statement struct SwitchErrorStatement : Statement { SwitchErrorStatement(Loc loc); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -653,7 +653,7 @@ struct ReturnStatement : Statement Statement *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); - int blockExit(); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); int inlineCost(InlineCostState *ics); @@ -673,7 +673,7 @@ struct BreakStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -692,7 +692,7 @@ struct ContinueStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -714,7 +714,7 @@ struct SynchronizedStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -739,7 +739,7 @@ struct WithStatement : Statement Statement *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -757,7 +757,7 @@ struct TryCatchStatement : Statement Statement *semantic(Scope *sc); int hasBreak(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -778,7 +778,7 @@ struct Catch : Object Catch(Loc loc, Type *t, Identifier *id, Statement *handler); Catch *syntaxCopy(); void semantic(Scope *sc); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -794,7 +794,7 @@ struct TryFinallyStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -809,7 +809,7 @@ struct OnScopeStatement : Statement OnScopeStatement(Loc loc, TOK tok, Statement *statement); Statement *syntaxCopy(); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); int usesEH(); @@ -827,7 +827,7 @@ struct ThrowStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int blockExit(); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -843,7 +843,7 @@ struct VolatileStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); - int blockExit(); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -861,7 +861,7 @@ struct GotoStatement : Statement GotoStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - int blockExit(); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); void toIR(IRState *irs); @@ -884,7 +884,7 @@ struct LabelStatement : Statement Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); int usesEH(); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -923,7 +923,7 @@ struct AsmStatement : Statement AsmStatement(Loc loc, Token *tokens); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - int blockExit(); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); diff --git a/dmd2/struct.c b/dmd2/struct.c index 8d6b765b..c525a84c 100644 --- a/dmd2/struct.c +++ b/dmd2/struct.c @@ -338,11 +338,11 @@ void StructDeclaration::semantic(Scope *sc) error("structs, unions cannot be abstract"); #if DMDV2 if (storage_class & STCimmutable) - type = type->invariantOf(); - else if (storage_class & STCconst) - type = type->constOf(); - else if (storage_class & STCshared) - type = type->sharedOf(); + type = type->addMod(MODimmutable); + if (storage_class & STCconst) + type = type->addMod(MODconst); + if (storage_class & STCshared) + type = type->addMod(MODshared); #endif if (sizeok == 0) // if not already done the addMember step @@ -393,7 +393,7 @@ void StructDeclaration::semantic(Scope *sc) sizeok = 0; sc2 = sc->push(this); - sc2->stc &= storage_class & STC_TYPECTOR; + sc2->stc &= STCsafe | STCtrusted | STCsystem; sc2->parent = this; if (isUnionDeclaration()) sc2->inunion = 1; diff --git a/dmd2/template.c b/dmd2/template.c index c1f999e4..f3faa909 100644 --- a/dmd2/template.c +++ b/dmd2/template.c @@ -212,9 +212,19 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) } else if (s1) { - //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars()); if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) { + if (s2) + { + VarDeclaration *v1 = s1->isVarDeclaration(); + VarDeclaration *v2 = s2->isVarDeclaration(); + if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest) + { ExpInitializer *ei1 = v1->init->isExpInitializer(); + ExpInitializer *ei2 = v2->init->isExpInitializer(); + if (ei1 && ei2 && ei1->exp->equals(ei2->exp)) + goto Lmatch; + } + } goto Lnomatch; } #if DMDV2 @@ -242,6 +252,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) goto Lnomatch; } } +Lmatch: //printf("match\n"); return 1; // match Lnomatch: @@ -716,8 +727,10 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, */ makeParamNamesVisibleInConstraint(paramscope); Expression *e = constraint->syntaxCopy(); - paramscope->flags |= SCOPEstaticif; - e = e->semantic(paramscope); + Scope *sc = paramscope->push(); + sc->flags |= SCOPEstaticif; + e = e->semantic(sc); + sc->pop(); e = e->optimize(WANTvalue | WANTinterpret); if (e->isBool(TRUE)) ; @@ -1304,17 +1317,31 @@ Lmatch: paramscope->flags |= SCOPEstaticif; /* Detect recursive attempts to instantiate this template declaration, + * Bugzilla 4072 * void foo(T)(T x) if (is(typeof(foo(x)))) { } - * static assert(!is(typeof(bug4072(7)))); + * static assert(!is(typeof(foo(7)))); * Recursive attempts are regarded as a constraint failure. */ + int nmatches = 0; for (Previous *p = previous; p; p = p->prev) { if (arrayObjectMatch(p->dedargs, dedargs, this, sc)) - goto Lnomatch; + { + //printf("recursive, no match %p %s\n", this, this->toChars()); + nmatches++; + } /* BUG: should also check for ref param differences */ } + /* Look for 2 matches at least, because sometimes semantic3() gets run causing what appears to + * be recursion but isn't. + * Template A's constraint instantiates B, B's semantic3() run includes something that has A in its constraint. + * Perhaps a better solution is to always defer semantic3() rather than doing it eagerly. The risk + * with that is what if semantic3() fails, but our constraint "succeeded"? + */ + if (nmatches >= 2) + goto Lnomatch; + Previous pr; pr.prev = previous; pr.dedargs = dedargs; @@ -3523,7 +3550,11 @@ MATCH TemplateTupleParameter::matchArg(Scope *sc, */ assert(i + 1 == dedtypes->dim); // must be the last one Tuple *ovar; - if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i])) + + if (dedtypes->data[i] && isTuple((Object *)dedtypes->data[i])) + // It was already been deduced + ovar = isTuple((Object *)dedtypes->data[i]); + else if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i])) ovar = isTuple((Object *)tiargs->data[i]); else { @@ -3865,7 +3896,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) /* So, we need to implement 'this' instance. */ #if LOG - printf("\timplement template instance '%s'\n", toChars()); + printf("\timplement template instance %s '%s'\n", tempdecl->parent->toChars(), toChars()); + printf("\ttempdecl %s\n", tempdecl->toChars()); #endif unsigned errorsave = global.errors; inst = this; @@ -3874,7 +3906,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) parent = tempdecl->parent; //printf("parent = '%s'\n", parent->kind()); - ident = genIdent(); // need an identifier for name mangling purposes. + ident = genIdent(tiargs); // need an identifier for name mangling purposes. #if 1 if (isnested) @@ -3917,7 +3949,9 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); a = m->members; if (m->semanticRun >= 3) + { dosemantic3 = 1; + } } for (int i = 0; 1; i++) { @@ -4122,13 +4156,14 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) // Give additional context info if error occurred during instantiation if (global.errors != errorsave) { - error("error instantiating"); + error(loc, "error instantiating"); if (tinst) { tinst->printInstantiationTrace(); } errors = 1; if (global.gag) { // Try to reset things so we can try again later to instantiate it + //printf("remove %s\n", toChars()); tempdecl->instances.remove(tempdecl_instance_idx); if (!(sc->flags & SCOPEstaticif)) { // Bugzilla 4302 for discussion @@ -4345,11 +4380,7 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) if (s->parent && (ti = s->parent->isTemplateInstance()) != NULL) { - if ( - (ti->name == id || - ti->toAlias()->ident == id) - && - ti->tempdecl) + if (ti->tempdecl && ti->tempdecl->ident == id) { /* This is so that one can refer to the enclosing * template, even if it has the same name as a member @@ -4637,13 +4668,12 @@ int TemplateInstance::hasNestedArgs(Objects *args) * the type signature for it. */ -Identifier *TemplateInstance::genIdent() +Identifier *TemplateInstance::genIdent(Objects *args) { OutBuffer buf; //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); char *id = tempdecl->ident->toChars(); buf.printf("__T%zu%s", strlen(id), id); - Objects *args = tiargs; for (int i = 0; i < args->dim; i++) { Object *o = (Object *)args->data[i]; Type *ta = isType(o); @@ -4723,6 +4753,14 @@ Identifier *TemplateInstance::genIdent() } #endif const char *p = sa->mangle(); + + /* Bugzilla 3043: if the first character of p is a digit this + * causes ambiguity issues because the digits of the two numbers are adjacent. + * Current demanglers resolve this by trying various places to separate the + * numbers until one gets a successful demangle. + * Unfortunately, fixing this ambiguity will break existing binary + * compatibility and the demanglers, so we'll leave it as is. + */ buf.printf("%zu%s", strlen(p), p); } else if (va) @@ -4736,9 +4774,9 @@ Identifier *TemplateInstance::genIdent() } buf.writeByte('Z'); id = buf.toChars(); - buf.data = NULL; + //buf.data = NULL; // we can free the string after call to idPool() //printf("\tgenIdent = %s\n", id); - return new Identifier(id, TOKidentifier); + return Lexer::idPool(id); } @@ -5269,7 +5307,7 @@ void TemplateMixin::semantic(Scope *sc) } if (!ident) - ident = genIdent(); + ident = genIdent(tiargs); inst = this; parent = sc->parent; diff --git a/dmd2/template.h b/dmd2/template.h index 1178d69f..85068820 100644 --- a/dmd2/template.h +++ b/dmd2/template.h @@ -336,7 +336,7 @@ struct TemplateInstance : ScopeDsymbol TemplateDeclaration *findBestMatch(Scope *sc); void declareParameters(Scope *sc); int hasNestedArgs(Objects *tiargs); - Identifier *genIdent(); + Identifier *genIdent(Objects *args); TemplateInstance *isTemplateInstance() { return this; } AliasDeclaration *isAliasDeclaration(); diff --git a/druntime.patch b/druntime.patch index 0db6c427..1b917ed7 100644 --- a/druntime.patch +++ b/druntime.patch @@ -1,6 +1,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/core/atomic.di druntime/import/core/atomic.di ---- druntime-orig/import/core/atomic.di 2010-10-29 04:54:24.000000000 +0400 -+++ druntime/import/core/atomic.di 2010-12-31 12:58:56.716952002 +0300 +--- druntime-orig/import/core/atomic.di 2010-12-20 10:27:04.000000000 +0300 ++++ druntime/import/core/atomic.di 2011-01-05 14:41:38.000000000 +0300 @@ -1,567 +1,664 @@ -// D import file generated from 'src\core\atomic.d' -module core.atomic; @@ -54,7 +54,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. -} - -} --version (ddoc) +-version (D_Ddoc) -{ - template atomicOp(string op,T,V1) -{ @@ -621,7 +621,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} + +} -+version (ddoc) ++version (D_Ddoc) +{ + template atomicOp(string op,T,V1) +{ @@ -1233,316 +1233,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} +} + } -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/core/stdc/math.d druntime/import/core/stdc/math.d ---- druntime-orig/import/core/stdc/math.d 2009-11-30 10:04:54.000000000 +0300 -+++ druntime/import/core/stdc/math.d 2010-11-04 17:49:07.000000000 +0300 -@@ -17,6 +17,7 @@ - - extern (C): - nothrow: -+pure: // LDC - - alias float float_t; - alias double double_t; -@@ -367,7 +368,7 @@ - } - } - } --else version( freebsd ) -+else version( FreeBSD ) - { - enum - { -@@ -468,37 +469,123 @@ - int isunordered(real x, real y) { return (x !<>= y); } - } - --// NOTE: freebsd < 8-CURRENT doesn't appear to support *l, but we can --// approximate. --version( freebsd ) -+/* NOTE: freebsd < 8-CURRENT doesn't appear to support *l, but we can -+ * approximate. -+ * A lot of them were added in 8.0-RELEASE, and so a lot of these workarounds -+ * should then be removed. -+ */ -+// NOTE: FreeBSD 8.0-RELEASE doesn't support log2* nor these *l functions: -+// acoshl, asinhl, atanhl, coshl, sinhl, tanhl, cbrtl, powl, expl, -+// expm1l, logl, log1pl, log10l, erfcl, erfl, lgammal, tgammal; -+// but we can approximate. -+version( FreeBSD ) - { -+ version (all) // < 8-CURRENT -+ { -+ real acosl(real x) { return acos(x); } -+ real asinl(real x) { return asin(x); } -+ real atanl(real x) { return atan(x); } -+ real atan2l(real y, real x) { return atan2(y, x); } -+ real cosl(real x) { return cos(x); } -+ real sinl(real x) { return sin(x); } -+ real tanl(real x) { return tan(x); } -+ real exp2l(real x) { return exp2(x); } -+ real frexpl(real value, int* exp) { return frexp(value, exp); } -+ int ilogbl(real x) { return ilogb(x); } -+ real ldexpl(real x, int exp) { return ldexp(x, exp); } -+ real logbl(real x) { return logb(x); } -+ //real modfl(real value, real *iptr); // nontrivial conversion -+ real scalbnl(real x, int n) { return scalbn(x, n); } -+ real scalblnl(real x, c_long n) { return scalbln(x, n); } -+ real fabsl(real x) { return fabs(x); } -+ real hypotl(real x, real y) { return hypot(x, y); } -+ real sqrtl(real x) { return sqrt(x); } -+ real ceill(real x) { return ceil(x); } -+ real floorl(real x) { return floor(x); } -+ real nearbyintl(real x) { return nearbyint(x); } -+ real rintl(real x) { return rint(x); } -+ c_long lrintl(real x) { return lrint(x); } -+ real roundl(real x) { return round(x); } -+ c_long lroundl(real x) { return lround(x); } -+ long llroundl(real x) { return llround(x); } -+ real truncl(real x) { return trunc(x); } -+ real fmodl(real x, real y) { return fmod(x, y); } -+ real remainderl(real x, real y) { return remainder(x, y); } -+ real remquol(real x, real y, int* quo) { return remquo(x, y, quo); } -+ real copysignl(real x, real y) { return copysign(x, y); } -+// double nan(char* tagp); -+// float nanf(char* tagp); -+// real nanl(char* tagp); -+ real nextafterl(real x, real y) { return nextafter(x, y); } -+ real nexttowardl(real x, real y) { return nexttoward(x, y); } -+ real fdiml(real x, real y) { return fdim(x, y); } -+ real fmaxl(real x, real y) { return fmax(x, y); } -+ real fminl(real x, real y) { return fmin(x, y); } -+ real fmal(real x, real y, real z) { return fma(x, y, z); } -+ } -+ else -+ { -+ real acosl(real x); -+ real asinl(real x); -+ real atanl(real x); -+ real atan2l(real y, real x); -+ real cosl(real x); -+ real sinl(real x); -+ real tanl(real x); -+ real exp2l(real x); -+ real frexpl(real value, int* exp); -+ int ilogbl(real x); -+ real ldexpl(real x, int exp); -+ real logbl(real x); -+ real modfl(real value, real *iptr); -+ real scalbnl(real x, int n); -+ real scalblnl(real x, c_long n); -+ real fabsl(real x); -+ real hypotl(real x, real y); -+ real sqrtl(real x); -+ real ceill(real x); -+ real floorl(real x); -+ real nearbyintl(real x); -+ real rintl(real x); -+ c_long lrintl(real x); -+ real roundl(real x); -+ c_long lroundl(real x); -+ long llroundl(real x); -+ real truncl(real x); -+ real fmodl(real x, real y); -+ real remainderl(real x, real y); -+ real remquol(real x, real y, int* quo); -+ real copysignl(real x, real y); -+ double nan(char* tagp); -+ float nanf(char* tagp); -+ real nanl(char* tagp); -+ real nextafterl(real x, real y); -+ real nexttowardl(real x, real y); -+ real fdiml(real x, real y); -+ real fmaxl(real x, real y); -+ real fminl(real x, real y); -+ real fmal(real x, real y, real z); -+ } - double acos(double x); - float acosf(float x); -- real acosl(real x) { return acos(x); } - - double asin(double x); - float asinf(float x); -- real asinl(real x) { return asin(x); } - - double atan(double x); - float atanf(float x); -- real atanl(real x) { return atan(x); } - - double atan2(double y, double x); - float atan2f(float y, float x); -- real atan2l(real y, real x) { return atan2(y, x); } - - double cos(double x); - float cosf(float x); -- real cosl(real x) { return cos(x); } - - double sin(double x); - float sinf(float x); -- real sinl(real x) { return sin(x); } - - double tan(double x); - float tanf(float x); -- real tanl(real x) { return tan(x); } - - double acosh(double x); - float acoshf(float x); -@@ -530,7 +617,6 @@ - - double exp2(double x); - float exp2f(float x); -- real exp2l(real x) { return exp2(x); } - - double expm1(double x); - float expm1f(float x); -@@ -538,15 +624,12 @@ - - double frexp(double value, int* exp); - float frexpf(float value, int* exp); -- real frexpl(real value, int* exp) { return frexp(value, exp); } - - int ilogb(double x); - int ilogbf(float x); -- int ilogbl(real x) { return ilogb(x); } - - double ldexp(double x, int exp); - float ldexpf(float x, int exp); -- real ldexpl(real x, int exp) { return ldexp(x, exp); } - - double log(double x); - float logf(float x); -@@ -567,20 +650,15 @@ - - double logb(double x); - float logbf(float x); -- real logbl(real x) { return logb(x); } - - double modf(double value, double* iptr); - float modff(float value, float* iptr); -- //real modfl(real value, real *iptr); // nontrivial conversion - - double scalbn(double x, int n); - float scalbnf(float x, int n); -- real scalbnl(real x, int n) { return scalbn(x, n); } - - double scalbln(double x, c_long n); - float scalblnf(float x, c_long n); -- real scalblnl(real x, c_long n) { return scalbln(x, n); } -- - - double cbrt(double x); - float cbrtf(float x); -@@ -588,11 +666,9 @@ - - double fabs(double x); - float fabsf(float x); -- real fabsl(real x) { return fabs(x); } - - double hypot(double x, double y); - float hypotf(float x, float y); -- real hypotl(real x, real y) { return hypot(x, y); } - - double pow(double x, double y); - float powf(float x, float y); -@@ -600,7 +676,6 @@ - - double sqrt(double x); - float sqrtf(float x); -- real sqrtl(real x) { return sqrt(x); } - - double erf(double x); - float erff(float x); -@@ -620,23 +695,18 @@ - - double ceil(double x); - float ceilf(float x); -- real ceill(real x) { return ceil(x); } - - double floor(double x); - float floorf(float x); -- real floorl(real x) { return floor(x); } - - double nearbyint(double x); - float nearbyintf(float x); -- real nearbyintl(real x) { return nearbyint(x); } - - double rint(double x); - float rintf(float x); -- real rintl(real x) { return rint(x); } - - c_long lrint(double x); - c_long lrintf(float x); -- c_long lrintl(real x) { return lrint(x); } - - long llrint(double x); - long llrintf(float x); -@@ -644,63 +714,45 @@ - - double round(double x); - float roundf(float x); -- real roundl(real x) { return round(x); } - - c_long lround(double x); - c_long lroundf(float x); -- c_long lroundl(real x) { return lround(x); } - - long llround(double x); - long llroundf(float x); -- long llroundl(real x) { return llround(x); } - - double trunc(double x); - float truncf(float x); -- real truncl(real x) { return trunc(x); } - - double fmod(double x, double y); - float fmodf(float x, float y); -- real fmodl(real x, real y) { return fmod(x, y); } - - double remainder(double x, double y); - float remainderf(float x, float y); -- real remainderl(real x, real y) { return remainder(x, y); } - - double remquo(double x, double y, int* quo); - float remquof(float x, float y, int* quo); -- real remquol(real x, real y, int* quo) { return remquo(x, y, quo); } - - double copysign(double x, double y); - float copysignf(float x, float y); -- real copysignl(real x, real y) { return copysign(x, y); } -- --// double nan(char* tagp); --// float nanf(char* tagp); --// real nanl(char* tagp); - - double nextafter(double x, double y); - float nextafterf(float x, float y); -- real nextafterl(real x, real y) { return nextafter(x, y); } - - double nexttoward(double x, real y); - float nexttowardf(float x, real y); -- real nexttowardl(real x, real y) { return nexttoward(x, y); } - - double fdim(double x, double y); - float fdimf(float x, float y); -- real fdiml(real x, real y) { return fdim(x, y); } - - double fmax(double x, double y); - float fmaxf(float x, float y); -- real fmaxl(real x, real y) { return fmax(x, y); } - - double fmin(double x, double y); - float fminf(float x, float y); -- real fminl(real x, real y) { return fmin(x, y); } - - double fma(double x, double y, double z); - float fmaf(float x, float y, float z); -- real fmal(real x, real y, real z) { return fma(x, y, z); } - } - else - { diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/core/stdc/math.di druntime/import/core/stdc/math.di ---- druntime-orig/import/core/stdc/math.di 2010-10-29 04:54:24.000000000 +0400 -+++ druntime/import/core/stdc/math.di 2010-12-30 15:26:21.142104001 +0300 +--- druntime-orig/import/core/stdc/math.di 2010-12-20 10:27:04.000000000 +0300 ++++ druntime/import/core/stdc/math.di 2011-01-05 14:40:22.000000000 +0300 @@ -1,1134 +1,1135 @@ -// D import file generated from 'src\core\stdc\math.d' -module core.stdc.math; @@ -3813,26 +3506,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} + + -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/core/stdc/stdlib.d druntime/import/core/stdc/stdlib.d ---- druntime-orig/import/core/stdc/stdlib.d 2009-11-30 10:02:20.000000000 +0300 -+++ druntime/import/core/stdc/stdlib.d 2010-11-04 17:49:07.000000000 +0300 -@@ -92,3 +92,13 @@ - { - void* alloca(size_t size); // non-standard - } -+else version( LDC ) -+{ -+ pragma(alloca) -+ void* alloca(size_t size); -+} -+else version( GNU ) -+{ -+ private import gcc.builtins; -+ alias gcc.builtins.__builtin_alloca alloca; -+} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/core/stdc/stdlib.di druntime/import/core/stdc/stdlib.di ---- druntime-orig/import/core/stdc/stdlib.di 2010-10-29 04:54:24.000000000 +0400 -+++ druntime/import/core/stdc/stdlib.di 2010-12-30 15:26:39.786104000 +0300 +--- druntime-orig/import/core/stdc/stdlib.di 2010-12-20 10:27:04.000000000 +0300 ++++ druntime/import/core/stdc/stdlib.di 2011-01-05 14:40:22.000000000 +0300 @@ -1,72 +1,89 @@ -// D import file generated from 'src\core\stdc\stdlib.d' -module core.stdc.stdlib; @@ -3996,20 +3672,22 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} + diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/core/vararg.di druntime/import/core/vararg.di ---- druntime-orig/import/core/vararg.di 2010-10-29 04:54:24.000000000 +0400 -+++ druntime/import/core/vararg.di 2011-01-02 18:55:32.561075001 +0300 -@@ -1,26 +1,37 @@ +--- druntime-orig/import/core/vararg.di 2010-12-20 10:27:04.000000000 +0300 ++++ druntime/import/core/vararg.di 2011-01-05 14:41:51.000000000 +0300 +@@ -1,34 +1,45 @@ -// D import file generated from 'src\core\vararg.d' -module core.vararg; --alias void* va_list; --template va_start(T) +-version (X86) +-{ +- alias void* va_list; +- template va_start(T) -{ -void va_start(out va_list ap, ref T parmn) -{ -ap = cast(va_list)(cast(void*)&parmn + (T.sizeof + (int).sizeof - 1 & ~((int).sizeof - 1))); -} -} --template va_arg(T) +- template va_arg(T) -{ -T va_arg(ref va_list ap) -{ @@ -4018,16 +3696,24 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. -return arg; -} -} --void va_end(va_list ap) +- void va_end(va_list ap) -{ -} --void va_copy(out va_list dst, va_list src) +- void va_copy(out va_list dst, va_list src) -{ -dst = src; -} +-} +-else +-{ +- public import core.stdc.stdarg; +- +-} +// D import file generated from 'src/core/vararg.d' +module core.vararg; -+alias void* va_list; ++version (X86) ++{ ++ alias void* va_list; +version (LDC) +{ + pragma (va_start)template va_start(T) @@ -4046,7 +3732,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +} +} +} -+template va_arg(T) ++ template va_arg(T) +{ +T va_arg(ref va_list ap) +{ @@ -4055,16 +3741,22 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +return arg; +} +} -+void va_end(va_list ap) ++ void va_end(va_list ap) +{ +} -+void va_copy(out va_list dst, va_list src) ++ void va_copy(out va_list dst, va_list src) +{ +dst = src; +} ++} ++else ++{ ++ public import core.stdc.stdarg; ++ ++} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/intrinsics.di druntime/import/ldc/intrinsics.di --- druntime-orig/import/ldc/intrinsics.di 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/intrinsics.di 2010-12-30 13:40:26.000000000 +0300 ++++ druntime/import/ldc/intrinsics.di 2011-01-05 14:40:22.000000000 +0300 @@ -0,0 +1,359 @@ +/* + * This module holds declarations to LLVM intrinsics. @@ -4427,7 +4119,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + void llvm_trap(); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/ldc/llvmasm.di druntime/import/ldc/llvmasm.di --- druntime-orig/import/ldc/llvmasm.di 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/import/ldc/llvmasm.di 2010-12-30 13:40:26.000000000 +0300 ++++ druntime/import/ldc/llvmasm.di 2011-01-05 14:40:22.000000000 +0300 @@ -0,0 +1,17 @@ +module ldc.llvmasm; + @@ -4447,8 +4139,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + } +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/object.di druntime/import/object.di ---- druntime-orig/import/object.di 2010-10-13 10:37:58.000000000 +0400 -+++ druntime/import/object.di 2011-01-03 16:21:43.223688001 +0300 +--- druntime-orig/import/object.di 2010-12-16 01:43:28.000000000 +0300 ++++ druntime/import/object.di 2011-01-05 14:40:22.000000000 +0300 @@ -142,7 +142,7 @@ // 32: // has typeinfo member void* deallocator; @@ -4466,10 +4158,257 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } string msg; +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/std/intrinsic.di druntime/import/std/intrinsic.di +--- druntime-orig/import/std/intrinsic.di 2010-12-15 10:30:54.000000000 +0300 ++++ druntime/import/std/intrinsic.di 2011-01-05 18:03:08.459062852 +0300 +@@ -1,171 +1,72 @@ +-/** +- * These functions are built-in intrinsics to the compiler. +- * +- * Intrinsic functions are functions built in to the compiler, usually to take +- * advantage of specific CPU features that are inefficient to handle via +- * external functions. The compiler's optimizer and code generator are fully +- * integrated in with intrinsic functions, bringing to bear their full power on +- * them. This can result in some surprising speedups. +- * +- * Copyright: Public Domain +- * License: Public Domain +- * Authors: Walter Bright +- */ +-module std.intrinsic; +- +-nothrow: +- +-/** +- * Scans the bits in v starting with bit 0, looking +- * for the first set bit. +- * Returns: +- * The bit number of the first bit set. +- * The return value is undefined if v is zero. +- */ +-pure int bsf(size_t v); +- +-/** +- * Scans the bits in v from the most significant bit +- * to the least significant bit, looking +- * for the first set bit. +- * Returns: +- * The bit number of the first bit set. +- * The return value is undefined if v is zero. +- * Example: +- * --- +- * import std.stdio; +- * import std.intrinsic; +- * +- * int main() +- * { +- * uint v; +- * int x; +- * +- * v = 0x21; +- * x = bsf(v); +- * writefln("bsf(x%x) = %d", v, x); +- * x = bsr(v); +- * writefln("bsr(x%x) = %d", v, x); +- * return 0; +- * } +- * --- +- * Output: +- * bsf(x21) = 0
+- * bsr(x21) = 5 +- */ +-pure int bsr(size_t v); +- +-/** +- * Tests the bit. +- */ +-pure int bt(in size_t* p, size_t bitnum); +- +-/** +- * Tests and complements the bit. +- */ +-int btc(size_t* p, size_t bitnum); +- +-/** +- * Tests and resets (sets to 0) the bit. +- */ +-int btr(size_t* p, size_t bitnum); +- +-/** +- * Tests and sets the bit. +- * Params: +- * p = a non-NULL pointer to an array of size_ts. +- * index = a bit number, starting with bit 0 of p[0], +- * and progressing. It addresses bits like the expression: +---- +-p[index / (size_t.sizeof*8)] & (1 << (index & ((size_t.sizeof*8) - 1))) +---- +- * Returns: +- * A non-zero value if the bit was set, and a zero +- * if it was clear. +- * +- * Example: +- * --- +-import std.stdio; +-import std.intrinsic; +- +-int main() +-{ +- size_t array[2]; +- +- array[0] = 2; +- array[1] = 0x100; +- +- writefln("btc(array, 35) = %d", btc(array, 35)); +- writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); +- +- writefln("btc(array, 35) = %d", btc(array, 35)); +- writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); +- +- writefln("bts(array, 35) = %d", bts(array, 35)); +- writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); +- +- writefln("btr(array, 35) = %d", btr(array, 35)); +- writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); +- +- writefln("bt(array, 1) = %d", bt(array, 1)); +- writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); +- +- return 0; +-} +- * --- +- * Output: +-
+-btc(array, 35) = 0
+-array = [0]:x2, [1]:x108
+-btc(array, 35) = -1
+-array = [0]:x2, [1]:x100
+-bts(array, 35) = 0
+-array = [0]:x2, [1]:x108
+-btr(array, 35) = -1
+-array = [0]:x2, [1]:x100
+-bt(array, 1) = -1
+-array = [0]:x2, [1]:x100
+-
+- */ +-int bts(size_t* p, size_t bitnum); +- +-/** +- * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes +- * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 +- * becomes byte 0. +- */ +-pure uint bswap(uint v); +- +- +-/** +- * Reads I/O port at port_address. +- */ +-ubyte inp(uint port_address); +- +-/** +- * ditto +- */ +-ushort inpw(uint port_address); +- +-/** +- * ditto +- */ +-uint inpl(uint port_address); +- +- +-/** +- * Writes and returns value to I/O port at port_address. +- */ +-ubyte outp(uint port_address, ubyte value); +- +-/** +- * ditto +- */ +-ushort outpw(uint port_address, ushort value); +- +-/** +- * ditto +- */ +-uint outpl(uint port_address, uint value); +- +- ++// D import file generated from 'src/std/intrinsic.d' ++module std.intrinsic; ++version (LDC) ++{ ++} ++else ++{ ++ static assert(false,"This module is only valid for LDC"); ++} ++nothrow ++{ ++ pure int bsf(size_t v); ++ ++ pure int bsr(size_t v); ++ ++ pure int bt(in size_t* p, size_t bitnum) ++{ ++return p[bitnum / ((uint).sizeof * 8)] & 1 << (bitnum & (uint).sizeof * 8 - 1) ? -1 : 0; ++} ++ ++ int btc(size_t* p, size_t bitnum) ++{ ++uint* q = p + bitnum / ((uint).sizeof * 8); ++uint mask = 1 << (bitnum & (uint).sizeof * 8 - 1); ++int result = *q & mask; ++*q ^= mask; ++return result ? -1 : 0; ++} ++ int btr(size_t* p, size_t bitnum) ++{ ++uint* q = p + bitnum / ((uint).sizeof * 8); ++uint mask = 1 << (bitnum & (uint).sizeof * 8 - 1); ++int result = *q & mask; ++*q &= ~mask; ++return result ? -1 : 0; ++} ++ int bts(size_t* p, size_t bitnum) ++{ ++uint* q = p + bitnum / ((uint).sizeof * 8); ++uint mask = 1 << (bitnum & (uint).sizeof * 8 - 1); ++int result = *q & mask; ++*q |= mask; ++return result ? -1 : 0; ++} ++ pure pragma (intrinsic, "llvm.bswap.i32")uint bswap(uint val); ++ ++ ++ ubyte inp(uint port_address) ++{ ++assert(false && "inp intrinsic not yet implemented"); ++} ++ ushort inpw(uint port_address) ++{ ++assert(false && "inpw intrinsic not yet implemented"); ++} ++ uint inpl(uint port_address) ++{ ++assert(false && "inpl intrinsic not yet implemented"); ++} ++ ubyte outp(uint port_address, ubyte value) ++{ ++assert(false && "outp intrinsic not yet implemented"); ++} ++ ushort outpw(uint port_address, ushort value) ++{ ++assert(false && "outpw intrinsic not yet implemented"); ++} ++ uint outpl(uint port_address, uint value) ++{ ++assert(false && "outpl intrinsic not yet implemented"); ++} ++} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/atomic.d druntime/src/core/atomic.d ---- druntime-orig/src/core/atomic.d 2010-10-11 00:37:54.000000000 +0400 -+++ druntime/src/core/atomic.d 2010-11-07 19:11:32.000000000 +0300 -@@ -89,6 +89,117 @@ +--- druntime-orig/src/core/atomic.d 2010-12-15 22:30:58.000000000 +0300 ++++ druntime/src/core/atomic.d 2011-01-05 14:40:22.000000000 +0300 +@@ -91,6 +91,117 @@ return false; } } @@ -4587,7 +4526,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. else version( AsmX86_32 ) { T atomicOp(string op, T, V1)( ref shared T val, V1 mod ) -@@ -396,6 +507,12 @@ +@@ -398,6 +509,12 @@ } } } @@ -4601,9 +4540,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { T atomicOp(string op, T, V1)( ref shared T val, V1 mod ) diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/stdc/math.d druntime/src/core/stdc/math.d ---- druntime-orig/src/core/stdc/math.d 2010-09-03 12:28:52.000000000 +0400 -+++ druntime/src/core/stdc/math.d 2010-11-04 17:49:07.000000000 +0300 -@@ -17,6 +17,7 @@ +--- druntime-orig/src/core/stdc/math.d 2010-12-15 10:30:50.000000000 +0300 ++++ druntime/src/core/stdc/math.d 2011-01-05 14:40:22.000000000 +0300 +@@ -18,6 +18,7 @@ extern (C): nothrow: @@ -4611,10 +4550,84 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. alias float float_t; alias double double_t; +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/stdc/stdarg.d druntime/src/core/stdc/stdarg.d +--- druntime-orig/src/core/stdc/stdarg.d 2010-12-15 10:30:50.000000000 +0300 ++++ druntime/src/core/stdc/stdarg.d 2011-01-05 16:38:59.387062854 +0300 +@@ -16,7 +16,69 @@ + + @system: + +-version( X86 ) ++version( LDC ) ++{ ++ /********************* ++ * The argument pointer type. ++ */ ++ alias void* va_list; ++ ++ /********** ++ * Initialize ap. ++ * Parmn should be the last named parameter. ++ */ ++ pragma(va_start) ++ void va_start(T)(va_list ap, ref T); ++ ++ /************ ++ * Retrieve and return the next value that is type T. ++ * Should use the other va_arg instead, as this won't work for 64 bit code. ++ */ ++ T va_arg(T)(ref va_list ap) ++ { ++ T arg = *cast(T*) ap; ++ ap = cast(va_list)( cast(void*) ap + ( ( T.sizeof + size_t.sizeof - 1 ) & ~( size_t.sizeof - 1 ) ) ); ++ return arg; ++ } ++ ++ /************ ++ * Retrieve and return the next value that is type T. ++ * This is the preferred version. ++ */ ++ void va_arg(T)(ref va_list ap, ref T parmn) ++ { ++ parmn = *cast(T*)ap; ++ ap = cast(va_list)(cast(void*)ap + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); ++ } ++ ++ /************* ++ * Retrieve and store through parmn the next value that is of TypeInfo ti. ++ * Used when the static type is not known. ++ */ ++ void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) ++ { ++ // Wait until everyone updates to get TypeInfo.talign() ++ //auto talign = ti.talign(); ++ //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1); ++ auto p = ap; ++ auto tsize = ti.tsize(); ++ ap = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); ++ parmn[0..tsize] = p[0..tsize]; ++ } ++ ++ /*********************** ++ * End use of ap. ++ */ ++ void va_end(va_list ap) ++ { ++ } ++ ++ void va_copy(out va_list dest, va_list src) ++ { ++ dest = src; ++ } ++} ++else version( X86 ) + { + /********************* + * The argument pointer type. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/stdc/stdlib.d druntime/src/core/stdc/stdlib.d ---- druntime-orig/src/core/stdc/stdlib.d 2010-08-05 05:39:08.000000000 +0400 -+++ druntime/src/core/stdc/stdlib.d 2010-11-04 17:49:07.000000000 +0300 -@@ -92,3 +92,13 @@ +--- druntime-orig/src/core/stdc/stdlib.d 2010-12-15 10:30:50.000000000 +0300 ++++ druntime/src/core/stdc/stdlib.d 2011-01-05 14:40:22.000000000 +0300 +@@ -93,3 +93,13 @@ { void* alloca(size_t size); // non-standard } @@ -4629,12 +4642,12 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + alias gcc.builtins.__builtin_alloca alloca; +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/core/vararg.d druntime/src/core/vararg.d ---- druntime-orig/src/core/vararg.d 2010-08-05 05:39:08.000000000 +0400 -+++ druntime/src/core/vararg.d 2011-01-02 18:52:38.045075000 +0300 -@@ -30,9 +30,21 @@ - * paramn = The identifier of the rightmost parameter in the function - * parameter list. - */ +--- druntime-orig/src/core/vararg.d 2010-12-15 10:30:52.000000000 +0300 ++++ druntime/src/core/vararg.d 2011-01-05 14:42:18.000000000 +0300 +@@ -32,10 +32,22 @@ + * paramn = The identifier of the rightmost parameter in the function + * parameter list. + */ +version(LDC) +{ + @@ -4645,19 +4658,19 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +else +{ + - void va_start(T) ( out va_list ap, ref T parmn ) - { -- ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); -+ ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + size_t.sizeof - 1 ) & ~( size_t.sizeof - 1 ) ) ); + void va_start(T)( out va_list ap, ref T parmn ) + { + ap = cast(va_list)( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); + } ++ +} -+ - } - /** + /** + * This function returns the next argument in the sequence referenced by diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/gc/gcbits.d druntime/src/gc/gcbits.d ---- druntime-orig/src/gc/gcbits.d 2010-08-08 04:10:24.000000000 +0400 -+++ druntime/src/gc/gcbits.d 2010-11-04 17:49:07.000000000 +0300 -@@ -26,6 +26,10 @@ +--- druntime-orig/src/gc/gcbits.d 2010-12-15 10:30:52.000000000 +0300 ++++ druntime/src/gc/gcbits.d 2011-01-05 14:40:22.000000000 +0300 +@@ -27,6 +27,10 @@ { version = bitops; } @@ -4669,9 +4682,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { // use the unoptimized version diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/gc/gcx.d druntime/src/gc/gcx.d ---- druntime-orig/src/gc/gcx.d 2010-10-03 10:52:12.000000000 +0400 -+++ druntime/src/gc/gcx.d 2010-11-07 19:11:32.000000000 +0300 -@@ -1464,7 +1464,8 @@ +--- druntime-orig/src/gc/gcx.d 2010-12-15 10:30:52.000000000 +0300 ++++ druntime/src/gc/gcx.d 2011-01-05 14:40:22.000000000 +0300 +@@ -1465,7 +1465,8 @@ void initialize() @@ -4681,7 +4694,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. (cast(byte*)&this)[0 .. Gcx.sizeof] = 0; stackBottom = cast(char*)&dummy; -@@ -2200,7 +2201,7 @@ +@@ -2201,7 +2202,7 @@ if ((cast(size_t)p & ~(PAGESIZE-1)) == pcache) continue; @@ -4690,7 +4703,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. if (pool) { size_t offset = cast(size_t)(p - pool.baseAddr); -@@ -2270,80 +2271,129 @@ +@@ -2271,80 +2272,129 @@ __builtin_unwind_init(); sp = & sp; } @@ -4888,7 +4901,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. return result; } -@@ -2357,7 +2407,7 @@ +@@ -2358,7 +2408,7 @@ Pool* pool; debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n"); @@ -4898,9 +4911,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. thread_suspendAll(); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/object_.d druntime/src/object_.d ---- druntime-orig/src/object_.d 2010-12-27 21:21:19.176120002 +0300 -+++ druntime/src/object_.d 2010-12-28 13:30:49.239335001 +0300 -@@ -1754,7 +1754,6 @@ +--- druntime-orig/src/object_.d 2010-12-16 01:43:28.000000000 +0300 ++++ druntime/src/object_.d 2011-01-05 14:40:22.000000000 +0300 +@@ -1763,7 +1763,6 @@ { int len = 0; ModuleReference *mr; @@ -4908,7 +4921,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. for (mr = _Dmodule_ref; mr; mr = mr.next) len++; _moduleinfo_array = new ModuleInfo*[len]; -@@ -2116,7 +2115,6 @@ +@@ -2278,7 +2277,6 @@ _d_monitor_create(h); m = getMonitor(h); } @@ -4916,7 +4929,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. IMonitor i = m.impl; if (i is null) -@@ -2215,7 +2213,7 @@ +@@ -2377,7 +2375,7 @@ size_t _aaLen(void* p); void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...); void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...); @@ -4925,7 +4938,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. void _aaDel(void* p, TypeInfo keyti, ...); void[] _aaValues(void* p, size_t keysize, size_t valuesize); void[] _aaKeys(void* p, size_t keysize, size_t valuesize); -@@ -2260,7 +2258,7 @@ +@@ -2422,7 +2420,7 @@ return *cast(Key[]*) &a; } @@ -4934,74 +4947,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { return _aaApply2(p, aligntsize(Key.sizeof), cast(_dg2_t)dg); } -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/aaA.d druntime/src/rt/aaA.d ---- druntime-orig/src/rt/aaA.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/aaA.d 2011-01-02 20:06:15.617075000 +0300 -@@ -204,7 +204,7 @@ - * Add entry for key if it is not already there. - */ - --void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...) -+void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void *pkey) - in - { - assert(aa); -@@ -218,7 +218,6 @@ - } - body - { -- auto pkey = cast(void *)(&valuesize + 1); - size_t i; - aaA *e; - //printf("keyti = %p\n", keyti); -@@ -274,13 +273,12 @@ - * Returns null if it is not already there. - */ - --void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...) -+void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void *pkey) - { - //printf("_aaGetRvalue(valuesize = %u)\n", valuesize); - if (!aa.a) - return null; - -- auto pkey = cast(void *)(&valuesize + 1); - auto keysize = aligntsize(keyti.tsize()); - auto len = aa.a.b.length; - -@@ -312,7 +310,7 @@ - * !=null in aa, return pointer to value - */ - --void* _aaIn(AA aa, TypeInfo keyti, ...) -+void* _aaIn(AA aa, TypeInfo keyti, void *pkey) - in - { - } -@@ -324,8 +322,6 @@ - { - if (aa.a) - { -- auto pkey = cast(void *)(&keyti + 1); -- - //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr); - auto len = aa.a.b.length; - -@@ -357,9 +353,8 @@ - * If key is not in aa[], do nothing. - */ - --void _aaDel(AA aa, TypeInfo keyti, ...) -+void _aaDel(AA aa, TypeInfo keyti, void *pkey) - { -- auto pkey = cast(void *)(&keyti + 1); - aaA *e; - - if (aa.a && aa.a.b.length) diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/adi.d druntime/src/rt/adi.d ---- druntime-orig/src/rt/adi.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/adi.d 2010-11-04 17:49:07.000000000 +0300 -@@ -35,6 +35,8 @@ +--- druntime-orig/src/rt/adi.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/adi.d 2011-01-05 15:13:25.247062853 +0300 +@@ -36,6 +36,8 @@ extern (C) void gc_free( void* p ); } @@ -5010,7 +4959,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. struct Array { -@@ -48,7 +50,7 @@ +@@ -49,7 +51,7 @@ * reversed. */ @@ -5019,90 +4968,24 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { if (a.length > 1) { -@@ -108,7 +110,7 @@ +@@ -109,7 +111,7 @@ hi = hi - 1 + (stridehi - stridelo); } } - return *cast(long*)(&a); -+ return a; ++ return *cast(char[]*)&a; } unittest -@@ -143,7 +145,7 @@ - * reversed. - */ - --extern (C) long _adReverseWchar(wchar[] a) -+extern (C) wchar[] _adReverseWchar(wchar[] a) - { - if (a.length > 1) - { -@@ -201,7 +203,7 @@ - hi = hi - 1 + (stridehi - stridelo); - } - } -- return *cast(long*)(&a); -+ return a; - } - - unittest -@@ -225,10 +227,10 @@ +@@ -226,7 +228,7 @@ * Support for array.reverse property. */ --extern (C) long _adReverse(Array a, size_t szelem) +-extern (C) void[] _adReverse(Array a, size_t szelem) +extern (C) void[] _adReverse(void[] a, size_t szelem) out (result) { -- assert(result is *cast(long*)(&a)); -+ assert(result.ptr is a.ptr); - } - body - { -@@ -267,7 +269,7 @@ - //gc_free(tmp); - } - } -- return *cast(long*)(&a); -+ return a; - } - - unittest -@@ -311,7 +313,7 @@ - * Sort array of chars. - */ - --extern (C) long _adSortChar(char[] a) -+extern (C) char[] _adSortChar(char[] a) - { - if (a.length > 1) - { -@@ -326,14 +328,14 @@ - } - delete da; - } -- return *cast(long*)(&a); -+ return a; - } - - /********************************************** - * Sort array of wchars. - */ - --extern (C) long _adSortWchar(wchar[] a) -+extern (C) wchar[] _adSortWchar(wchar[] a) - { - if (a.length > 1) - { -@@ -348,7 +350,7 @@ - } - delete da; - } -- return *cast(long*)(&a); -+ return a; - } - - /*************************************** + assert(result is *cast(void[]*)(&a)); @@ -358,7 +360,7 @@ * 0 not equal */ @@ -5151,39 +5034,33 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { asm { naked ; -@@ -569,8 +571,8 @@ - - ret ; - } -- } -- else -+ } -+ else - { - int len; - int c; diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/alloca.d druntime/src/rt/alloca.d ---- druntime-orig/src/rt/alloca.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/alloca.d 2010-11-04 17:49:07.000000000 +0300 -@@ -12,6 +12,9 @@ - */ - module rt.alloca; - -+version (DMD) -+{ -+ - /+ - #if DOS386 - extern size_t _x386_break; -@@ -133,3 +136,5 @@ - ret ; +--- druntime-orig/src/rt/alloca.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/alloca.d 2011-01-05 14:54:45.903062853 +0300 +@@ -52,16 +52,16 @@ + { + asm + { +- add EAX,15 ; +- and EAX,0xFFFFFFF0 ; // round up to 16 byte boundary ++ add EAX,15 ; ++ and EAX,0xFFFFFFF0 ; // round up to 16 byte boundary } - } -+ -+} + } + else + { + asm + { +- add EAX,3 ; +- and EAX,0xFFFFFFFC ; // round up to dword ++ add EAX,3 ; ++ and EAX,0xFFFFFFFC ; // round up to dword + } + } + diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/arrayInit.d druntime/src/rt/arrayInit.d --- druntime-orig/src/rt/arrayInit.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/src/rt/arrayInit.d 2010-12-28 13:20:38.239335002 +0300 ++++ druntime/src/rt/arrayInit.d 2011-01-05 14:40:22.000000000 +0300 @@ -0,0 +1,150 @@ +private import ldc.intrinsics; + @@ -5336,9 +5213,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + throw new Exception("overlapping array copy"); +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/dmain2.d druntime/src/rt/dmain2.d ---- druntime-orig/src/rt/dmain2.d 2010-10-13 08:41:12.000000000 +0400 -+++ druntime/src/rt/dmain2.d 2010-12-30 13:43:46.730104001 +0300 -@@ -38,6 +38,8 @@ +--- druntime-orig/src/rt/dmain2.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/dmain2.d 2011-01-05 14:40:22.000000000 +0300 +@@ -39,6 +39,8 @@ pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW } @@ -5349,7 +5226,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. Throwable _d_unhandled = null; diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/ldc_eh.d druntime/src/rt/ldc_eh.d --- druntime-orig/src/rt/ldc_eh.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/src/rt/ldc_eh.d 2011-01-02 19:03:34.733075000 +0300 ++++ druntime/src/rt/ldc_eh.d 2011-01-05 14:40:22.000000000 +0300 @@ -0,0 +1,428 @@ +/** + * This module contains functions and structures required for @@ -5780,9 +5657,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + _Unwind_Resume(&exception_struct.unwind_info); +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/lifetime.d druntime/src/rt/lifetime.d ---- druntime-orig/src/rt/lifetime.d 2010-10-12 07:07:36.000000000 +0400 -+++ druntime/src/rt/lifetime.d 2010-12-30 13:11:36.226104002 +0300 -@@ -92,6 +92,18 @@ +--- druntime-orig/src/rt/lifetime.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/lifetime.d 2011-01-05 17:33:37.155062853 +0300 +@@ -89,6 +89,18 @@ return gc_malloc(sz); } @@ -5801,119 +5678,52 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /** * -@@ -702,7 +714,7 @@ - __setArrayAllocLength(info, size, isshared); - result = arrstart[0..length]; - } -- return result; -+ return *cast(void[]*)&result; +@@ -820,14 +832,22 @@ + __setArrayAllocLength(info, allocsize, isshared); + auto p = __arrayStart(info)[0 .. dim]; - Loverflow: - onOutOfMemoryError(); -@@ -764,7 +776,7 @@ - __setArrayAllocLength(info, size, isshared); - result = arrstart[0..length]; - } -- return result; -+ return *cast(void[]*)&result; - - Loverflow: - onOutOfMemoryError(); -@@ -773,7 +785,7 @@ - /** - * - */ --extern (C) void[] _d_newarraymT(TypeInfo ti, size_t ndims, ...) -+extern (C) void[] _d_newarraymT(TypeInfo ti, size_t ndims, size_t *pdim) - { - void[] result; - -@@ -781,9 +793,7 @@ - if (ndims == 0) - result = null; - else -- { va_list q; -- va_start!(size_t)(q, ndims); -- -+ { - void[] foo(TypeInfo ti, size_t* pdim, size_t ndims) - { - auto dim = *pdim; -@@ -810,7 +820,6 @@ - return p; - } - -- auto pdim = cast(size_t *)q; - result = foo(ti, pdim, ndims); - debug(PRINTF) printf("result = %llx\n", result); - -@@ -821,16 +830,15 @@ - printf("index %d: %d\n", i, va_arg!(int)(q)); - } - } -- va_end(q); - } -- return result; -+ return *cast(void[]*)&result; - } - - - /** - * - */ --extern (C) void[] _d_newarraymiT(TypeInfo ti, size_t ndims, ...) -+extern (C) void[] _d_newarraymiT(TypeInfo ti, size_t ndims, size_t *pdim) - { - void[] result; - -@@ -839,9 +847,6 @@ - result = null; +- version(X86) ++ version(LDC) ++ { ++ va_list ap2; ++ va_copy(ap2, ap); ++ } ++ else version(X86) + { + va_list ap2; + va_copy(ap2, ap); + } + for (size_t i = 0; i < dim; i++) + { +- version(X86_64) ++ version(LDC) ++ { ++ } ++ else version(X86_64) + { + __va_list argsave = *cast(__va_list*)ap; + va_list ap2 = &argsave; +@@ -870,7 +890,9 @@ else { -- va_list q; -- va_start!(size_t)(q, ndims); -- - void[] foo(TypeInfo ti, size_t* pdim, size_t ndims) - { - size_t dim = *pdim; -@@ -867,7 +872,6 @@ - return p; - } - -- size_t* pdim = cast(size_t *)q; - result = foo(ti, pdim, ndims); - debug(PRINTF) printf("result = %llx\n", result); - -@@ -879,9 +883,8 @@ - printf("init = %d\n", va_arg!(int)(q)); - } - } -- va_end(q); - } -- return result; -+ return *cast(void[]*)&result; - } - - -@@ -1381,7 +1384,7 @@ - * Append y[] to array pointed to by px - * size is size of each array element. - */ --extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) -+extern (C) void[] _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) - { - // only optimize array append where ti is not a shared type - auto sizeelem = ti.next.tsize(); // array element size -@@ -1468,7 +1471,7 @@ - L1: - px.length = newlength; - memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); -- return *cast(long*)px; -+ return *cast(void[]*)px; - } - - -@@ -1552,21 +1555,36 @@ + va_list q; +- version(X86) ++ version(LDC) ++ va_start(q, ndims); ++ else version(X86) + va_start(q, ndims); + else version(X86_64) + va_start(q, __va_argsave); +@@ -893,6 +915,8 @@ + else + { + va_list q; ++ version(LDC) ++ va_start(q, ndims); + version(X86) + va_start(q, ndims); + else version(X86_64) +@@ -1597,6 +1621,20 @@ return newcap; } @@ -5934,55 +5744,27 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /** * - */ --extern (C) long _d_arrayappendcT(TypeInfo ti, Array *x, ...) -+extern (C) void[] _d_arrayappendcT(TypeInfo ti, Array *x, ...) - { - byte *argp = cast(byte*)(&ti + 2); - return _d_arrayappendT(ti, x, argp[0..1]); +@@ -1622,6 +1660,7 @@ + } } +} /** * Append dchar to char[] - */ --extern (C) long _d_arrayappendcd(ref char[] x, dchar c) -+extern (C) void[] _d_arrayappendcd(ref char[] x, dchar c) - { - // c could encode into from 1 to 4 characters - char[4] buf = void; -@@ -1612,7 +1630,7 @@ - /** - * Append dchar to wchar[] - */ --extern (C) long _d_arrayappendwd(ref wchar[] x, dchar c) -+extern (C) void[] _d_arrayappendwd(ref wchar[] x, dchar c) - { - // c could encode into from 1 to 2 w characters - wchar[2] buf = void; -@@ -1798,7 +1816,7 @@ +@@ -1904,7 +1943,7 @@ /** * */ --extern (C) long _adDupT(TypeInfo ti, Array2 a) +-extern (C) void[] _adDupT(TypeInfo ti, Array2 a) +extern (C) void[] _adDupT(TypeInfo ti, void[] a) out (result) { auto sizeelem = ti.next.tsize(); // array element size -@@ -1819,7 +1837,7 @@ - r.length = a.length; - memcpy(r.ptr, a.ptr, size); - } -- return *cast(long*)(&r); -+ return *cast(void[]*)(&r); - } - - diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/memory.d druntime/src/rt/memory.d ---- druntime-orig/src/rt/memory.d 2010-10-11 00:37:52.000000000 +0400 -+++ druntime/src/rt/memory.d 2010-11-07 19:11:32.000000000 +0300 -@@ -12,6 +12,8 @@ +--- druntime-orig/src/rt/memory.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/memory.d 2011-01-05 14:40:22.000000000 +0300 +@@ -13,6 +13,8 @@ */ module rt.memory; @@ -5991,7 +5773,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. private { -@@ -230,3 +232,616 @@ +@@ -240,3 +242,616 @@ static assert( false, "Operating system not supported." ); } } @@ -6609,8 +6391,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + static assert( false, "Compiler not supported." ); +} diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/qsort.d druntime/src/rt/qsort.d ---- druntime-orig/src/rt/qsort.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/qsort.d 2010-11-04 17:49:07.000000000 +0300 +--- druntime-orig/src/rt/qsort.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/qsort.d 2011-01-05 14:40:22.000000000 +0300 @@ -44,7 +44,7 @@ structures. The default value is optimized for a high cost for compares. */ @@ -6618,9 +6400,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. -extern (C) long _adSort(Array a, TypeInfo ti) +extern (C) void[] _adSort(void[] a, TypeInfo ti) { - byte* base; byte*[40] stack; // stack -@@ -124,7 +124,7 @@ + byte* i, j; // scan and limit pointers +@@ -121,7 +121,7 @@ limit = sp[1]; } else // else stack empty, all done @@ -6630,9 +6412,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. assert(0); } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/qsort2.d druntime/src/rt/qsort2.d ---- druntime-orig/src/rt/qsort2.d 2010-08-05 05:39:06.000000000 +0400 -+++ druntime/src/rt/qsort2.d 2010-11-04 17:49:07.000000000 +0300 -@@ -31,14 +31,14 @@ +--- druntime-orig/src/rt/qsort2.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/qsort2.d 2011-01-05 14:40:22.000000000 +0300 +@@ -32,14 +32,14 @@ return tiglobal.compare(p1, p2); } @@ -6650,9 +6432,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/rt/trace.d druntime/src/rt/trace.d ---- druntime-orig/src/rt/trace.d 2010-08-07 09:46:06.000000000 +0400 -+++ druntime/src/rt/trace.d 2010-11-04 17:49:07.000000000 +0300 -@@ -855,7 +855,7 @@ +--- druntime-orig/src/rt/trace.d 2010-12-15 10:30:48.000000000 +0300 ++++ druntime/src/rt/trace.d 2011-01-05 14:40:22.000000000 +0300 +@@ -829,7 +829,7 @@ version (OSX) { // 16 byte align stack asm @@ -6661,7 +6443,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. pushad ; sub ESP,12 ; } -@@ -870,7 +870,7 @@ +@@ -844,7 +844,7 @@ else { asm @@ -6672,8 +6454,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. trace_epi(); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/src/std/intrinsic.d druntime/src/std/intrinsic.d --- druntime-orig/src/std/intrinsic.d 1970-01-01 03:00:00.000000000 +0300 -+++ druntime/src/std/intrinsic.d 2010-12-16 14:51:15.179832001 +0300 -@@ -0,0 +1,212 @@ ++++ druntime/src/std/intrinsic.d 2011-01-05 18:02:19.255062853 +0300 +@@ -0,0 +1,215 @@ +/* + * D phobos intrinsics for LDC + * @@ -6691,6 +6473,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + static assert(false, "This module is only valid for LDC"); +} + ++nothrow: ++ +/** + * Scans the bits in v starting with bit 0, looking + * for the first set bit. @@ -6698,7 +6482,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + * The bit number of the first bit set. + * The return value is undefined if v is zero. + */ -+pure nothrow int bsf(uint v) ++pure int bsf(size_t v) +{ + uint m = 1; + uint i; @@ -6737,7 +6521,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + * bsf(x21) = 0
+ * bsr(x21) = 5 + */ -+pure nothrow int bsr(uint v) ++pure int bsr(size_t v) +{ + uint m = 0x80000000; + uint i; @@ -6752,7 +6536,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +/** + * Tests the bit. + */ -+pure nothrow int bt(const uint *p, uint bitnum) ++pure int bt(in size_t* p, size_t bitnum) +{ + return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ; +} @@ -6761,7 +6545,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +/** + * Tests and complements the bit. + */ -+nothrow int btc(uint *p, uint bitnum) ++int btc(size_t* p, size_t bitnum) +{ + uint * q = p + (bitnum / (uint.sizeof*8)); + uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1)); @@ -6774,7 +6558,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +/** + * Tests and resets (sets to 0) the bit. + */ -+nothrow int btr(uint *p, uint bitnum) ++int btr(size_t* p, size_t bitnum) +{ + uint * q = p + (bitnum / (uint.sizeof*8)); + uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1)); @@ -6840,7 +6624,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +array = [0]:x2, [1]:x100 + + */ -+nothrow int bts(uint *p, uint bitnum) ++int bts(size_t* p, size_t bitnum) +{ + uint * q = p + (bitnum / (uint.sizeof*8)); + uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1)); @@ -6854,35 +6638,36 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 + * becomes byte 0. + */ -+pure nothrow pragma(intrinsic, "llvm.bswap.i32") ++pure pragma(intrinsic, "llvm.bswap.i32") + uint bswap(uint val); + +/** + * Reads I/O port at port_address. + */ -+ubyte inp(uint p) { throw new Exception("inp intrinsic not yet implemented"); } ++ubyte inp(uint port_address) { assert(false && "inp intrinsic not yet implemented"); }; + +/** + * ditto + */ -+ushort inpw(uint p) { throw new Exception("inpw intrinsic not yet implemented"); } ++ushort inpw(uint port_address) { assert(false && "inpw intrinsic not yet implemented"); }; + +/** + * ditto + */ -+uint inpl(uint p) { throw new Exception("inpl intrinsic not yet implemented"); } ++uint inpl(uint port_address) { assert(false && "inpl intrinsic not yet implemented"); }; ++ ++ ++/** ++ * Writes and returns value to I/O port at port_address. ++ */ ++ubyte outp(uint port_address, ubyte value) { assert(false && "outp intrinsic not yet implemented"); }; + +/** + * ditto + */ -+ubyte outp(uint p, ubyte v) { throw new Exception("outp intrinsic not yet implemented"); } ++ushort outpw(uint port_address, ushort value) { assert(false && "outpw intrinsic not yet implemented"); }; + +/** + * ditto + */ -+ushort outpw(uint p, ushort v) { throw new Exception("outpw intrinsic not yet implemented"); } -+ -+/** -+ * ditto -+ */ -+uint outpl(uint p, uint v) { throw new Exception("outpl intrinsic not yet implemented"); } ++uint outpl(uint port_address, uint value) { assert(false && "outpl intrinsic not yet implemented"); }; diff --git a/gen/aa.cpp b/gen/aa.cpp index c08f247a..45433873 100644 --- a/gen/aa.cpp +++ b/gen/aa.cpp @@ -37,13 +37,25 @@ static LLValue* to_keyti(DValue* key) DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue) { + // D1: // call: // extern(C) void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) // or // extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) + // D2: + // call: + // extern(C) void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) + // or + // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey) + // first get the runtime function +#if DMDV2 + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGetX":"_aaInX"); +#else + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGet":"_aaIn"); +#endif const llvm::FunctionType* funcTy = func->getFunctionType(); // aa param @@ -127,11 +139,20 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue) DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key) { + // D1: // call: // extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) + // D2: + // call: + // extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey) + // first get the runtime function +#if DMDV2 + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaInX"); +#else llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaIn"); +#endif const llvm::FunctionType* funcTy = func->getFunctionType(); if (Logger::enabled()) @@ -173,11 +194,20 @@ DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key) void DtoAARemove(Loc& loc, DValue* aa, DValue* key) { + // D1: // call: // extern(C) void _aaDel(AA aa, TypeInfo keyti, void* pkey) + // D2: + // call: + // extern(C) void _aaDelX(AA aa, TypeInfo keyti, void* pkey) + // first get the runtime function +#if DMDV2 + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaDelX"); +#else llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaDel"); +#endif const llvm::FunctionType* funcTy = func->getFunctionType(); if (Logger::enabled()) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index c4de5dd2..a14be8f1 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -627,9 +627,27 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size #if DMDV2 const char* fnname = zeroInit ? "_d_newarraymT" : "_d_newarraymiT"; + + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname); + + std::vector args; + args.push_back(arrayTypeInfo); + args.push_back(DtoConstSize_t(ndims)); + + // build dims + for (size_t i=0; igetRVal()); + + // call allocator + LLValue* newptr = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".gc_mem").getInstruction(); + + if (Logger::enabled()) + Logger::cout() << "final ptr = " << *newptr << '\n'; + + return getSlice(arrayType, newptr); #else + const char* fnname = defaultInit ? (zeroInit ? "_d_newarraymT" : "_d_newarraymiT") : "_d_newarraymvT"; -#endif LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname); // build dims @@ -645,9 +663,6 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size // call allocator LLValue* newptr = gIR->CreateCallOrInvoke3(fn, arrayTypeInfo, DtoConstSize_t(ndims), dimsArg, ".gc_mem").getInstruction(); -#if DMDV2 - return getSlice(arrayType, newptr); -#else // cast to wanted type const LLType* dstType = DtoType(arrayType)->getContainedType(1); if (newptr->getType() != dstType) diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index f7a40283..9c5a78ad 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -182,9 +182,17 @@ Statement *AsmStatement::semantic(Scope *sc) return this; } +#if DMDV2 +int AsmStatement::blockExit(bool mustNotThrow) +#else int AsmStatement::blockExit() +#endif { //printf("AsmStatement::blockExit(%p)\n", this); +#if DMDV2 + if (mustNotThrow) + error("asm statements are assumed to throw", toChars()); +#endif return BEfallthru | BEreturn | BEgoto | BEhalt; } diff --git a/gen/functions.cpp b/gen/functions.cpp index 9684fbc5..90c699ee 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -915,10 +915,8 @@ DValue* DtoArgument(Parameter* fnarg, Expression* argexp) // ref/out arg if (fnarg && (fnarg->storageClass & (STCref | STCout))) { - if (arg->isVar()) - arg = new DImValue(argexp->type, arg->getLVal()); - else - arg = new DImValue(argexp->type, arg->getRVal()); + Loc loc; + arg = new DImValue(argexp->type, makeLValue(loc, arg)); } // lazy arg else if (fnarg && (fnarg->storageClass & STClazy)) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 05bd2c9d..47c4f4ec 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1279,7 +1279,7 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp) LLConstant* val = exp->toConstElem(gIR); - Type* expbase = exp->type->toBasetype(); + Type* expbase = stripModifiers(exp->type->toBasetype()); Logger::println("expbase: %s", expbase->toChars()); Type* t = base->toBasetype(); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 163c81e4..6c05fbba 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -360,8 +360,7 @@ static void LLVM_D_BuildRuntimeModule() std::vector types; types.push_back(typeInfoTy); types.push_back(sizeTy); - types.push_back(rt_ptr(sizeTy)); - const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, true); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); } @@ -833,9 +832,16 @@ static void LLVM_D_BuildRuntimeModule() ->setAttributes(Attr_ReadOnly_NoUnwind_1_NoCapture); } + // D1: // void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) + // D2: + // void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey) { +#if DMDV2 + llvm::StringRef fname("_aaGetX"); +#else llvm::StringRef fname("_aaGet"); +#endif std::vector types; types.push_back(aaTy); types.push_back(typeInfoTy); @@ -846,9 +852,16 @@ static void LLVM_D_BuildRuntimeModule() ->setAttributes(Attr_1_4_NoCapture); } + // D1: // void* _aaIn(AA aa, TypeInfo keyti, void* pkey) + // D2: + // void* _aaInX(AA aa, TypeInfo keyti, void* pkey) { +#if DMDV2 + llvm::StringRef fname("_aaInX"); +#else llvm::StringRef fname("_aaIn"); +#endif std::vector types; types.push_back(aaTy); types.push_back(typeInfoTy); @@ -858,9 +871,16 @@ static void LLVM_D_BuildRuntimeModule() ->setAttributes(Attr_ReadOnly_1_3_NoCapture); } + // D1: // void _aaDel(AA aa, TypeInfo keyti, void* pkey) + // D2: + // void _aaDelX(AA aa, TypeInfo keyti, void* pkey) { +#if DMDV2 + llvm::StringRef fname("_aaDelX"); +#else llvm::StringRef fname("_aaDel"); +#endif std::vector types; types.push_back(aaTy); types.push_back(typeInfoTy); diff --git a/gen/statements.cpp b/gen/statements.cpp index 18f81c0b..59951e57 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -1568,12 +1568,16 @@ void VolatileStatement::toIR(IRState* p) DtoMemoryBarrier(false, true, false, false); // do statement - p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL)); + p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL)); statement->toIR(p); - p->func()->gen->targetScopes.pop_back(); + p->func()->gen->targetScopes.pop_back(); // no point in a unreachable barrier, terminating statements must insert this themselves. +#if DMDV2 + if (statement->blockExit(false) & BEfallthru) +#else if (statement->blockExit() & BEfallthru) +#endif { // store-load DtoMemoryBarrier(false, false, true, false); diff --git a/gen/toir.cpp b/gen/toir.cpp index fe6b4938..deb45215 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -52,6 +52,14 @@ llvm::cl::opt checkPrintf("check-printf-calls", void Expression::cacheLvalue(IRState* irs) { +#if DMDV2 + if (isLvalue()) { + Logger::println("Caching l-value of %s", toChars()); + LOG_SCOPE; + cachedLvalue = toElem(irs)->getLVal(); + return; + } +#endif error("expression %s does not mask any l-value", toChars()); fatal(); } diff --git a/phobos.patch b/phobos.patch index 9df920a2..81bf5089 100644 --- a/phobos.patch +++ b/phobos.patch @@ -1,6 +1,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/concurrency.d phobos/std/concurrency.d ---- phobos-orig/std/concurrency.d 2010-10-29 05:54:44.000000000 +0400 -+++ phobos/std/concurrency.d 2010-11-07 19:26:52.000000000 +0300 +--- phobos-orig/std/concurrency.d 2010-12-20 23:02:36.000000000 +0300 ++++ phobos/std/concurrency.d 2011-01-05 15:15:31.000000000 +0300 @@ -359,9 +359,10 @@ owner = ownerTid; fn( args ); @@ -14,9 +14,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. return spawnTid; } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/conv.d phobos/std/conv.d ---- phobos-orig/std/conv.d 2010-10-29 05:54:44.000000000 +0400 -+++ phobos/std/conv.d 2010-11-08 15:54:33.109464001 +0300 -@@ -1405,7 +1405,7 @@ +--- phobos-orig/std/conv.d 2010-12-20 23:02:36.000000000 +0300 ++++ phobos/std/conv.d 2011-01-05 15:15:31.000000000 +0300 +@@ -1425,7 +1425,7 @@ else // not hex { if (toupper(p.front) == 'N' && !startsWithZero) @@ -25,7 +25,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. // nan enforce((p.popFront(), !p.empty && toupper(p.front) == 'A') && (p.popFront(), !p.empty && toupper(p.front) == 'N'), -@@ -3243,6 +3243,11 @@ +@@ -3263,6 +3263,11 @@ T toImpl(T, S)(S d) if (is(Unqual!S == double) && isSomeString!(T)) { //alias Unqual!(ElementType!T) Char; @@ -38,9 +38,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. int len = sprintf(buffer.ptr, "%g", d); return to!T(buffer[0 .. len].dup); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/functional.d phobos/std/functional.d ---- phobos-orig/std/functional.d 2010-10-29 05:54:44.000000000 +0400 -+++ phobos/std/functional.d 2010-12-30 13:56:03.206104002 +0300 -@@ -713,6 +713,13 @@ +--- phobos-orig/std/functional.d 2010-12-20 23:02:36.000000000 +0300 ++++ phobos/std/functional.d 2011-01-05 15:15:31.000000000 +0300 +@@ -714,6 +714,13 @@ assert(dg_pure_nothrow() == 7); //assert(dg_pure_nothrow_safe() == 8); } @@ -54,7 +54,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /* test for linkage */ { struct S -@@ -724,4 +731,6 @@ +@@ -725,4 +732,6 @@ auto dg_xtrnD = toDelegate(&S.xtrnD); static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD))); } @@ -62,8 +62,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + } } diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/internal/math/biguintx86.d phobos/std/internal/math/biguintx86.d ---- phobos-orig/std/internal/math/biguintx86.d 2010-10-29 05:54:44.000000000 +0400 -+++ phobos/std/internal/math/biguintx86.d 2010-11-07 19:26:52.000000000 +0300 +--- phobos-orig/std/internal/math/biguintx86.d 2010-12-20 23:02:36.000000000 +0300 ++++ phobos/std/internal/math/biguintx86.d 2011-01-05 15:15:30.000000000 +0300 @@ -734,7 +734,10 @@ // EDI = dest // ESI = src @@ -98,56 +98,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. mixin(asmMulAdd_enter_odd(OP, "ESP+LASTPARAM")); } -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/intrinsic.d phobos/std/intrinsic.d ---- phobos-orig/std/intrinsic.d 2010-10-29 05:54:44.000000000 +0400 -+++ phobos/std/intrinsic.d 2010-12-16 14:56:59.311832002 +0300 -@@ -22,7 +22,7 @@ - - module std.intrinsic; - --nothrow: -+//nothrow: - - /** - * Scans the bits in v starting with bit 0, looking -@@ -72,12 +72,12 @@ - /** - * Tests and complements the bit. - */ --int btc(uint *p, uint bitnum); -+nothrow int btc(uint *p, uint bitnum); - - /** - * Tests and resets (sets to 0) the bit. - */ --int btr(uint *p, size_t bitnum); -+nothrow int btr(uint *p, size_t bitnum); - - /** - * Tests and sets the bit. -@@ -136,7 +136,7 @@ - array = [0]:x2, [1]:x100 - - */ --int bts(uint *p, size_t bitnum); -+nothrow int bts(uint *p, size_t bitnum); - - - /** -@@ -144,7 +144,8 @@ - byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 - becomes byte 0. - */ --pure uint bswap(uint v); -+pure nothrow pragma(intrinsic, "llvm.bswap.i32") -+ uint bswap(uint val); - - - /** diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/math.d phobos/std/math.d ---- phobos-orig/std/math.d 2010-10-29 05:54:44.000000000 +0400 -+++ phobos/std/math.d 2010-12-28 21:51:24.775335002 +0300 -@@ -276,7 +276,7 @@ +--- phobos-orig/std/math.d 2011-01-05 16:04:59.087062853 +0300 ++++ phobos/std/math.d 2011-01-05 18:17:40.283062853 +0300 +@@ -266,7 +266,7 @@ assert(abs(71.6Li) == 71.6L); assert(abs(-56) == 56); assert(abs(2321312L) == 2321312L); @@ -156,55 +110,57 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } /*********************************** -@@ -318,7 +318,10 @@ +@@ -308,7 +308,10 @@ * Results are undefined if |x| >= $(POWER 2,64). */ --@safe pure nothrow real cos(real x); /* intrinsic */ +-real cos(real x) @safe pure nothrow; /* intrinsic */ +version(LDC) + @safe pure nothrow real cos(real x) { return llvm_cos(x); } +else -+ @safe pure nothrow real cos(real x); /* intrinsic */ ++ real cos(real x) @safe pure nothrow; /* intrinsic */ /*********************************** * Returns sine of x. x is in radians. -@@ -333,7 +336,10 @@ +@@ -323,7 +326,10 @@ * Results are undefined if |x| >= $(POWER 2,64). */ --@safe pure nothrow real sin(real x); /* intrinsic */ +-real sin(real x) @safe pure nothrow; /* intrinsic */ +version(LDC) + @safe pure nothrow real sin(real x) { return llvm_sin(x); } +else -+ @safe pure nothrow real sin(real x); /* intrinsic */ ++ real sin(real x) @safe pure nothrow; /* intrinsic */ /*********************************** -@@ -400,7 +406,9 @@ +@@ -390,7 +396,9 @@ - @trusted pure nothrow real tan(real x) + real tan(real x) @trusted pure nothrow { -- version(Naked_D_InlineAsm_X86) { +- version(D_InlineAsm_X86) { + version(LDC) { + return core.stdc.math.tanl(x); -+ } else version(Naked_D_InlineAsm_X86) { ++ } else version(D_InlineAsm_X86) { asm { fld x[EBP] ; // load theta -@@ -809,6 +817,12 @@ +@@ -806,7 +814,13 @@ * greater than long.max, the result is * indeterminate. */ +-long rndtol(real x) @safe pure nothrow; /* intrinsic */ +version(LDC) +pure nothrow long rndtol(real x) +{ + return core.stdc.math.llroundl(x); +} +else - @safe pure nothrow long rndtol(real x); /* intrinsic */ ++ long rndtol(real x) @safe pure nothrow; /* intrinsic */ -@@ -831,6 +845,20 @@ + /***************************************** +@@ -828,6 +842,20 @@ * ) */ @@ -225,7 +181,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. @safe pure nothrow { float sqrt(float x); /* intrinsic */ -@@ -838,6 +866,8 @@ +@@ -835,6 +863,8 @@ real sqrt(real x); /* intrinsic */ /// ditto } @@ -234,7 +190,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. @trusted pure nothrow { // Should be @safe. See bugs 4628, 4630. // Create explicit overloads for integer sqrts. No ddoc for these because // hopefully a more elegant solution will eventually be found, so we don't -@@ -1413,9 +1443,22 @@ +@@ -1421,9 +1451,22 @@ * Compute n * 2$(SUP exp) * References: frexp */ @@ -250,27 +206,20 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. +else +{ - @safe pure nothrow real ldexp(real n, int exp); /* intrinsic */ + real ldexp(real n, int exp) @safe pure nothrow; /* intrinsic */ +} + unittest { assert(ldexp(1, -16384) == 0x1p-16384L); assert(ldexp(1, -16382) == 0x1p-16382L); -@@ -1608,7 +1651,31 @@ +@@ -1617,7 +1660,24 @@ * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) ) * ) */ --@safe pure nothrow real fabs(real x); /* intrinsic */ +-real fabs(real x) @safe pure nothrow; /* intrinsic */ +version(LDC) { -+ version( FreeBSD ) -+ version (all) // < 8-CURRENT -+ private extern(C) real fabsl(real x) { return fabs(x); } -+ else -+ private extern(C) real fabsl(real x); -+ else -+ private extern(C) real fabsl(real x); -+ pure nothrow real fabs(real x) ++ @trusted pure nothrow real fabs(real x) + { + version(D_InlineAsm_X86) + { @@ -285,12 +234,12 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. + } + } +} else { -+ @safe pure nothrow real fabs(real x); /* intrinsic */ ++ real fabs(real x) @safe pure nothrow; /* intrinsic */ +} /*********************************************************************** -@@ -2993,9 +3060,15 @@ +@@ -3017,9 +3077,15 @@ assert(pow(x,eight) == (x * x) * (x * x) * (x * x) * (x * x)); assert(pow(x, neg1) == 1 / x); @@ -310,7 +259,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /** Compute the value of an integer x, raised to the power of a positive diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/openrj.d phobos/std/openrj.d --- phobos-orig/std/openrj.d 2009-09-03 12:01:40.000000000 +0400 -+++ phobos/std/openrj.d 2010-10-26 13:17:37.000000000 +0400 ++++ phobos/std/openrj.d 2011-01-05 15:15:30.000000000 +0300 @@ -620,11 +620,11 @@ /** * @@ -354,8 +303,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. result = dg(field); diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/outbuffer.d phobos/std/outbuffer.d ---- phobos-orig/std/outbuffer.d 2010-10-29 05:54:44.000000000 +0400 -+++ phobos/std/outbuffer.d 2010-11-05 13:59:42.000000000 +0300 +--- phobos-orig/std/outbuffer.d 2010-12-20 23:02:36.000000000 +0300 ++++ phobos/std/outbuffer.d 2011-01-05 15:15:31.000000000 +0300 @@ -308,8 +308,15 @@ void printf(string format, ...) {