Refactor checkGC (#21058)

This commit is contained in:
Dennis 2025-03-22 23:08:04 +01:00 committed by GitHub
parent 7fb4d613af
commit 90e1a584b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 46 additions and 41 deletions

View file

@ -306,6 +306,7 @@ extern (C++) abstract class Expression : ASTNode
{
bool parens; // if this is a parenthesized expression
bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue
bool gcPassDone; // `checkGC` has been run on this expression
}
import dmd.common.bitfields;
mixin(generateBitFields!(BitFields, ubyte));

View file

@ -11762,6 +11762,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
res = new LoweredAssignExp(ae, res);
res.type = ae.type;
res = res.checkGC(sc);
return res;
}

View file

@ -2368,14 +2368,17 @@ public:
{
bool parens;
bool rvalue;
bool gcPassDone;
BitFields() :
parens(),
rvalue()
rvalue(),
gcPassDone()
{
}
BitFields(bool parens, bool rvalue = false) :
BitFields(bool parens, bool rvalue = false, bool gcPassDone = false) :
parens(parens),
rvalue(rvalue)
rvalue(rvalue),
gcPassDone(gcPassDone)
{}
};
@ -2383,6 +2386,8 @@ public:
bool parens(bool v);
bool rvalue() const;
bool rvalue(bool v);
bool gcPassDone() const;
bool gcPassDone(bool v);
private:
uint8_t bitFields;
public:
@ -7584,6 +7589,7 @@ class NOGCVisitor final : public StoppableVisitor
public:
using StoppableVisitor::visit;
FuncDeclaration* f;
Scope* sc;
bool checkOnly;
bool err;
bool nogcExceptions;

View file

@ -45,13 +45,15 @@ extern (C++) final class NOGCVisitor : StoppableVisitor
alias visit = typeof(super).visit;
public:
FuncDeclaration f;
Scope* sc;
bool checkOnly; // don't print errors
bool err;
bool nogcExceptions; // -preview=dip1008 enabled
extern (D) this(FuncDeclaration f) scope @safe
extern (D) this(FuncDeclaration f, Scope* sc) scope @safe
{
this.f = f;
this.sc = sc;
}
void doCond(Expression exp)
@ -86,6 +88,8 @@ public:
*/
private bool setGC(Expression e, const(char)* msg)
{
if (sc.debug_)
return false;
if (checkOnly)
{
err = true;
@ -208,9 +212,10 @@ public:
}
}
Expression checkGC(Scope* sc, Expression e)
Expression checkGC(Expression e, Scope* sc)
{
if (sc.ctfeBlock) // ignore GC in ctfe blocks
// printf("%s checkGC(%s)\n", e.loc.toChars, e.toChars);
if (e.gcPassDone || sc.ctfeBlock || sc.ctfe || sc.intypeof == 1 || !sc.func)
return e;
/* If betterC, allow GC to happen in non-CTFE code.
@ -219,28 +224,20 @@ Expression checkGC(Scope* sc, Expression e)
*/
const betterC = !global.params.useGC;
FuncDeclaration f = sc.func;
if (e && e.op != EXP.error && f && sc.intypeof != 1 &&
(!sc.ctfe || betterC) &&
(f.type.ty == Tfunction &&
(cast(TypeFunction)f.type).isNogc || f.nogcInprocess || global.params.v.gc) &&
!sc.debug_)
{
scope NOGCVisitor gcv = new NOGCVisitor(f);
gcv.checkOnly = betterC;
gcv.nogcExceptions = sc.previews.dip1008;
walkPostorder(e, gcv);
if (gcv.err)
{
if (betterC)
{
/* Allow ctfe to use the gc code, but don't let it into the runtime
*/
f.skipCodegen = true;
}
else
return ErrorExp.get();
}
}
scope NOGCVisitor gcv = new NOGCVisitor(f, sc);
gcv.checkOnly = betterC && (f.type.isTypeFunction().isNogc || f.nogcInprocess);
gcv.nogcExceptions = sc.previews.dip1008;
walkPostorder(e, gcv);
e.gcPassDone = true;
if (!gcv.err)
return e;
if (!betterC)
return ErrorExp.get();
// Allow ctfe to use the gc code, but don't let it into the runtime
f.skipCodegen = true;
return e;
}

