mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
[svn r135] * Merged DMD 1.025 *
* Fixed a minor linking order mishap * * Added an command line option -annotate * * Fixed some problems with running optimizations * * Added std.stdio and dependencies to lphobos (still not 100% working, but compiles and links) * * Fixed problems with passing aggregate types to variadic functions * * Added initial code towards full GC support, currently based on malloc and friends, not all the runtime calls the GC yet for memory * * Fixed problems with resolving nested function context pointers for some heavily nested cases * * Redid function argument passing + other minor code cleanups, still lots to do on this end... *
This commit is contained in:
158
dmd/cast.c
158
dmd/cast.c
@@ -547,30 +547,27 @@ MATCH CondExp::implicitConvTo(Type *t)
|
||||
*/
|
||||
|
||||
Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
{ Expression *e;
|
||||
Type *tb;
|
||||
|
||||
{
|
||||
//printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars());
|
||||
#if 0
|
||||
printf("Expression::castTo(this=%s, type=%s, t=%s)\n",
|
||||
toChars(), type->toChars(), t->toChars());
|
||||
#endif
|
||||
e = this;
|
||||
tb = t->toBasetype();
|
||||
type = type->toBasetype();
|
||||
if (tb != type)
|
||||
if (type == t)
|
||||
return this;
|
||||
Expression *e = this;
|
||||
Type *tb = t->toBasetype();
|
||||
Type *typeb = type->toBasetype();
|
||||
if (tb != typeb)
|
||||
{
|
||||
if (tb->ty == Tbit && isBit())
|
||||
;
|
||||
|
||||
// Do (type *) cast of (type [dim])
|
||||
else if (tb->ty == Tpointer &&
|
||||
type->ty == Tsarray
|
||||
if (tb->ty == Tpointer &&
|
||||
typeb->ty == Tsarray
|
||||
)
|
||||
{
|
||||
//printf("Converting [dim] to *\n");
|
||||
|
||||
if (type->size(loc) == 0)
|
||||
if (typeb->size(loc) == 0)
|
||||
e = new NullExp(loc);
|
||||
else
|
||||
e = new AddrExp(loc, e);
|
||||
@@ -579,8 +576,8 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
else if (tb->ty == Tdelegate && type->ty != Tdelegate)
|
||||
{
|
||||
TypeDelegate *td = (TypeDelegate *)tb;
|
||||
TypeFunction *tf = (TypeFunction *)td->next;
|
||||
return toDelegate(sc, tf->next);
|
||||
TypeFunction *tf = (TypeFunction *)td->nextOf();
|
||||
return toDelegate(sc, tf->nextOf());
|
||||
}
|
||||
#endif
|
||||
else
|
||||
@@ -588,6 +585,11 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
e = new CastExp(loc, e, tb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e = e->copy(); // because of COW for assignment to e->type
|
||||
}
|
||||
assert(e != this);
|
||||
e->type = t;
|
||||
//printf("Returning: %s\n", e->toChars());
|
||||
return e;
|
||||
@@ -595,47 +597,62 @@ Expression *Expression::castTo(Scope *sc, Type *t)
|
||||
|
||||
|
||||
Expression *RealExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
if (type->isreal() && t->isreal())
|
||||
type = t;
|
||||
else if (type->isimaginary() && t->isimaginary())
|
||||
type = t;
|
||||
else
|
||||
return Expression::castTo(sc, t);
|
||||
return this;
|
||||
{ Expression *e = this;
|
||||
if (type != t)
|
||||
{
|
||||
if ((type->isreal() && t->isreal()) ||
|
||||
(type->isimaginary() && t->isimaginary())
|
||||
)
|
||||
{ e = copy();
|
||||
e->type = t;
|
||||
}
|
||||
else
|
||||
e = Expression::castTo(sc, t);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *ComplexExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
if (type->iscomplex() && t->iscomplex())
|
||||
type = t;
|
||||
else
|
||||
return Expression::castTo(sc, t);
|
||||
return this;
|
||||
{ Expression *e = this;
|
||||
if (type != t)
|
||||
{
|
||||
if (type->iscomplex() && t->iscomplex())
|
||||
{ e = copy();
|
||||
e->type = t;
|
||||
}
|
||||
else
|
||||
e = Expression::castTo(sc, t);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *NullExp::castTo(Scope *sc, Type *t)
|
||||
{ Expression *e;
|
||||
{ NullExp *e;
|
||||
Type *tb;
|
||||
|
||||
//printf("NullExp::castTo(t = %p)\n", t);
|
||||
committed = 1;
|
||||
e = this;
|
||||
if (type == t)
|
||||
{
|
||||
committed = 1;
|
||||
return this;
|
||||
}
|
||||
e = (NullExp *)copy();
|
||||
e->committed = 1;
|
||||
tb = t->toBasetype();
|
||||
type = type->toBasetype();
|
||||
if (tb != type)
|
||||
e->type = type->toBasetype();
|
||||
if (tb != e->type)
|
||||
{
|
||||
// NULL implicitly converts to any pointer type or dynamic array
|
||||
if (type->ty == Tpointer && type->next->ty == Tvoid &&
|
||||
if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
|
||||
(tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray ||
|
||||
tb->ty == Tdelegate))
|
||||
{
|
||||
#if 0
|
||||
if (tb->ty == Tdelegate)
|
||||
{ TypeDelegate *td = (TypeDelegate *)tb;
|
||||
TypeFunction *tf = (TypeFunction *)td->next;
|
||||
TypeFunction *tf = (TypeFunction *)td->nextOf();
|
||||
|
||||
if (!tf->varargs &&
|
||||
!(tf->arguments && tf->arguments->dim)
|
||||
@@ -648,8 +665,7 @@ Expression *NullExp::castTo(Scope *sc, Type *t)
|
||||
}
|
||||
else
|
||||
{
|
||||
return Expression::castTo(sc, t);
|
||||
//e = new CastExp(loc, e, tb);
|
||||
return e->Expression::castTo(sc, t);
|
||||
}
|
||||
}
|
||||
e->type = t;
|
||||
@@ -919,23 +935,31 @@ Expression *AddrExp::castTo(Scope *sc, Type *t)
|
||||
|
||||
|
||||
Expression *TupleExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = (Expression *)exps->data[i];
|
||||
e = e->castTo(sc, t);
|
||||
exps->data[i] = (void *)e;
|
||||
{ TupleExp *e = (TupleExp *)copy();
|
||||
e->exps = (Expressions *)exps->copy();
|
||||
for (size_t i = 0; i < e->exps->dim; i++)
|
||||
{ Expression *ex = (Expression *)e->exps->data[i];
|
||||
ex = ex->castTo(sc, t);
|
||||
e->exps->data[i] = (void *)ex;
|
||||
}
|
||||
return this;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
#if 0
|
||||
printf("ArrayLiteralExp::castTo(this=%s, type=%s, t=%s)\n",
|
||||
toChars(), type->toChars(), t->toChars());
|
||||
#endif
|
||||
if (type == t)
|
||||
return this;
|
||||
ArrayLiteralExp *e = this;
|
||||
Type *typeb = type->toBasetype();
|
||||
Type *tb = t->toBasetype();
|
||||
if ((tb->ty == Tarray || tb->ty == Tsarray) &&
|
||||
(typeb->ty == Tarray || typeb->ty == Tsarray) &&
|
||||
tb->next->toBasetype()->ty != Tvoid)
|
||||
tb->nextOf()->toBasetype()->ty != Tvoid)
|
||||
{
|
||||
if (tb->ty == Tsarray)
|
||||
{ TypeSArray *tsa = (TypeSArray *)tb;
|
||||
@@ -943,46 +967,56 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
|
||||
goto L1;
|
||||
}
|
||||
|
||||
e = (ArrayLiteralExp *)copy();
|
||||
e->elements = (Expressions *)elements->copy();
|
||||
for (int i = 0; i < elements->dim; i++)
|
||||
{ Expression *e = (Expression *)elements->data[i];
|
||||
e = e->castTo(sc, tb->next);
|
||||
elements->data[i] = (void *)e;
|
||||
{ Expression *ex = (Expression *)elements->data[i];
|
||||
ex = ex->castTo(sc, tb->nextOf());
|
||||
e->elements->data[i] = (void *)ex;
|
||||
}
|
||||
type = t;
|
||||
return this;
|
||||
e->type = t;
|
||||
return e;
|
||||
}
|
||||
if (tb->ty == Tpointer && typeb->ty == Tsarray)
|
||||
{
|
||||
type = typeb->next->pointerTo();
|
||||
e = (ArrayLiteralExp *)copy();
|
||||
e->type = typeb->nextOf()->pointerTo();
|
||||
}
|
||||
L1:
|
||||
return Expression::castTo(sc, t);
|
||||
return e->Expression::castTo(sc, t);
|
||||
}
|
||||
|
||||
Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
if (type == t)
|
||||
return this;
|
||||
AssocArrayLiteralExp *e = this;
|
||||
Type *typeb = type->toBasetype();
|
||||
Type *tb = t->toBasetype();
|
||||
if (tb->ty == Taarray && typeb->ty == Taarray &&
|
||||
tb->next->toBasetype()->ty != Tvoid)
|
||||
tb->nextOf()->toBasetype()->ty != Tvoid)
|
||||
{
|
||||
e = (AssocArrayLiteralExp *)copy();
|
||||
e->keys = (Expressions *)keys->copy();
|
||||
e->values = (Expressions *)values->copy();
|
||||
assert(keys->dim == values->dim);
|
||||
for (size_t i = 0; i < keys->dim; i++)
|
||||
{ Expression *e = (Expression *)values->data[i];
|
||||
e = e->castTo(sc, tb->next);
|
||||
values->data[i] = (void *)e;
|
||||
{ Expression *ex = (Expression *)values->data[i];
|
||||
ex = ex->castTo(sc, tb->nextOf());
|
||||
e->values->data[i] = (void *)ex;
|
||||
|
||||
e = (Expression *)keys->data[i];
|
||||
e = e->castTo(sc, ((TypeAArray *)tb)->key);
|
||||
keys->data[i] = (void *)e;
|
||||
ex = (Expression *)keys->data[i];
|
||||
ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
|
||||
e->keys->data[i] = (void *)ex;
|
||||
}
|
||||
type = t;
|
||||
return this;
|
||||
e->type = t;
|
||||
return e;
|
||||
}
|
||||
L1:
|
||||
return Expression::castTo(sc, t);
|
||||
return e->Expression::castTo(sc, t);
|
||||
}
|
||||
|
||||
|
||||
Expression *SymOffExp::castTo(Scope *sc, Type *t)
|
||||
{
|
||||
Type *tb;
|
||||
|
||||
@@ -1760,7 +1760,7 @@ Lagain:
|
||||
em = s->isEnumMember();
|
||||
if (em)
|
||||
{
|
||||
e = em->value;
|
||||
e = em->value->copy();
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
||||
s = ad->search(loc, id, 0);
|
||||
if (!s)
|
||||
{
|
||||
error("'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ Expression *interpret_aaValues(InterState *istate, Expressions *arguments);
|
||||
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments)
|
||||
{
|
||||
#if LOG
|
||||
printf("FuncDeclaration::interpret() %s\n", toChars());
|
||||
printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars());
|
||||
printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun);
|
||||
#endif
|
||||
if (global.errors)
|
||||
@@ -161,7 +161,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
else
|
||||
{ /* Value parameters
|
||||
*/
|
||||
earg = earg->interpret(&istatex);
|
||||
Type *ta = arg->type->toBasetype();
|
||||
if (ta->ty == Tsarray && earg->op == TOKaddress)
|
||||
{
|
||||
/* Static arrays are passed by a simple pointer.
|
||||
* Skip past this to get at the actual arg.
|
||||
*/
|
||||
earg = ((AddrExp *)earg)->e1;
|
||||
}
|
||||
earg = earg->interpret(istate ? istate : &istatex);
|
||||
if (earg == EXP_CANT_INTERPRET)
|
||||
return NULL;
|
||||
v->value = earg;
|
||||
@@ -177,13 +185,13 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
Expressions valueSaves;
|
||||
if (istate)
|
||||
{
|
||||
//printf("saving state...\n");
|
||||
//printf("saving local variables...\n");
|
||||
valueSaves.setDim(istate->vars.dim);
|
||||
for (size_t i = 0; i < istate->vars.dim; i++)
|
||||
{ VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
|
||||
if (v)
|
||||
{
|
||||
//printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value->toChars());
|
||||
//printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
|
||||
valueSaves.data[i] = v->value;
|
||||
v->value = NULL;
|
||||
}
|
||||
@@ -230,10 +238,13 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
{
|
||||
/* Restore the variable values
|
||||
*/
|
||||
//printf("restoring local variables...\n");
|
||||
for (size_t i = 0; i < istate->vars.dim; i++)
|
||||
{ VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
|
||||
if (v)
|
||||
v->value = (Expression *)valueSaves.data[i];
|
||||
{ v->value = (Expression *)valueSaves.data[i];
|
||||
//printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,6 +915,8 @@ Expression *Expression::interpret(InterState *istate)
|
||||
{
|
||||
#if LOG
|
||||
printf("Expression::interpret() %s\n", toChars());
|
||||
printf("type = %s\n", type->toChars());
|
||||
dump(0);
|
||||
#endif
|
||||
return EXP_CANT_INTERPRET;
|
||||
}
|
||||
@@ -949,7 +962,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
|
||||
SymbolDeclaration *s = d->isSymbolDeclaration();
|
||||
if (v)
|
||||
{
|
||||
#if V2
|
||||
if ((v->isConst() || v->isInvariant()) && v->init && !v->value)
|
||||
#else
|
||||
if (v->isConst() && v->init)
|
||||
#endif
|
||||
{ e = v->init->toExpression();
|
||||
if (e && !e->type)
|
||||
e->type = v->type;
|
||||
@@ -1001,7 +1018,11 @@ Expression *DeclarationExp::interpret(InterState *istate)
|
||||
else if (v->init->isVoidInitializer())
|
||||
e = NULL;
|
||||
}
|
||||
#if V2
|
||||
else if (s == v && (v->isConst() || v->isInvariant()) && v->init)
|
||||
#else
|
||||
else if (s == v && v->isConst() && v->init)
|
||||
#endif
|
||||
{ e = v->init->toExpression();
|
||||
if (!e)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
@@ -1416,8 +1437,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
*/
|
||||
if (v->value && v->value->op == TOKvar)
|
||||
{
|
||||
ve = (VarExp *)v->value;
|
||||
v = ve->var->isVarDeclaration();
|
||||
VarExp *ve2 = (VarExp *)v->value;
|
||||
if (ve2->var->isSymbolDeclaration())
|
||||
{
|
||||
/* This can happen if v is a struct initialized to
|
||||
* 0 using an __initZ SymbolDeclaration from
|
||||
* TypeStruct::defaultInit()
|
||||
*/
|
||||
}
|
||||
else
|
||||
v = ve2->var->isVarDeclaration();
|
||||
assert(v);
|
||||
}
|
||||
|
||||
@@ -1445,6 +1474,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
||||
{
|
||||
if (i == istate->vars.dim)
|
||||
{ istate->vars.push(v);
|
||||
//printf("\tadding %s to istate\n", v->toChars());
|
||||
break;
|
||||
}
|
||||
if (v == (VarDeclaration *)istate->vars.data[i])
|
||||
@@ -1797,7 +1827,27 @@ Expression *CallExp::interpret(InterState *istate)
|
||||
{
|
||||
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
|
||||
if (fd)
|
||||
{ // Inline .dup
|
||||
{
|
||||
#if V2
|
||||
enum BUILTIN b = fd->isBuiltin();
|
||||
if (b)
|
||||
{ Expressions args;
|
||||
args.setDim(arguments->dim);
|
||||
for (size_t i = 0; i < args.dim; i++)
|
||||
{
|
||||
Expression *earg = (Expression *)arguments->data[i];
|
||||
earg = earg->interpret(istate);
|
||||
if (earg == EXP_CANT_INTERPRET)
|
||||
return earg;
|
||||
args.data[i] = (void *)earg;
|
||||
}
|
||||
e = eval_builtin(b, &args);
|
||||
if (!e)
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// Inline .dup
|
||||
if (fd->ident == Id::adDup && arguments && arguments->dim == 2)
|
||||
{
|
||||
e = (Expression *)arguments->data[1];
|
||||
@@ -1812,7 +1862,7 @@ Expression *CallExp::interpret(InterState *istate)
|
||||
Expression *eresult = fd->interpret(istate, arguments);
|
||||
if (eresult)
|
||||
e = eresult;
|
||||
else if (fd->type->toBasetype()->nextOf()->ty == Tvoid)
|
||||
else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
|
||||
e = EXP_VOID_INTERPRET;
|
||||
else
|
||||
error("cannot evaluate %s at compile time", toChars());
|
||||
|
||||
@@ -283,15 +283,15 @@ int runLINK()
|
||||
* passed with -l.
|
||||
*/
|
||||
|
||||
//argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a
|
||||
argv.push((void *)"-lpthread");
|
||||
argv.push((void *)"-lm");
|
||||
|
||||
std::string corelibpath = global.params.runtimeImppath;
|
||||
corelibpath.append("/llvmdcore.bc");
|
||||
argv.append(global.params.objfiles);
|
||||
argv.push((void *)corelibpath.c_str());
|
||||
|
||||
//argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a
|
||||
//argv.push((void *)"-lpthread");
|
||||
argv.push((void *)"-l=m");
|
||||
|
||||
if (!global.params.quiet)
|
||||
{
|
||||
// Print it
|
||||
|
||||
10
dmd/mars.c
10
dmd/mars.c
@@ -71,7 +71,7 @@ Global::Global()
|
||||
copyright = "Copyright (c) 1999-2007 by Digital Mars and Tomas Lindquist Olsen";
|
||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||
llvmdc_version = "0.1";
|
||||
version = "v1.024";
|
||||
version = "v1.025";
|
||||
global.structalign = 8;
|
||||
|
||||
memset(¶ms, 0, sizeof(Param));
|
||||
@@ -167,6 +167,7 @@ Usage:\n\
|
||||
dmd files.d ... { -switch }\n\
|
||||
\n\
|
||||
files.d D source files\n%s\
|
||||
-annotate annotate the bitcode with human readable source code\n\
|
||||
-c do not link\n\
|
||||
-cov do code coverage analysis\n\
|
||||
-D generate documentation\n\
|
||||
@@ -290,7 +291,7 @@ int main(int argc, char *argv[])
|
||||
global.params.forceBE = 0;
|
||||
global.params.noruntime = 0;
|
||||
global.params.novalidate = 0;
|
||||
global.params.optimizeLevel = 2;
|
||||
global.params.optimizeLevel = -1;
|
||||
global.params.runtimeImppath = 0;
|
||||
|
||||
global.params.defaultlibname = "phobos";
|
||||
@@ -370,6 +371,7 @@ int main(int argc, char *argv[])
|
||||
else if (p[1] == 'O')
|
||||
{
|
||||
global.params.optimize = 1;
|
||||
global.params.optimizeLevel = 2;
|
||||
if (p[2] != 0) {
|
||||
int optlevel = atoi(p+2);
|
||||
if (optlevel < 0 || optlevel > 5) {
|
||||
@@ -389,6 +391,8 @@ int main(int argc, char *argv[])
|
||||
global.params.novalidate = 1;
|
||||
else if (strcmp(p + 1, "dis") == 0)
|
||||
global.params.disassemble = 1;
|
||||
else if (strcmp(p + 1, "annotate") == 0)
|
||||
global.params.llvmAnnotate = 1;
|
||||
else if (p[1] == 'o')
|
||||
{
|
||||
switch (p[2])
|
||||
@@ -683,6 +687,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (strcmp(global.params.llvmArch,"x86")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("X86");
|
||||
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86");
|
||||
global.params.isLE = true;
|
||||
global.params.is64bit = false;
|
||||
tt_arch = "i686";
|
||||
@@ -690,6 +695,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else if (strcmp(global.params.llvmArch,"x86-64")==0) {
|
||||
VersionCondition::addPredefinedGlobalIdent("X86_64");
|
||||
//VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64");
|
||||
global.params.isLE = true;
|
||||
global.params.is64bit = true;
|
||||
tt_arch = "x86_64";
|
||||
|
||||
@@ -130,6 +130,7 @@ struct Param
|
||||
char *data_layout;
|
||||
char disassemble;
|
||||
char llvmInline;
|
||||
char llvmAnnotate;
|
||||
};
|
||||
|
||||
struct Global
|
||||
|
||||
@@ -5077,7 +5077,6 @@ Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Express
|
||||
this->ident = ident;
|
||||
this->storageClass = storageClass;
|
||||
this->defaultArg = defaultArg;
|
||||
this->llvmCopy = false;
|
||||
this->vardecl = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -692,7 +692,6 @@ struct Argument : Object
|
||||
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
|
||||
|
||||
// backend
|
||||
bool llvmCopy;
|
||||
VarDeclaration* vardecl;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "gen/functions.h"
|
||||
#include "gen/todebug.h"
|
||||
#include "gen/classes.h"
|
||||
#include "gen/dvalue.h"
|
||||
|
||||
const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
|
||||
{
|
||||
@@ -90,13 +91,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
Type* argT = DtoDType(arg->type);
|
||||
assert(argT);
|
||||
|
||||
if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
|
||||
//assert(arg->vardecl);
|
||||
//arg->vardecl->refparam = true;
|
||||
}
|
||||
else
|
||||
arg->llvmCopy = true;
|
||||
|
||||
const llvm::Type* at = DtoType(argT);
|
||||
if (isaStruct(at)) {
|
||||
Logger::println("struct param");
|
||||
@@ -114,8 +108,8 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
|
||||
paramvec.push_back(llvm::PointerType::get(at));
|
||||
}
|
||||
else {
|
||||
if (!arg->llvmCopy) {
|
||||
Logger::println("ref param");
|
||||
if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
|
||||
Logger::println("by ref param");
|
||||
at = llvm::PointerType::get(at);
|
||||
}
|
||||
else {
|
||||
@@ -509,8 +503,8 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||
if (global.params.symdebug) DtoDwarfFuncStart(fd);
|
||||
|
||||
llvm::Value* parentNested = NULL;
|
||||
if (FuncDeclaration* fd2 = fd->toParent()->isFuncDeclaration()) {
|
||||
if (!fd->isStatic())
|
||||
if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) {
|
||||
if (!fd->isStatic()) // huh?
|
||||
parentNested = fd2->llvmNested;
|
||||
}
|
||||
|
||||
@@ -722,3 +716,47 @@ const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DValue* DtoArgument(Argument* fnarg, Expression* argexp)
|
||||
{
|
||||
Logger::println("DtoArgument");
|
||||
LOG_SCOPE;
|
||||
|
||||
DValue* arg = argexp->toElem(gIR);
|
||||
|
||||
// ref/out arg
|
||||
if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout)))
|
||||
{
|
||||
if (arg->isVar() || arg->isLRValue())
|
||||
arg = new DImValue(argexp->type, arg->getLVal(), false);
|
||||
else
|
||||
arg = new DImValue(argexp->type, arg->getRVal(), false);
|
||||
}
|
||||
// aggregate arg
|
||||
else if (DtoIsPassedByRef(argexp->type))
|
||||
{
|
||||
llvm::Value* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
|
||||
DVarValue* vv = new DVarValue(argexp->type, alloc, true);
|
||||
DtoAssign(vv, arg);
|
||||
arg = vv;
|
||||
}
|
||||
// normal arg (basic/value type)
|
||||
else
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoVariadicArgument(Expression* argexp, llvm::Value* dst)
|
||||
{
|
||||
Logger::println("DtoVariadicArgument");
|
||||
LOG_SCOPE;
|
||||
DVarValue* vv = new DVarValue(argexp->type, dst, true);
|
||||
DtoAssign(vv, argexp->toElem(gIR));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -10,6 +10,9 @@ void DtoResolveFunction(FuncDeclaration* fdecl);
|
||||
void DtoDeclareFunction(FuncDeclaration* fdecl);
|
||||
void DtoDefineFunc(FuncDeclaration* fd);
|
||||
|
||||
DValue* DtoArgument(Argument* fnarg, Expression* argexp);
|
||||
void DtoVariadicArgument(Expression* argexp, llvm::Value* dst);
|
||||
|
||||
void DtoMain();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,30 +13,30 @@ namespace Logger
|
||||
static std::string indent_str;
|
||||
static std::ofstream null_out("/dev/null");
|
||||
|
||||
static bool enabled = false;
|
||||
static bool _enabled = false;
|
||||
void indent()
|
||||
{
|
||||
if (enabled) {
|
||||
if (_enabled) {
|
||||
indent_str += "* ";
|
||||
}
|
||||
}
|
||||
void undent()
|
||||
{
|
||||
if (enabled) {
|
||||
if (_enabled) {
|
||||
assert(!indent_str.empty());
|
||||
indent_str.resize(indent_str.size()-2);
|
||||
}
|
||||
}
|
||||
std::ostream& cout()
|
||||
{
|
||||
if (enabled)
|
||||
if (_enabled)
|
||||
return std::cout << indent_str;
|
||||
else
|
||||
return null_out;
|
||||
}
|
||||
void println(const char* fmt,...)
|
||||
{
|
||||
if (enabled) {
|
||||
if (_enabled) {
|
||||
printf(indent_str.c_str());
|
||||
va_list va;
|
||||
va_start(va,fmt);
|
||||
@@ -47,7 +47,7 @@ namespace Logger
|
||||
}
|
||||
void print(const char* fmt,...)
|
||||
{
|
||||
if (enabled) {
|
||||
if (_enabled) {
|
||||
printf(indent_str.c_str());
|
||||
va_list va;
|
||||
va_start(va,fmt);
|
||||
@@ -57,11 +57,15 @@ namespace Logger
|
||||
}
|
||||
void enable()
|
||||
{
|
||||
enabled = true;
|
||||
_enabled = true;
|
||||
}
|
||||
void disable()
|
||||
{
|
||||
enabled = false;
|
||||
_enabled = false;
|
||||
}
|
||||
bool enabled()
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
void attention(const char* fmt,...)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Logger
|
||||
void print(const char* fmt, ...);
|
||||
void enable();
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
void attention(const char* fmt, ...);
|
||||
|
||||
|
||||
@@ -12,11 +12,22 @@ using namespace llvm;
|
||||
|
||||
void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
{
|
||||
if (!doinline && lvl < 0)
|
||||
return;
|
||||
|
||||
assert(lvl >= 0 && lvl <= 5);
|
||||
|
||||
PassManager pm;
|
||||
pm.add(new TargetData(m));
|
||||
|
||||
// -O0
|
||||
if (lvl >= 0)
|
||||
{
|
||||
//pm.add(createStripDeadPrototypesPass());
|
||||
pm.add(createGlobalDCEPass());
|
||||
}
|
||||
|
||||
// -O1
|
||||
if (lvl >= 1)
|
||||
{
|
||||
pm.add(createRaiseAllocationsPass());
|
||||
@@ -26,6 +37,7 @@ void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
pm.add(createGlobalDCEPass());
|
||||
}
|
||||
|
||||
// -O2
|
||||
if (lvl >= 2)
|
||||
{
|
||||
pm.add(createIPConstantPropagationPass());
|
||||
@@ -35,10 +47,12 @@ void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
pm.add(createPruneEHPass());
|
||||
}
|
||||
|
||||
// -inline
|
||||
if (doinline) {
|
||||
pm.add(createFunctionInliningPass());
|
||||
}
|
||||
|
||||
// -O3
|
||||
if (lvl >= 3)
|
||||
{
|
||||
pm.add(createArgumentPromotionPass());
|
||||
@@ -73,8 +87,7 @@ void llvmdc_optimize_module(Module* m, char lvl, bool doinline)
|
||||
pm.add(createConstantMergePass());
|
||||
}
|
||||
|
||||
// level 4 and 5 are linktime optimizations
|
||||
// level -O4 and -O5 are linktime optimizations
|
||||
|
||||
if (lvl > 0 || doinline)
|
||||
pm.run(*m);
|
||||
pm.run(*m);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "gen/llvm.h"
|
||||
#include "llvm/InlineAsm.h"
|
||||
|
||||
#include "total.h"
|
||||
#include "init.h"
|
||||
@@ -129,6 +130,9 @@ void ExpStatement::toIR(IRState* p)
|
||||
Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
if (global.params.llvmAnnotate)
|
||||
DtoAnnotation(exp->toChars());
|
||||
|
||||
if (global.params.symdebug)
|
||||
DtoDwarfStopPoint(loc.linnum);
|
||||
|
||||
@@ -146,8 +150,7 @@ void ExpStatement::toIR(IRState* p)
|
||||
|
||||
void IfStatement::toIR(IRState* p)
|
||||
{
|
||||
static int wsi = 0;
|
||||
Logger::println("IfStatement::toIR(%d): %s", wsi++, toChars());
|
||||
Logger::println("IfStatement::toIR()");
|
||||
LOG_SCOPE;
|
||||
|
||||
DValue* cond_e = condition->toElem(p);
|
||||
@@ -983,6 +986,40 @@ void SynchronizedStatement::toIR(IRState* p)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AsmStatement::toIR(IRState* p)
|
||||
{
|
||||
Logger::println("AsmStatement::toIR(): %s", toChars());
|
||||
LOG_SCOPE;
|
||||
error("%s: inline asm is not yet implemented", loc.toChars());
|
||||
fatal();
|
||||
|
||||
assert(!asmcode && !asmalign && !refparam && !naked && !regs);
|
||||
|
||||
Token* t = tokens;
|
||||
assert(t);
|
||||
|
||||
std::string asmstr;
|
||||
|
||||
do {
|
||||
Logger::println("token: %s", t->toChars());
|
||||
asmstr.append(t->toChars());
|
||||
asmstr.append(" ");
|
||||
} while (t = t->next);
|
||||
|
||||
Logger::println("asm expr = '%s'", asmstr.c_str());
|
||||
|
||||
// create function type
|
||||
std::vector<const llvm::Type*> args;
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(DtoSize_t(), args, false);
|
||||
|
||||
// create inline asm callee
|
||||
llvm::InlineAsm* inasm = llvm::InlineAsm::get(fty, asmstr, "r,r", false);
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
|
||||
@@ -1004,7 +1041,7 @@ STUBST(Statement);
|
||||
//STUBST(ExpStatement);
|
||||
//STUBST(CompoundStatement);
|
||||
//STUBST(ScopeStatement);
|
||||
STUBST(AsmStatement);
|
||||
//STUBST(AsmStatement);
|
||||
//STUBST(TryCatchStatement);
|
||||
//STUBST(TryFinallyStatement);
|
||||
STUBST(VolatileStatement);
|
||||
|
||||
@@ -120,10 +120,10 @@ llvm::GlobalVariable* DtoDwarfCompileUnit(Module* m, bool define)
|
||||
DtoConstUint(llvm::LLVMDebugVersion)));
|
||||
vals.push_back(dbgToArrTy(GetDwarfAnchor(DW_TAG_compile_unit)));
|
||||
|
||||
vals.push_back(DtoConstUint(DW_LANG_D));
|
||||
vals.push_back(DtoConstUint(DW_LANG_C));// _D)); // doesn't seem to work
|
||||
vals.push_back(DtoConstStringPtr(m->srcfile->name->toChars(), "llvm.metadata"));
|
||||
std::string srcpath(FileName::path(m->srcfile->name->toChars()));
|
||||
srcpath.append("/");
|
||||
//srcpath.append("/");
|
||||
vals.push_back(DtoConstStringPtr(srcpath.c_str(), "llvm.metadata"));
|
||||
vals.push_back(DtoConstStringPtr("LLVMDC (http://www.dsource.org/projects/llvmdc)", "llvm.metadata"));
|
||||
|
||||
|
||||
89
gen/toir.cpp
89
gen/toir.cpp
@@ -31,6 +31,7 @@
|
||||
#include "gen/complex.h"
|
||||
#include "gen/dvalue.h"
|
||||
#include "gen/aa.h"
|
||||
#include "gen/functions.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -51,6 +52,9 @@ DValue* DeclarationExp::toElem(IRState* p)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (global.params.llvmAnnotate)
|
||||
DtoAnnotation(toChars());
|
||||
|
||||
Logger::println("vdtype = %s", vd->type->toChars());
|
||||
// referenced by nested delegate?
|
||||
if (vd->nestedref) {
|
||||
@@ -600,7 +604,16 @@ DValue* AddAssignExp::toElem(IRState* p)
|
||||
}
|
||||
DtoAssign(l, res);
|
||||
|
||||
return l;
|
||||
// used as lvalue :/
|
||||
if (p->topexp() && p->topexp()->e1 == this)
|
||||
{
|
||||
assert(!l->isLRValue());
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -650,6 +663,7 @@ DValue* MinAssignExp::toElem(IRState* p)
|
||||
|
||||
DValue* res;
|
||||
if (DtoDType(e1->type)->ty == Tpointer) {
|
||||
Logger::println("ptr");
|
||||
llvm::Value* tmp = r->getRVal();
|
||||
llvm::Value* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
|
||||
tmp = llvm::BinaryOperator::createSub(zero,tmp,"tmp",p->scopebb());
|
||||
@@ -657,9 +671,11 @@ DValue* MinAssignExp::toElem(IRState* p)
|
||||
res = new DImValue(type, tmp);
|
||||
}
|
||||
else if (t->iscomplex()) {
|
||||
Logger::println("complex");
|
||||
res = DtoComplexSub(type, l, r);
|
||||
}
|
||||
else {
|
||||
Logger::println("basic");
|
||||
res = DtoBinSub(l,r);
|
||||
}
|
||||
DtoAssign(l, res);
|
||||
@@ -904,7 +920,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
Logger::cout() << "what are we calling? : " << *funcval << '\n';
|
||||
}
|
||||
assert(llfnty);
|
||||
Logger::cout() << "Function LLVM type: " << *llfnty << '\n';
|
||||
//Logger::cout() << "Function LLVM type: " << *llfnty << '\n';
|
||||
|
||||
// argument handling
|
||||
llvm::FunctionType::param_iterator argiter = llfnty->param_begin();
|
||||
@@ -969,7 +985,7 @@ DValue* CallExp::toElem(IRState* p)
|
||||
// nested call
|
||||
else if (dfn && dfn->func && dfn->func->isNested()) {
|
||||
Logger::println("Nested Call");
|
||||
llvm::Value* contextptr = p->func()->decl->llvmNested;
|
||||
llvm::Value* contextptr = DtoNestedContext(dfn->func->toParent2()->isFuncDeclaration());
|
||||
if (!contextptr)
|
||||
contextptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
llargs[j] = DtoBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
@@ -978,7 +994,8 @@ DValue* CallExp::toElem(IRState* p)
|
||||
}
|
||||
|
||||
// va arg function special argument passing
|
||||
if (va_magic) {
|
||||
if (va_magic)
|
||||
{
|
||||
size_t n = va_intrinsic ? arguments->dim : 1;
|
||||
for (int i=0; i<n; i++,j++)
|
||||
{
|
||||
@@ -989,7 +1006,9 @@ DValue* CallExp::toElem(IRState* p)
|
||||
}
|
||||
}
|
||||
// regular arguments
|
||||
else {
|
||||
else
|
||||
{
|
||||
// d variadic function?
|
||||
if (tf->linkage == LINKd && tf->varargs == 1)
|
||||
{
|
||||
Logger::println("doing d-style variadic arguments");
|
||||
@@ -997,53 +1016,71 @@ DValue* CallExp::toElem(IRState* p)
|
||||
size_t nimplicit = j;
|
||||
|
||||
std::vector<const llvm::Type*> vtypes;
|
||||
std::vector<llvm::Value*> vvalues;
|
||||
std::vector<llvm::Value*> vtypeinfos;
|
||||
|
||||
for (int i=0; i<arguments->dim; i++) {
|
||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
// build struct with argument types
|
||||
for (int i=0; i<arguments->dim; i++)
|
||||
{
|
||||
Expression* argexp = (Expression*)arguments->data[i];
|
||||
vvalues.push_back(DtoArgument(NULL, fnarg, argexp));
|
||||
vtypes.push_back(vvalues.back()->getType());
|
||||
vtypes.push_back(DtoType(argexp->type));
|
||||
}
|
||||
const llvm::StructType* vtype = llvm::StructType::get(vtypes);
|
||||
Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n';
|
||||
llvm::Value* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
|
||||
|
||||
TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration();
|
||||
DtoForceDeclareDsymbol(tidecl);
|
||||
assert(tidecl->llvmValue);
|
||||
vtypeinfos.push_back(tidecl->llvmValue);
|
||||
// store arguments in the struct
|
||||
for (int i=0; i<arguments->dim; i++)
|
||||
{
|
||||
Expression* argexp = (Expression*)arguments->data[i];
|
||||
if (global.params.llvmAnnotate)
|
||||
DtoAnnotation(argexp->toChars());
|
||||
DtoVariadicArgument(argexp, DtoGEPi(mem,0,i,"tmp"));
|
||||
}
|
||||
|
||||
const llvm::StructType* vtype = llvm::StructType::get(vtypes);
|
||||
llvm::Value* mem = new llvm::AllocaInst(vtype,"_argptr_storage",p->topallocapoint());
|
||||
for (unsigned i=0; i<vtype->getNumElements(); ++i)
|
||||
p->ir->CreateStore(vvalues[i], DtoGEPi(mem,0,i,"tmp"));
|
||||
|
||||
//llvm::Constant* typeinfoparam = llvm::ConstantPointerNull::get(isaPointer(llfnty->getParamType(j)));
|
||||
// build type info array
|
||||
assert(Type::typeinfo->llvmConstInit);
|
||||
const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmConstInit->getType());
|
||||
Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n';
|
||||
const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements());
|
||||
|
||||
llvm::Value* typeinfomem = new llvm::AllocaInst(typeinfoarraytype,"_arguments_storage",p->topallocapoint());
|
||||
for (unsigned i=0; i<vtype->getNumElements(); ++i) {
|
||||
for (int i=0; i<arguments->dim; i++)
|
||||
{
|
||||
Expression* argexp = (Expression*)arguments->data[i];
|
||||
TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration();
|
||||
DtoForceDeclareDsymbol(tidecl);
|
||||
assert(tidecl->llvmValue);
|
||||
vtypeinfos.push_back(tidecl->llvmValue);
|
||||
llvm::Value* v = p->ir->CreateBitCast(vtypeinfos[i], typeinfotype, "tmp");
|
||||
p->ir->CreateStore(v, DtoGEPi(typeinfomem,0,i,"tmp"));
|
||||
}
|
||||
|
||||
// put data in d-array
|
||||
llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint());
|
||||
p->ir->CreateStore(DtoConstSize_t(vtype->getNumElements()), DtoGEPi(typeinfoarrayparam,0,0,"tmp"));
|
||||
llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp");
|
||||
p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp"));
|
||||
|
||||
// specify arguments
|
||||
llargs[j] = typeinfoarrayparam;;
|
||||
j++;
|
||||
llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp");
|
||||
j++;
|
||||
llargs.resize(nimplicit+2);
|
||||
}
|
||||
// normal function
|
||||
else {
|
||||
Logger::println("doing normal arguments");
|
||||
for (int i=0; i<arguments->dim; i++,j++) {
|
||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
|
||||
if (global.params.llvmAnnotate)
|
||||
DtoAnnotation(((Expression*)arguments->data[i])->toChars());
|
||||
DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]);
|
||||
llargs[j] = argval->getRVal();
|
||||
if (fnarg && llargs[j]->getType() != llfnty->getParamType(j)) {
|
||||
llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
|
||||
}
|
||||
|
||||
// this hack is necessary :/
|
||||
if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
|
||||
if (llfnty->getParamType(j) != NULL) {
|
||||
@@ -1850,7 +1887,11 @@ DValue* NewExp::toElem(IRState* p)
|
||||
{
|
||||
Expression* ex = (Expression*)arguments->data[i];
|
||||
Argument* fnarg = Argument::getNth(tf->parameters, i);
|
||||
llvm::Value* a = DtoArgument(fn->getFunctionType()->getParamType(i+1), fnarg, ex);
|
||||
DValue* argval = DtoArgument(fnarg, ex);
|
||||
llvm::Value* a = argval->getRVal();
|
||||
const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1);
|
||||
if (a->getType() != aty) // this param might have type mismatch
|
||||
a = DtoBitCast(a, aty);
|
||||
ctorargs.push_back(a);
|
||||
}
|
||||
llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb());
|
||||
@@ -2895,7 +2936,7 @@ void obj_includelib(char*){}
|
||||
AsmStatement::AsmStatement(Loc loc, Token *tokens) :
|
||||
Statement(loc)
|
||||
{
|
||||
Logger::println("Ignoring AsmStatement");
|
||||
this->tokens = tokens;
|
||||
}
|
||||
Statement *AsmStatement::syntaxCopy()
|
||||
{
|
||||
|
||||
303
gen/tollvm.cpp
303
gen/tollvm.cpp
@@ -673,156 +673,12 @@ void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp)
|
||||
{
|
||||
llvm::Value* retval = 0;
|
||||
|
||||
bool haslvals = !gIR->exps.empty();
|
||||
if (haslvals)
|
||||
gIR->exps.push_back(IRExp(NULL,NULL,NULL));
|
||||
|
||||
DValue* arg = argexp->toElem(gIR);
|
||||
|
||||
if (haslvals)
|
||||
gIR->exps.pop_back();
|
||||
|
||||
if (arg->inPlace()) {
|
||||
retval = arg->getRVal();
|
||||
return retval;
|
||||
}
|
||||
|
||||
Type* realtype = DtoDType(argexp->type);
|
||||
TY argty = realtype->ty;
|
||||
if (DtoIsPassedByRef(realtype)) {
|
||||
if (!fnarg || !fnarg->llvmCopy) {
|
||||
if (DSliceValue* sv = arg->isSlice()) {
|
||||
retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint());
|
||||
DtoSetArray(retval, DtoArrayLen(sv), DtoArrayPtr(sv));
|
||||
}
|
||||
else if (DComplexValue* cv = arg->isComplex()) {
|
||||
retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint());
|
||||
DtoComplexSet(retval, cv->re, cv->im);
|
||||
}
|
||||
else {
|
||||
retval = arg->getRVal();
|
||||
}
|
||||
}
|
||||
else {
|
||||
llvm::Value* allocaInst = 0;
|
||||
llvm::BasicBlock* entryblock = &gIR->topfunc()->front();
|
||||
|
||||
const llvm::Type* realtypell = DtoType(realtype);
|
||||
const llvm::PointerType* pty = llvm::PointerType::get(realtypell);
|
||||
if (argty == Tstruct) {
|
||||
allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
|
||||
DValue* dst = new DVarValue(realtype, allocaInst, true);
|
||||
DtoAssign(dst,arg);
|
||||
delete dst;
|
||||
}
|
||||
else if (argty == Tdelegate) {
|
||||
allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
|
||||
DValue* dst = new DVarValue(realtype, allocaInst, true);
|
||||
DtoAssign(dst,arg);
|
||||
delete dst;
|
||||
}
|
||||
else if (argty == Tarray) {
|
||||
if (arg->isSlice()) {
|
||||
allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint());
|
||||
}
|
||||
else {
|
||||
allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
|
||||
}
|
||||
}
|
||||
else if (realtype->iscomplex()) {
|
||||
if (arg->isComplex()) {
|
||||
allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint());
|
||||
}
|
||||
else {
|
||||
allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint());
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
DValue* dst = new DVarValue(realtype, allocaInst, true);
|
||||
DtoAssign(dst,arg);
|
||||
delete dst;
|
||||
|
||||
retval = allocaInst;
|
||||
}
|
||||
}
|
||||
else if (!fnarg || fnarg->llvmCopy) {
|
||||
Logger::println("regular arg");
|
||||
if (DSliceValue* sl = arg->isSlice()) {
|
||||
if (sl->ptr) Logger::cout() << "ptr = " << *sl->ptr << '\n';
|
||||
if (sl->len) Logger::cout() << "len = " << *sl->len << '\n';
|
||||
assert(0);
|
||||
}
|
||||
else if (DComplexValue* cl = arg->isComplex()) {
|
||||
assert(0 && "complex in the wrong place");
|
||||
}
|
||||
else {
|
||||
retval = arg->getRVal();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Logger::println("as ptr arg");
|
||||
retval = arg->getLVal();
|
||||
if (paramtype && retval->getType() != paramtype)
|
||||
{
|
||||
assert(0);
|
||||
/*assert(retval->getType() == paramtype->getContainedType(0));
|
||||
new llvm::StoreInst(retval, arg->getLVal(), gIR->scopebb());
|
||||
retval = arg->getLVal();*/
|
||||
}
|
||||
}
|
||||
|
||||
if (fnarg && paramtype && retval->getType() != paramtype) {
|
||||
// this is unfortunately needed with the way SymOffExp is overused
|
||||
// and static arrays can end up being a pointer to their element type
|
||||
if (arg->isField()) {
|
||||
retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp");
|
||||
}
|
||||
else {
|
||||
Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n";
|
||||
assert(0 && "parameter type that was actually passed is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
delete arg;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void print_frame_worker(VarDeclaration* var, Dsymbol* par)
|
||||
{
|
||||
if (var->toParent2() == par)
|
||||
{
|
||||
Logger::println("parent found: '%s' kind: '%s'", par->toChars(), par->kind());
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::println("diving into parent: '%s' kind: '%s'", par->toChars(), par->kind());
|
||||
LOG_SCOPE;
|
||||
print_frame_worker(var, par->toParent2());
|
||||
}
|
||||
|
||||
static void print_nested_frame_list(VarDeclaration* var, Dsymbol* par)
|
||||
{
|
||||
Logger::println("PRINTING FRAME LIST FOR NESTED VAR: '%s'", var->toChars());
|
||||
{
|
||||
LOG_SCOPE;
|
||||
print_frame_worker(var, par);
|
||||
}
|
||||
Logger::println("DONE");
|
||||
}
|
||||
|
||||
static const llvm::Type* get_next_frame_ptr_type(Dsymbol* sc)
|
||||
{
|
||||
assert(sc->isFuncDeclaration() || sc->isClassDeclaration());
|
||||
Dsymbol* p = sc->toParent2();
|
||||
if (!p->isFuncDeclaration() && !p->isClassDeclaration())
|
||||
Logger::println("unexpected parent symbol found while resolving frame pointer - '%s' kind: '%s'", p->toChars(), p->kind());
|
||||
assert(p->isFuncDeclaration() || p->isClassDeclaration());
|
||||
if (FuncDeclaration* fd = p->isFuncDeclaration())
|
||||
{
|
||||
@@ -841,21 +697,29 @@ static const llvm::Type* get_next_frame_ptr_type(Dsymbol* sc)
|
||||
}
|
||||
}
|
||||
|
||||
static llvm::Value* get_frame_ptr_impl(VarDeclaration* vd, Dsymbol* sc, llvm::Value* v)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::Value* get_frame_ptr_impl(FuncDeclaration* func, Dsymbol* sc, llvm::Value* v)
|
||||
{
|
||||
if (vd->toParent2() == sc)
|
||||
LOG_SCOPE;
|
||||
if (sc == func)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
else if (FuncDeclaration* fd = sc->isFuncDeclaration())
|
||||
{
|
||||
Logger::println("scope is function");
|
||||
Logger::println("scope is function: %s", fd->toChars());
|
||||
|
||||
if (fd->toParent2() == func)
|
||||
{
|
||||
if (!func->llvmNested)
|
||||
return NULL;
|
||||
return DtoBitCast(v, func->llvmNested->getType());
|
||||
}
|
||||
|
||||
v = DtoBitCast(v, get_next_frame_ptr_type(fd));
|
||||
Logger::cout() << "v = " << *v << '\n';
|
||||
|
||||
if (fd->toParent2() == vd->toParent2())
|
||||
return v;
|
||||
|
||||
if (fd->toParent2()->isFuncDeclaration())
|
||||
{
|
||||
v = DtoGEPi(v, 0,0, "tmp");
|
||||
@@ -872,33 +736,35 @@ static llvm::Value* get_frame_ptr_impl(VarDeclaration* vd, Dsymbol* sc, llvm::Va
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return get_frame_ptr_impl(vd, fd->toParent2(), v);
|
||||
return get_frame_ptr_impl(func, fd->toParent2(), v);
|
||||
}
|
||||
else if (ClassDeclaration* cd = sc->isClassDeclaration())
|
||||
{
|
||||
Logger::println("scope is class");
|
||||
Logger::println("scope is class: %s", cd->toChars());
|
||||
/*size_t idx = 2;
|
||||
idx += cd->llvmIRStruct->interfaces.size();
|
||||
v = DtoGEPi(v,0,idx,"tmp");
|
||||
Logger::cout() << "gep = " << *v << '\n';
|
||||
v = DtoLoad(v);*/
|
||||
return get_frame_ptr_impl(vd, cd->toParent2(), v);
|
||||
return get_frame_ptr_impl(func, cd->toParent2(), v);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::println("symbol: '%s'", sc->toChars());
|
||||
Logger::println("symbol: '%s'", sc->toPrettyChars());
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static llvm::Value* get_frame_ptr(VarDeclaration* vd)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::Value* get_frame_ptr(FuncDeclaration* func)
|
||||
{
|
||||
Logger::println("RESOLVING FRAME PTR FOR NESTED VAR: '%s'", vd->toChars());
|
||||
Logger::println("Resolving context pointer for nested function: '%s'", func->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
IRFunction* irfunc = gIR->func();
|
||||
|
||||
// in the parent scope already
|
||||
if (vd->toParent2() == irfunc->decl)
|
||||
// in the right scope already
|
||||
if (func == irfunc->decl)
|
||||
return irfunc->decl->llvmNested;
|
||||
|
||||
// use the 'this' pointer
|
||||
@@ -906,24 +772,71 @@ static llvm::Value* get_frame_ptr(VarDeclaration* vd)
|
||||
assert(ptr);
|
||||
|
||||
// return the fully resolved frame pointer
|
||||
ptr = get_frame_ptr_impl(vd, irfunc->decl, ptr);
|
||||
Logger::cout() << "FOUND: '" << *ptr << "'\n";
|
||||
ptr = get_frame_ptr_impl(func, irfunc->decl, ptr);
|
||||
if (ptr) Logger::cout() << "Found context!" << *ptr;
|
||||
else Logger::cout() << "NULL context!\n";
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Value* DtoNestedContext(FuncDeclaration* func)
|
||||
{
|
||||
// resolve frame ptr
|
||||
llvm::Value* ptr = get_frame_ptr(func);
|
||||
Logger::cout() << "Nested context ptr = ";
|
||||
if (ptr) Logger::cout() << *ptr;
|
||||
else Logger::cout() << "NULL";
|
||||
Logger::cout() << '\n';
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void print_frame_worker(VarDeclaration* vd, Dsymbol* par)
|
||||
{
|
||||
if (vd->toParent2() == par)
|
||||
{
|
||||
Logger::println("found: '%s' kind: '%s'", par->toChars(), par->kind());
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::println("diving into: '%s' kind: '%s'", par->toChars(), par->kind());
|
||||
LOG_SCOPE;
|
||||
print_frame_worker(vd, par->toParent2());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void print_nested_frame_list(VarDeclaration* vd, Dsymbol* par)
|
||||
{
|
||||
Logger::println("Frame pointer list for nested var: '%s'", vd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
if (vd->toParent2() != par)
|
||||
print_frame_worker(vd, par);
|
||||
else
|
||||
Logger::println("Found at level 0");
|
||||
Logger::println("Done");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::Value* DtoNestedVariable(VarDeclaration* vd)
|
||||
{
|
||||
// log the frame list
|
||||
IRFunction* irfunc = gIR->func();
|
||||
print_nested_frame_list(vd, irfunc->decl);
|
||||
if (Logger::enabled)
|
||||
print_nested_frame_list(vd, irfunc->decl);
|
||||
|
||||
// resolve frame ptr
|
||||
llvm::Value* ptr = get_frame_ptr(vd);
|
||||
Logger::cout() << "nested ptr = " << *ptr << '\n';
|
||||
FuncDeclaration* func = vd->toParent2()->isFuncDeclaration();
|
||||
assert(func);
|
||||
llvm::Value* ptr = DtoNestedContext(func);
|
||||
assert(ptr && "nested var, but no context");
|
||||
|
||||
// we must cast here to be sure. nested classes just have a void*
|
||||
ptr = DtoBitCast(ptr, vd->toParent2()->isFuncDeclaration()->llvmNested->getType());
|
||||
ptr = DtoBitCast(ptr, func->llvmNested->getType());
|
||||
|
||||
// index nested var and load (if necessary)
|
||||
llvm::Value* v = DtoGEPi(ptr, 0, vd->llvmNestedIndex, "tmp");
|
||||
@@ -931,7 +844,8 @@ llvm::Value* DtoNestedVariable(VarDeclaration* vd)
|
||||
if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
|
||||
v = DtoLoad(v);
|
||||
|
||||
Logger::cout() << "FINAL RESULT: " << *v << '\n';
|
||||
// log and return
|
||||
Logger::cout() << "Nested var ptr = " << *v << '\n';
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -940,6 +854,8 @@ llvm::Value* DtoNestedVariable(VarDeclaration* vd)
|
||||
void DtoAssign(DValue* lhs, DValue* rhs)
|
||||
{
|
||||
Logger::cout() << "DtoAssign(...);\n";
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* t = DtoDType(lhs->getType());
|
||||
Type* t2 = DtoDType(rhs->getType());
|
||||
|
||||
@@ -1024,19 +940,15 @@ void DtoAssign(DValue* lhs, DValue* rhs)
|
||||
DtoComplexAssign(dst, rhs->getRVal());
|
||||
}
|
||||
else {
|
||||
llvm::Value* l;
|
||||
if (DLRValue* lr = lhs->isLRValue()) {
|
||||
l = lr->getLVal();
|
||||
rhs = DtoCast(rhs, lr->getLType());
|
||||
}
|
||||
else {
|
||||
l = lhs->getLVal();
|
||||
}
|
||||
llvm::Value* l = lhs->getLVal();
|
||||
llvm::Value* r = rhs->getRVal();
|
||||
Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
|
||||
const llvm::Type* lit = l->getType()->getContainedType(0);
|
||||
if (r->getType() != lit) { // :(
|
||||
r = DtoBitCast(r, lit);
|
||||
if (r->getType() != lit) {
|
||||
if (DLRValue* lr = lhs->isLRValue()) // handle lvalue cast assignments
|
||||
r = DtoCast(rhs, lr->getLType())->getRVal();
|
||||
else
|
||||
r = DtoCast(rhs, lhs->getType())->getRVal();
|
||||
Logger::cout() << "really assign\nlhs: " << *l << "rhs: " << *r << '\n';
|
||||
}
|
||||
gIR->ir->CreateStore(r, l);
|
||||
@@ -1055,34 +967,38 @@ DValue* DtoCastInt(DValue* val, Type* _to)
|
||||
size_t fromsz = from->size();
|
||||
size_t tosz = to->size();
|
||||
|
||||
llvm::Value* rval;
|
||||
llvm::Value* rval = val->getRVal();
|
||||
if (rval->getType() == tolltype) {
|
||||
return new DImValue(_to, rval);
|
||||
}
|
||||
|
||||
if (to->isintegral()) {
|
||||
if (fromsz < tosz) {
|
||||
Logger::cout() << "cast to: " << *tolltype << '\n';
|
||||
if (from->isunsigned() || from->ty == Tbool) {
|
||||
rval = new llvm::ZExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
||||
rval = new llvm::ZExtInst(rval, tolltype, "tmp", gIR->scopebb());
|
||||
} else {
|
||||
rval = new llvm::SExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
||||
rval = new llvm::SExtInst(rval, tolltype, "tmp", gIR->scopebb());
|
||||
}
|
||||
}
|
||||
else if (fromsz > tosz) {
|
||||
rval = new llvm::TruncInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
||||
rval = new llvm::TruncInst(rval, tolltype, "tmp", gIR->scopebb());
|
||||
}
|
||||
else {
|
||||
rval = new llvm::BitCastInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
||||
rval = new llvm::BitCastInst(rval, tolltype, "tmp", gIR->scopebb());
|
||||
}
|
||||
}
|
||||
else if (to->isfloating()) {
|
||||
if (from->isunsigned()) {
|
||||
rval = new llvm::UIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
||||
rval = new llvm::UIToFPInst(rval, tolltype, "tmp", gIR->scopebb());
|
||||
}
|
||||
else {
|
||||
rval = new llvm::SIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb());
|
||||
rval = new llvm::SIToFPInst(rval, tolltype, "tmp", gIR->scopebb());
|
||||
}
|
||||
}
|
||||
else if (to->ty == Tpointer) {
|
||||
rval = gIR->ir->CreateIntToPtr(val->getRVal(), tolltype, "tmp");
|
||||
Logger::cout() << "cast pointer: " << *tolltype << '\n';
|
||||
rval = gIR->ir->CreateIntToPtr(rval, tolltype, "tmp");
|
||||
}
|
||||
else {
|
||||
assert(0 && "bad int cast");
|
||||
@@ -1771,3 +1687,20 @@ void DtoForceDefineDsymbol(Dsymbol* dsym)
|
||||
|
||||
DtoDefineDsymbol(dsym);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DtoAnnotation(const char* str)
|
||||
{
|
||||
std::string s("CODE: ");
|
||||
s.append(str);
|
||||
char* p = &s[0];
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '"')
|
||||
*p = '\'';
|
||||
++p;
|
||||
}
|
||||
// create a noop with the code as the result name!
|
||||
gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str());
|
||||
}
|
||||
|
||||
@@ -41,10 +41,11 @@ llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* len);
|
||||
|
||||
void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg);
|
||||
|
||||
llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp);
|
||||
|
||||
llvm::Value* DtoNestedContext(FuncDeclaration* func);
|
||||
llvm::Value* DtoNestedVariable(VarDeclaration* vd);
|
||||
|
||||
void DtoAnnotation(const char* str);
|
||||
|
||||
llvm::ConstantInt* DtoConstSize_t(size_t);
|
||||
llvm::ConstantInt* DtoConstUint(unsigned i);
|
||||
llvm::ConstantInt* DtoConstInt(int i);
|
||||
|
||||
@@ -137,9 +137,7 @@ void Module::genobjfile()
|
||||
}
|
||||
|
||||
// run optimizer
|
||||
if (global.params.optimize) {
|
||||
llvmdc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
|
||||
}
|
||||
llvmdc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
|
||||
|
||||
// write bytecode
|
||||
{
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
</ignoredoxygen>
|
||||
</kdevdoctreeview>
|
||||
<kdevfilecreate>
|
||||
<filetypes/>
|
||||
<useglobaltypes>
|
||||
<type ext="cpp" />
|
||||
<type ext="h" />
|
||||
@@ -191,6 +192,10 @@
|
||||
<filetype>*.c</filetype>
|
||||
<filetype>*.cpp</filetype>
|
||||
<filetype>*.d</filetype>
|
||||
<filetype>*.di</filetype>
|
||||
<filetype>build.sh</filetype>
|
||||
<filetype>premake.lua</filetype>
|
||||
<filetype>Doxyfile</filetype>
|
||||
</filetypes>
|
||||
<blacklist>
|
||||
<path>dbgtypes.bc.cpp</path>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# KDevelop Custom Project File List
|
||||
Doxyfile
|
||||
demos
|
||||
demos/gl.d
|
||||
demos/glfuncs.d
|
||||
@@ -11,6 +12,7 @@ demos/ray.d
|
||||
demos/sdl.d
|
||||
demos/sdldemo1.d
|
||||
dmd
|
||||
dmd/Doxyfile
|
||||
dmd/access.c
|
||||
dmd/aggregate.h
|
||||
dmd/array.c
|
||||
@@ -137,6 +139,7 @@ gen/toobj.cpp
|
||||
gen/typeinf.h
|
||||
gen/typinf.cpp
|
||||
lphobos
|
||||
lphobos/build.sh
|
||||
lphobos/crc32.d
|
||||
lphobos/gc
|
||||
lphobos/gc/gcbits.d
|
||||
@@ -185,6 +188,7 @@ lphobos/std/compiler.d
|
||||
lphobos/std/conv.d
|
||||
lphobos/std/ctype.d
|
||||
lphobos/std/format.d
|
||||
lphobos/std/gc.di
|
||||
lphobos/std/intrinsic.d
|
||||
lphobos/std/math.d
|
||||
lphobos/std/moduleinit.d
|
||||
@@ -193,6 +197,7 @@ lphobos/std/stdarg.d
|
||||
lphobos/std/stdint.d
|
||||
lphobos/std/stdio.d
|
||||
lphobos/std/string.d
|
||||
lphobos/std/thread.d
|
||||
lphobos/std/traits.d
|
||||
lphobos/std/uni.d
|
||||
lphobos/std/utf.d
|
||||
@@ -232,6 +237,7 @@ lphobos/typeinfo2/ti_Ashort.d
|
||||
lphobos/typeinfo2/ti_C.d
|
||||
lphobos/typeinfos1.d
|
||||
lphobos/typeinfos2.d
|
||||
premake.lua
|
||||
runalltests.d
|
||||
test
|
||||
test/a.d
|
||||
@@ -258,8 +264,8 @@ test/arrays6.d
|
||||
test/arrays7.d
|
||||
test/arrays8.d
|
||||
test/arrays9.d
|
||||
test/asm1.d
|
||||
test/assign.d
|
||||
test/ast1.d
|
||||
test/b.d
|
||||
test/bitops.d
|
||||
test/bug1.d
|
||||
@@ -332,9 +338,12 @@ test/bug75.d
|
||||
test/bug76.d
|
||||
test/bug77.d
|
||||
test/bug78.d
|
||||
test/bug79.d
|
||||
test/bug8.d
|
||||
test/bug80.d
|
||||
test/bug9.d
|
||||
test/c.d
|
||||
test/calls1.d
|
||||
test/classes.d
|
||||
test/classes10.d
|
||||
test/classes11.d
|
||||
@@ -409,6 +418,8 @@ test/multiarr4.d
|
||||
test/neg.d
|
||||
test/nested1.d
|
||||
test/nested10.d
|
||||
test/nested11.d
|
||||
test/nested12.d
|
||||
test/nested2.d
|
||||
test/nested3.d
|
||||
test/nested4.d
|
||||
@@ -432,6 +443,7 @@ test/static_ctor.d
|
||||
test/staticarrays.d
|
||||
test/staticvars.d
|
||||
test/stdiotest.d
|
||||
test/stdiotest2.d
|
||||
test/strings1.d
|
||||
test/strings2.d
|
||||
test/structinit.d
|
||||
@@ -479,6 +491,7 @@ test/vararg1.d
|
||||
test/vararg2.d
|
||||
test/vararg3.d
|
||||
test/vararg4.d
|
||||
test/vararg5.d
|
||||
test/virtcall.d
|
||||
test/with1.d
|
||||
tester.d
|
||||
|
||||
@@ -5,8 +5,8 @@ mkdir -p obj
|
||||
rm -f obj/*.bc
|
||||
rm -f ../lib/*.bc
|
||||
|
||||
LLVMDCFLAGS="-c -odobj"
|
||||
REBUILDFLAGS="-dc=llvmdc-posix-internal -c -oqobj"
|
||||
LLVMDCFLAGS="-c -odobj -g"
|
||||
REBUILDFLAGS="-dc=llvmdc-posix-internal -c -oqobj -g"
|
||||
|
||||
echo "compiling contract runtime"
|
||||
llvmdc internal/contract.d -c -of../lib/llvmdcore.bc -noruntime || exit 1
|
||||
@@ -56,12 +56,14 @@ llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || ex
|
||||
|
||||
echo "compiling garbage collector"
|
||||
llvmdc gc/gclinux.d $LLVMDCFLAGS || exit 1
|
||||
llvmdc gc/gcstub.d $LLVMDCFLAGS -Igc || exit 1
|
||||
llvmdc gc/gcx.d $LLVMDCFLAGS -Igc || exit 1
|
||||
llvmdc gc/gcbits.d $LLVMDCFLAGS -Igc || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc obj/gcbits.bc ../lib/llvmdcore.bc || exit 1
|
||||
llvmdc gc/gc.d $LLVMDCFLAGS -Igc || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcx.bc obj/gcbits.bc obj/gc.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling phobos"
|
||||
rebuild phobos.d $REBUILDFLAGS || exit 1
|
||||
echo "linking phobos"
|
||||
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "optimizing"
|
||||
|
||||
151
lphobos/gc/gc.d
Normal file
151
lphobos/gc/gc.d
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
|
||||
// Storage allocation
|
||||
|
||||
module std.gc;
|
||||
|
||||
//debug = PRINTF;
|
||||
|
||||
public import std.c.stdarg;
|
||||
public import std.c.stdlib;
|
||||
public import std.c.string;
|
||||
public import gcx;
|
||||
public import std.outofmemory;
|
||||
public import gcstats;
|
||||
public import std.thread;
|
||||
|
||||
version=GCCLASS;
|
||||
|
||||
version (GCCLASS)
|
||||
alias GC gc_t;
|
||||
else
|
||||
alias GC* gc_t;
|
||||
|
||||
gc_t _gc;
|
||||
|
||||
void addRoot(void *p) { _gc.addRoot(p); }
|
||||
void removeRoot(void *p) { _gc.removeRoot(p); }
|
||||
void addRange(void *pbot, void *ptop) { _gc.addRange(pbot, ptop); }
|
||||
void removeRange(void *pbot) { _gc.removeRange(pbot); }
|
||||
void fullCollect() { _gc.fullCollect(); }
|
||||
void fullCollectNoStack() { _gc.fullCollectNoStack(); }
|
||||
void genCollect() { _gc.genCollect(); }
|
||||
void minimize() { _gc.minimize(); }
|
||||
void disable() { _gc.disable(); }
|
||||
void enable() { _gc.enable(); }
|
||||
void getStats(out GCStats stats) { _gc.getStats(stats); }
|
||||
void hasPointers(void* p) { _gc.hasPointers(p); }
|
||||
void hasNoPointers(void* p) { _gc.hasNoPointers(p); }
|
||||
void setV1_0() { _gc.setV1_0(); }
|
||||
|
||||
void[] malloc(size_t nbytes)
|
||||
{
|
||||
void* p = _gc.malloc(nbytes);
|
||||
return p[0 .. nbytes];
|
||||
}
|
||||
|
||||
void[] realloc(void* p, size_t nbytes)
|
||||
{
|
||||
void* q = _gc.realloc(p, nbytes);
|
||||
return q[0 .. nbytes];
|
||||
}
|
||||
|
||||
size_t extend(void* p, size_t minbytes, size_t maxbytes)
|
||||
{
|
||||
return _gc.extend(p, minbytes, maxbytes);
|
||||
}
|
||||
|
||||
size_t capacity(void* p)
|
||||
{
|
||||
return _gc.capacity(p);
|
||||
}
|
||||
|
||||
void setTypeInfo(TypeInfo ti, void* p)
|
||||
{
|
||||
if (ti.flags() & 1)
|
||||
hasNoPointers(p);
|
||||
else
|
||||
hasPointers(p);
|
||||
}
|
||||
|
||||
void* getGCHandle()
|
||||
{
|
||||
return cast(void*)_gc;
|
||||
}
|
||||
|
||||
void setGCHandle(void* p)
|
||||
{
|
||||
void* oldp = getGCHandle();
|
||||
gc_t g = cast(gc_t)p;
|
||||
if (g.gcversion != gcx.GCVERSION)
|
||||
throw new Error("incompatible gc versions");
|
||||
|
||||
// Add our static data to the new gc
|
||||
GC.scanStaticData(g);
|
||||
|
||||
_gc = g;
|
||||
// return oldp;
|
||||
}
|
||||
|
||||
void endGCHandle()
|
||||
{
|
||||
GC.unscanStaticData(_gc);
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
|
||||
void _d_monitorrelease(Object h);
|
||||
|
||||
|
||||
void gc_init()
|
||||
{
|
||||
version (GCCLASS)
|
||||
{ void* p;
|
||||
ClassInfo ci = GC.classinfo;
|
||||
|
||||
p = std.c.stdlib.malloc(ci.init.length);
|
||||
(cast(byte*)p)[0 .. ci.init.length] = ci.init[];
|
||||
_gc = cast(GC)p;
|
||||
}
|
||||
else
|
||||
{
|
||||
_gc = cast(GC *) std.c.stdlib.calloc(1, GC.sizeof);
|
||||
}
|
||||
_gc.initialize();
|
||||
GC.scanStaticData(_gc);
|
||||
std.thread.Thread.thread_init();
|
||||
}
|
||||
|
||||
void gc_term()
|
||||
{
|
||||
_gc.fullCollectNoStack();
|
||||
_gc.Dtor();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2004 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
// D Garbage Collector stub to prevent linking in gc
|
||||
|
||||
module gcx;
|
||||
|
||||
//debug=PRINTF;
|
||||
|
||||
/***************************************************/
|
||||
|
||||
import object;
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
import win32;
|
||||
}
|
||||
|
||||
version (linux)
|
||||
{
|
||||
import gclinux;
|
||||
}
|
||||
|
||||
|
||||
//alias GC* gc_t;
|
||||
alias GC gc_t;
|
||||
|
||||
struct GCStats { }
|
||||
|
||||
/* ============================ GC =============================== */
|
||||
|
||||
|
||||
//alias int size_t;
|
||||
alias void (*GC_FINALIZER)(void *p, void *dummy);
|
||||
|
||||
const uint GCVERSION = 1; // increment every time we change interface
|
||||
// to GC.
|
||||
|
||||
class GC
|
||||
{
|
||||
uint gcversion = GCVERSION;
|
||||
|
||||
void *gcx; // implementation
|
||||
|
||||
void initialize()
|
||||
{
|
||||
debug(PRINTF) printf("initialize()\n");
|
||||
}
|
||||
|
||||
|
||||
void Dtor()
|
||||
{
|
||||
debug(PRINTF) printf("Dtor()\n");
|
||||
}
|
||||
|
||||
/+invariant
|
||||
{
|
||||
debug(PRINTF) printf("invariant()\n");
|
||||
}+/
|
||||
|
||||
void *malloc(size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("malloc()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
void *mallocNoSync(size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("mallocNoSync()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
void *calloc(size_t size, size_t n)
|
||||
{
|
||||
debug(PRINTF) printf("calloc()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
void *realloc(void *p, size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("realloc()\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
void free(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("free()\n");
|
||||
}
|
||||
|
||||
size_t capacity(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("capacity()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void check(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("check()\n");
|
||||
}
|
||||
|
||||
|
||||
void setStackBottom(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("setStackBottom()\n");
|
||||
}
|
||||
|
||||
static void scanStaticData(gc_t g)
|
||||
{
|
||||
void *pbot;
|
||||
void *ptop;
|
||||
uint nbytes;
|
||||
|
||||
debug(PRINTF) printf("scanStaticData()\n");
|
||||
//debug(PRINTF) printf("+GC.scanStaticData()\n");
|
||||
os_query_staticdataseg(&pbot, &nbytes);
|
||||
ptop = pbot + nbytes;
|
||||
g.addRange(pbot, ptop);
|
||||
//debug(PRINTF) printf("-GC.scanStaticData()\n");
|
||||
}
|
||||
|
||||
static void unscanStaticData(gc_t g)
|
||||
{
|
||||
void *pbot;
|
||||
uint nbytes;
|
||||
|
||||
debug(PRINTF) printf("unscanStaticData()\n");
|
||||
os_query_staticdataseg(&pbot, &nbytes);
|
||||
g.removeRange(pbot);
|
||||
}
|
||||
|
||||
|
||||
void addRoot(void *p) // add p to list of roots
|
||||
{
|
||||
debug(PRINTF) printf("addRoot()\n");
|
||||
}
|
||||
|
||||
void removeRoot(void *p) // remove p from list of roots
|
||||
{
|
||||
debug(PRINTF) printf("removeRoot()\n");
|
||||
}
|
||||
|
||||
void addRange(void *pbot, void *ptop) // add range to scan for roots
|
||||
{
|
||||
debug(PRINTF) printf("addRange()\n");
|
||||
}
|
||||
|
||||
void removeRange(void *pbot) // remove range
|
||||
{
|
||||
debug(PRINTF) printf("removeRange()\n");
|
||||
}
|
||||
|
||||
void fullCollect() // do full garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("fullCollect()\n");
|
||||
}
|
||||
|
||||
void fullCollectNoStack() // do full garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("fullCollectNoStack()\n");
|
||||
}
|
||||
|
||||
void genCollect() // do generational garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("genCollect()\n");
|
||||
}
|
||||
|
||||
void minimize() // minimize physical memory usage
|
||||
{
|
||||
debug(PRINTF) printf("minimize()\n");
|
||||
}
|
||||
|
||||
void setFinalizer(void *p, GC_FINALIZER pFn)
|
||||
{
|
||||
debug(PRINTF) printf("setFinalizer()\n");
|
||||
}
|
||||
|
||||
void enable()
|
||||
{
|
||||
debug(PRINTF) printf("enable()\n");
|
||||
}
|
||||
|
||||
void disable()
|
||||
{
|
||||
debug(PRINTF) printf("disable()\n");
|
||||
}
|
||||
|
||||
void getStats(out GCStats stats)
|
||||
{
|
||||
debug(PRINTF) printf("getStats()\n");
|
||||
}
|
||||
}
|
||||
243
lphobos/gc/gcx.d
Normal file
243
lphobos/gc/gcx.d
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (C) 2004 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
// D Garbage Collector stub to prevent linking in gc
|
||||
|
||||
/*
|
||||
* Modified for use as the preliminary GC for LLVMDC (LLVM D Compiler)
|
||||
* by Tomas Lindquist Olsen, Dec 2007
|
||||
*/
|
||||
|
||||
module gcx;
|
||||
|
||||
debug=PRINTF;
|
||||
|
||||
/***************************************************/
|
||||
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
import win32;
|
||||
}
|
||||
|
||||
version (linux)
|
||||
{
|
||||
import gclinux;
|
||||
}
|
||||
|
||||
import gcstats;
|
||||
import stdc = std.c.stdlib;
|
||||
|
||||
|
||||
//alias GC* gc_t;
|
||||
alias GC gc_t;
|
||||
|
||||
//struct GCStats { }
|
||||
|
||||
/* ============================ GC =============================== */
|
||||
|
||||
|
||||
//alias int size_t;
|
||||
alias void (*GC_FINALIZER)(void *p, bool dummy);
|
||||
|
||||
const uint GCVERSION = 1; // increment every time we change interface
|
||||
// to GC.
|
||||
|
||||
class GC
|
||||
{
|
||||
uint gcversion = GCVERSION;
|
||||
|
||||
void *gcx; // implementation
|
||||
|
||||
void initialize()
|
||||
{
|
||||
debug(PRINTF) printf("GC initialize()\n");
|
||||
}
|
||||
|
||||
|
||||
void Dtor()
|
||||
{
|
||||
debug(PRINTF) printf("GC Dtor()\n");
|
||||
}
|
||||
|
||||
invariant
|
||||
{
|
||||
debug(PRINTF) printf("GC invariant()\n");
|
||||
}
|
||||
|
||||
void *malloc(size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("GC malloc()\n");
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *mallocNoSync(size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("GC mallocNoSync()\n");
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
|
||||
void *calloc(size_t size, size_t n)
|
||||
{
|
||||
debug(PRINTF) printf("GC calloc()\n");
|
||||
return calloc(n, size);
|
||||
}
|
||||
|
||||
|
||||
void *realloc(void *p, size_t size)
|
||||
{
|
||||
debug(PRINTF) printf("GC realloc()\n");
|
||||
return realloc(p, size);
|
||||
}
|
||||
|
||||
|
||||
void free(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("GC free()\n");
|
||||
stdc.free(p);
|
||||
}
|
||||
|
||||
size_t capacity(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("GC capacity()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void check(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("GC check()\n");
|
||||
}
|
||||
|
||||
|
||||
void setStackBottom(void *p)
|
||||
{
|
||||
debug(PRINTF) printf("GC setStackBottom()\n");
|
||||
}
|
||||
|
||||
static void scanStaticData(gc_t g)
|
||||
{
|
||||
void *pbot;
|
||||
void *ptop;
|
||||
uint nbytes;
|
||||
|
||||
debug(PRINTF) printf("GC scanStaticData()\n");
|
||||
//debug(PRINTF) printf("+GC.scanStaticData()\n");
|
||||
os_query_staticdataseg(&pbot, &nbytes);
|
||||
ptop = pbot + nbytes;
|
||||
g.addRange(pbot, ptop);
|
||||
//debug(PRINTF) printf("-GC.scanStaticData()\n");
|
||||
}
|
||||
|
||||
static void unscanStaticData(gc_t g)
|
||||
{
|
||||
void *pbot;
|
||||
uint nbytes;
|
||||
|
||||
debug(PRINTF) printf("GC unscanStaticData()\n");
|
||||
os_query_staticdataseg(&pbot, &nbytes);
|
||||
g.removeRange(pbot);
|
||||
}
|
||||
|
||||
|
||||
void addRoot(void *p) // add p to list of roots
|
||||
{
|
||||
debug(PRINTF) printf("GC addRoot()\n");
|
||||
}
|
||||
|
||||
void removeRoot(void *p) // remove p from list of roots
|
||||
{
|
||||
debug(PRINTF) printf("GC removeRoot()\n");
|
||||
}
|
||||
|
||||
void addRange(void *pbot, void *ptop) // add range to scan for roots
|
||||
{
|
||||
debug(PRINTF) printf("GC addRange()\n");
|
||||
}
|
||||
|
||||
void removeRange(void *pbot) // remove range
|
||||
{
|
||||
debug(PRINTF) printf("GC removeRange()\n");
|
||||
}
|
||||
|
||||
void fullCollect() // do full garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("GC fullCollect()\n");
|
||||
}
|
||||
|
||||
void fullCollectNoStack() // do full garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("GC fullCollectNoStack()\n");
|
||||
}
|
||||
|
||||
void genCollect() // do generational garbage collection
|
||||
{
|
||||
debug(PRINTF) printf("GC genCollect()\n");
|
||||
}
|
||||
|
||||
void minimize() // minimize physical memory usage
|
||||
{
|
||||
debug(PRINTF) printf("GC minimize()\n");
|
||||
}
|
||||
|
||||
void setFinalizer(void *p, GC_FINALIZER pFn)
|
||||
{
|
||||
debug(PRINTF) printf("GC setFinalizer()\n");
|
||||
}
|
||||
|
||||
void enable()
|
||||
{
|
||||
debug(PRINTF) printf("GC enable()\n");
|
||||
}
|
||||
|
||||
void disable()
|
||||
{
|
||||
debug(PRINTF) printf("GC disable()\n");
|
||||
}
|
||||
|
||||
void getStats(out GCStats stats)
|
||||
{
|
||||
debug(PRINTF) printf("GC getStats()\n");
|
||||
}
|
||||
|
||||
void hasPointers(void* p)
|
||||
{
|
||||
debug(PRINTF) printf("GC hasPointers()\n");
|
||||
}
|
||||
|
||||
void hasNoPointers(void* p)
|
||||
{
|
||||
debug(PRINTF) printf("GC hasNoPointers()\n");
|
||||
}
|
||||
|
||||
void setV1_0()
|
||||
{
|
||||
debug(PRINTF) printf("GC setV1_0()\n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
size_t extend(void* p, size_t minsize, size_t maxsize)
|
||||
{
|
||||
debug(PRINTF) printf("GC extend()\n");
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ module llvm.intrinsic;
|
||||
/*
|
||||
pragma(LLVM_internal, "intrinsic", "llvm.returnaddress")
|
||||
void* llvm_returnaddress(uint level);
|
||||
|
||||
*/
|
||||
pragma(LLVM_internal, "intrinsic", "llvm.frameaddress")
|
||||
void* llvm_frameaddress(uint level);
|
||||
|
||||
/*
|
||||
pragma(LLVM_internal, "intrinsic", "llvm.stacksave")
|
||||
void* llvm_stacksave();
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ std.stdarg,
|
||||
std.stdint,
|
||||
std.stdio,
|
||||
std.string,
|
||||
std.thread,
|
||||
std.traits,
|
||||
std.uni,
|
||||
std.utf,
|
||||
|
||||
1578
lphobos/std/conv.d
Normal file
1578
lphobos/std/conv.d
Normal file
File diff suppressed because it is too large
Load Diff
@@ -170,15 +170,12 @@ private TypeInfo primitiveTypeInfo(Mangle m)
|
||||
ti = typeid(idouble);break;
|
||||
case Mangle.Tireal:
|
||||
ti = typeid(ireal);break;
|
||||
/+
|
||||
// No complex in LLVMDC yes
|
||||
case Mangle.Tcfloat:
|
||||
ti = typeid(cfloat);break;
|
||||
case Mangle.Tcdouble:
|
||||
ti = typeid(cdouble);break;
|
||||
case Mangle.Tcreal:
|
||||
ti = typeid(creal);break;
|
||||
+/
|
||||
case Mangle.Tchar:
|
||||
ti = typeid(char);break;
|
||||
case Mangle.Twchar:
|
||||
@@ -450,7 +447,8 @@ formattedPrint("The answer is %s:", x, 6);
|
||||
*/
|
||||
|
||||
void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
{ int j;
|
||||
{ //printf("doFormat(...)\n");
|
||||
int j;
|
||||
TypeInfo ti;
|
||||
Mangle m;
|
||||
uint flags;
|
||||
@@ -503,7 +501,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
|
||||
void putstr(char[] s)
|
||||
{
|
||||
//printf("flags = x%x\n", flags);
|
||||
//printf("flags = 0x%x\n", flags);
|
||||
int prepad = 0;
|
||||
int postpad = 0;
|
||||
int padding = field_width - (strlen(prefix) + s.length);
|
||||
@@ -539,7 +537,8 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
|
||||
void putreal(real v)
|
||||
{
|
||||
//printf("putreal %Lg\n", vreal);
|
||||
//printf("putreal %Lg\n", vreal); // no 80 bit float
|
||||
//printf("putreal %g\n", vreal);
|
||||
|
||||
switch (fc)
|
||||
{
|
||||
@@ -593,9 +592,11 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
format[i + 0] = '*';
|
||||
format[i + 1] = '.';
|
||||
format[i + 2] = '*';
|
||||
format[i + 3] = 'L';
|
||||
format[i + 4] = fc;
|
||||
format[i + 5] = 0;
|
||||
format[i + 3] = fc;
|
||||
format[i + 4] = 0;
|
||||
//format[i + 3] = 'L'; // no 80 bit yet
|
||||
//format[i + 4] = fc;
|
||||
//format[i + 5] = 0;
|
||||
if (!(flags & FLprecision))
|
||||
precision = -1;
|
||||
while (1)
|
||||
@@ -638,7 +639,8 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
auto tiSave = ti;
|
||||
auto mSave = m;
|
||||
ti = valti;
|
||||
//printf("\n%.*s\n", valti.classinfo.name);
|
||||
auto className = valti.classinfo.name;
|
||||
printf("\n%.*s\n", className.length, className.ptr);
|
||||
m = getMan(valti);
|
||||
while (len--)
|
||||
{
|
||||
@@ -831,10 +833,12 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
goto Lcomplex;
|
||||
|
||||
case Mangle.Tsarray:
|
||||
//printf("static array\n");
|
||||
putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next);
|
||||
return;
|
||||
|
||||
case Mangle.Tarray:
|
||||
//printf("dynamic array\n");
|
||||
int mi = 10;
|
||||
if (ti.classinfo.name.length == 14 &&
|
||||
ti.classinfo.name[9..14] == "Array")
|
||||
@@ -863,6 +867,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
return;
|
||||
}
|
||||
|
||||
//printf("primitive type\n");
|
||||
while (1)
|
||||
{
|
||||
m2 = cast(Mangle)ti.classinfo.name[mi];
|
||||
@@ -897,6 +902,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
continue;
|
||||
|
||||
default:
|
||||
//printf("primitive type default handling\n");
|
||||
TypeInfo ti2 = primitiveTypeInfo(m2);
|
||||
if (!ti2)
|
||||
goto Lerror;
|
||||
@@ -1058,9 +1064,10 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr)
|
||||
}
|
||||
|
||||
|
||||
//printf("arguments length: %u\n", arguments.length);
|
||||
for (j = 0; j < arguments.length; )
|
||||
{ ti = arguments[j++];
|
||||
//printf("test1: '%.*s' %d\n", ti.classinfo.name, ti.classinfo.name.length);
|
||||
//printf("test1: '%.*s' %d\n", ti.classinfo.name.length, ti.classinfo.name.ptr, ti.classinfo.name.length);
|
||||
//ti.print();
|
||||
|
||||
flags = 0;
|
||||
|
||||
193
lphobos/std/gc.di
Normal file
193
lphobos/std/gc.di
Normal file
@@ -0,0 +1,193 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 1999-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The garbage collector normally works behind the scenes without needing any
|
||||
* specific interaction. These functions are for advanced applications that
|
||||
* benefit from tuning the operation of the collector.
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdGc
|
||||
*/
|
||||
|
||||
module std.gc;
|
||||
|
||||
import gcstats;
|
||||
|
||||
/**
|
||||
* Add p to list of roots. Roots are references to memory allocated by the
|
||||
collector that are maintained in memory outside the collector pool. The garbage
|
||||
collector will by default look for roots in the stacks of each thread, the
|
||||
registers, and the default static data segment. If roots are held elsewhere,
|
||||
use addRoot() or addRange() to tell the collector not to free the memory it
|
||||
points to.
|
||||
*/
|
||||
void addRoot(void *p); // add p to list of roots
|
||||
|
||||
/**
|
||||
* Remove p from list of roots.
|
||||
*/
|
||||
void removeRoot(void *p); // remove p from list of roots
|
||||
|
||||
/**
|
||||
* Add range to scan for roots.
|
||||
*/
|
||||
void addRange(void *pbot, void *ptop); // add range to scan for roots
|
||||
|
||||
/**
|
||||
* Remove range.
|
||||
*/
|
||||
void removeRange(void *pbot); // remove range
|
||||
|
||||
/**
|
||||
* Mark a gc allocated block of memory as possibly containing pointers.
|
||||
*/
|
||||
void hasPointers(void* p);
|
||||
|
||||
/**
|
||||
* Mark a gc allocated block of memory as definitely NOT containing pointers.
|
||||
*/
|
||||
void hasNoPointers(void* p);
|
||||
|
||||
/**
|
||||
* Mark a gc allocated block of memory pointed to by p as being populated with
|
||||
* an array of TypeInfo ti (as many as will fit).
|
||||
*/
|
||||
void setTypeInfo(TypeInfo ti, void* p);
|
||||
|
||||
/**
|
||||
* Allocate nbytes of uninitialized data.
|
||||
* The allocated memory will be scanned for pointers during
|
||||
* a gc collection cycle, unless
|
||||
* it is followed by a call to hasNoPointers().
|
||||
*/
|
||||
void[] malloc(size_t nbytes);
|
||||
|
||||
/**
|
||||
* Resize allocated memory block pointed to by p to be at least nbytes long.
|
||||
* It will try to resize the memory block in place.
|
||||
* If nbytes is 0, the memory block is free'd.
|
||||
* If p is null, the memory block is allocated using malloc.
|
||||
* The returned array may not be at the same location as the original
|
||||
* memory block.
|
||||
* The allocated memory will be scanned for pointers during
|
||||
* a gc collection cycle, unless
|
||||
* it is followed by a call to hasNoPointers().
|
||||
*/
|
||||
void[] realloc(void* p, size_t nbytes);
|
||||
|
||||
/**
|
||||
* Attempt to enlarge the memory block pointed to by p
|
||||
* by at least minbytes beyond its current capacity,
|
||||
* up to a maximum of maxbytes.
|
||||
* Returns:
|
||||
* 0 if could not extend p,
|
||||
* total size of entire memory block if successful.
|
||||
*/
|
||||
size_t extend(void* p, size_t minbytes, size_t maxbytes);
|
||||
|
||||
/**
|
||||
* Returns capacity (size of the memory block) that p
|
||||
* points to the beginning of.
|
||||
* If p does not point into the gc memory pool, or does
|
||||
* not point to the beginning of an allocated memory block,
|
||||
* 0 is returned.
|
||||
*/
|
||||
size_t capacity(void* p);
|
||||
|
||||
/**
|
||||
* Set gc behavior to match that of 1.0.
|
||||
*/
|
||||
void setV1_0();
|
||||
|
||||
/***********************************
|
||||
* Run a full garbage collection cycle.
|
||||
*
|
||||
* The collector normally runs synchronously with a storage allocation request
|
||||
(i.e. it never happens when in code that does not allocate memory). In some
|
||||
circumstances, for example when a particular task is finished, it is convenient
|
||||
to explicitly run the collector and free up all memory used by that task. It
|
||||
can also be helpful to run a collection before starting a new task that would
|
||||
be annoying if it ran a collection in the middle of that task. Explicitly
|
||||
running a collection can also be done in a separate very low priority thread,
|
||||
so that if the program is idly waiting for input, memory can be cleaned up.
|
||||
*/
|
||||
|
||||
void fullCollect();
|
||||
|
||||
/***********************************
|
||||
* Run a generational garbage collection cycle.
|
||||
* Takes less time than a fullcollect(), but isn't
|
||||
* as effective.
|
||||
*/
|
||||
|
||||
void genCollect();
|
||||
|
||||
void genCollectNoStack();
|
||||
|
||||
/**
|
||||
* Minimizes physical memory usage
|
||||
*/
|
||||
void minimize();
|
||||
|
||||
/***************************************
|
||||
* disable() temporarily disables garbage collection cycle, enable()
|
||||
* then reenables them.
|
||||
*
|
||||
* This is used for brief time critical sections of code, so the amount of time
|
||||
* it will take is predictable.
|
||||
* If the collector runs out of memory while it is disabled, it will throw an
|
||||
* std.outofmemory.OutOfMemoryException.
|
||||
* The disable() function calls can be nested, but must be
|
||||
* matched with corresponding enable() calls.
|
||||
* By default collections are enabled.
|
||||
*/
|
||||
|
||||
void disable();
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
void enable();
|
||||
|
||||
void getStats(out GCStats stats);
|
||||
|
||||
/***************************************
|
||||
* Get handle to the collector.
|
||||
*/
|
||||
|
||||
void* getGCHandle();
|
||||
|
||||
/***************************************
|
||||
* Set handle to the collector.
|
||||
*/
|
||||
|
||||
void setGCHandle(void* p);
|
||||
|
||||
void endGCHandle();
|
||||
|
||||
extern (C)
|
||||
{
|
||||
void gc_init();
|
||||
void gc_term();
|
||||
}
|
||||
@@ -6,14 +6,16 @@
|
||||
|
||||
/* This is for use with variable argument lists with extern(D) linkage. */
|
||||
|
||||
/* Modified for LLVMDC (LLVM D Compiler) by Tomas Lindquist Olsen, 2007 */
|
||||
|
||||
module std.stdarg;
|
||||
|
||||
alias void* va_list;
|
||||
|
||||
T va_arg(T)(inout va_list vp)
|
||||
T va_arg(T)(ref va_list vp)
|
||||
{
|
||||
static assert((T.sizeof & (T.sizeof -1)) == 0);
|
||||
va_list vptmp = cast(va_list)((cast(size_t)vp + T.sizeof - 1) & ~(T.sizeof - 1));
|
||||
size_t size = T.sizeof > size_t.sizeof ? size_t.sizeof : T.sizeof;
|
||||
va_list vptmp = cast(va_list)((cast(size_t)vp + size - 1) & ~(size - 1));
|
||||
vp = vptmp + T.sizeof;
|
||||
return *cast(T*)vptmp;
|
||||
}
|
||||
|
||||
@@ -1,44 +1,548 @@
|
||||
|
||||
// Written in the D programming language.
|
||||
|
||||
/* Written by Walter Bright and Andrei Alexandrescu
|
||||
* www.digitalmars.com
|
||||
* Placed in the Public Domain.
|
||||
*/
|
||||
|
||||
/********************************
|
||||
* Standard I/O functions that extend $(B std.c.stdio).
|
||||
* $(B std.c.stdio) is automatically imported when importing
|
||||
* $(B std.stdio).
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdStdio
|
||||
*/
|
||||
|
||||
module std.stdio;
|
||||
|
||||
import std.traits;
|
||||
public import std.c.stdio;
|
||||
|
||||
void _writef(T)(T t) {
|
||||
static if (is(T == char)) {
|
||||
printf("%c", t);
|
||||
import std.format;
|
||||
import std.utf;
|
||||
import std.string;
|
||||
import std.gc;
|
||||
import std.c.stdlib;
|
||||
import std.c.string;
|
||||
import std.c.stddef;
|
||||
|
||||
|
||||
version (DigitalMars)
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
// Specific to the way Digital Mars C does stdio
|
||||
version = DIGITAL_MARS_STDIO;
|
||||
}
|
||||
else static if (is(T : char[])) {
|
||||
printf("%.*s", t.length, t.ptr);
|
||||
}
|
||||
else static if (is(T : long)) {
|
||||
printf("%ld", t);
|
||||
}
|
||||
else static if (is(T : ulong)) {
|
||||
printf("%lu", t);
|
||||
}
|
||||
else static if (is(T : real)) {
|
||||
printf("%f", t);
|
||||
}
|
||||
else static if (is(T : Object)) {
|
||||
_writef(t.toString());
|
||||
}
|
||||
else static if(isArray!(T)) {
|
||||
_writef('[');
|
||||
if (t.length) {
|
||||
_writef(t[0]);
|
||||
foreach(v; t[1..$]) {
|
||||
_writef(','); _writef(v);
|
||||
}
|
||||
}
|
||||
_writef(']');
|
||||
}
|
||||
else static assert(0, "Cannot writef:"~T.tostring);
|
||||
}
|
||||
|
||||
void writef(T...)(T t)
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
{
|
||||
foreach(v;t) _writef(v);
|
||||
}
|
||||
void writefln(T...)(T t)
|
||||
else
|
||||
{
|
||||
writef(t, '\n');
|
||||
// Specific to the way Gnu C does stdio
|
||||
version = GCC_IO;
|
||||
import std.c.linux.linux;
|
||||
}
|
||||
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
{
|
||||
extern (C)
|
||||
{
|
||||
/* **
|
||||
* Digital Mars under-the-hood C I/O functions
|
||||
*/
|
||||
int _fputc_nlock(int, FILE*);
|
||||
int _fputwc_nlock(int, FILE*);
|
||||
int _fgetc_nlock(FILE*);
|
||||
int _fgetwc_nlock(FILE*);
|
||||
int __fp_lock(FILE*);
|
||||
void __fp_unlock(FILE*);
|
||||
}
|
||||
alias _fputc_nlock FPUTC;
|
||||
alias _fputwc_nlock FPUTWC;
|
||||
alias _fgetc_nlock FGETC;
|
||||
alias _fgetwc_nlock FGETWC;
|
||||
|
||||
alias __fp_lock FLOCK;
|
||||
alias __fp_unlock FUNLOCK;
|
||||
}
|
||||
else version (GCC_IO)
|
||||
{
|
||||
/* **
|
||||
* Gnu under-the-hood C I/O functions; see
|
||||
* http://www.gnu.org/software/libc/manual/html_node/I_002fO-on-Streams.html#I_002fO-on-Streams
|
||||
*/
|
||||
extern (C)
|
||||
{
|
||||
int fputc_unlocked(int, FILE*);
|
||||
int fputwc_unlocked(wchar_t, FILE*);
|
||||
int fgetc_unlocked(FILE*);
|
||||
int fgetwc_unlocked(FILE*);
|
||||
void flockfile(FILE*);
|
||||
void funlockfile(FILE*);
|
||||
ssize_t getline(char**, size_t*, FILE*);
|
||||
ssize_t getdelim (char**, size_t*, int, FILE*);
|
||||
}
|
||||
|
||||
alias fputc_unlocked FPUTC;
|
||||
alias fputwc_unlocked FPUTWC;
|
||||
alias fgetc_unlocked FGETC;
|
||||
alias fgetwc_unlocked FGETWC;
|
||||
|
||||
alias flockfile FLOCK;
|
||||
alias funlockfile FUNLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0, "unsupported C I/O system");
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
* Thrown if I/O errors happen.
|
||||
*/
|
||||
class StdioException : Exception
|
||||
{
|
||||
uint errno; // operating system error code
|
||||
|
||||
this(char[] msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
this(uint errno)
|
||||
{ char* s = strerror(errno);
|
||||
super(std.string.toString(s).dup);
|
||||
}
|
||||
|
||||
static void opCall(char[] msg)
|
||||
{
|
||||
throw new StdioException(msg);
|
||||
}
|
||||
|
||||
static void opCall()
|
||||
{
|
||||
throw new StdioException(getErrno());
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
void writefx(FILE* fp, TypeInfo[] arguments, void* argptr, int newline=false)
|
||||
{ int orientation;
|
||||
|
||||
orientation = fwide(fp, 0);
|
||||
|
||||
/* Do the file stream locking at the outermost level
|
||||
* rather than character by character.
|
||||
*/
|
||||
FLOCK(fp);
|
||||
scope(exit) FUNLOCK(fp);
|
||||
|
||||
if (orientation <= 0) // byte orientation or no orientation
|
||||
{
|
||||
void putc(dchar c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
FPUTC(c, fp);
|
||||
}
|
||||
else
|
||||
{ char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, c);
|
||||
for (size_t i = 0; i < b.length; i++)
|
||||
FPUTC(b[i], fp);
|
||||
}
|
||||
}
|
||||
|
||||
std.format.doFormat(&putc, arguments, argptr);
|
||||
if (newline)
|
||||
FPUTC('\n', fp);
|
||||
}
|
||||
else if (orientation > 0) // wide orientation
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
void putcw(dchar c)
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
FPUTWC(c, fp);
|
||||
}
|
||||
else
|
||||
{ wchar[2] buf;
|
||||
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
FPUTWC(buf[0], fp);
|
||||
FPUTWC(buf[1], fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
void putcw(dchar c)
|
||||
{
|
||||
FPUTWC(c, fp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
std.format.doFormat(&putcw, arguments, argptr);
|
||||
if (newline)
|
||||
FPUTWC('\n', fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Arguments are formatted per the
|
||||
* $(LINK2 std_format.html#format-string, format strings)
|
||||
* and written to $(B stdout).
|
||||
*/
|
||||
|
||||
void writef(...)
|
||||
{
|
||||
writefx(stdout, _arguments, _argptr, 0);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Same as $(B writef), but a newline is appended
|
||||
* to the output.
|
||||
*/
|
||||
|
||||
void writefln(...)
|
||||
{
|
||||
writefx(stdout, _arguments, _argptr, 1);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Same as $(B writef), but output is sent to the
|
||||
* stream fp instead of $(B stdout).
|
||||
*/
|
||||
|
||||
void fwritef(FILE* fp, ...)
|
||||
{
|
||||
writefx(fp, _arguments, _argptr, 0);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Same as $(B writefln), but output is sent to the
|
||||
* stream fp instead of $(B stdout).
|
||||
*/
|
||||
|
||||
void fwritefln(FILE* fp, ...)
|
||||
{
|
||||
writefx(fp, _arguments, _argptr, 1);
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Read line from stream fp.
|
||||
* Returns:
|
||||
* null for end of file,
|
||||
* char[] for line read from fp, including terminating '\n'
|
||||
* Params:
|
||||
* fp = input stream
|
||||
* Throws:
|
||||
* $(B StdioException) on error
|
||||
* Example:
|
||||
* Reads $(B stdin) and writes it to $(B stdout).
|
||||
---
|
||||
import std.stdio;
|
||||
|
||||
int main()
|
||||
{
|
||||
char[] buf;
|
||||
while ((buf = readln()) != null)
|
||||
writef("%s", buf);
|
||||
return 0;
|
||||
}
|
||||
---
|
||||
*/
|
||||
char[] readln(FILE* fp = stdin)
|
||||
{
|
||||
char[] buf;
|
||||
readln(fp, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Read line from stream fp and write it to buf[],
|
||||
* including terminating '\n'.
|
||||
*
|
||||
* This is often faster than readln(FILE*) because the buffer
|
||||
* is reused each call. Note that reusing the buffer means that
|
||||
* the previous contents of it need to be copied if needed.
|
||||
* Params:
|
||||
* fp = input stream
|
||||
* buf = buffer used to store the resulting line data. buf
|
||||
* is resized as necessary.
|
||||
* Returns:
|
||||
* 0 for end of file, otherwise
|
||||
* number of characters read
|
||||
* Throws:
|
||||
* $(B StdioException) on error
|
||||
* Example:
|
||||
* Reads $(B stdin) and writes it to $(B stdout).
|
||||
---
|
||||
import std.stdio;
|
||||
|
||||
int main()
|
||||
{
|
||||
char[] buf;
|
||||
while (readln(stdin, buf))
|
||||
writef("%s", buf);
|
||||
return 0;
|
||||
}
|
||||
---
|
||||
*/
|
||||
size_t readln(FILE* fp, inout char[] buf)
|
||||
{
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
{
|
||||
FLOCK(fp);
|
||||
scope(exit) FUNLOCK(fp);
|
||||
|
||||
if (__fhnd_info[fp._file] & FHND_WCHAR)
|
||||
{ /* Stream is in wide characters.
|
||||
* Read them and convert to chars.
|
||||
*/
|
||||
static assert(wchar_t.sizeof == 2);
|
||||
buf.length = 0;
|
||||
int c2;
|
||||
for (int c; (c = FGETWC(fp)) != -1; )
|
||||
{
|
||||
if ((c & ~0x7F) == 0)
|
||||
{ buf ~= c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c >= 0xD800 && c <= 0xDBFF)
|
||||
{
|
||||
if ((c2 = FGETWC(fp)) != -1 ||
|
||||
c2 < 0xDC00 && c2 > 0xDFFF)
|
||||
{
|
||||
StdioException("unpaired UTF-16 surrogate");
|
||||
}
|
||||
c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
|
||||
}
|
||||
std.utf.encode(buf, c);
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
auto sz = std.gc.capacity(buf.ptr);
|
||||
//auto sz = buf.length;
|
||||
buf = buf.ptr[0 .. sz];
|
||||
if (fp._flag & _IONBF)
|
||||
{
|
||||
/* Use this for unbuffered I/O, when running
|
||||
* across buffer boundaries, or for any but the common
|
||||
* cases.
|
||||
*/
|
||||
L1:
|
||||
char *p;
|
||||
|
||||
if (sz)
|
||||
{
|
||||
p = buf.ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = 64;
|
||||
p = cast(char*) std.gc.malloc(sz);
|
||||
std.gc.hasNoPointers(p);
|
||||
buf = p[0 .. sz];
|
||||
}
|
||||
size_t i = 0;
|
||||
for (int c; (c = FGETC(fp)) != -1; )
|
||||
{
|
||||
if ((p[i] = c) != '\n')
|
||||
{
|
||||
i++;
|
||||
if (i < sz)
|
||||
continue;
|
||||
buf = p[0 .. i] ~ readln(fp);
|
||||
return buf.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = p[0 .. i + 1];
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
buf = p[0 .. i];
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
int u = fp._cnt;
|
||||
char* p = fp._ptr;
|
||||
int i;
|
||||
if (fp._flag & _IOTRAN)
|
||||
{ /* Translated mode ignores \r and treats ^Z as end-of-file
|
||||
*/
|
||||
char c;
|
||||
while (1)
|
||||
{
|
||||
if (i == u) // if end of buffer
|
||||
goto L1; // give up
|
||||
c = p[i];
|
||||
i++;
|
||||
if (c != '\r')
|
||||
{
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c != 0x1A)
|
||||
continue;
|
||||
goto L1;
|
||||
}
|
||||
else
|
||||
{ if (i != u && p[i] == '\n')
|
||||
break;
|
||||
goto L1;
|
||||
}
|
||||
}
|
||||
if (i > sz)
|
||||
{
|
||||
buf = cast(char[])std.gc.malloc(i);
|
||||
std.gc.hasNoPointers(buf.ptr);
|
||||
}
|
||||
if (i - 1)
|
||||
memcpy(buf.ptr, p, i - 1);
|
||||
buf[i - 1] = '\n';
|
||||
if (c == '\r')
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (i == u) // if end of buffer
|
||||
goto L1; // give up
|
||||
auto c = p[i];
|
||||
i++;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
if (i > sz)
|
||||
{
|
||||
buf = cast(char[])std.gc.malloc(i);
|
||||
std.gc.hasNoPointers(buf.ptr);
|
||||
}
|
||||
memcpy(buf.ptr, p, i);
|
||||
}
|
||||
fp._cnt -= i;
|
||||
fp._ptr += i;
|
||||
buf = buf[0 .. i];
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else version (GCC_IO)
|
||||
{
|
||||
if (fwide(fp, 0) > 0)
|
||||
{ /* Stream is in wide characters.
|
||||
* Read them and convert to chars.
|
||||
*/
|
||||
FLOCK(fp);
|
||||
scope(exit) FUNLOCK(fp);
|
||||
version (Windows)
|
||||
{
|
||||
buf.length = 0;
|
||||
int c2;
|
||||
for (int c; (c = FGETWC(fp)) != -1; )
|
||||
{
|
||||
if ((c & ~0x7F) == 0)
|
||||
{ buf ~= c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c >= 0xD800 && c <= 0xDBFF)
|
||||
{
|
||||
if ((c2 = FGETWC(fp)) != -1 ||
|
||||
c2 < 0xDC00 && c2 > 0xDFFF)
|
||||
{
|
||||
StdioException("unpaired UTF-16 surrogate");
|
||||
}
|
||||
c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
|
||||
}
|
||||
std.utf.encode(buf, c);
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
return buf.length;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
buf.length = 0;
|
||||
for (int c; (c = FGETWC(fp)) != -1; )
|
||||
{
|
||||
if ((c & ~0x7F) == 0)
|
||||
buf ~= c;
|
||||
else
|
||||
std.utf.encode(buf, cast(dchar)c);
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
return buf.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
char *lineptr = null;
|
||||
size_t n = 0;
|
||||
auto s = getdelim(&lineptr, &n, '\n', fp);
|
||||
scope(exit) free(lineptr);
|
||||
if (s < 0)
|
||||
{
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
buf.length = 0; // end of file
|
||||
return 0;
|
||||
}
|
||||
buf = buf.ptr[0 .. std.gc.capacity(buf.ptr)];
|
||||
if (s <= buf.length)
|
||||
{
|
||||
buf.length = s;
|
||||
buf[] = lineptr[0 .. s];
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = lineptr[0 .. s].dup;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t readln(inout char[] buf)
|
||||
{
|
||||
return readln(stdin, buf);
|
||||
}
|
||||
|
||||
|
||||
1127
lphobos/std/thread.d
Normal file
1127
lphobos/std/thread.d
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,11 @@ package.language = "c++"
|
||||
package.files = { matchfiles("dmd/*.c"), matchfiles("gen/*.cpp") }
|
||||
package.excludes = { "dmd/idgen.c", "dmd/impcnvgen.c" }
|
||||
package.buildoptions = { "-x c++", "`llvm-config --cxxflags`" }
|
||||
package.linkoptions = { "`llvm-config --libs all`", "`llvm-config --ldflags`" }
|
||||
package.linkoptions = {
|
||||
-- long but it's faster than just 'all'
|
||||
"`llvm-config --libs core asmparser bitreader bitwriter support target transformutils scalaropts ipo instrumentation x86 powerpc`",
|
||||
"`llvm-config --ldflags`"
|
||||
}
|
||||
package.defines = { "IN_LLVM", "_DH" }
|
||||
package.config.Release.defines = { "LLVMD_NO_LOGGER" }
|
||||
package.config.Debug.buildoptions = { "-g -O0" }
|
||||
|
||||
19
test/asm1.d
Normal file
19
test/asm1.d
Normal file
@@ -0,0 +1,19 @@
|
||||
module asm1;
|
||||
|
||||
void main()
|
||||
{
|
||||
version(LLVM_InlineAsm_X86_64)
|
||||
{
|
||||
long x;
|
||||
asm
|
||||
{
|
||||
mov RAX, 42L;
|
||||
mov x, RAX;
|
||||
}
|
||||
printf("x = %ld\n", x);
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0, "no llvm inline asm for this platform yet");
|
||||
}
|
||||
}
|
||||
9
test/bug79.d
Normal file
9
test/bug79.d
Normal file
@@ -0,0 +1,9 @@
|
||||
module bug79;
|
||||
import std.c.linux.linux;
|
||||
void main()
|
||||
{
|
||||
timespec ts;
|
||||
ts.tv_nsec -= 1;
|
||||
//auto t = ts.tv_nsec - 1;
|
||||
//t -= 1;
|
||||
}
|
||||
10
test/bug80.d
Normal file
10
test/bug80.d
Normal file
@@ -0,0 +1,10 @@
|
||||
module bug80;
|
||||
|
||||
void main()
|
||||
{
|
||||
byte b = 10;
|
||||
int i = b += 2;
|
||||
printf("byte=%d int=%d\n", b, i);
|
||||
assert(b == 12);
|
||||
assert(i == 12);
|
||||
}
|
||||
65
test/calls1.d
Normal file
65
test/calls1.d
Normal file
@@ -0,0 +1,65 @@
|
||||
module calls1;
|
||||
import std.stdarg;
|
||||
void main()
|
||||
{
|
||||
{int a = byVal1(3);}
|
||||
{int a = void; byRef1(a);}
|
||||
{char[] c = void; refType(c);}
|
||||
{char[] c = void; refTypeByRef(c);}
|
||||
{S s = void; structByVal(s);}
|
||||
{S s = void; structByRef(s);}
|
||||
{S s = void; structByPtr(&s);}
|
||||
{printf("c-varargs %d %d %d\n", 1,2,3);}
|
||||
{int i=3; float f=24.7; dvararg(i,f);}
|
||||
{char[] s = "hello"; dvarargRefTy(s);}
|
||||
{char[] ss = "hello world!"; dvarargRefTy(ss);}
|
||||
}
|
||||
|
||||
int byVal1(int a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
void byRef1(ref int a)
|
||||
{
|
||||
a = 3;
|
||||
}
|
||||
|
||||
void refType(char[] s)
|
||||
{
|
||||
}
|
||||
|
||||
void refTypeByRef(ref char[] s)
|
||||
{
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
long l;
|
||||
byte b;
|
||||
}
|
||||
|
||||
void structByVal(S s)
|
||||
{
|
||||
}
|
||||
|
||||
void structByRef(ref S s)
|
||||
{
|
||||
}
|
||||
|
||||
void structByPtr(S* s)
|
||||
{
|
||||
}
|
||||
|
||||
void dvararg(...)
|
||||
{
|
||||
printf("%d %.1f\n", va_arg!(int)(_argptr), va_arg!(float)(_argptr));
|
||||
}
|
||||
|
||||
void dvarargRefTy(...)
|
||||
{
|
||||
char[] s = va_arg!(char[])(_argptr);
|
||||
printf("%.*s\n", s.length, s.ptr);
|
||||
}
|
||||
42
test/nested11.d
Normal file
42
test/nested11.d
Normal file
@@ -0,0 +1,42 @@
|
||||
module nested11;
|
||||
|
||||
void main()
|
||||
{
|
||||
int i;
|
||||
|
||||
void f()
|
||||
{
|
||||
i++;
|
||||
|
||||
void g()
|
||||
{
|
||||
i++;
|
||||
|
||||
void h()
|
||||
{
|
||||
printf("i = %d\n", i);
|
||||
}
|
||||
|
||||
h();
|
||||
}
|
||||
|
||||
g();
|
||||
}
|
||||
|
||||
f();
|
||||
assert(i == 2);
|
||||
|
||||
void foo()
|
||||
{
|
||||
i = 42;
|
||||
}
|
||||
|
||||
void bar()
|
||||
{
|
||||
foo();
|
||||
}
|
||||
|
||||
bar();
|
||||
printf("i = %d\n", i);
|
||||
assert(i == 42);
|
||||
}
|
||||
21
test/nested12.d
Normal file
21
test/nested12.d
Normal file
@@ -0,0 +1,21 @@
|
||||
module nested12;
|
||||
|
||||
void main()
|
||||
{
|
||||
func();
|
||||
}
|
||||
|
||||
void func()
|
||||
{
|
||||
void a(int i)
|
||||
{
|
||||
printf("%d\n", i);
|
||||
}
|
||||
|
||||
void b()
|
||||
{
|
||||
a(42);
|
||||
}
|
||||
|
||||
b();
|
||||
}
|
||||
@@ -2,7 +2,27 @@ module stdiotest;
|
||||
|
||||
import std.stdio;
|
||||
|
||||
T typed(T)(T x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
writefln("hello world",42,'x');
|
||||
/*char[] str = "hello";
|
||||
writefln(str);
|
||||
|
||||
writefln("hello world");*/
|
||||
|
||||
char[] fmt = "%s";
|
||||
writefln(2.0f);
|
||||
|
||||
/*{writefln(typed!(byte)(1));}
|
||||
{writefln(typed!(short)(2));}
|
||||
{writefln(typed!(int)(3));}
|
||||
{writefln(typed!(long)(-4));}
|
||||
{writefln(typed!(ulong)(5));}
|
||||
{writefln("%f", typed!(float)(6));}
|
||||
{writefln("%f", typed!(double)(7));}
|
||||
{writefln("%f", typed!(real)(8));}*/
|
||||
}
|
||||
|
||||
22
test/stdiotest2.d
Normal file
22
test/stdiotest2.d
Normal file
@@ -0,0 +1,22 @@
|
||||
module stdiotest2;
|
||||
import std.stdio;
|
||||
void main()
|
||||
{
|
||||
int[4] v = [1,2,3,4];
|
||||
{
|
||||
writefln("%s", v);
|
||||
{
|
||||
int[] dv = v;
|
||||
{writefln("%s", dv);}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
writefln(v);
|
||||
{
|
||||
//int[] dv = v;
|
||||
//{writefln(dv);}
|
||||
}
|
||||
}
|
||||
//writefln(1,2,3,4.56,"hello",v);
|
||||
}
|
||||
12
test/vararg5.d
Normal file
12
test/vararg5.d
Normal file
@@ -0,0 +1,12 @@
|
||||
module vararg5;
|
||||
import std.stdarg;
|
||||
void func(...)
|
||||
{
|
||||
char[] str = va_arg!(char[])(_argptr);
|
||||
{printf("%.*s\n", str.length, str.ptr);}
|
||||
}
|
||||
void main()
|
||||
{
|
||||
char[] str = "hello";
|
||||
func(str);
|
||||
}
|
||||
Reference in New Issue
Block a user