This commit is contained in:
Alexey Prokhin
2010-12-14 14:49:12 +03:00
44 changed files with 1734 additions and 473 deletions

View File

@@ -19,6 +19,7 @@
#include <set>
#include <map>
#include <string>
#include <llvm/Analysis/DebugInfo.h>
#endif
#include "dsymbol.h"
@@ -350,6 +351,9 @@ struct VarDeclaration : Declaration
/// This var is used by a naked function.
bool nakedUse;
// debug description
llvm::DIVariable debugVariable;
#endif
};

View File

@@ -55,7 +55,19 @@ bool isArrayOpValid(Expression *e)
case TOKxor:
case TOKand:
case TOKor:
case TOKassign:
case TOKaddass:
case TOKminass:
case TOKmulass:
case TOKdivass:
case TOKmodass:
case TOKxorass:
case TOKandass:
case TOKorass:
#if DMDV2
case TOKpow:
case TOKpowass:
#endif
return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2);
case TOKcall:
@@ -341,10 +353,10 @@ Expression *BinExp::arrayOp(Scope *sc)
fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTpublic;
fd->linkage = LINKd;
fd->linkage = LINKd;
// special attention for array ops
fd->isArrayOp = true;
// special attention for array ops
fd->isArrayOp = true;
sc->module->importedFrom->members->push(fd);
@@ -607,6 +619,19 @@ int Expression::isArrayOperand()
case TOKxor:
case TOKand:
case TOKor:
case TOKassign:
case TOKaddass:
case TOKminass:
case TOKmulass:
case TOKdivass:
case TOKmodass:
case TOKxorass:
case TOKandass:
case TOKorass:
#if DMDV2
case TOKpow:
case TOKpowass:
#endif
case TOKneg:
case TOKtilde:
return 1;

View File

@@ -1321,25 +1321,31 @@ Lagain:
}
else if (ei)
{
if (isDataseg())
/* static const/invariant does CTFE
*/
if (isDataseg() || (storage_class & STCmanifest))
e = e->optimize(WANTvalue | WANTinterpret);
else
e = e->optimize(WANTvalue);
if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64)
switch (e->op)
{
ei->exp = e; // no errors, keep result
}
case TOKint64:
case TOKfloat64:
case TOKstring:
case TOKarrayliteral:
case TOKassocarrayliteral:
case TOKstructliteral:
case TOKnull:
ei->exp = e; // no errors, keep result
break;
default:
#if DMDV2
else
{
/* Save scope for later use, to try again
*/
scope = new Scope(*sc);
scope->setNoFree();
}
/* Save scope for later use, to try again
*/
scope = new Scope(*sc);
scope->setNoFree();
#endif
break;
}
}
else
init = i2; // no errors, keep result

View File

@@ -19,6 +19,7 @@
#include <set>
#include <map>
#include <string>
#include <llvm/Analysis/DebugInfo.h>
#endif
#include "dsymbol.h"
@@ -49,6 +50,7 @@ enum PROT;
enum LINK;
enum TOK;
enum MATCH;
enum PURE;
#define STCundefined 0LL
#define STCstatic 1LL
@@ -346,6 +348,9 @@ struct VarDeclaration : Declaration
/// This var is used by a naked function.
bool nakedUse;
// debug description
llvm::DIVariable debugVariable;
#endif
};
@@ -697,6 +702,7 @@ struct FuncDeclaration : Declaration
#if IN_GCC
VarDeclaration *v_argptr; // '_argptr' variable
#endif
VarDeclaration *v_argsave; // save area for args passed in registers for variadic functions
Dsymbols *parameters; // Array of VarDeclaration's for parameters
DsymbolTable *labtab; // statement label symbol table
Declaration *overnext; // next in overload list
@@ -776,7 +782,7 @@ struct FuncDeclaration : Declaration
int isAbstract();
int isCodeseg();
int isOverloadable();
int isPure();
enum PURE isPure();
int isSafe();
int isTrusted();
virtual int isNested();

View File

@@ -5619,6 +5619,11 @@ Expression *CompileExp::semantic(Scope *sc)
#endif
UnaExp::semantic(sc);
e1 = resolveProperties(sc, e1);
if (!e1->type->isString())
{
error("argument to mixin must be a string type, not %s\n", e1->type->toChars());
return new ErrorExp();
}
e1 = e1->optimize(WANTvalue | WANTinterpret);
if (e1->op != TOKstring)
{ error("argument to mixin must be a string, not (%s)", e1->toChars());
@@ -5749,7 +5754,8 @@ Expression *AssertExp::semantic(Scope *sc)
if (e1->isBool(FALSE))
{
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
fd->hasReturnExp |= 4;
if (fd)
fd->hasReturnExp |= 4;
if (!global.params.useAssert)
{ Expression *e = new HaltExp(loc);
@@ -7135,7 +7141,7 @@ Lagain:
{ TypeDelegate *td = (TypeDelegate *)t1;
assert(td->next->ty == Tfunction);
tf = (TypeFunction *)(td->next);
if (sc->func && sc->func->isPure() && !tf->ispure)
if (sc->func && sc->func->isPure() && !tf->purity)
{
error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars());
}
@@ -7149,7 +7155,7 @@ Lagain:
{
Expression *e = new PtrExp(loc, e1);
t1 = ((TypePointer *)t1)->next;
if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->ispure)
if (sc->func && sc->func->isPure() && !((TypeFunction *)t1)->purity)
{
error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars());
}
@@ -7272,9 +7278,9 @@ int CallExp::checkSideEffect(int flag)
* then this expression has no side effects.
*/
Type *t = e1->type->toBasetype();
if (t->ty == Tfunction && ((TypeFunction *)t)->ispure)
if (t->ty == Tfunction && ((TypeFunction *)t)->purity)
return 0;
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->ispure)
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity)
return 0;
#endif
return 1;
@@ -8111,6 +8117,8 @@ Expression *SliceExp::semantic(Scope *sc)
goto Lerror;
}
}
else if (t == Type::terror)
goto Lerr;
else
goto Lerror;
@@ -8145,8 +8153,8 @@ Expression *SliceExp::semantic(Scope *sc)
if (t->ty == Ttuple)
{
lwr = lwr->optimize(WANTvalue);
upr = upr->optimize(WANTvalue);
lwr = lwr->optimize(WANTvalue | WANTinterpret);
upr = upr->optimize(WANTvalue | WANTinterpret);
uinteger_t i1 = lwr->toUInteger();
uinteger_t i2 = upr->toUInteger();
@@ -9033,7 +9041,26 @@ Expression *AssignExp::semantic(Scope *sc)
if (op == TOKassign)
{
Expression *e = op_overload(sc);
if (e)
if (e && e1->op == TOKindex &&
((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray)
{
// Deal with AAs (Bugzilla 2451)
// Rewrite as:
// e1 = (typeof(e2) tmp = void, tmp = e2, tmp);
Identifier *id = Lexer::uniqueId("__aatmp");
VarDeclaration *v = new VarDeclaration(loc, e2->type,
id, new VoidInitializer(NULL));
v->storage_class |= STCctfe;
Expression *de = new DeclarationExp(loc, v);
VarExp *ve = new VarExp(loc, v);
AssignExp *ae = new AssignExp(loc, ve, e2);
e = ae->op_overload(sc);
e2 = new CommaExp(loc, new CommaExp(loc, de, e), ve);
e2 = e2->semantic(sc);
}
else if (e)
return e;
}
else if (op == TOKconstruct && !refinit)
@@ -9355,6 +9382,7 @@ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
Expression *CatAssignExp::semantic(Scope *sc)
{ Expression *e;
//printf("CatAssignExp::semantic() %s\n", toChars());
e = op_overload(sc);
if (e)
return e;
@@ -10747,6 +10775,14 @@ RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
type = Type::tvoid;
}
void RemoveExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
expToCBuffer(buf, hgs, e1, PREC_primary);
buf->writestring(".remove(");
expToCBuffer(buf, hgs, e2, PREC_assign);
buf->writestring(")");
}
/************************************************************/
CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)

View File

@@ -1912,6 +1912,7 @@ struct InExp : BinExp
struct RemoveExp : BinExp
{
RemoveExp(Loc loc, Expression *e1, Expression *e2);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
elem *toElem(IRState *irs);
#endif

View File

@@ -55,6 +55,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
#if IN_GCC
v_argptr = NULL;
#endif
v_argsave = NULL;
parameters = NULL;
labtab = NULL;
overnext = NULL;
@@ -805,6 +806,7 @@ void FuncDeclaration::semantic3(Scope *sc)
{ TypeFunction *f;
VarDeclaration *argptr = NULL;
VarDeclaration *_arguments = NULL;
int nerrors = global.errors;
if (!parent)
{
@@ -903,8 +905,8 @@ void FuncDeclaration::semantic3(Scope *sc)
#if STRUCTTHISREF
thandle = thandle->addMod(type->mod);
thandle = thandle->addStorageClass(storage_class);
if (isPure())
thandle = thandle->addMod(MODconst);
//if (isPure())
//thandle = thandle->addMod(MODconst);
#else
if (storage_class & STCconst || type->isConst())
{
@@ -1005,6 +1007,20 @@ void FuncDeclaration::semantic3(Scope *sc)
}
#endif
}
if (global.params.is64bit && f->varargs && f->linkage == LINKc)
{ // Declare save area for varargs registers
Type *t = new TypeIdentifier(loc, Id::va_argsave_t);
t = t->semantic(loc, sc);
if (t == Type::terror)
error("must import std.c.stdarg to use variadic functions");
else
{
v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
v_argsave->semantic(sc2);
sc2->insert(v_argsave);
v_argsave->parent = this;
}
}
#if IN_LLVM
// LDC make sure argument type is semanticed.
@@ -1072,8 +1088,8 @@ void FuncDeclaration::semantic3(Scope *sc)
arg->ident = id = Identifier::generateId("_param_", i);
}
Type *vtype = arg->type;
if (isPure())
vtype = vtype->addMod(MODconst);
//if (isPure())
//vtype = vtype->addMod(MODconst);
VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
//printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
v->storage_class |= STCparameter;
@@ -1716,7 +1732,11 @@ void FuncDeclaration::semantic3(Scope *sc)
sc2->callSuper = 0;
sc2->pop();
}
semanticRun = PASSsemantic3done;
if (global.gag && global.errors != nerrors)
semanticRun = PASSsemanticdone; // Ensure errors get reported again
else
semanticRun = PASSsemantic3done;
}
void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -1798,6 +1818,16 @@ Statement *FuncDeclaration::mergeFrequire(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).
*/
if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done)
{
assert(fdv->scope);
fdv->semantic3(fdv->scope);
}
sf = fdv->mergeFrequire(sf);
if (fdv->fdrequire)
{
@@ -2674,11 +2704,24 @@ int FuncDeclaration::isOverloadable()
return 1; // functions can be overloaded
}
int FuncDeclaration::isPure()
enum PURE FuncDeclaration::isPure()
{
//printf("FuncDeclaration::isPure() '%s'\n", toChars());
assert(type->ty == Tfunction);
return ((TypeFunction *)this->type)->ispure;
TypeFunction *tf = (TypeFunction *)type;
enum PURE purity = tf->purity;
if (purity == PUREfwdref)
tf->purityLevel();
if (purity > PUREweak && needThis())
{ // The attribute of the 'this' reference affects purity strength
if (type->mod & (MODimmutable | MODwild))
;
else if (type->mod & MODconst && purity >= PUREconst)
purity = PUREconst;
else
purity = PUREweak;
}
return purity;
}
int FuncDeclaration::isSafe()

View File

@@ -1,9 +1,10 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/idgen.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -295,6 +296,10 @@ Msgtable msgtable[] =
{ "DllMain" },
{ "tls_get_addr", "___tls_get_addr" },
// varargs implementation
{ "va_argsave_t", "__va_argsave_t" },
{ "va_argsave", "__va_argsave" },
// Builtin functions
{ "std" },
{ "math" },

View File