View file

@ -855,7 +855,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (tret.ty == Terror)
{
// https://issues.dlang.org/show_bug.cgi?id=13702
exp = checkGC(sc2, exp);
exp = exp.checkGC(sc2);
continue;
}
@ -977,7 +977,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
checkReturnEscape(*sc2, exp, false);
}
exp = checkGC(sc2, exp);
exp = exp.checkGC(sc2);
if (funcdecl.vresult)
{

View file

@ -219,7 +219,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
s.exp = ErrorExp.get();
s.exp = s.exp.optimize(WANTvalue);
s.exp = checkGC(sc, s.exp);
s.exp = s.exp.checkGC(sc);
if (s.exp.op == EXP.error)
return setError();
result = s;
@ -585,7 +585,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(ds.condition))
ds.condition = ErrorExp.get();
ds.condition = ds.condition.optimize(WANTvalue);
ds.condition = checkGC(sc, ds.condition);
ds.condition = ds.condition.checkGC(sc);
ds.condition = ds.condition.toBoolean(sc);
@ -658,7 +658,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(fs.condition))
fs.condition = ErrorExp.get();
fs.condition = fs.condition.optimize(WANTvalue);
fs.condition = checkGC(sc, fs.condition);
fs.condition = fs.condition.checkGC(sc);
fs.condition = fs.condition.toBoolean(sc);
}
@ -677,7 +677,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(fs.increment))
fs.increment = ErrorExp.get();
fs.increment = fs.increment.optimize(WANTvalue);
fs.increment = checkGC(sc, fs.increment);
fs.increment = fs.increment.checkGC(sc);
}
sc.sbreak = fs;
@ -1709,7 +1709,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
// checkGC after optimizing the condition so that
// compile time constants are reduced.
ifs.condition = checkGC(scd, ifs.condition);
ifs.condition = ifs.condition.checkGC(scd);
// Save 'root' of two branches (then and else) at the point where it forks
CtorFlow ctorflow_root = scd.ctorflow.clone();
@ -1897,7 +1897,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (checkNonAssignmentArrayOp(ss.condition))
ss.condition = ErrorExp.get();
ss.condition = ss.condition.optimize(WANTvalue);
ss.condition = checkGC(sc, ss.condition);
ss.condition = ss.condition.checkGC(sc);
if (ss.condition.op == EXP.error)
conditionError = true;
@ -2636,7 +2636,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
if (e0)
{
e0 = e0.optimize(WANTvalue);
e0 = checkGC(sc, e0);
e0 = e0.checkGC(sc);
}
}
@ -3054,7 +3054,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
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.checkGC(sc);
if (ss.exp.op == EXP.error)
{
if (ss._body)
@ -3178,7 +3178,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
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.checkGC(sc);
if (ws.exp.op == EXP.error)
return setError();
if (ws.exp.op == EXP.scope_)
@ -3740,7 +3740,7 @@ public bool throwSemantic(Loc loc, ref Expression exp, Scope* sc)
exp = exp.expressionSemantic(sc);
exp = resolveProperties(sc, exp);
exp = checkGC(sc, exp);
exp = exp.checkGC(sc);
if (exp.isErrorExp())
return false;
if (!exp.type.isNaked())

View file

@ -1847,7 +1847,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
const tf = sc2.func.type.isTypeFunction();
err |= tf.isNothrow && canThrow(ex, sc2.func, null);
}
ex = checkGC(sc2, ex);
ex = ex.checkGC(sc2);
if (ex.op == EXP.error)
err = true;
}