Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dmd/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ MATCH implicitConvTo(Expression e, Type t)
e.type = Type.terror;
}

Expression ex = e.optimize(WANTvalue);
Expression ex = e.optimize(WANTvalue | WANTnoctfe);
if (ex.type.equals(t))
{
result = MATCH.exact;
Expand Down
16 changes: 11 additions & 5 deletions src/dmd/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -2084,8 +2084,9 @@ public:
if (v._init.isVoidInitializer())
{
// var should have been initialized when it was created
// But this can happen with __swap=void generation
error(loc, "CTFE internal error: trying to access uninitialized var");
assert(0);
return CTFEExp.cantexp;
}
e = v._init.initializerToExpression();
}
Expand Down Expand Up @@ -6199,10 +6200,10 @@ public:
}

// We can't use getField, because it makes a copy
if (ex.op == TOK.classReference)
if (auto cre = ex.isClassReferenceExp())
{
se = (cast(ClassReferenceExp)ex).value;
i = (cast(ClassReferenceExp)ex).findFieldIndexByName(v);
se = cre.value;
i = cre.findFieldIndexByName(v);
}
else if (ex.op == TOK.typeid_)
{
Expand All @@ -6223,7 +6224,7 @@ public:
}
else
{
se = cast(StructLiteralExp)ex;
se = ex.isStructLiteralExp();
i = findFieldIndexByName(se.sd, v);
}
if (i == -1)
Expand Down Expand Up @@ -6253,13 +6254,16 @@ public:
return;
}

assert(i < se.elements.dim);
result = (*se.elements)[i];
if (!result)
{
e.error("Internal Compiler Error: null field `%s`", v.toChars());
result = CTFEExp.cantexp;
return;
}