@@ -564,13 +564,13 @@ Expression *ReturnStatement::interpret(InterState *istate)
}
#endif
#if LOG
Expression *e = exp->interpret(istate);
printf("e = %p\n", e);
if (e == EXP_CANT_INTERPRET)
return e;
// Convert lvalues into rvalues (See Bugzilla 4825 for rationale)
if (e->op == TOKvar)
e = e->interpret(istate);
return e;
#else
return exp->interpret(istate);
#endif
}
Expression *BreakStatement::interpret(InterState *istate)
@@ -2710,21 +2710,32 @@ Expression *CallExp::interpret(InterState *istate)
Expression * pe = ((PtrExp*)ecall)->e1;
if (pe->op == TOKvar) {
VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration();
if (vd && vd->value && vd->value->op==TOKsymoff)
if (vd && vd->value && vd->value->op == TOKsymoff)
fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration();
else {
ecall = vd->value->interpret(istate);
if (ecall->op==TOKsymoff)
if (ecall->op == TOKsymoff)
fd = ((SymOffExp *)ecall)->var->isFuncDeclaration();
}
}
else
ecall = ((PtrExp*)ecall)->e1->interpret(istate);
}
if (ecall == EXP_CANT_INTERPRET)
return ecall;
if (ecall->op == TOKindex)
ecall = e1->interpret(istate);
{ ecall = e1->interpret(istate);
if (ecall == EXP_CANT_INTERPRET)
return ecall;
}
if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration())
ecall = e1->interpret(istate);
{ ecall = e1->interpret(istate);
if (ecall == EXP_CANT_INTERPRET)
return ecall;
}
if (ecall->op == TOKdotvar)
{ // Calling a member function

View File

@@ -4,6 +4,7 @@
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/mars.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -99,7 +100,7 @@ Global::Global()
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.049";
version = "v2.050";
#if IN_LLVM
ldc_version = "LDC trunk";
llvm_version = "LLVM 2.8";
@@ -237,6 +238,8 @@ void halt()
#endif
}
extern signed char tyalignsize[];
/***********************************
* Parse and append contents of environment variable envvar
* to argc and argv[].

View File

@@ -4,6 +4,7 @@
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/mtype.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -3480,7 +3481,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
return this;
}
dinteger_t d1 = dim->toInteger();
dim = dim->castTo(sc, tsize_t);
dim = dim->implicitCastTo(sc, tsize_t);
dim = dim->optimize(WANTvalue);
dinteger_t d2 = dim->toInteger();
@@ -4585,7 +4586,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e
this->linkage = linkage;
this->inuse = 0;
this->isnothrow = false;
this->ispure = false;
this->purity = PUREimpure;
this->isproperty = false;
this->isref = false;
this->fargs = NULL;
@@ -4594,7 +4595,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e
this->funcdecl = NULL;
#endif
if (stc & STCpure)
this->ispure = true;
this->purity = PUREfwdref;
if (stc & STCnothrow)
this->isnothrow = true;
if (stc & STCproperty)
@@ -4616,7 +4617,7 @@ Type *TypeFunction::syntaxCopy()
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
t->mod = mod;
t->isnothrow = isnothrow;
t->ispure = ispure;
t->purity = purity;
t->isproperty = isproperty;
t->isref = isref;
t->trust = trust;
@@ -4750,7 +4751,7 @@ Lcovariant:
/* Can convert pure to impure, and nothrow to throw
*/
if (!t1->ispure && t2->ispure)
if (!t1->purity && t2->purity)
goto Lnotcovariant;
if (!t1->isnothrow && t2->isnothrow)
@@ -4802,9 +4803,9 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
assert(0);
}
buf->writeByte(mc);
if (ispure || isnothrow || isproperty || isref || trust)
if (purity || isnothrow || isproperty || isref || trust)
{
if (ispure)
if (purity)
buf->writestring("Na");
if (isnothrow)
buf->writestring("Nb");
@@ -4876,7 +4877,7 @@ void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs
buf->writeByte(' ');
}
if (ispure)
if (purity)
buf->writestring("pure ");
if (isnothrow)
buf->writestring("nothrow ");
@@ -4976,7 +4977,7 @@ void TypeFunction::attributesToCBuffer(OutBuffer *buf, int mod)
{
modToBuffer(buf);
}
if (ispure)
if (purity)
buf->writestring(" pure");
if (isnothrow)
buf->writestring(" nothrow");
@@ -5028,7 +5029,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
if (sc->stc & STCpure)
tf->ispure = TRUE;
tf->purity = PUREfwdref;
if (sc->stc & STCnothrow)
tf->isnothrow = TRUE;
if (sc->stc & STCref)
@@ -5205,6 +5206,84 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
return tf;
}
/********************************************
* Do this lazily, as the parameter types might be forward referenced.
*/
void TypeFunction::purityLevel()
{
TypeFunction *tf = this;
if (tf->purity == PUREfwdref)
{ /* Evaluate what kind of purity based on the modifiers for the parameters
*/
tf->purity = PUREstrong; // assume strong until something weakens it
if (tf->parameters)
{
size_t dim = Parameter::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
{ Parameter *fparam = Parameter::getNth(tf->parameters, i);
if (fparam->storageClass & STClazy)
{
/* We could possibly allow this by doing further analysis on the
* lazy parameter to see if it's pure.
*/
error(0, "cannot have lazy parameters to a pure function");
}
if (fparam->storageClass & STCout)
{
tf->purity = PUREweak;
break;
}
if (!fparam->type)
continue;
if (fparam->storageClass & STCref)
{
if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild)))
{ tf->purity = PUREweak;
break;
}
if (fparam->type->mod & MODconst)
{ tf->purity = PUREconst;
continue;
}
}
Type *t = fparam->type->toBasetype();
if (!t->hasPointers())
continue;
if (t->mod & (MODimmutable | MODwild))
continue;
/* The rest of this is too strict; fix later.
* For example, the only pointer members of a struct may be immutable,
* which would maintain strong purity.
*/
if (t->mod & MODconst)
{ tf->purity = PUREconst;
continue;
}
Type *tn = t->nextOf();
if (tn)
{ tn = tn->toBasetype();
if (tn->ty == Tpointer || tn->ty == Tarray)
{ /* Accept immutable(T)* and immutable(T)[] as being strongly pure
*/
if (tn->mod & (MODimmutable | MODwild))
continue;
if (tn->mod & MODconst)
{ tf->purity = PUREconst;
continue;
}
}
}
/* Should catch delegates and function pointers, and fold in their purity
*/
tf->purity = PUREweak; // err on the side of too strict
break;
}
}
}
}
/********************************
* 'args' are being matched to function 'this'
* Determine match level.
@@ -5425,7 +5504,7 @@ bool TypeFunction::parameterEscapes(Parameter *p)
if (p->storageClass & (STCscope | STClazy))
return FALSE;
if (ispure)
if (purity)
{ /* With pure functions, we need only be concerned if p escapes
* via any return statement.
*/
@@ -6039,7 +6118,7 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc)
printf("2: ");
#endif
error(loc, "%s is used as a type", toChars());
t = tvoid;
t = terror;
}
return t;
}
@@ -7979,11 +8058,11 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc)
TypeTuple *tt = (TypeTuple *)tbn;
lwr = semanticLength(sc, tbn, lwr);
lwr = lwr->optimize(WANTvalue);
lwr = lwr->optimize(WANTvalue | WANTinterpret);
uinteger_t i1 = lwr->toUInteger();
upr = semanticLength(sc, tbn, upr);
upr = upr->optimize(WANTvalue);
upr = upr->optimize(WANTvalue | WANTinterpret);
uinteger_t i2 = upr->toUInteger();
if (!(i1 <= i2 && i2 <= tt->arguments->dim))
@@ -8023,11 +8102,11 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
sc = sc->push(sym);
lwr = lwr->semantic(sc);
lwr = lwr->optimize(WANTvalue);
lwr = lwr->optimize(WANTvalue | WANTinterpret);
uinteger_t i1 = lwr->toUInteger();
upr = upr->semantic(sc);
upr = upr->optimize(WANTvalue);
upr = upr->optimize(WANTvalue | WANTinterpret);
uinteger_t i2 = upr->toUInteger();
sc = sc->pop();

View File

@@ -589,6 +589,15 @@ enum TRUST
TRUSTsafe = 3, // @safe
};
enum PURE
{
PUREimpure = 0, // not pure at all
PUREweak = 1, // no mutable globals are read or written
PUREconst = 2, // parameters are values or const
PUREstrong = 3, // parameters are values or immutable
PUREfwdref = 4, // it's pure, but not known which level yet
};
struct TypeFunction : TypeNext
{
// .next is the return type
@@ -597,11 +606,11 @@ struct TypeFunction : TypeNext
int varargs; // 1: T t, ...) style for variable number of arguments
// 2: T t ...) style for variable number of arguments
bool isnothrow; // true: nothrow
bool ispure; // true: pure
bool isproperty; // can be called without parentheses
bool isref; // true: returns a reference
enum LINK linkage; // calling convention
enum TRUST trust; // level of trust
enum PURE purity; // PURExxxx
Expressions *fargs; // function arguments
int inuse;
@@ -609,6 +618,7 @@ struct TypeFunction : TypeNext
TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc = 0);
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);

View File

