mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-10 08:53:13 +01:00
Merged
This commit is contained in:
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
57
dmd2/func.c
57
dmd2/func.c
@@ -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()
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[].
|
||||
|
||||
111
dmd2/mtype.c
111
dmd2/mtype.c
@@ -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();
|
||||
|
||||
12
dmd2/mtype.h
12
dmd2/mtype.h
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
78
dmd2/parse.c
78
dmd2/parse.c
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
758
druntime.patch
758
druntime.patch
@@ -1,6 +1,6 @@
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-orig/import/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
|
||||
|
||||
16
gen/aa.cpp
16
gen/aa.cpp
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
259
gen/nested.cpp
259
gen/nested.cpp
@@ -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);
|
||||
}
|
||||
|
||||
14
gen/nested.h
14
gen/nested.h
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
88
gen/toir.cpp
88
gen/toir.cpp
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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);
|
||||
|
||||
142
gen/toobj.cpp
142
gen/toobj.cpp
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ IrFunction::IrFunction(FuncDeclaration* fd)
|
||||
nestedVar = NULL;
|
||||
frameType = NULL;
|
||||
depth = -1;
|
||||
nestedContextCreated = false;
|
||||
|
||||
_arguments = NULL;
|
||||
_argptr = NULL;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
169
phobos.patch
169
phobos.patch
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user