assert(result.op != 0xFF);
if (auto vie = result.isVoidInitExp())
{
const s = vie.var.toChars();
Expand Down Expand Up @@ -6662,6 +6666,8 @@ private Expression copyRegionExp(Expression e)
if (!e)
return e;

assert(e.op != 0xFF);

static void copyArray(Expressions* elems)
{
foreach (ref e; *elems)
Expand Down
1 change: 1 addition & 0 deletions src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ enum OwnedBy : ubyte

enum WANTvalue = 0; // default
enum WANTexpand = 1; // expand const/immutable variables if possible
enum WANTnoctfe = 2; // do not run CTFE on pure functions

/***********************************************************
* http://dlang.org/spec/expression.html#expression
Expand Down
92 changes: 69 additions & 23 deletions src/dmd/optimize.d
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ module dmd.optimize;

import core.stdc.stdio;

import dmd.printast;
import dmd.constfold;
import dmd.ctfeexpr;
import dmd.dclass;
import dmd.declaration;
import dmd.dinterpret;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
Expand Down Expand Up @@ -270,12 +272,14 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)

Expression ret;
private const int result;
private const int want;
private const bool keepLvalue;

extern (D) this(Expression e, int result, bool keepLvalue)
{
this.ret = e; // default result is original expression
this.result = result;
this.want = result & WANTnoctfe;
this.keepLvalue = keepLvalue;
}

Expand Down Expand Up @@ -331,10 +335,10 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)

override void visit(TupleExp e)
{
expOptimize(e.e0, WANTvalue);
expOptimize(e.e0, want);
for (size_t i = 0; i < e.exps.dim; i++)
{
expOptimize((*e.exps)[i], WANTvalue);
expOptimize((*e.exps)[i], want);
}
}

Expand Down Expand Up @@ -575,42 +579,84 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)

override void visit(NewExp e)
{
expOptimize(e.thisexp, WANTvalue);
expOptimize(e.thisexp, want);
// Optimize parameters
if (e.newargs)
{
for (size_t i = 0; i < e.newargs.dim; i++)
{
expOptimize((*e.newargs)[i], WANTvalue);
expOptimize((*e.newargs)[i], want);
}
}
if (e.arguments)
{
for (size_t i = 0; i < e.arguments.dim; i++)
{
expOptimize((*e.arguments)[i], WANTvalue);
expOptimize((*e.arguments)[i], want);
}
}
}

override void visit(CallExp e)
{
//printf("CallExp::optimize(result = %d) %s\n", result, e.toChars());
enum log = false;
//if (log) printf("CallExp::optimize(result = %d) %s\n", result, e.toChars());
// Optimize parameters with keeping lvalue-ness
if (expOptimize(e.e1, result))
return;
Type t1 = e.e1.type.toBasetype();
if (t1.ty == Tdelegate)
t1 = t1.nextOf();
auto tf = t1.isTypeFunction();
bool tryCTFE = !(want & WANTnoctfe) &&
(tf.purity == PURE.strong || tf.purity == PURE.weak || tf.purity == PURE.const_);

/* A @nogc function that tries to return an array literal is going
* go cause an error in checkGC()
*/
if (tf.isnogc)
{
const ty = e.type.toBasetype().ty;
if (ty == Tarray || ty == Taarray)
tryCTFE = false;
}

if (e.arguments)
{
Type t1 = e.e1.type.toBasetype();
if (t1.ty == Tdelegate)
t1 = t1.nextOf();
assert(t1.ty == Tfunction);
TypeFunction tf = cast(TypeFunction)t1;
for (size_t i = 0; i < e.arguments.dim; i++)
foreach (i; 0 .. e.arguments.dim)
{
Parameter p = tf.parameterList[i];
bool keep = p && p.isReference();
expOptimize((*e.arguments)[i], WANTvalue, keep);
expOptimize((*e.arguments)[i], want, keep);
auto ea = (*e.arguments)[i];

/* Attempting CTFE is slow, so try to quickly eliminate
* cases where it won't work anyway
*/
tryCTFE = tryCTFE && !keep &&
(ea.op == TOK.int64 ||
ea.op == TOK.null_ ||
ea.op == TOK.string_ ||
ea.op == TOK.arrayLiteral ||
ea.op == TOK.assocArrayLiteral ||
ea.op == TOK.structLiteral ||
ea.op == TOK.float64 ||
ea.op == TOK.complex80);
}
}
if (tryCTFE)
{
if (log) printf("trying CTFE %d %s %s\n", tf.purity, tf.toChars(), e.toChars());
const gaggedErrorsSave = global.startGagging();
auto ex = ctfeInterpret(e);
if (!global.endGagging(gaggedErrorsSave) && ex.op != TOK.error)
{
if (log) printf("succeeded %p %d\n", ex, ex.op);
ret = ex;
}
else
{
if (log) printf("failed\n");
}
}
}
Expand Down Expand Up @@ -917,7 +963,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
// otherwise we must NOT attempt to constant-fold them.
// In particular, if the comma returns a temporary variable, it needs
// to be an lvalue (this is particularly important for struct constructors)
expOptimize(e.e1, WANTvalue);
expOptimize(e.e1, want);
expOptimize(e.e2, result, keepLvalue);
if (ret.op == TOK.error)
return;
Expand Down Expand Up @@ -954,7 +1000,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
override void visit(EqualExp e)
{
//printf("EqualExp::optimize(result = %x) %s\n", result, e.toChars());
if (binOptimize(e, WANTvalue))
if (binOptimize(e, want))
return;
Expression e1 = fromConstInitializer(result, e.e1);
Expression e2 = fromConstInitializer(result, e.e2);
Expand All @@ -976,7 +1022,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
override void visit(IdentityExp e)
{
//printf("IdentityExp::optimize(result = %d) %s\n", result, e.toChars());
if (binOptimize(e, WANTvalue))
if (binOptimize(e, want))
return;
if ((e.e1.isConst() && e.e2.isConst()) || (e.e1.op == TOK.null_ && e.e2.op == TOK.null_))
{
Expand All @@ -994,7 +1040,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
Expression ex = fromConstInitializer(result, e.e1);
// We might know $ now
setLengthVarIfKnown(e.lengthVar, ex);
if (expOptimize(e.e2, WANTvalue))
if (expOptimize(e.e2, want))
return;
// Don't optimize to an array literal element directly in case an lvalue is requested
if (keepLvalue && ex.op == TOK.arrayLiteral)
Expand Down Expand Up @@ -1024,8 +1070,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
e.e1 = fromConstInitializer(result, e.e1);
// We might know $ now
setLengthVarIfKnown(e.lengthVar, e.e1);
expOptimize(e.lwr, WANTvalue);
expOptimize(e.upr, WANTvalue);
expOptimize(e.lwr, want);
expOptimize(e.upr, want);
if (ret.op == TOK.error)
return;
ret = Slice(e.type, e.e1, e.lwr, e.upr).copy();
Expand All @@ -1050,7 +1096,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
override void visit(LogicalExp e)
{
//printf("LogicalExp::optimize(%d) %s\n", result, e.toChars());
if (expOptimize(e.e1, WANTvalue))
if (expOptimize(e.e1, want))
return;
const oror = e.op == TOK.orOr;
if (e.e1.isBool(oror))
Expand All @@ -1066,7 +1112,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
ret = Expression_optimize(ret, result, false);
return;
}
if (expOptimize(e.e2, WANTvalue))
if (expOptimize(e.e2, want))
return;
if (e.e1.isConst())
{
Expand All @@ -1092,7 +1138,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
override void visit(CmpExp e)
{
//printf("CmpExp::optimize() %s\n", e.toChars());
if (binOptimize(e, WANTvalue))
if (binOptimize(e, want))
return;
Expression e1 = fromConstInitializer(result, e.e1);
Expression e2 = fromConstInitializer(result, e.e2);
Expand Down Expand Up @@ -1140,7 +1186,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)

override void visit(CondExp e)
{
if (expOptimize(e.econd, WANTvalue))
if (expOptimize(e.econd, want))
return;
if (e.econd.isBool(true))
ret = Expression_optimize(e.e1, result, keepLvalue);
Expand Down
20 changes: 11 additions & 9 deletions src/dmd/statementsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
if (discardValue(s.exp))
s.exp = ErrorExp.get();

s.exp = s.exp.optimize(WANTvalue);
s.exp = checkGC(sc, s.exp);
s.exp = s.exp.optimize(WANTvalue);
if (s.exp.op == TOK.error)
return setError();
}
Expand Down Expand Up @@ -529,8 +529,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
ds.condition = resolveProperties(sc, ds.condition);
if (checkNonAssignmentArrayOp(ds.condition))
ds.condition = ErrorExp.get();
ds.condition = ds.condition.optimize(WANTvalue);
ds.condition = checkGC(sc, ds.condition);
ds.condition = ds.condition.optimize(WANTvalue);

ds.condition = ds.condition.toBoolean(sc);

Expand Down Expand Up @@ -602,8 +602,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
fs.condition = resolveProperties(sc, fs.condition);
if (checkNonAssignmentArrayOp(fs.condition))
fs.condition = ErrorExp.get();
fs.condition = fs.condition.optimize(WANTvalue);
fs.condition = checkGC(sc, fs.condition);
fs.condition = fs.condition.optimize(WANTvalue);

fs.condition = fs.condition.toBoolean(sc);
}
Expand All @@ -614,8 +614,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
fs.increment = resolveProperties(sc, fs.increment);
if (checkNonAssignmentArrayOp(fs.increment))
fs.increment = ErrorExp.get();
fs.increment = fs.increment.optimize(WANTvalue);
fs.increment = checkGC(sc, fs.increment);
fs.increment = fs.increment.optimize(WANTvalue);
}

sc.sbreak = fs;
Expand Down Expand Up @@ -2566,8 +2566,8 @@ else
}
if (checkNonAssignmentArrayOp(ss.condition))
ss.condition = ErrorExp.get();
ss.condition = ss.condition.optimize(WANTvalue);
ss.condition = checkGC(sc, ss.condition);
ss.condition = ss.condition.optimize(WANTvalue);
if (ss.condition.op == TOK.error)
conditionError = true;

Expand Down Expand Up @@ -3214,7 +3214,10 @@ else
rs.exp = valueNoDtor(rs.exp);

if (e0)
{
e0 = checkGC(sc, e0);
e0 = e0.optimize(WANTvalue);
}

/* Void-return function can have void typed expression
* on return statement.
Expand All @@ -3228,6 +3231,7 @@ else
rs.exp = new CastExp(rs.loc, rs.exp, Type.tvoid);
rs.exp = rs.exp.expressionSemantic(sc);
}
rs.exp = checkGC(sc, rs.exp);

/* Replace:
* return exp;
Expand All @@ -3237,8 +3241,6 @@ else
e0 = Expression.combine(e0, rs.exp);
rs.exp = null;
}
if (e0)
e0 = checkGC(sc, e0);
}

if (rs.exp)
Expand Down Expand Up @@ -3624,8 +3626,8 @@ else
{
ss.exp = ss.exp.expressionSemantic(sc);
ss.exp = resolveProperties(sc, ss.exp);
ss.exp = ss.exp.optimize(WANTvalue);
ss.exp = checkGC(sc, ss.exp);
ss.exp = ss.exp.optimize(WANTvalue);
if (ss.exp.op == TOK.error)
{
if (ss._body)
Expand Down Expand Up @@ -3745,8 +3747,8 @@ else
//printf("WithStatement::semantic()\n");
ws.exp = ws.exp.expressionSemantic(sc);
ws.exp = resolveProperties(sc, ws.exp);
ws.exp = ws.exp.optimize(WANTvalue);
ws.exp = checkGC(sc, ws.exp);
ws.exp = ws.exp.optimize(WANTvalue);
if (ws.exp.op == TOK.error)
return setError();
if (ws.exp.op == TOK.scope_)
Expand Down
Loading