@@ -251,7 +251,7 @@ Expression *UnaExp::op_overload(Scope *sc)
((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
}
@@ -294,7 +294,7 @@ Expression *UnaExp::op_overload(Scope *sc)
((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
}
@@ -356,7 +356,7 @@ Expression *UnaExp::op_overload(Scope *sc)
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
#endif
@@ -391,7 +391,7 @@ Expression *ArrayExp::op_overload(Scope *sc)
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
}
@@ -438,7 +438,7 @@ Expression *CastExp::op_overload(Scope *sc)
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
}
@@ -683,7 +683,8 @@ L1:
#if DMDV2
// Try alias this on first operand
if (ad1 && ad1->aliasthis)
if (ad1 && ad1->aliasthis &&
!(op == TOKassign && ad2 && ad1 == ad2)) // See Bugzilla 2943
{
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
@@ -691,12 +692,16 @@ L1:
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
// Try alias this on second operand
if (ad2 && ad2->aliasthis)
if (ad2 && ad2->aliasthis &&
/* Bugzilla 2943: make sure that when we're copying the struct, we don't
* just copy the alias this member
*/
!(op == TOKassign && ad1 && ad1 == ad2))
{
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
@@ -704,7 +709,7 @@ L1:
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
#endif
@@ -860,7 +865,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
@@ -873,7 +878,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
@@ -954,7 +959,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
}
@@ -998,7 +1003,7 @@ Expression *BinAssignExp::op_overload(Scope *sc)
((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
}
@@ -1099,7 +1104,7 @@ L1:
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
@@ -1113,7 +1118,7 @@ L1:
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->semantic(sc);
e = e->trySemantic(sc);
return e;
}
#endif

View File

@@ -138,7 +138,15 @@ Expression *fromConstInitializer(int result, Expression *e1)
int fwdref = (v && !v->originalType && v->scope);
e = expandVar(result, v);
if (e)
{ if (e->type != e1->type && e1->type && e1->type->ty != Tident)
{
// If it is a comma expression involving a declaration, we mustn't
// perform a copy -- we'd get two declarations of the same variable.
// See bugzilla 4465.
if (e->op == TOKcomma && ((CommaExp *)e)->e1->op == TOKdeclaration)
e = e1;
else
if (e->type != e1->type && e1->type && e1->type->ty != Tident)
{ // Type 'paint' operation
e = e->copy();
e->type = e1->type;

View File

@@ -2413,12 +2413,6 @@ Type *Parser::parseBasicType2(Type *t)
t = new TypeDArray(t); // []
nextToken();
}
else if (token.value == TOKnew && peekNext() == TOKrbracket)
{
t = new TypeNewArray(t); // [new]
nextToken();
nextToken();
}
else if (isDeclaration(&token, 0, TOKrbracket, NULL))
{ // It's an associative array declaration
@@ -2498,14 +2492,39 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters *
break;
case TOKlparen:
/* Parse things with parentheses around the identifier, like:
* int (*ident[3])[]
* although the D style would be:
* int[]*[3] ident
if (peekNext() == TOKmul || // like: T (*fp)();
peekNext() == TOKlparen // like: T ((*fp))();
/* || peekNext() == TOKlbracket*/) // like: T ([] a)
{
/* Parse things with parentheses around the identifier, like:
* int (*ident[3])[]
* although the D style would be:
* int[]*[3] ident
*/
if (!global.params.useDeprecated)
{
error("C-style function pointer and pointer to array syntax is deprecated. Use 'function' to declare function pointers");
}
nextToken();
ts = parseDeclarator(t, pident);
check(TOKrparen);
break;
}
ts = t;
{
Token *peekt = &token;
/* Completely disallow C-style things like:
* T (a);
* Improve error messages for the common bug of a missing return type
* by looking to see if (a) looks like a parameter list.
*/
nextToken();
ts = parseDeclarator(t, pident);
check(TOKrparen);
if (isParameters(&peekt)) {
error("function declaration without return type. "
"(Note that constructors are always named 'this')");
}
else
error("unexpected ( in declarator");
}
break;
default:
@@ -2533,12 +2552,6 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters *
ta = new TypeDArray(t); // []
nextToken();
}
else if (token.value == TOKnew && peekNext() == TOKrbracket)
{
t = new TypeNewArray(t); // [new]
nextToken();
nextToken();
}
else if (isDeclaration(&token, 0, TOKrbracket, NULL))
{ // It's an associative array
@@ -4457,11 +4470,6 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
{
t = peek(t);
}
else if (t->value == TOKnew && peek(t)->value == TOKrbracket)
{
t = peek(t);
t = peek(t);
}
else if (isDeclaration(t, 0, TOKrbracket, &t))
{ // It's an associative array declaration
t = peek(t);
@@ -6273,37 +6281,53 @@ void initPrecedence()
precedence[TOKsuper] = PREC_primary;
precedence[TOKint64] = PREC_primary;
precedence[TOKfloat64] = PREC_primary;
precedence[TOKcomplex80] = PREC_primary;
precedence[TOKnull] = PREC_primary;
precedence[TOKstring] = PREC_primary;
precedence[TOKarrayliteral] = PREC_primary;
precedence[TOKassocarrayliteral] = PREC_primary;
#if DMDV2
precedence[TOKfile] = PREC_primary;
precedence[TOKline] = PREC_primary;
#endif
precedence[TOKtypeid] = PREC_primary;
precedence[TOKis] = PREC_primary;
precedence[TOKassert] = PREC_primary;
precedence[TOKhalt] = PREC_primary;
precedence[TOKtemplate] = PREC_primary;
precedence[TOKdsymbol] = PREC_primary;
precedence[TOKfunction] = PREC_primary;
precedence[TOKvar] = PREC_primary;
precedence[TOKsymoff] = PREC_primary;
precedence[TOKstructliteral] = PREC_primary;
precedence[TOKarraylength] = PREC_primary;
precedence[TOKremove] = PREC_primary;
precedence[TOKtuple] = PREC_primary;
#if DMDV2
precedence[TOKtraits] = PREC_primary;
precedence[TOKdefault] = PREC_primary;
precedence[TOKoverloadset] = PREC_primary;
#endif
// post
precedence[TOKdotti] = PREC_primary;
precedence[TOKdot] = PREC_primary;
precedence[TOKdottd] = PREC_primary;
precedence[TOKdotexp] = PREC_primary;
precedence[TOKdottype] = PREC_primary;
// precedence[TOKarrow] = PREC_primary;
precedence[TOKplusplus] = PREC_primary;
precedence[TOKminusminus] = PREC_primary;
#if DMDV2
precedence[TOKpreplusplus] = PREC_primary;
precedence[TOKpreminusminus] = PREC_primary;
#endif
precedence[TOKcall] = PREC_primary;
precedence[TOKslice] = PREC_primary;
precedence[TOKarray] = PREC_primary;
precedence[TOKindex] = PREC_primary;
precedence[TOKdelegate] = PREC_unary;
precedence[TOKaddress] = PREC_unary;
precedence[TOKstar] = PREC_unary;
precedence[TOKneg] = PREC_unary;
@@ -6313,14 +6337,16 @@ void initPrecedence()
precedence[TOKtilde] = PREC_unary;
precedence[TOKdelete] = PREC_unary;
precedence[TOKnew] = PREC_unary;
precedence[TOKnewanonclass] = PREC_unary;
precedence[TOKcast] = PREC_unary;
#if DMDV2
precedence[TOKpow] = PREC_pow;
#endif
precedence[TOKmul] = PREC_mul;
precedence[TOKdiv] = PREC_mul;
precedence[TOKmod] = PREC_mul;
precedence[TOKpow] = PREC_mul;
precedence[TOKadd] = PREC_add;
precedence[TOKmin] = PREC_add;
@@ -6380,7 +6406,9 @@ void initPrecedence()
precedence[TOKmulass] = PREC_assign;
precedence[TOKdivass] = PREC_assign;
precedence[TOKmodass] = PREC_assign;
#if DMDV2
precedence[TOKpowass] = PREC_assign;
#endif
precedence[TOKshlass] = PREC_assign;
precedence[TOKshrass] = PREC_assign;
precedence[TOKushrass] = PREC_assign;

View File

@@ -4286,6 +4286,9 @@ int TryCatchStatement::blockExit()
for (size_t i = 0; i < catches->dim; i++)
{
Catch *c = (Catch *)catches->data[i];
if (c->type == Type::terror)
continue;
catchresult |= c->blockExit();
/* If we're catching Object, then there is no throwing
@@ -4361,7 +4364,12 @@ void Catch::semantic(Scope *sc)
type = new TypeIdentifier(0, Id::Object);
type = type->semantic(loc, sc);
if (!type->toBasetype()->isClassHandle())
error(loc, "can only catch class objects, not '%s'", type->toChars());
{
if (type != Type::terror)
{ error(loc, "can only catch class objects, not '%s'", type->toChars());
type = Type::terror;
}
}
else if (ident)
{
var = new VarDeclaration(loc, type, ident, NULL);

View File

@@ -1,8 +1,9 @@
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/staticassert.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -55,6 +56,8 @@ void StaticAssert::semantic2(Scope *sc)
//printf("StaticAssert::semantic2() %s\n", toChars());
e = exp->semantic(sc);
if (e->op == TOKerror)
return;
e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(FALSE))
{

View File

@@ -226,11 +226,14 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
if (!isUnionDeclaration())
sc->offset = ofs;
#endif
if (sc->structalign < memalignsize)
if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16)
/* Not sure how to handle this */
;
else if (sc->structalign < memalignsize)
memalignsize = sc->structalign;
if (alignsize < memalignsize)
alignsize = memalignsize;
//printf("\talignsize = %d\n", alignsize);
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
v->storage_class |= STCfield;
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);

View File

@@ -894,6 +894,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
ScopeDsymbol *paramsym = new ScopeDsymbol();
paramsym->parent = scope->parent;
Scope *paramscope = scope->push(paramsym);
paramscope->stc = 0;
TemplateTupleParameter *tp = isVariadic();
int tp_is_declared = 0;

View File

@@ -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/ldc/cstdarg.di druntime/import/ldc/cstdarg.di
--- druntime-orig/import/ldc/cstdarg.di 1970-01-01 03:00:00.000000000 +0300
+++ druntime/import/ldc/cstdarg.di 2010-09-30 22:10:37.000000000 +0400
+++ druntime/import/ldc/cstdarg.di 2010-11-05 13:57:24.000000000 +0300
@@ -0,0 +1,29 @@
+/*
+ * vararg support for extern(C) functions
@@ -33,7 +33,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
+ void va_copy(va_list dst, va_list src);
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-10-30 19:17:52.538555000 +0400
+++ druntime/import/ldc/intrinsics.di 2010-11-04 17:49:07.000000000 +0300
@@ -0,0 +1,359 @@
+/*
+ * This module holds declarations to LLVM intrinsics.
@@ -396,7 +396,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-09-30 22:10:37.000000000 +0400
+++ druntime/import/ldc/llvmasm.di 2010-11-04 17:49:07.000000000 +0300
@@ -0,0 +1,17 @@
+module ldc.llvmasm;
+
@@ -417,7 +417,7 @@ 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/ldc/vararg.d druntime/import/ldc/vararg.d
--- druntime-orig/import/ldc/vararg.d 1970-01-01 03:00:00.000000000 +0300
+++ druntime/import/ldc/vararg.d 2010-09-30 22:10:37.000000000 +0400
+++ druntime/import/ldc/vararg.d 2010-11-05 13:57:12.000000000 +0300
@@ -0,0 +1,43 @@
+/*
+ * This module holds the implementation of special vararg templates for D style var args.
@@ -463,18 +463,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
+ dst = src;
+}
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-09-03 12:28:52.000000000 +0400
+++ druntime/import/object.di 2010-10-27 00:22:27.444925001 +0400
@@ -130,7 +130,7 @@
Interface[] interfaces;
TypeInfo_Class base;
void* destructor;
- void(*classInvariant)(Object);
+ void function(Object) classInvariant;
uint m_flags;
// 1: // is IUnknown or is derived from IUnknown
// 2: // has no possible pointers into GC memory
@@ -140,7 +140,7 @@
--- druntime-orig/import/object.di 2010-10-13 10:37:58.000000000 +0400
+++ druntime/import/object.di 2010-11-07 19:11:32.000000000 +0300
@@ -142,7 +142,7 @@
// 32: // has typeinfo member
void* deallocator;
OffsetTypeInfo[] m_offTi;
@@ -483,7 +474,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
const(MemberInfo[]) function(string) xgetMembers;
static TypeInfo_Class find(in char[] classname);
@@ -179,7 +179,7 @@
@@ -189,7 +189,7 @@
class TypeInfo_Const : TypeInfo
{
@@ -492,7 +483,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
}
class TypeInfo_Invariant : TypeInfo_Const
@@ -288,7 +288,6 @@
@@ -298,7 +298,6 @@
interface TraceInfo
{
int opApply(scope int delegate(ref char[]));
@@ -501,8 +492,8 @@ 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/src/core/atomic.d druntime/src/core/atomic.d
--- druntime-orig/src/core/atomic.d 2010-09-03 12:28:52.000000000 +0400
+++ druntime/src/core/atomic.d 2010-10-05 15:55:10.893150001 +0400
--- 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 @@
return false;
}
@@ -636,7 +627,7 @@ 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-10-26 16:47:04.036925000 +0400
+++ druntime/src/core/stdc/math.d 2010-11-04 17:49:07.000000000 +0300
@@ -17,6 +17,7 @@
extern (C):
@@ -647,7 +638,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
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/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-10-26 19:26:03.996925001 +0400
+++ druntime/src/core/stdc/stdlib.d 2010-11-04 17:49:07.000000000 +0300
@@ -92,3 +92,13 @@
{
void* alloca(size_t size); // non-standard
@@ -664,7 +655,7 @@ 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/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-10-01 20:49:51.268892001 +0400
+++ druntime/src/gc/gcbits.d 2010-11-04 17:49:07.000000000 +0300
@@ -26,6 +26,10 @@
{
version = bitops;
@@ -677,8 +668,8 @@ 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-08-27 01:23:26.000000000 +0400
+++ druntime/src/gc/gcx.d 2010-10-07 22:27:41.879253001 +0400
--- 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 @@
@@ -906,18 +897,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-09-03 12:28:52.000000000 +0400
+++ druntime/src/object_.d 2010-10-26 19:27:09.224925000 +0400
@@ -1073,7 +1073,7 @@
abstract class MemberInfo
{
- string name();
+ string name() { return ""; }; // LDC: FIXME:
}
class MemberInfo_field : MemberInfo
@@ -1663,7 +1663,6 @@
--- druntime-orig/src/object_.d 2010-10-13 10:37:58.000000000 +0400
+++ druntime/src/object_.d 2010-11-07 19:11:32.000000000 +0300
@@ -1754,7 +1754,6 @@
{
int len = 0;
ModuleReference *mr;
@@ -925,7 +907,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];
@@ -2025,7 +2024,6 @@
@@ -2116,7 +2115,6 @@
_d_monitor_create(h);
m = getMonitor(h);
}
@@ -933,7 +915,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)
@@ -2124,7 +2122,7 @@
@@ -2215,7 +2213,7 @@
size_t _aaLen(void* p);
void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...);
void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...);
@@ -942,7 +924,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);
@@ -2169,7 +2167,7 @@
@@ -2260,7 +2258,7 @@
return *cast(Key[]*) &a;
}
@@ -953,7 +935,7 @@ 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/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 2010-10-29 10:48:36.165035001 +0400
+++ druntime/src/rt/aaA.d 2010-11-05 11:43:19.000000000 +0300
@@ -204,7 +204,7 @@
* Add entry for key if it is not already there.
*/
@@ -1017,7 +999,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
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-10-29 11:49:52.065035002 +0400
+++ druntime/src/rt/adi.d 2010-11-04 17:49:07.000000000 +0300
@@ -35,6 +35,8 @@
extern (C) void gc_free( void* p );
}
@@ -1181,7 +1163,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
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-10-08 22:31:50.989547000 +0400
+++ druntime/src/rt/alloca.d 2010-11-04 17:49:07.000000000 +0300
@@ -12,6 +12,9 @@
*/
module rt.alloca;
@@ -1200,7 +1182,7 @@ 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/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-10-30 19:18:05.322555000 +0400
+++ druntime/src/rt/arrayInit.d 2010-11-04 17:49:07.000000000 +0300
@@ -0,0 +1,150 @@
+private import ldc.intrinsics;
+
@@ -1343,8 +1325,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
+// slice copy when assertions are enabled
+void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen)
+{
+ assert(dst);
+ assert(src);
+ if (dstlen != 0) assert(dst);
+ if (dstlen != 0) assert(src);
+ if (dstlen != srclen)
+ throw new Exception("lengths don't match for array copy");
+ else if (dst+dstlen <= src || src+srclen <= dst)
@@ -1354,7 +1336,7 @@ 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/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 2010-10-29 10:43:18.469035000 +0400
+++ druntime/src/rt/ldc_eh.d 2010-11-04 17:49:07.000000000 +0300
@@ -0,0 +1,428 @@
+/**
+ * This module contains functions and structures required for
@@ -1785,8 +1767,8 @@ 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-08-05 05:39:06.000000000 +0400
+++ druntime/src/rt/lifetime.d 2010-10-29 10:40:39.533035001 +0400
--- druntime-orig/src/rt/lifetime.d 2010-10-12 07:07:36.000000000 +0400
+++ druntime/src/rt/lifetime.d 2010-11-07 19:12:13.000000000 +0300
@@ -92,6 +92,18 @@
return gc_malloc(sz);
}
@@ -1806,52 +1788,25 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
/**
*
@@ -670,7 +682,7 @@
* ti is the type of the resulting array, or pointer to element.
* (For when the array is initialized to 0)
*/
-extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length)
+extern (C) void[] _d_newarrayT(TypeInfo ti, size_t length)
{
ulong result;
auto size = ti.next.tsize(); // array element size
@@ -702,7 +714,7 @@
__setArrayAllocLength(info, size, isshared);
result = cast(ulong)length + (cast(ulong)cast(size_t)arrstart << 32);
result = arrstart[0..length];
}
- return result;
+ return *cast(void[]*)&result;
Loverflow:
onOutOfMemoryError();
@@ -711,7 +723,7 @@
/**
* For when the array has a non-zero initializer.
*/
-extern (C) ulong _d_newarrayiT(TypeInfo ti, size_t length)
+extern (C) void[] _d_newarrayiT(TypeInfo ti, size_t length)
{
ulong result;
auto size = ti.next.tsize(); // array element size
@@ -764,7 +776,7 @@
__setArrayAllocLength(info, size, isshared);
result = cast(ulong)length + (cast(ulong)cast(uint)arrstart << 32);
result = arrstart[0..length];
}
- return result;
+ return *cast(void[]*)&result;
Loverflow:
onOutOfMemoryError();
@@ -773,7 +785,7 @@
/**
*
*/
-extern (C) ulong _d_newarraymT(TypeInfo ti, int ndims, ...)
+extern (C) void[] _d_newarraymT(TypeInfo ti, int ndims, ...)
{
ulong result;
@@ -823,14 +835,14 @@
@@ -823,7 +835,7 @@
}
va_end(q);
}
@@ -1860,14 +1815,6 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
}
/**
*
*/
-extern (C) ulong _d_newarraymiT(TypeInfo ti, int ndims, ...)
+extern (C) void[] _d_newarraymiT(TypeInfo ti, int ndims, ...)
{
ulong result;
@@ -881,7 +893,7 @@
}
va_end(q);
@@ -1961,9 +1908,638 @@ 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/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 @@
*/
module rt.memory;
+version(DMD)
+{
private
{
@@ -230,3 +232,616 @@
static assert( false, "Operating system not supported." );
}
}
+
+}
+else version(LDC)
+{
+
+version = GC_Use_Dynamic_Ranges;
+
+version(darwin)
+{
+ version = GC_Use_Data_Dyld;
+ version = GC_Use_Dynamic_Ranges;
+ import core.stdc.config : c_ulong;
+}
+else version(Posix)
+{
+ version = GC_Use_Data_Proc_Maps;
+}
+else version(solaris)
+{
+ version = GC_Use_Data_Proc_Maps;
+}
+else version(freebsd)
+{
+ version = GC_Use_Data_Proc_Maps;
+}
+
+
+version(GC_Use_Data_Proc_Maps)
+{
+ version(Posix) {} else {
+ static assert(false, "Proc Maps only supported on Posix systems");
+ }
+ import core.stdc.string : memmove;
+ import core.sys.posix.fcntl : open, O_RDONLY;
+ import core.sys.posix.unistd : close, read;
+
+ version = GC_Use_Dynamic_Ranges;
+}
+
+private
+{
+ version( linux )
+ {
+ //version = SimpleLibcStackEnd;
+
+ version( SimpleLibcStackEnd )
+ {
+ extern (C) extern void* __libc_stack_end;
+ }
+ else
+ {
+ import core.sys.posix.dlfcn;
+ }
+ }
+ else version(freebsd)
+ {
+ //version = SimpleLibcStackEnd;
+
+ version( SimpleLibcStackEnd )
+ {
+ extern (C) extern void* __libc_stack_end;
+ }
+ else
+ {
+ import core.sys.posix.dlfcn;
+ }
+ }
+ pragma(intrinsic, "llvm.frameaddress")
+ {
+ void* llvm_frameaddress(uint level=0);
+ }
+ extern (C) void gc_addRange( void* p, size_t sz );
+ extern (C) void gc_removeRange( void* p );
+}
+
+
+/**
+ *
+ */
+
+version( solaris ) {
+ version(X86_64) {
+ extern (C) void* _userlimit;
+ }
+}
+
+extern (C) void* rt_stackBottom()
+{
+ version( Win32 )
+ {
+ void* bottom;
+ asm
+ {
+ mov EAX, FS:4;
+ mov bottom, EAX;
+ }
+ return bottom;
+ }
+ else version( linux )
+ {
+ version( SimpleLibcStackEnd )
+ {
+ return __libc_stack_end;
+ }
+ else
+ {
+ // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
+ static void** libc_stack_end;
+
+ if( libc_stack_end == libc_stack_end.init )
+ {
+ void* handle = dlopen( null, RTLD_NOW );
+ libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
+ dlclose( handle );
+ }
+ return *libc_stack_end;
+ }
+ }
+ else version( freebsd )
+ {
+ version( SimpleLibcStackEnd )
+ {
+ return __libc_stack_end;
+ }
+ else
+ {
+ // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
+ static void** libc_stack_end;
+
+ if( libc_stack_end == libc_stack_end.init )
+ {
+ void* handle = dlopen( null, RTLD_NOW );
+ libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
+ dlclose( handle );
+ }
+ return *libc_stack_end;
+ }
+ }
+ else version( darwin )
+ {
+ // darwin has a fixed stack bottom
+ version( D_LP64 )
+ return cast(void*) 0x7fff5fc00000;
+ else
+ return cast(void*) 0xc0000000;
+ }
+ else version( solaris )
+ {
+ version(X86_64) {
+ return _userlimit;
+ }
+ else {
+ // <sys/vmparam.h>
+ return cast(void*) 0x8048000;
+ }
+ }
+ else
+ {
+ static assert( false, "Operating system not supported." );
+ }
+}
+
+
+/**
+ *
+ */
+extern (C) void* rt_stackTop()
+{
+ version( D_InlineAsm_X86 )
+ {
+ asm
+ {
+ naked;
+ mov EAX, ESP;
+ ret;
+ }
+ }
+ else
+ {
+ return llvm_frameaddress();
+ }
+}
+
+
+private
+{
+ version( Win32 )
+ {
+ extern (C)
+ {
+ extern __gshared int _data_start__;
+ extern __gshared int _bss_end__;
+ }
+
+ alias _data_start__ Data_Start;
+ alias _bss_end__ Data_End;
+ }
+ else version( linux )
+ {
+ extern (C)
+ {
+ extern __gshared int _data;
+ extern __gshared int __data_start;
+ extern __gshared int _end;
+ extern __gshared int _data_start__;
+ extern __gshared int _data_end__;
+ extern __gshared int _bss_start__;
+ extern __gshared int _bss_end__;
+ extern __gshared int __fini_array_end;
+ }
+
+ alias __data_start Data_Start;
+ alias _end Data_End;
+ }
+ else version( freebsd )
+ {
+ extern (C)
+ {
+ extern __gshared char etext;
+ extern __gshared int _end;
+ }
+
+ alias etext Data_Start;
+ alias _end Data_End;
+ }
+ else version( solaris )
+ {
+ extern(C)
+ {
+ extern __gshared int _environ;
+ extern __gshared int _end;
+ }
+
+ alias _environ Data_Start;
+ alias _end Data_End;
+ }
+
+ version( GC_Use_Dynamic_Ranges )
+ {
+ private import core.stdc.stdlib;
+ }
+
+ void* dataStart, dataEnd;
+}
+
+
+void initStaticDataGC()
+{
+
+ static const int S = (void*).sizeof;
+
+ // Can't assume the input addresses are word-aligned
+ static void* adjust_up( void* p )
+ {
+ return p + ((S - (cast(size_t)p & (S-1))) & (S-1)); // cast ok even if 64-bit
+ }
+
+ static void * adjust_down( void* p )
+ {
+ return p - (cast(size_t) p & (S-1));
+ }
+
+ version( Win32 )
+ {
+ dataStart = adjust_up( &Data_Start );
+ dataEnd = adjust_down( &Data_End );
+ }
+ else version(linux)
+ {
+ dataStart = adjust_up( &Data_Start );
+ dataEnd = adjust_down( &Data_End );
+ }
+ else version( freebsd )
+ {
+ dataStart = adjust_up( &Data_Start );
+ dataEnd = adjust_down( &Data_End );
+ }
+ else version(solaris)
+ {
+ dataStart = adjust_up( &Data_Start );
+ dataEnd = adjust_down( &Data_End );
+ }
+ else version(GC_Use_Data_Dyld)
+ {
+ _d_dyld_start();
+ }
+ else
+ {
+ static assert( false, "Operating system not supported." );
+ }
+
+ version( GC_Use_Data_Proc_Maps )
+ {
+ parseDataProcMaps();
+ }
+ gc_addRange(dataStart, dataEnd - dataStart);
+}
+
+version( GC_Use_Data_Proc_Maps )
+{
+version(solaris)
+{
+ typedef long offset_t;
+ enum : uint { PRMAPSZ = 64, MA_WRITE = 0x02 }
+ extern(C)
+ {
+ struct prmap {
+ uintptr_t pr_vaddr; /* virtual address of mapping */
+ size_t pr_size; /* size of mapping in bytes */
+ char[PRMAPSZ] pr_mapname; /* name in /proc/<pid>/object */
+ private offset_t pr_offset; /* offset into mapped object, if any */
+ int pr_mflags; /* protection and attribute flags (see below) */
+ int pr_pagesize; /* pagesize (bytes) for this mapping */
+ int pr_shmid; /* SysV shmid, -1 if not SysV shared memory */
+
+ private int[1] pr_filler;
+ }
+ }
+
+ debug (ProcMaps) extern (C) int printf(char*, ...);
+
+ void parseDataProcMaps()
+ {
+ debug (ProcMaps) printf("initStaticDataPtrs()\n");
+ // http://docs.sun.com/app/docs/doc/816-5174/proc-4
+ prmap pr;
+
+ int fd = open("/proc/self/map", O_RDONLY);
+ scope (exit) close(fd);
+
+ while (prmap.sizeof == read(fd, &pr, prmap.sizeof))
+ if (pr.pr_mflags & MA_WRITE)
+ {
+ void* start = cast(void*) pr.pr_vaddr;
+ void* end = cast(void*)(pr.pr_vaddr + pr.pr_size);
+ debug (ProcMaps) printf(" vmem at %p - %p with size %d bytes\n", start, end, pr.pr_size);
+
+ // Exclude stack and dataStart..dataEnd
+ if ( ( !dataEnd ||
+ !( dataStart >= start && dataEnd <= end ) ) &&
+ !( &pr >= start && &pr < end ) )
+ {
+ // we already have static data from this region. anything else
+ // is heap (%% check)
+ debug (ProcMaps) printf(" Adding map range %p - %p\n", start, end);
+ gc_addRange(start, end - start);
+ }
+ }
+ }
+}
+else
+{
+ const int S = (void*).sizeof;
+
+ // TODO: This could use cleanup!
+ void parseDataProcMaps()
+ {
+ // TODO: Exclude zero-mapped regions
+
+ int fd = open("/proc/self/maps", O_RDONLY);
+ ptrdiff_t count; // %% need to configure ret for read..
+ char buf[2024];
+ char* p;
+ char* e;
+ char* s;
+ void* start;
+ void* end;
+
+ p = buf.ptr;
+ if (fd != -1)
+ {
+ while ( (count = read(fd, p, buf.sizeof - (p - buf.ptr))) > 0 )
+ {
+ e = p + count;
+ p = buf.ptr;
+ while (true)
+ {
+ s = p;
+ while (p < e && *p != '\n')
+ p++;
+ if (p < e)
+ {
+ // parse the entry in [s, p)
+ static if( S == 4 )
+ {
+ enum Ofs
+ {
+ Write_Prot = 19,
+ Start_Addr = 0,
+ End_Addr = 9,
+ Addr_Len = 8,
+ }
+ }
+ else static if( S == 8 )
+ {
+ //X86-64 only has 12 bytes address space(in PAE mode) - not 16
+ //We also need the 32 bit offsets for 32 bit apps
+ version(X86_64) {
+ enum Ofs
+ {
+ Write_Prot = 27,
+ Start_Addr = 0,
+ End_Addr = 13,
+ Addr_Len = 12,
+ Write_Prot_32 = 19,
+ Start_Addr_32 = 0,
+ End_Addr_32 = 9,
+ Addr_Len_32 = 8,
+ }
+ }
+ else
+ {
+ enum Ofs
+ {
+ Write_Prot = 35,
+ Start_Addr = 0,
+ End_Addr = 9,
+ Addr_Len = 17,
+ }
+ }
+ }
+ else
+ {
+ static assert( false );
+ }
+
+ // %% this is wrong for 64-bit:
+ // long strtoul(const char*,char**,int);
+ // but seems to work on x86-64:
+ // probably because C's long is 64 bit there
+
+ if( s[Ofs.Write_Prot] == 'w' )
+ {
+ s[Ofs.Start_Addr + Ofs.Addr_Len] = '\0';
+ s[Ofs.End_Addr + Ofs.Addr_Len] = '\0';
+ start = cast(void*) strtoul(s + Ofs.Start_Addr, null, 16);
+ end = cast(void*) strtoul(s + Ofs.End_Addr, null, 16);
+
+ // 1. Exclude anything overlapping [dataStart, dataEnd)
+ // 2. Exclude stack
+ if ( ( !dataEnd ||
+ !( dataStart >= start && dataEnd <= end ) ) &&
+ !( &buf[0] >= start && &buf[0] < end ) )
+ {
+ // we already have static data from this region. anything else
+ // is heap (%% check)
+ debug (ProcMaps) printf("Adding map range %p 0%p\n", start, end);
+ gc_addRange(start, end - start);
+ }
+ }
+ version(X86_64)
+ {
+ //We need to check here for 32 bit apps like ldc produces
+ //and add them to the gc scan range
+ if( s[Ofs.Write_Prot_32] == 'w' )
+ {
+ s[Ofs.Start_Addr_32 + Ofs.Addr_Len_32] = '\0';
+ s[Ofs.End_Addr_32 + Ofs.Addr_Len_32] = '\0';
+ start = cast(void*) strtoul(s + Ofs.Start_Addr_32, null, 16);
+ end = cast(void*) strtoul(s + Ofs.End_Addr_32, null, 16);
+ if ( ( !dataEnd ||
+ !( dataStart >= start && dataEnd <= end ) ) &&
+ !( &buf[0] >= start && &buf[0] < end ) )
+ {
+ gc_addRange(start, end - start);
+ }
+ }
+ }
+
+ p++;
+ }
+ else
+ {
+ count = p - s;
+ memmove(buf.ptr, s, cast(size_t)count);
+ p = buf.ptr + count;
+ break;
+ }
+ }
+ }
+ close(fd);
+ }
+ }
+}
+}
+
+/*
+ * GDC dyld memory module:
+ * http://www.dsource.org/projects/tango/browser/trunk/lib/compiler/gdc/memory_dyld.c
+ * Port to the D programming language: Jacob Carlborg
+ */
+version (GC_Use_Data_Dyld)
+{
+ private
+ {
+ const char* SEG_DATA = "__DATA".ptr;
+ const char* SECT_DATA = "__data".ptr;
+ const char* SECT_BSS = "__bss".ptr;
+ const char* SECT_COMMON = "__common".ptr;
+
+ struct SegmentSection
+ {
+ const char* segment;
+ const char* section;
+ }
+
+ struct mach_header
+ {
+ uint magic;
+ int cputype;
+ int cpusubtype;
+ uint filetype;
+ uint ncmds;
+ uint sizeofcmds;
+ uint flags;
+ version (D_LP64)
+ uint reserved;
+ }
+
+ struct section
+ {
+ char[16] sectname;
+ char[16] segname;
+ c_ulong addr;
+ c_ulong size;
+ uint offset;
+ uint align_;
+ uint reloff;
+ uint nreloc;
+ uint flags;
+ uint reserved1;
+ uint reserved2;
+ version (D_LP64)
+ uint reserved3;
+ }
+
+ alias extern (C) void function (mach_header* mh, ptrdiff_t vmaddr_slide) DyldFuncPointer;
+
+ version (D_LP64)
+ extern (C) /*const*/ section* getsectbynamefromheader_64(/*const*/ mach_header* mhp, /*const*/ char* segname, /*const*/ char* sectname);
+ else
+ extern (C) /*const*/ section* getsectbynamefromheader(/*const*/ mach_header* mhp, /*const*/ char* segname, /*const*/ char* sectname);
+ extern (C) void _dyld_register_func_for_add_image(DyldFuncPointer func);
+ extern (C) void _dyld_register_func_for_remove_image(DyldFuncPointer func);
+
+ const SegmentSection[3] GC_dyld_sections = [SegmentSection(SEG_DATA, SECT_DATA), SegmentSection(SEG_DATA, SECT_BSS), SegmentSection(SEG_DATA, SECT_COMMON)];
+
+ extern (C) void on_dyld_add_image (/*const*/ mach_header* hdr, ptrdiff_t slide)
+ {
+ void* start;
+ void* end;
+ /*const*/ section* sec;
+
+ foreach (s ; GC_dyld_sections)
+ {
+ version (D_LP64)
+ sec = getsectbynamefromheader_64(hdr, s.segment, s.section);
+ else
+ sec = getsectbynamefromheader(hdr, s.segment, s.section);
+
+ if (sec == null || sec.size == 0)
+ continue;
+
+ start = cast(void*) (sec.addr + slide);
+ end = cast(void*) (start + sec.size);
+
+ gc_addRange(start, end - start);
+ }
+ }
+
+ extern (C) void on_dyld_remove_image (/*const*/ mach_header* hdr, ptrdiff_t slide)
+ {
+ void* start;
+ void* end;
+ /*const*/ section* sec;
+
+ foreach (s ; GC_dyld_sections)
+ {
+ version (D_LP64)
+ sec = getsectbynamefromheader_64(hdr, s.segment, s.section);
+ else
+ sec = getsectbynamefromheader(hdr, s.segment, s.section);
+
+ if (sec == null || sec.size == 0)
+ continue;
+
+ start = cast(void*) (sec.addr + slide);
+ end = cast(void*) (start + sec.size);
+
+ gc_removeRange(start);
+ }
+ }
+
+ void _d_dyld_start ()
+ {
+ static bool started;
+
+ if (!started)
+ {
+ started = true;
+
+ _dyld_register_func_for_add_image(&on_dyld_add_image);
+ _dyld_register_func_for_remove_image(&on_dyld_remove_image);
+ }
+ }
+ }
+}
+
+}
+else
+{
+ 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-10-07 13:59:06.815253002 +0400
+++ druntime/src/rt/qsort.d 2010-11-04 17:49:07.000000000 +0300
@@ -44,7 +44,7 @@
structures. The default value is optimized for a high cost for compares. */
@@ -1984,7 +2560,7 @@ 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/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-10-07 14:01:41.359253001 +0400
+++ druntime/src/rt/qsort2.d 2010-11-04 17:49:07.000000000 +0300
@@ -31,14 +31,14 @@
return tiglobal.compare(p1, p2);
}
@@ -2004,7 +2580,7 @@ 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-10-01 21:01:58.444892002 +0400
+++ druntime/src/rt/trace.d 2010-11-04 17:49:07.000000000 +0300
@@ -855,7 +855,7 @@
version (OSX)
{ // 16 byte align stack
@@ -2025,7 +2601,7 @@ 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-10-26 20:18:29.668925001 +0400
+++ druntime/src/std/intrinsic.d 2010-11-04 17:49:07.000000000 +0300
@@ -0,0 +1,212 @@
+/*
+ * D phobos intrinsics for LDC

View File

@@ -129,12 +129,8 @@ DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key)
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
// pkey param
#if DMDV1
LLValue* pkey = makeLValue(loc, key);
pkey = DtoBitCast(pkey, funcTy->getParamType(2));
#else
LLValue* pkey = getNullValue(getVoidPtrType());
#endif
pkey = DtoBitCast(pkey, getVoidPtrType());
// call runtime
LLValue* ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.in").getInstruction();
@@ -194,7 +190,15 @@ LLValue* DtoAAEquals(Loc& loc, TOK op, DValue* l, DValue* r)
{
Type* t = l->getType()->toBasetype();
assert(t == r->getType()->toBasetype() && "aa equality is only defined for aas of same type");
#if DMDV2
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaEqual");
const llvm::FunctionType* funcTy = func->getFunctionType();
LLValue* aaval = DtoBitCast(l->getRVal(), funcTy->getParamType(1));
LLValue* abval = DtoBitCast(r->getRVal(), funcTy->getParamType(2));
LLValue* aaTypeInfo = DtoTypeInfoOf(t);
LLValue* res = gIR->CreateCallOrInvoke3(func, aaTypeInfo, aaval, abval, "aaEqRes").getInstruction();
#else
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaEq");
const llvm::FunctionType* funcTy = func->getFunctionType();
@@ -202,7 +206,7 @@ LLValue* DtoAAEquals(Loc& loc, TOK op, DValue* l, DValue* r)
LLValue* abval = DtoBitCast(r->getRVal(), funcTy->getParamType(1));
LLValue* aaTypeInfo = DtoTypeInfoOf(t);
LLValue* res = gIR->CreateCallOrInvoke3(func, aaval, abval, aaTypeInfo, "aaEqRes").getInstruction();
#endif
res = gIR->ir->CreateICmpNE(res, DtoConstInt(0), "tmp");
if (op == TOKnotequal)
res = gIR->ir->CreateNot(res, "tmp");

View File

@@ -422,10 +422,8 @@ static bool isInitialized(Type* et) {
static DSliceValue *getSlice(Type *arrayType, LLValue *array)
{
// Get ptr and length of the array
LLValue* newArrayLVal = DtoRawAlloca(array->getType(), 0, "newArray");
DtoStore(array, newArrayLVal);
LLValue* arrayLen = DtoLoad(DtoGEPi(newArrayLVal,0,0));
LLValue* newptr = DtoLoad(DtoGEPi(newArrayLVal,0,1));
LLValue* arrayLen = DtoExtractValue(array, 0, ".ptr");
LLValue* newptr = DtoExtractValue(array, 1, ".len");
// cast pointer to wanted type
const LLType* dstType = DtoType(arrayType)->getContainedType(1);
@@ -684,13 +682,13 @@ DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2)
// TypeInfo ti
args.push_back(DtoTypeInfoOf(arrayType));
// byte[] x
LLValue *val = makeLValue(exp1->loc, exp1->toElem(gIR));
val = DtoBitCast(val, getPtrToType(fn->getFunctionType()->getParamType(1)));
args.push_back(DtoLoad(val));
LLValue *val = exp1->toElem(gIR)->getRVal();
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(1));
args.push_back(val);
// byte[] y
val = makeLValue(exp2->loc, exp2->toElem(gIR));
val = DtoBitCast(val, getPtrToType(fn->getFunctionType()->getParamType(2)));
args.push_back(DtoLoad(val));
val = exp2->toElem(gIR)->getRVal();
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(2));
args.push_back(val);
// Call _d_arraycatT
LLValue* newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray").getInstruction();

View File

@@ -170,16 +170,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
// set the context for nested classes
else if (tc->sym->isNested() && tc->sym->vthis)
{
Logger::println("Resolving nested context");
LOG_SCOPE;
// get context
LLValue* nest = DtoNestedContext(loc, tc->sym);
// store into right location
size_t idx = tc->sym->vthis->ir.irField->index;
LLValue* gep = DtoGEPi(mem,0,idx,"tmp");
DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
DtoResolveNestedContext(loc, tc->sym, mem);
}
// call constructor

View File

@@ -513,10 +513,23 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
gIR->dtors.push_back(fdecl);
}
}
#if DMDV2
// shared static ctor
else if (fdecl->isSharedStaticCtorDeclaration()) {
if (mustDefineSymbol(fdecl)) {
gIR->sharedCtors.push_back(fdecl);
}
}
// static dtor
else if (fdecl->isSharedStaticDtorDeclaration()) {
if (mustDefineSymbol(fdecl)) {
gIR->sharedDtors.push_back(fdecl);
}
}
#endif
// we never reference parameters of function prototypes
std::string str;
if (!declareOnly)
// if (!declareOnly)
{
// name parameters
llvm::Function::arg_iterator iarg = func->arg_begin();
@@ -759,16 +772,6 @@ void DtoDefineFunction(FuncDeclaration* fd)
}
#endif
#if DMDV2
// fill nestedVars
size_t nnest = fd->closureVars.dim;
for (size_t i = 0; i < nnest; ++i)
{
VarDeclaration* vd = (VarDeclaration*)fd->closureVars.data[i];
fd->nestedVars.insert(vd);
}
#endif
DtoCreateNestedContext(fd);
#if DMDV2

View File

@@ -163,6 +163,10 @@ struct IRState
typedef std::vector<FuncDeclaration*> FuncDeclVector;
FuncDeclVector ctors;
FuncDeclVector dtors;
#if DMDV2
FuncDeclVector sharedCtors;
FuncDeclVector sharedDtors;
#endif
FuncDeclVector unitTests;
// all template instances that had members emitted

View File

@@ -86,10 +86,15 @@ void DtoDeleteArray(DValue* arr)
{
// get runtime function
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_delarray");
// build args
LLSmallVector<LLValue*,2> arg;
#if DMDV2
arg.push_back(DtoBitCast(arr->getLVal(), fn->getFunctionType()->getParamType(0)));
#else
arg.push_back(DtoArrayLen(arr));
arg.push_back(DtoBitCast(DtoArrayPtr(arr), getVoidPtrType(), ".tmp"));
#endif
// call
gIR->CreateCallOrInvoke(fn, arg.begin(), arg.end());
}
@@ -364,10 +369,16 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
if (!t->equals(t2)) {
// FIXME: use 'rhs' for something !?!
DtoAggrZeroInit(lhs->getLVal());
#if DMDV2
TypeStruct *ts = (TypeStruct*) lhs->getType();
if (ts->sym->isNested() && ts->sym->vthis)
DtoResolveNestedContext(loc, ts->sym, lhs->getLVal());
#endif
}
else {
DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
}
}
else if (t->ty == Tarray) {
// lhs is slice
@@ -459,6 +470,13 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
}
gIR->ir->CreateStore(r, l);
}
#ifndef DISABLE_DEBUG_INFO
DVarValue *var = lhs->isVar();
VarDeclaration *varDecl = var ? var->var : 0;
if (global.params.symdebug && varDecl && varDecl->debugVariable)
DtoDwarfValue(rhs->getRVal(), lhs->isVar()->var);
#endif
}
/****************************************************************************************/
@@ -940,7 +958,6 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
#endif
Logger::println("has nestedref set");
assert(vd->ir.irLocal);
DtoNestedInit(vd);
}
// normal stack variable, allocate storage on the stack if it has not already been done

View File

@@ -68,7 +68,9 @@ static FuncDeclaration* getParentFunc(Dsymbol* sym, bool stopOnStatic) {
return (parent ? parent->isFuncDeclaration() : NULL);
}
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
static void DtoCreateNestedContextType(FuncDeclaration* fd);
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref)
{
Logger::println("DtoNestedVariable for %s @ %s", vd->toChars(), loc.toChars());
LOG_SCOPE;
@@ -109,6 +111,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
ctx = irfunc->nestArg;
assert(ctx);
DtoCreateNestedContextType(vdparent->isFuncDeclaration());
assert(vd->ir.irLocal);
////////////////////////////////////
@@ -150,7 +153,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
Logger::cout() << "Addr: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n';
if (vd->ir.irLocal->byref) {
if (vd->ir.irLocal->byref || byref) {
val = DtoAlignedLoad(val);
Logger::cout() << "Was byref, now: " << *val << '\n';
Logger::cout() << "of type: " << *val->getType() << '\n';
@@ -213,6 +216,24 @@ void DtoNestedInit(VarDeclaration* vd)
}
}
#if DMDV2
LLValue* DtoResolveNestedContext(Loc loc, AggregateDeclaration *decl, LLValue *value)
#else
LLValue* DtoResolveNestedContext(Loc loc, ClassDeclaration *decl, LLValue *value)
#endif
{
Logger::println("Resolving nested context");
LOG_SCOPE;
// get context
LLValue* nest = DtoNestedContext(loc, decl);
// store into right location
size_t idx = decl->vthis->ir.irField->index;
LLValue* gep = DtoGEPi(value,0,idx,"tmp");
DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
}
LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
{
Logger::println("DtoNestedContext for %s", sym->toPrettyChars());
@@ -234,11 +255,16 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
// or just have a this argument
else if (irfunc->thisArg)
{
ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
if (!cd || !cd->vthis)
return llvm::UndefValue::get(getVoidPtrType());
#if DMDV2
AggregateDeclaration* ad = irfunc->decl->isMember2();
val = ad->isClassDeclaration() ? DtoLoad(irfunc->thisArg) : irfunc->thisArg;
#else
ClassDeclaration* ad = irfunc->decl->isMember2()->isClassDeclaration();
val = DtoLoad(irfunc->thisArg);
val = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
#endif
if (!ad || !ad->vthis)
return llvm::UndefValue::get(getVoidPtrType());
val = DtoLoad(DtoGEPi(val, 0,ad->vthis->ir.irField->index, ".vthis"));
}
else
{
@@ -247,14 +273,18 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
if (nestedCtx == NCHybrid) {
if (FuncDeclaration* symfd = sym->isFuncDeclaration()) {
// Make sure we've had a chance to analyze nested context usage
#if DMDV2
DtoCreateNestedContextType(symfd);
#else
DtoDefineFunction(symfd);
#endif
// if this is for a function that doesn't access variables from
// enclosing scopes, it doesn't matter what we pass.
// Tell LLVM about it by passing an 'undef'.
if (symfd && symfd->ir.irFunc->depth == -1)
return llvm::UndefValue::get(getVoidPtrType());
// If sym is a nested function, and it's parent context is different than the
// one we got, adjust it.
if (FuncDeclaration* fd = getParentFunc(symfd, true)) {
@@ -266,13 +296,13 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
assert(ctxfd && "Context from outer function, but no outer function?");
}
Logger::println("Context is from %s", ctxfd->toChars());
unsigned neededDepth = fd->ir.irFunc->depth;
unsigned ctxDepth = ctxfd->ir.irFunc->depth;
Logger::cout() << "Needed depth: " << neededDepth << '\n';
Logger::cout() << "Context depth: " << ctxDepth << '\n';
if (neededDepth >= ctxDepth) {
// assert(neededDepth <= ctxDepth + 1 && "How are we going more than one nesting level up?");
// fd needs the same context as we do, so all is well
@@ -290,10 +320,125 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
return val;
}
static void DtoCreateNestedContextType(FuncDeclaration* fd) {
Logger::println("DtoCreateNestedContextType for %s", fd->toChars());
LOG_SCOPE
if (fd->ir.irFunc->nestedContextCreated)
return;
fd->ir.irFunc->nestedContextCreated = true;
#if DMDV2
DtoDeclareFunction(fd);
if (fd->nestedVars.empty()) {
// fill nestedVars
size_t nnest = fd->closureVars.dim;
for (size_t i = 0; i < nnest; ++i)
{
VarDeclaration* vd = (VarDeclaration*)fd->closureVars.data[i];
fd->nestedVars.insert(vd);
}
}
#endif
if (nestedCtx == NCHybrid) {
// construct nested variables array
if (!fd->nestedVars.empty())
{
Logger::println("has nested frame");
// start with adding all enclosing parent frames until a static parent is reached
const LLStructType* innerFrameType = NULL;
unsigned depth = -1;
if (!fd->isStatic()) {
if (FuncDeclaration* parfd = getParentFunc(fd, true)) {
innerFrameType = parfd->ir.irFunc->frameType;
if (innerFrameType)
depth = parfd->ir.irFunc->depth;
}
}
fd->ir.irFunc->depth = ++depth;
Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';
typedef std::vector<const LLType*> TypeVec;
TypeVec types;
if (depth != 0) {
assert(innerFrameType);
// Add frame pointer types for all but last frame
if (depth > 1) {
for (unsigned i = 0; i < (depth - 1); ++i) {
types.push_back(innerFrameType->getElementType(i));
}
}
// Add frame pointer type for last frame
types.push_back(LLPointerType::getUnqual(innerFrameType));
}
if (Logger::enabled()) {
Logger::println("Frame types: ");
LOG_SCOPE;
for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
Logger::cout() << **i << '\n';
}
// Add the direct nested variables of this function, and update their indices to match.
// TODO: optimize ordering for minimal space usage?
for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
{
VarDeclaration* vd = *i;
if (!vd->ir.irLocal)
vd->ir.irLocal = new IrLocal(vd);
vd->ir.irLocal->nestedIndex = types.size();
vd->ir.irLocal->nestedDepth = depth;
if (vd->isParameter()) {
// Parameters already have storage associated with them (to handle byref etc.),
// so handle those cases specially by storing a pointer instead of a value.
assert(vd->ir.irLocal->value);
LLValue* value = vd->ir.irLocal->value;
const LLType* type = value->getType();
if (llvm::isa<llvm::AllocaInst>(value->getUnderlyingObject()))
// This will be copied to the nesting frame.
type = type->getContainedType(0);
types.push_back(type);
} else if (vd->isRef() || vd->isOut()) {
// Foreach variables can also be by reference, for instance.
types.push_back(DtoType(vd->type->pointerTo()));
} else {
types.push_back(DtoType(vd->type));
}
if (Logger::enabled()) {
Logger::println("Nested var: %s", vd->toChars());
Logger::cout() << "of type: " << *types.back() << '\n';
}
}
const LLStructType* frameType = LLStructType::get(gIR->context(), types);
gIR->module->addTypeName(std::string("nest.") + fd->toChars(), frameType);
Logger::cout() << "frameType = " << *frameType << '\n';
// Store type in IrFunction
fd->ir.irFunc->frameType = frameType;
} else if (FuncDeclaration* parFunc = getParentFunc(fd, true)) {
// Propagate context arg properties if the context arg is passed on unmodified.
DtoCreateNestedContextType(parFunc);
fd->ir.irFunc->frameType = parFunc->ir.irFunc->frameType;
fd->ir.irFunc->depth = parFunc->ir.irFunc->depth;
}
}
else {
assert(0 && "Not implemented yet");
}
}
void DtoCreateNestedContext(FuncDeclaration* fd) {
Logger::println("DtoCreateNestedContext for %s", fd->toChars());
LOG_SCOPE
DtoCreateNestedContextType(fd);
if (nestedCtx == NCArray) {
// construct nested variables array
if (!fd->nestedVars.empty())
@@ -385,84 +530,9 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
// construct nested variables array
if (!fd->nestedVars.empty())
{
Logger::println("has nested frame");
// start with adding all enclosing parent frames until a static parent is reached
const LLStructType* innerFrameType = NULL;
unsigned depth = -1;
if (!fd->isStatic()) {
if (FuncDeclaration* parfd = getParentFunc(fd, true)) {
innerFrameType = parfd->ir.irFunc->frameType;
if (innerFrameType)
depth = parfd->ir.irFunc->depth;
}
}
fd->ir.irFunc->depth = ++depth;
Logger::cout() << "Function " << fd->toChars() << " has depth " << depth << '\n';
typedef std::vector<const LLType*> TypeVec;
TypeVec types;
if (depth != 0) {
assert(innerFrameType);
// Add frame pointer types for all but last frame
if (depth > 1) {
for (unsigned i = 0; i < (depth - 1); ++i) {
types.push_back(innerFrameType->getElementType(i));
}
}
// Add frame pointer type for last frame
types.push_back(LLPointerType::getUnqual(innerFrameType));
}
if (Logger::enabled()) {
Logger::println("Frame types: ");
LOG_SCOPE;
for (TypeVec::iterator i = types.begin(); i != types.end(); ++i)
Logger::cout() << **i << '\n';
}
// Add the direct nested variables of this function, and update their indices to match.
// TODO: optimize ordering for minimal space usage?
for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
{
VarDeclaration* vd = *i;
if (!vd->ir.irLocal)
vd->ir.irLocal = new IrLocal(vd);
vd->ir.irLocal->nestedIndex = types.size();
vd->ir.irLocal->nestedDepth = depth;
if (vd->isParameter()) {
// Parameters already have storage associated with them (to handle byref etc.),
// so handle those cases specially by storing a pointer instead of a value.
assert(vd->ir.irLocal->value);
LLValue* value = vd->ir.irLocal->value;
const LLType* type = value->getType();
if (llvm::isa<llvm::AllocaInst>(value->getUnderlyingObject()))
// This will be copied to the nesting frame.
type = type->getContainedType(0);
types.push_back(type);
} else if (vd->isRef() || vd->isOut()) {
// Foreach variables can also be by reference, for instance.
types.push_back(DtoType(vd->type->pointerTo()));
} else {
types.push_back(DtoType(vd->type));
}
if (Logger::enabled()) {
Logger::println("Nested var: %s", vd->toChars());
Logger::cout() << "of type: " << *types.back() << '\n';
}
}
const LLStructType* frameType = LLStructType::get(gIR->context(), types);
gIR->module->addTypeName(std::string("nest.") + fd->toChars(), frameType);
Logger::cout() << "frameType = " << *frameType << '\n';
// Store type in IrFunction
IrFunction* irfunction = fd->ir.irFunc;
irfunction->frameType = frameType;
unsigned depth = irfunction->depth;
const llvm::StructType *frameType = irfunction->frameType;
// Create frame for current function and append to frames list
// FIXME: For D2, this should be a gc_malloc (or similar) call, not alloca
// (Note that it'd also require more aggressive copying of
@@ -477,10 +547,19 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
assert(irfunction->thisArg);
assert(fd->isMember2());
LLValue* thisval = DtoLoad(irfunction->thisArg);
#if DMDV2
AggregateDeclaration* cd = fd->isMember2();
#else
ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
#endif
assert(cd);
assert(cd->vthis);
Logger::println("Indexing to 'this'");
#if DMDV2
if (cd->isStructDeclaration())
src = DtoExtractValue(thisval, cd->vthis->ir.irField->index, ".vthis");
else
#endif
src = DtoLoad(DtoGEPi(thisval, 0, cd->vthis->ir.irField->index, ".vthis"));
}
if (depth > 1) {
@@ -490,7 +569,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) {
getABITypeAlign(getVoidPtrType()));
}
// Copy nestArg into framelist; the outer frame is not in the list of pointers
src = DtoBitCast(src, types[depth-1]);
src = DtoBitCast(src, frameType->getContainedType(depth-1));
LLValue* gep = DtoGEPi(frame, 0, depth-1);
DtoAlignedStore(src, gep);
}

View File

@@ -4,6 +4,7 @@
#include "declaration.h"
#include "mtype.h"
#include "gen/dvalue.h"
#include "gen/llvm.h"
///////////////////////////////////////////////////////////
// Nested variable and context helpers
@@ -15,11 +16,18 @@ void DtoCreateNestedContext(FuncDeclaration* fd);
/// Allocate space for variable accessed from nested function.
void DtoNestedInit(VarDeclaration* vd);
/// Gets the context value for a call to a nested function or newing a nested
/// class with arbitrary nesting.
/// Resolves the nested context for classes and structs with arbitrary nesting.
#if DMDV2
LLValue* DtoResolveNestedContext(Loc loc, AggregateDeclaration *decl, LLValue *value);
#else
LLValue* DtoResolveNestedContext(Loc loc, ClassDeclaration *decl, LLValue *value);
#endif
/// Gets the context value for a call to a nested function or creating a nested
/// class or struct with arbitrary nesting.
llvm::Value* DtoNestedContext(Loc loc, Dsymbol* sym);
/// Gets the DValue of a nested variable with arbitrary nesting.
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd);
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref = false);
#endif

View File

@@ -431,12 +431,17 @@ static void LLVM_D_BuildRuntimeModule()
->setAttributes(Attr_NoAlias);
}
// void _d_delarray(size_t plength, void* pdata)
// D1: void _d_delarray(size_t plength, void* pdata)
// D2: void _d_delarray(void[]* array)
{
llvm::StringRef fname("_d_delarray");
std::vector<const LLType*> types;
#if DMDV2
types.push_back(voidArrayPtrTy);
#else
types.push_back(sizeTy);
types.push_back(voidPtrTy);
#endif
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
}
@@ -839,6 +844,19 @@ static void LLVM_D_BuildRuntimeModule()
->setAttributes(Attr_1_NoCapture);
}
#if DMDV2
// int _aaEqual(TypeInfo_AssociativeArray ti, AA e1, AA e2)
{
llvm::StringRef fname("_aaEqual");
std::vector<const LLType*> types;
types.push_back(typeInfoTy);
types.push_back(aaTy);
types.push_back(aaTy);
const llvm::FunctionType* fty = llvm::FunctionType::get(intTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
->setAttributes(Attr_1_2_NoCapture);
}
#else
// int _aaEq(AA aa, AA ab, TypeInfo_AssociativeArray ti)
{
llvm::StringRef fname("_aaEq");
@@ -850,6 +868,7 @@ static void LLVM_D_BuildRuntimeModule()
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
->setAttributes(Attr_1_2_NoCapture);
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

View File

@@ -77,6 +77,23 @@ void ReturnStatement::toIR(IRState* p)
// store return value
DtoAssign(loc, rvar, e);
#if DMDV2
// Call postBlit()
Type *tb = exp->type->toBasetype();
if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar) &&
tb->ty == Tstruct)
{ StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->postblit)
{
FuncDeclaration *fd = sd->postblit;
fd->codegen(Type::sir);
Expressions args;
DFuncValue dfn(fd, fd->ir.irFunc->func, e->getLVal());
DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args);
}
}
#endif
// emit scopes
DtoEnclosingHandlers(loc, NULL);

View File

@@ -424,13 +424,29 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
LLSmallVector<unsigned, 10> attrptr(n, 0);
std::vector<DValue*> argvals;
if (dfnval && dfnval->func->isArrayOp) {
// slightly different approach for array operators
for (int i=n-1; i>=0; --i) {
Parameter* fnarg = Parameter::getNth(tf->parameters, i);
assert(fnarg);
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
argvals.insert(argvals.begin(), argval);
}
} else {
for (int i=0; i<n; ++i) {
Parameter* fnarg = Parameter::getNth(tf->parameters, i);
assert(fnarg);
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
argvals.push_back(argval);
}
}
// do formal params
int beg = argiter-argbegin;
for (int i=0; i<n; i++)
{
Parameter* fnarg = Parameter::getNth(tf->parameters, i);
assert(fnarg);
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
DValue* argval = argvals.at(i);
#if 0
if (Logger::enabled()) {

View File

@@ -114,7 +114,7 @@ static llvm::DIDerivedType dwarfDerivedType(Type* type, llvm::DICompileUnit comp
return gIR->difactory.CreateDerivedType(
DW_TAG_pointer_type, // tag
compileUnit, // context
"", // name
type->toChars(), // name
DtoDwarfFile(Loc(gIR->dmodule, 0), DtoDwarfCompileUnit(gIR->dmodule)), // file
0, // line number
getTypeBitSize(T), // size (bits)
@@ -350,11 +350,12 @@ static llvm::DIVariable dwarfVariable(VarDeclaration* vd, llvm::DIType type)
return gIR->difactory.CreateVariable(
tag, // tag
gIR->func()->diSubprogram, // context
gIR->func()->diLexicalBlock, // context
vd->toChars(), // name
DtoDwarfFile(vd->loc, DtoDwarfCompileUnit(getDefinedModule(vd))), // file
vd->loc.linnum, // line num
type // type
type, // type
true // preserve
);
}
@@ -408,10 +409,10 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd)
return; // unsupported
// get variable description
llvm::DIVariable VD = dwarfVariable(vd, TD);
vd->debugVariable = dwarfVariable(vd, TD);
// declare
dwarfDeclare(ll, VD);
dwarfDeclare(ll, vd->debugVariable);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
@@ -421,6 +422,8 @@ llvm::DICompileUnit DtoDwarfCompileUnit(Module* m)
Logger::println("D to dwarf compile_unit");
LOG_SCOPE;
static bool mainUnitCreated = false;
// we might be generating for an import
IrModule* irmod = getIrModule(m);
@@ -441,16 +444,18 @@ llvm::DICompileUnit DtoDwarfCompileUnit(Module* m)
srcpath = srcpath + '/';
}
bool isMain = !mainUnitCreated && gIR->dmodule == m;
// make compile unit
irmod->diCompileUnit = gIR->difactory.CreateCompileUnit(
global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D,
m->srcfile->name->toChars(),
srcpath,
"LDC (http://www.dsource.org/projects/ldc)",
//FIXME: What do these two mean?
gIR->dmodule == m, // isMain,
isMain, // isMain,
false // isOptimized
);
if (isMain)
mainUnitCreated = true;
return irmod->diCompileUnit;
}
@@ -464,6 +469,7 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd)
llvm::DICompileUnit context = DtoDwarfCompileUnit(gIR->dmodule);
llvm::DIFile file = DtoDwarfFile(fd->loc, DtoDwarfCompileUnit(getDefinedModule(fd)));
Type *retType = ((TypeFunction*)fd->type)->next;
// FIXME: duplicates ?
return gIR->difactory.CreateSubprogram(
@@ -473,10 +479,14 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd)
fd->mangle(), // linkage name
file, // file
fd->loc.linnum, // line no
//FIXME: what's this type for?
llvm::DIType(NULL), // type
dwarfTypeDescription(retType, context, NULL), // type
fd->protection == PROTprivate, // is local to unit
gIR->dmodule == getDefinedModule(fd) // isdefinition
gIR->dmodule == getDefinedModule(fd), // isdefinition
0, 0, // VK, Index
llvm::DIType(),
false, // isArtificial
false, // isOptimized
fd->ir.irFunc->func
);
}
@@ -497,8 +507,7 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char
mangledname, // linkage name
DtoDwarfFile(Loc(gIR->dmodule, 0), context), // compile unit
0, // line no
//FIXME: what's this type for?
llvm::DIType(NULL), // type
llvm::DIType(NULL), // return type. TODO: fill it up
true, // is local to unit
true // isdefinition
);
@@ -523,8 +532,11 @@ void DtoDwarfFuncStart(FuncDeclaration* fd)
LOG_SCOPE;
assert((llvm::MDNode*)fd->ir.irFunc->diSubprogram != 0);
//TODO:
//gIR->difactory.InsertSubprogramStart(fd->ir.irFunc->diSubprogram, gIR->scopebb());
fd->ir.irFunc->diLexicalBlock = gIR->difactory.CreateLexicalBlock(
fd->ir.irFunc->diSubprogram, // context
DtoDwarfFile(fd->loc, DtoDwarfCompileUnit(getDefinedModule(fd))), // file
fd->loc.linnum
);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
@@ -535,8 +547,6 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd)
LOG_SCOPE;
assert((llvm::MDNode*)fd->ir.irFunc->diSubprogram != 0);
//TODO:
//gIR->difactory.InsertRegionEnd(fd->ir.irFunc->diSubprogram, gIR->scopebb());
}
//////////////////////////////////////////////////////////////////////////////////////////////////
@@ -549,4 +559,11 @@ void DtoDwarfStopPoint(unsigned ln)
gIR->ir->SetCurrentDebugLocation(loc);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void DtoDwarfValue(LLValue* var, VarDeclaration* vd)
{
gIR->difactory.InsertDbgValueIntrinsic(var, 0, vd->debugVariable, gIR->scopebb());
}
#endif

View File

@@ -32,6 +32,8 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd);
void DtoDwarfStopPoint(unsigned ln);
void DtoDwarfValue(LLValue* var, VarDeclaration* vd);
/**
* Emits all things necessary for making debug info for a local variable vd.
* @param ll LLVM Value of the variable.
@@ -47,6 +49,7 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd);
*/
llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd);
#endif // DISABLE_DEBUG_INFO
#endif // LDC_GEN_TODEBUG_H

View File

@@ -1202,7 +1202,11 @@ DValue* ThisExp::toElem(IRState* p)
LLValue* v;
if (vd->toParent2() != p->func()->decl) {
Logger::println("nested this exp");
#if STRUCTTHISREF
return DtoNestedVariable(loc, type, vd, type->ty == Tstruct);
#else
return DtoNestedVariable(loc, type, vd);
#endif
}
else {
Logger::println("normal this exp");
@@ -1694,6 +1698,20 @@ DValue* NewExp::toElem(IRState* p)
ts->sym->codegen(Type::sir);
DtoAggrCopy(mem, ts->sym->ir.irStruct->getInitSymbol());
}
#if DMDV2
if (ts->sym->isNested() && ts->sym->vthis)
DtoResolveNestedContext(loc, ts->sym, mem);
// call constructor
if (member)
{
Logger::println("Calling constructor");
assert(arguments != NULL);
member->codegen(Type::sir);
DFuncValue dfn(member, member->ir.irFunc->func, mem);
return DtoCallFunction(loc, ts, &dfn, arguments);
}
#endif
return new DImValue(type, mem);
}
// new basic type
@@ -2337,10 +2355,30 @@ DValue* FuncExp::toElem(IRState* p)
LLValue* cval;
IrFunction* irfn = p->func();
if (irfn->nestedVar)
if (irfn->nestedVar
#if DMDV2
// We cannot use a frame allocated in one function
// for a delegate created in another function
// (that happens with anonymous functions)
&& fd->toParent2() == irfn->decl
#endif
)
cval = irfn->nestedVar;
else if (irfn->nestArg)
cval = irfn->nestArg;
#if DMDV2
// TODO: should we enable that for D1 as well?
else if (irfn->thisArg)
{
AggregateDeclaration* ad = irfn->decl->isMember2();
if (!ad || !ad->vthis) {
cval = getNullPtr(getVoidPtrType());
} else {
cval = ad->isClassDeclaration() ? DtoLoad(irfn->thisArg) : irfn->thisArg;
cval = DtoLoad(DtoGEPi(cval, 0,ad->vthis->ir.irField->index, ".vthis"));
}
}
#endif
else
cval = getNullPtr(getVoidPtrType());
cval = DtoBitCast(cval, dgty->getContainedType(0));
@@ -2558,6 +2596,24 @@ DValue* StructLiteralExp::toElem(IRState* p)
// store the initializer there
DtoAssign(loc, &field, val);
#if DMDV2
Type *tb = vd->type->toBasetype();
if (tb->ty == Tstruct)
{
// Call postBlit()
StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->postblit)
{
FuncDeclaration *fd = sd->postblit;
fd->codegen(Type::sir);
Expressions args;
DFuncValue dfn(fd, fd->ir.irFunc->func, val->getLVal());
DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args);
}
}
#endif
}
// initialize trailing padding
if (sd->structsize != offset)
@@ -2661,6 +2717,25 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p)
DtoAssign(loc, mem, val);
}
#if DMDV2
// Rehash array
if (keys->dim) {
// first get the runtime function
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_aaRehash");
const llvm::FunctionType* funcTy = fn->getFunctionType();
// aa param
LLValue* aaval = DtoBitCast(tmp, funcTy->getParamType(0));
// keyti param
LLValue* keyti = DtoTypeInfoOf(((TypeAArray*)aatype)->index, false);
keyti = DtoBitCast(keyti, funcTy->getParamType(1));
// Call function
gIR->CreateCallOrInvoke2(fn, aaval, keyti, ".gc_mem").getInstruction();
}
#endif
return aa;
}
@@ -2711,15 +2786,20 @@ DValue* TupleExp::toElem(IRState *p)
for (size_t i = 0; i < exps->dim; i++)
{
Expression *el = (Expression *)exps->data[i];
DValue* ep = el->toElem(p);
types[i] = ep->getRVal()->getType();
types[i] = DtoTypeNotVoid(el->type);
}
LLValue *val = DtoRawAlloca(LLStructType::get(gIR->context(), types),0, "tuple");
for (size_t i = 0; i < exps->dim; i++)
{
Expression *el = (Expression *)exps->data[i];
DValue* ep = el->toElem(p);
DtoStore(ep->getRVal(), DtoGEPi(val,0,i));
LLValue *gep = DtoGEPi(val,0,i);
if (el->type->ty == Tstruct)
DtoStore(DtoLoad(ep->getRVal()), gep);
else if (el->type->ty != Tvoid)
DtoStore(ep->getRVal(), gep);
else
DtoStore(LLConstantInt::get(LLType::getInt8Ty(gIR->context()), 0, false), gep);
}
return new DImValue(type, val);
}

View File

@@ -117,6 +117,10 @@ const LLType* DtoType(Type* t)
// aggregates
case Tstruct: {
TypeStruct* ts = (TypeStruct*)t;
#if 1
if (t != ts->sym->type) // TODO: interesting... why does it happen?
ts->sym->type->irtype = NULL; // set irtype to NULL, so IrTypeStruct constructor would not assert...
#endif
t->irtype = new IrTypeStruct(ts->sym);
return t->irtype->buildType();
}
@@ -299,8 +303,9 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym)
// The following breaks for nested naked functions and other declarations, so check for that.
bool skipNestedCheck = !mustDefineSymbol(sym);
if (FuncDeclaration* fd = sym->isFuncDeclaration())
skipNestedCheck = (fd->naked != 0);
if (!skipNestedCheck)
if (FuncDeclaration* fd = sym->isFuncDeclaration())
skipNestedCheck = (fd->naked != 0);
// Any symbol nested in a function can't be referenced directly from
// outside that function, so we can give such symbols internal linkage.
@@ -349,10 +354,10 @@ llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym)
llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym)
{
if (isAvailableExternally(sym) && mustDefineSymbol(sym))
return llvm::GlobalValue::AvailableExternallyLinkage;
if (needsTemplateLinkage(sym))
return templateLinkage;
else if (isAvailableExternally(sym) && mustDefineSymbol(sym))
return llvm::GlobalValue::AvailableExternallyLinkage;
else
return llvm::GlobalValue::ExternalLinkage;
}
@@ -657,14 +662,14 @@ LLConstant* DtoBitCast(LLConstant* v, const LLType* t)
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx)
LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx, const char* name)
{
return gIR->ir->CreateInsertValue(aggr, v, idx);
return gIR->ir->CreateInsertValue(aggr, v, idx, name);
}
LLValue* DtoExtractValue(LLValue* aggr, unsigned idx)
LLValue* DtoExtractValue(LLValue* aggr, unsigned idx, const char* name)
{
return gIR->ir->CreateExtractValue(aggr, idx);
return gIR->ir->CreateExtractValue(aggr, idx, name);
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -68,8 +68,8 @@ void DtoStore(LLValue* src, LLValue* dst);
void DtoAlignedStore(LLValue* src, LLValue* dst);
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
LLConstant* DtoBitCast(LLConstant* v, const LLType* t);
LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx);
LLValue* DtoExtractValue(LLValue* aggr, unsigned idx);
LLValue* DtoInsertValue(LLValue* aggr, LLValue* v, unsigned idx, const char* name=0);
LLValue* DtoExtractValue(LLValue* aggr, unsigned idx, const char* name=0);
// llvm::dyn_cast wrappers
const LLPointerType* isaPointer(LLValue* v);

View File

@@ -387,25 +387,14 @@ void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath)
/* ================================================================== */
// the following code generates functions and needs to output
// debug info. these macros are useful for that
#define DBG_TYPE ( getPtrToType(llvm::StructType::get(gIR->context(),NULL,NULL)) )
#define DBG_CAST(X) ( llvm::ConstantExpr::getBitCast(X, DBG_TYPE) )
// build module ctor
llvm::Function* build_module_ctor()
static llvm::Function* build_module_function(const std::string &name, const std::vector<FuncDeclaration*> &funcs)
{
if (gIR->ctors.empty())
if (funcs.empty())
return NULL;
size_t n = gIR->ctors.size();
size_t n = funcs.size();
if (n == 1)
return gIR->ctors[0]->ir.irFunc->func;
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("6__ctorZ");
return funcs[0]->ir.irFunc->func;
std::vector<const LLType*> argsTy;
const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
@@ -423,7 +412,7 @@ llvm::Function* build_module_ctor()
#endif
for (size_t i=0; i<n; i++) {
llvm::Function* f = gIR->ctors[i]->ir.irFunc->func;
llvm::Function* f = funcs[i]->ir.irFunc->func;
llvm::CallInst* call = builder.CreateCall(f,"");
call->setCallingConv(DtoCallingConv(0, LINKd));
}
@@ -432,87 +421,60 @@ llvm::Function* build_module_ctor()
return fn;
}
// build module ctor
llvm::Function* build_module_ctor()
{
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("6__ctorZ");
return build_module_function(name, gIR->ctors);
}
// build module dtor
static llvm::Function* build_module_dtor()
{
if (gIR->dtors.empty())
return NULL;
size_t n = gIR->dtors.size();
if (n == 1)
return gIR->dtors[0]->ir.irFunc->func;
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("6__dtorZ");
std::vector<const LLType*> argsTy;
const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
assert(gIR->module->getFunction(name) == NULL);
llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
fn->setCallingConv(DtoCallingConv(0, LINKd));
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn);
IRBuilder<> builder(bb);
#ifndef DISABLE_DEBUG_INFO
// debug info
if(global.params.symdebug)
DtoDwarfSubProgramInternal(name.c_str(), name.c_str());
#endif
for (size_t i=0; i<n; i++) {
llvm::Function* f = gIR->dtors[i]->ir.irFunc->func;
llvm::CallInst* call = builder.CreateCall(f,"");
call->setCallingConv(DtoCallingConv(0, LINKd));
}
builder.CreateRetVoid();
return fn;
return build_module_function(name, gIR->dtors);
}
// build module unittest
static llvm::Function* build_module_unittest()
{
if (gIR->unitTests.empty())
return NULL;
size_t n = gIR->unitTests.size();
if (n == 1)
return gIR->unitTests[0]->ir.irFunc->func;
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("10__unittestZ");
std::vector<const LLType*> argsTy;
const llvm::FunctionType* fnTy = llvm::FunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
assert(gIR->module->getFunction(name) == NULL);
llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
fn->setCallingConv(DtoCallingConv(0, LINKd));
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn);
IRBuilder<> builder(bb);
#ifndef DISABLE_DEBUG_INFO
// debug info
llvm::DISubprogram subprog;
if(global.params.symdebug)
subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str());
#endif
for (size_t i=0; i<n; i++) {
llvm::Function* f = gIR->unitTests[i]->ir.irFunc->func;
llvm::CallInst* call = builder.CreateCall(f,"");
call->setCallingConv(DtoCallingConv(0, LINKd));
}
builder.CreateRetVoid();
return fn;
return build_module_function(name, gIR->unitTests);
}
#if DMDV2
// build module shared ctor
llvm::Function* build_module_shared_ctor()
{
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("13__shared_ctorZ");
return build_module_function(name, gIR->sharedCtors);
}
// build module shared dtor
static llvm::Function* build_module_shared_dtor()
{
std::string name("_D");
name.append(gIR->dmodule->mangle());
name.append("13__shared_dtorZ");
return build_module_function(name, gIR->sharedDtors);
}
#endif
// build ModuleReference and register function, to register the module info in the global linked list
static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
{
@@ -722,12 +684,20 @@ void Module::genmoduleinfo()
const LLType* fnptrTy = getPtrToType(LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<const LLType*>(), false));
// ctor
#if DMDV2
llvm::Function* fctor = build_module_shared_ctor();
#else
llvm::Function* fctor = build_module_ctor();
#endif
c = fctor ? fctor : getNullValue(fnptrTy);
b.push(c);
// dtor
#if DMDV2
llvm::Function* fdtor = build_module_shared_dtor();
#else
llvm::Function* fdtor = build_module_dtor();
#endif
c = fdtor ? fdtor : getNullValue(fnptrTy);
b.push(c);
@@ -746,8 +716,18 @@ void Module::genmoduleinfo()
#if DMDV2
// void*[4] reserved :/
const LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 4);
// tls ctor
fctor = build_module_ctor();
c = fctor ? fctor : getNullValue(fnptrTy);
b.push(c);
// tls dtor
fdtor = build_module_dtor();
c = fdtor ? fdtor : getNullValue(fnptrTy);
b.push(c);
// index + reserved void*[1]
const LLType* AT = llvm::ArrayType::get(getVoidPtrType(), 2);
c = getNullValue(AT);
b.push(c);

View File

@@ -661,7 +661,7 @@ void TypeInfoStructDeclaration::llvmDefine()
ClassDeclaration* tscd = Type::typeinfostruct;
assert(tscd->fields.dim == 10);
assert(tscd->fields.dim == 11);
// const(MemberInfo[]) function(in char[]) xgetMembers;
VarDeclaration* xgetMembers = (VarDeclaration*)tscd->fields.data[7];
@@ -674,6 +674,9 @@ void TypeInfoStructDeclaration::llvmDefine()
//void function(void*) xpostblit;
VarDeclaration* xpostblit = (VarDeclaration*)tscd->fields.data[9];
b.push_null(xpostblit->type);
//uint m_align;
b.push_uint(0);
#endif
// finish

View File

@@ -159,7 +159,7 @@ LLConstant * IrStruct::getVtblInit()
FuncDeclaration* fd = dsym->isFuncDeclaration();
assert(fd && "vtbl entry not a function");
if (fd->isAbstract() && !fd->fbody)
if (cd->isAbstract() || (fd->isAbstract() && !fd->fbody))
{
c = getNullValue(DtoType(fd->type->pointerTo()));
}

View File

@@ -144,6 +144,7 @@ IrFunction::IrFunction(FuncDeclaration* fd)
nestedVar = NULL;
frameType = NULL;
depth = -1;
nestedContextCreated = false;
_arguments = NULL;
_argptr = NULL;

View File

@@ -93,11 +93,13 @@ struct IrFunction : IrBase
// number of enclosing functions with variables accessed by nested functions
// (-1 if neither this function nor any enclosing ones access variables from enclosing functions)
int depth;
bool nestedContextCreated; // holds whether nested context is created
llvm::Value* _arguments;
llvm::Value* _argptr;
llvm::DISubprogram diSubprogram;
llvm::DILexicalBlock diLexicalBlock;
};
#endif

View File

@@ -149,7 +149,8 @@ LLConstant * IrStruct::createStructDefaultInitializer()
assert(type->ty == Tstruct && "cannot build struct default initializer for non struct type");
IrTypeStruct* ts = type->irtype->isStruct();
DtoType(type);
IrTypeStruct* ts = stripModifiers(type)->irtype->isStruct();
assert(ts);
// start at offset zero

View File

@@ -1,16 +1,31 @@
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
@@ -359,9 +359,10 @@
owner = ownerTid;
fn( args );
}
-
+
// TODO: MessageList and &exec should be shared.
auto t = new Thread( &exec ); t.start();
+ version(LDC) Thread.sleep(5_000);
links[spawnTid] = linked;
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-09-17 00:27:48.000000000 +0400
+++ phobos/std/conv.d 2010-10-29 12:06:21.221035000 +0400
@@ -1395,7 +1395,7 @@
--- 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 @@
else // not hex
{
if (toupper(p.front) == 'N')
if (toupper(p.front) == 'N' && !startsWithZero)
- {
+ {
// nan
enforce((p.popFront(), !p.empty && toupper(p.front) == 'A')
&& (p.popFront(), !p.empty && toupper(p.front) == 'N'),
@@ -3191,6 +3191,11 @@
@@ -3243,6 +3243,11 @@
T toImpl(T, S)(S d) if (is(Unqual!S == double) && isSomeString!(T))
{
//alias Unqual!(ElementType!T) Char;
@@ -22,9 +37,66 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
char[20] buffer;
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/format.d phobos/std/format.d
--- phobos-orig/std/format.d 2010-10-29 05:54:44.000000000 +0400
+++ phobos/std/format.d 2010-11-07 19:26:52.000000000 +0300
@@ -2582,20 +2582,42 @@
FLprecision = 0x80,
}
- static TypeInfo skipCI(TypeInfo valti)
+ version(LDC)
{
- for (;;)
+ static TypeInfo skipCI(TypeInfo valti)
{
- if (valti.classinfo.name.length == 18 &&
- valti.classinfo.name[9..18] == "Invariant")
- valti = (cast(TypeInfo_Invariant)valti).next;
- else if (valti.classinfo.name.length == 14 &&
- valti.classinfo.name[9..14] == "Const")
- valti = (cast(TypeInfo_Const)valti).next;
- else
- break;
+ for (;;)
+ {
+ if (valti.classinfo.name.length == 18 &&
+ valti.classinfo.name[9..18] == "Invariant")
+ valti = (cast(TypeInfo_Invariant)valti).base;
+ else if (valti.classinfo.name.length == 14 &&
+ valti.classinfo.name[9..14] == "Const")
+ valti = (cast(TypeInfo_Const)valti).base;
+ else
+ break;
+ }
+ return valti;
+ }
+
+ }
+ else
+ {
+ static TypeInfo skipCI(TypeInfo valti)
+ {
+ for (;;)
+ {
+ if (valti.classinfo.name.length == 18 &&
+ valti.classinfo.name[9..18] == "Invariant")
+ valti = (cast(TypeInfo_Invariant)valti).next;
+ else if (valti.classinfo.name.length == 14 &&
+ valti.classinfo.name[9..14] == "Const")
+ valti = (cast(TypeInfo_Const)valti).next;
+ else
+ break;
+ }
+ return valti;
}
- return valti;
}
void formatArg(char fc)
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-09-17 00:27:48.000000000 +0400
+++ phobos/std/functional.d 2010-10-29 12:01:35.285035001 +0400
--- phobos-orig/std/functional.d 2010-10-29 05:54:44.000000000 +0400
+++ phobos/std/functional.d 2010-11-07 19:26:52.000000000 +0300
@@ -713,6 +713,13 @@
assert(dg_pure_nothrow() == 7);
//assert(dg_pure_nothrow_safe() == 8);
@@ -47,9 +119,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' -- phobos-orig/std/internal/math/biguintx86.d phobos/std/internal/math/biguintx86.d
--- phobos-orig/std/internal/math/biguintx86.d 2010-09-17 00:27:48.000000000 +0400
+++ phobos/std/internal/math/biguintx86.d 2010-10-26 14:08:51.480925001 +0400
@@ -733,7 +733,10 @@
--- 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
@@ -734,7 +734,10 @@
// EDI = dest
// ESI = src
@@ -61,7 +133,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
version(D_PIC) {
enum { zero = 0 }
} else {
@@ -767,7 +770,10 @@
@@ -768,7 +771,10 @@
jnz L_enter_odd;
}
// Main loop, with entry point for even length
@@ -73,7 +145,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
asm {
mov EAX, EBP; // get final carry
pop EBP;
@@ -777,6 +783,9 @@
@@ -778,6 +784,9 @@
ret 5*4;
}
L_enter_odd:
@@ -84,8 +156,17 @@ 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/math.d phobos/std/math.d
--- phobos-orig/std/math.d 2010-09-17 00:27:48.000000000 +0400
+++ phobos/std/math.d 2010-10-29 12:08:18.925035001 +0400
--- phobos-orig/std/math.d 2010-10-29 05:54:44.000000000 +0400
+++ phobos/std/math.d 2010-11-07 19:26:52.000000000 +0300
@@ -276,7 +276,7 @@
assert(abs(71.6Li) == 71.6L);
assert(abs(-56) == 56);
assert(abs(2321312L) == 2321312L);
- assert(abs(-1+1i) == sqrt(2.0));
+ assert(abs(-1+1i) == sqrt(2.0L));
}
/***********************************
@@ -318,7 +318,10 @@
* Results are undefined if |x| >= $(POWER 2,64).
*/
@@ -110,7 +191,18 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
/***********************************
@@ -831,6 +837,20 @@
@@ -400,7 +406,9 @@
@trusted pure nothrow real tan(real x)
{
- version(Naked_D_InlineAsm_X86) {
+ version(LDC) {
+ return core.stdc.math.tanl(x);
+ } else version(Naked_D_InlineAsm_X86) {
asm
{
fld x[EBP] ; // load theta
@@ -831,6 +839,20 @@
* )
*/
@@ -131,7 +223,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 +858,8 @@
@@ -838,6 +860,8 @@
real sqrt(real x); /* intrinsic */ /// ditto
}
@@ -140,7 +232,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 +1435,22 @@
@@ -1413,9 +1437,22 @@
* Compute n * 2$(SUP exp)
* References: frexp
*/
@@ -163,7 +255,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
unittest {
assert(ldexp(1, -16384) == 0x1p-16384L);
assert(ldexp(1, -16382) == 0x1p-16382L);
@@ -1608,7 +1643,31 @@
@@ -1608,7 +1645,31 @@
* $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) )
* )
*/
@@ -196,9 +288,27 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
/***********************************************************************
@@ -2993,9 +3054,15 @@
assert(pow(x,eight) == (x * x) * (x * x) * (x * x) * (x * x));
assert(pow(x, neg1) == 1 / x);
- assert(pow(xd, neg2) == 1 / (x * x));
+ version(LDC) // FIXME:
+ assert(pow(xd, neg2) == 1 / (xd * xd));
+ else
+ assert(pow(xd, neg2) == 1 / (x * x));
assert(pow(x, neg3) == 1 / (x * x * x));
- assert(pow(xf, neg8) == 1 / ((x * x) * (x * x) * (x * x) * (x * x)));
+ version(LDC)
+ assert(pow(xf, neg8) == 1 / ((xf * xf) * (xf * xf) * (xf * xf) * (xf * xf)));
+ else
+ assert(pow(xf, neg8) == 1 / ((x * x) * (x * x) * (x * x) * (x * x)));
}
/** 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.480925001 +0400
+++ phobos/std/openrj.d 2010-10-26 13:17:37.000000000 +0400
@@ -620,11 +620,11 @@
/**
*
@@ -241,3 +351,24 @@ 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
@@ -308,8 +308,15 @@
void printf(string format, ...)
{
va_list ap;
- ap = cast(va_list)&format;
- ap += format.sizeof;
+ version(LDC)
+ {
+ ap = _argptr;
+ }
+ else
+ {
+ ap = cast(va_list)&format;
+ ap += format.sizeof;
+ }
vprintf(format, ap);
}

View File

@@ -80,7 +80,7 @@ elseif(D_VERSION EQUAL 2)
${RUNTIME_DC_DIR}/deh2.d
)
file(GLOB DCRT_C ${RUNTIME_DC_DIR}/*.c)
list(REMOVE_ITEM DCRT_C ${RUNTIME_DC_DIR}/deh.c)
list(REMOVE_ITEM DCRT_C ${RUNTIME_DC_DIR}/deh.c ${RUNTIME_DC_DIR}/memory_osx.c)
if(UNIX)
file(GLOB_RECURSE CORE_D_SYS ${RUNTIME_DIR}/src/core/sys/posix/*.d)
elseif(WIN32)
@@ -109,12 +109,19 @@ elseif(D_VERSION EQUAL 2)
list(REMOVE_ITEM ZLIB_C
${PHOBOS2_DIR}/etc/c/zlib/minigzip.c
${PHOBOS2_DIR}/etc/c/zlib/example.c
${PHOBOS2_DIR}/etc/c/zlib/gzio.c
)
if(WIN32)
file(GLOB PHOBOS2_D_WIN ${PHOBOS2_DIR}/std/windows/*.d)
endif(WIN32)
list(APPEND PHOBOS2_D ${PHOBOS2_D_MATH} ${PHOBOS2_D_WIN}
${PHOBOS2_D_C} ${PHOBOS2_D_C_SYS})
list(APPEND PHOBOS2_D
${PHOBOS2_D_MATH}
${PHOBOS2_D_WIN}
${PHOBOS2_D_C}
${PHOBOS2_D_C_SYS}
${PHOBOS2_DIR}/etc/c/zlib.d
${PHOBOS2_DIR}/crc32.d
)
endif(PHOBOS2_DIR)
endif(D_VERSION EQUAL 1)
@@ -166,7 +173,11 @@ macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH)
endif ("${PATH}" STREQUAL "")
get_filename_component(name ${output} NAME_WE)
get_filename_component(path ${output} PATH)
set(output ${path}/${name})
if ("${path}" STREQUAL "")
set(output ${name})
else ("${path}" STREQUAL "")
set(output ${path}/${name})
endif ("${path}" STREQUAL "")
set(OUTPUT_O ${PROJECT_BINARY_DIR}/${output}.o)
set(OUTPUT_BC ${PROJECT_BINARY_DIR}/${output}.bc)
list(APPEND ${OUTLIST_O} ${OUTPUT_O})
@@ -244,10 +255,12 @@ if(BUILD_BC_LIBS)
endif(BUILD_BC_LIBS)
set_target_properties(
${LIBS} PROPERTIES
LINKER_LANGUAGE C
ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib
${LIBS} PROPERTIES
LINKER_LANGUAGE C
ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib
COMPILE_FLAGS "-m32"
LINK_FLAGS "-m32"
)
# BCLIBS is empty if BUILD_BC_LIBS is not selected
@@ -260,4 +273,12 @@ if(PHOBOS2_DIR)
add_library(phobos2 ${ZLIB_C} ${PHOBOS2_O})
add_dependencies(phobos2 runtime)
set_target_properties(
phobos2 PROPERTIES
LINKER_LANGUAGE C
ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib
LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/../lib
COMPILE_FLAGS "-m32"
LINK_FLAGS "-m32"
)
endif(PHOBOS2_DIR)