Refactoring: Replace Expression::op check followed by static cast to Expression::is<ExpressionType> (#3141)

This may negatively impact performance, as the (final, i.e.,
non-virtual) Expression::is... family is implemented in D and not
available inline in the C++ headers.
This commit is contained in:
Martin Kinkelin 2020-01-15 12:54:05 +01:00 committed by GitHub
parent ec1c37a5a4
commit 26673c174f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 112 additions and 132 deletions

View file

@ -875,14 +875,13 @@ DSliceValue *DtoCatArrays(Loc &loc, Type *arrayType, Expression *exp1,
llvm::SmallVector<llvm::Value *, 3> args;
LLFunction *fn = nullptr;
if (exp1->op == TOKcat) { // handle multiple concat
if (auto ce = exp1->isCatExp()) { // handle multiple concat
fn = getRuntimeFunction(loc, gIR->module, "_d_arraycatnTX");
// Create array of slices
typedef llvm::SmallVector<llvm::Value *, 16> ArgVector;
ArgVector arrs;
arrs.push_back(DtoSlicePtr(exp2));
CatExp *ce = static_cast<CatExp *>(exp1);
do {
arrs.push_back(DtoSlicePtr(ce->e2));
ce = static_cast<CatExp *>(ce->e1);

View file

@ -2352,12 +2352,11 @@ struct AsmProcessor {
case Arg_Memory:
// Peel off one layer of explicitly taking the address, if present.
if (e->op == TOKaddress) {
e = static_cast<AddrExp *>(e)->e1;
if (auto ae = e->isAddrExp()) {
e = ae->e1;
}
if (e->op == TOKvar) {
VarExp *v = (VarExp *)e;
if (auto v = e->isVarExp()) {
if (VarDeclaration *vd = v->var->isVarDeclaration()) {
if (!vd->isDataseg()) {
stmt->error("only global variables can be referenced by "
@ -2968,8 +2967,8 @@ struct AsmProcessor {
Expression *e = operand->symbolDisplacement[0];
Declaration *decl = nullptr;
if (e->op == TOKvar) {
decl = ((VarExp *)e)->var;
if (auto ve = e->isVarExp()) {
decl = ve->var;
}
if (operand->baseReg != Reg_Invalid && decl && !decl->isDataseg()) {
@ -3028,8 +3027,8 @@ struct AsmProcessor {
if (isDollar(e)) {
stmt->error("dollar labels are not supported");
asmcode->dollarLabel = 1;
} else if (e->op == TOKdsymbol) {
LabelDsymbol *lbl = static_cast<DsymbolExp *>(e)->s->isLabel();
} else if (auto dse = e->isDsymbolExp()) {
LabelDsymbol *lbl = dse->s->isLabel();
stmt->isBranchToLabel = lbl;
use_star = false;
@ -3101,12 +3100,12 @@ struct AsmProcessor {
bool isRegExp(Expression *exp) { return exp->op == TOKmod; } // ewww.%%
bool isLocalSize(Expression *exp) {
// cleanup: make a static var
return exp->op == TOKidentifier &&
((IdentifierExp *)exp)->ident == Id::__LOCAL_SIZE;
auto ie = exp->isIdentifierExp();
return ie && ie->ident == Id::__LOCAL_SIZE;
}
bool isDollar(Expression *exp) {
return exp->op == TOKidentifier &&
((IdentifierExp *)exp)->ident == Id::dollar;
auto ie = exp->isIdentifierExp();
return ie && ie->ident == Id::dollar;
}
Expression *newRegExp(int regno) {
@ -3143,8 +3142,8 @@ struct AsmProcessor {
*/
bool is_offset = false;
if (exp->op == TOKaddress) {
exp = ((AddrExp *)exp)->e1;
if (auto ae = exp->isAddrExp()) {
exp = ae->e1;
is_offset = true;
}
@ -3176,8 +3175,8 @@ struct AsmProcessor {
stmt->error("too many registers memory operand");
}
}
} else if (exp->op == TOKvar) {
VarDeclaration *v = ((VarExp *)exp)->var->isVarDeclaration();
} else if (auto ve = exp->isVarExp()) {
VarDeclaration *v = ve->var->isVarDeclaration();
if (v && v->storage_class & STCfield) {
operand->constDisplacement += v->offset;

View file

@ -222,8 +222,8 @@ void AsmStatement_toIR(InlineAsmStatement *stmt, IRState *irs) {
case Arg_FrameRelative:
// FIXME
llvm_unreachable("Arg_FrameRelative not supported.");
/* if (arg->expr->op == TOKvar)
arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree;
/* if (auto ve = arg->expr->isVarExp())
arg_val = ve->var->toSymbol()->Stree;
else
assert(0);
if ( getFrameRelativeValue(arg_val, & var_frame_offset) ) {

View file

@ -56,14 +56,14 @@ RVals evalSides(DValue *lhs, Expression *rhs, bool loadLhsAfterRhs) {
Expression *extractNoStrideInc(Expression *e, d_uns64 baseSize, bool &negate) {
MulExp *mul;
while (true) {
if (e->op == TOKneg) {
if (auto ne = e->isNegExp()) {
negate = !negate;
e = static_cast<NegExp *>(e)->e1;
e = ne->e1;
continue;
}
if (e->op == TOKmul) {
mul = static_cast<MulExp *>(e);
if (auto me = e->isMulExp()) {
mul = me;
break;
}

View file

@ -37,10 +37,8 @@ bool parseStringExp(Expression *e, const char *&res) {
}
bool parseIntExp(Expression *e, dinteger_t &res) {
IntegerExp *i = nullptr;
e = e->optimize(WANTvalue);
if (e->op == TOKint64 && (i = static_cast<IntegerExp *>(e))) {
if (auto i = e->isIntegerExp()) {
res = i->getInteger();
return true;
}
@ -49,11 +47,12 @@ bool parseIntExp(Expression *e, dinteger_t &res) {
bool parseBoolExp(Expression *e, bool &res) {
e = e->optimize(WANTvalue);
if (e->op == TOKint64 && e->type->equals(Type::tbool)) {
IntegerExp *i = static_cast<IntegerExp *>(e);
if (auto i = e->isIntegerExp()) {
if (e->type->equals(Type::tbool)) {
res = i->isBool(true);
return true;
}
}
return false;
}

View file

@ -172,12 +172,13 @@ struct DComputeSemanticAnalyser : public StoppableVisitor {
stop = true;
}
void visit(SwitchStatement *e) override {
if (e->condition->op == TOKcall &&
static_cast<CallExp *>(e->condition)->f->ident == Id::__switch) {
if (auto ce = e->condition->isCallExp()) {
if (ce->f->ident == Id::__switch) {
e->error("cannot `switch` on strings in `@compute` code");
stop = true;
}
}
}
void visit(IfStatement *stmt) override {
// Don't descend into ctfe only code
@ -202,8 +203,7 @@ struct DComputeSemanticAnalyser : public StoppableVisitor {
// for the host and is therefore allowed to call non @compute functions.
// Thus, the if-statement body's code should not be checked for
// @compute semantics and the recursive visitor should stop here.
else if (stmt->condition->op == TOKcall) {
auto ce = (CallExp *)stmt->condition;
if (auto ce = stmt->condition->isCallExp()) {
if (ce->f && ce->f->ident == Id::dcReflect) {
auto arg1 = (DComputeTarget::ID)(*ce->arguments)[0]->toInteger();
if (arg1 == DComputeTarget::Host)

View file

@ -196,8 +196,8 @@ public:
// call postblit if the expression is a D lvalue
// exceptions: NRVO and special __result variable (out contracts)
bool doPostblit = !(fd->nrvo_can && fd->nrvo_var);
if (doPostblit && stmt->exp->op == TOKvar) {
auto ve = static_cast<VarExp *>(stmt->exp);
if (doPostblit) {
if (auto ve = stmt->exp->isVarExp())
if (ve->var->isResult())
doPostblit = false;
}
@ -374,8 +374,7 @@ public:
// to target multiple backends "simultaneously" with one
// pass through the front end, to have a single "static"
// context.
if (stmt->condition->op == TOKcall) {
auto ce = (CallExp *)stmt->condition;
if (auto ce = stmt->condition->isCallExp()) {
if (ce->f && ce->f->ident == Id::dcReflect) {
if (dcomputeReflectMatches(ce))
stmt->ifbody->accept(this);
@ -952,11 +951,11 @@ public:
for (auto cs : *cases) {
// skip over casts
auto ce = cs->exp;
while (ce->op == TOKcast)
ce = static_cast<CastExp *>(ce)->e1;
while (auto next = ce->isCastExp())
ce = next->e1;
if (ce->op == TOKvar) {
const auto vd = static_cast<VarExp *>(ce)->var->isVarDeclaration();
if (auto ve = ce->isVarExp()) {
const auto vd = ve->var->isVarDeclaration();
if (vd && (!vd->_init || !vd->isConst())) {
indices.push_back(DtoRVal(toElemDtor(cs->exp)));
useSwitchInst = false;

View file

@ -374,20 +374,17 @@ public:
// need to have a case for each thing we can take the address of
// address of global variable
if (e->e1->op == TOKvar) {
VarExp *vexp = static_cast<VarExp *>(e->e1);
if (auto vexp = e->e1->isVarExp()) {
LLConstant *c = DtoConstSymbolAddress(e->loc, vexp->var);
result = c ? DtoBitCast(c, DtoType(e->type)) : nullptr;
return;
}
// address of indexExp
if (e->e1->op == TOKindex) {
IndexExp *iexp = static_cast<IndexExp *>(e->e1);
if (auto iexp = e->e1->isIndexExp()) {
// indexee must be global static array var
assert(iexp->e1->op == TOKvar);
VarExp *vexp = static_cast<VarExp *>(iexp->e1);
VarExp *vexp = iexp->e1->isVarExp();
assert(vexp);
VarDeclaration *vd = vexp->var->isVarDeclaration();
assert(vd);
assert(vd->type->toBasetype()->ty == Tsarray);
@ -411,9 +408,7 @@ public:
return;
}
if (e->e1->op == TOKstructliteral) {
StructLiteralExp *se = static_cast<StructLiteralExp *>(e->e1);
if (auto se = e->e1->isStructLiteralExp()) {
result = p->getStructLiteralConstant(se);
if (result) {
IF_LOG Logger::cout()
@ -666,9 +661,7 @@ public:
// Array literals are assigned element-for-element; other expressions splat
// across the whole vector.
if (e->e1->op == TOKarrayliteral) {
const auto ale = static_cast<ArrayLiteralExp *>(e->e1);
if (auto ale = e->e1->isArrayLiteralExp()) {
llvm::SmallVector<llvm::Constant *, 16> elements;
elements.reserve(elemCount);
for (size_t i = 0; i < elemCount; ++i) {

View file

@ -199,8 +199,8 @@ void pushVarDtorCleanup(IRState *p, VarDeclaration *vd) {
////////////////////////////////////////////////////////////////////////////////
static Expression *skipOverCasts(Expression *e) {
while (e->op == TOKcast)
e = static_cast<CastExp *>(e)->e1;
while (auto ce = e->isCastExp())
e = ce->e1;
return e;
}
@ -441,9 +441,8 @@ public:
e->e2->type ? e->e2->type->toChars() : nullptr);
LOG_SCOPE;
if (e->e1->op == TOKarraylength) {
if (auto ale = e->e1->isArrayLengthExp()) {
Logger::println("performing array.length assignment");
ArrayLengthExp *ale = static_cast<ArrayLengthExp *>(e->e1);
DLValue arrval(ale->e1->type, DtoLVal(ale->e1));
DValue *newlen = toElem(e->e2);
DSliceValue *slice =
@ -459,10 +458,10 @@ public:
// coding style!
if (e->memset & referenceInit) {
assert(e->op == TOKconstruct || e->op == TOKblit);
assert(e->e1->op == TOKvar);
auto ve = e->e1->isVarExp();
assert(ve);
Declaration *d = static_cast<VarExp *>(e->e1)->var;
if (d->storage_class & (STCref | STCout)) {
if (ve->var->storage_class & (STCref | STCout)) {
Logger::println("performing ref variable initialization");
// Note that the variable value is accessed directly (instead
// of via getLVal(), which would perform a load from the
@ -485,8 +484,7 @@ public:
// when initializing a static array with an array literal.
// Use the static array as lhs in that case.
DValue *rewrittenLhsStaticArray = nullptr;
if (e->e1->op == TOKslice) {
SliceExp *se = static_cast<SliceExp *>(e->e1);
if (auto se = e->e1->isSliceExp()) {
Type *sliceeBaseType = se->e1->type->toBasetype();
if (se->lwr == nullptr && sliceeBaseType->ty == Tsarray &&
se->type->toBasetype()->nextOf() == sliceeBaseType->nextOf())
@ -527,12 +525,14 @@ public:
// where `i` is a ref variable aliasing with a).
// Be conservative with this optimization for now: only do the optimization
// for struct `.init` assignment.
if (lhs->isLVal() && (e->op == TOKassign) &&
((e->e2->op == TOKstructliteral) &&
static_cast<StructLiteralExp *>(e->e2)->useStaticInit)) {
if (toInPlaceConstruction(lhs->isLVal(), e->e2))
if (lhs->isLVal() && e->op == TOKassign) {
if (auto sle = e->e2->isStructLiteralExp()) {
if (sle->useStaticInit) {
if (toInPlaceConstruction(lhs->isLVal(), sle))
return;
}
}
}
DValue *r = toElem(e->e2);
@ -614,8 +614,7 @@ public:
static Expression *getLValExp(Expression *e) {
e = skipOverCasts(e);
if (e->op == TOKcomma) {
CommaExp *ce = static_cast<CommaExp *>(e);
if (auto ce = e->isCommaExp()) {
Expression *newCommaRhs = getLValExp(ce->e2);
if (newCommaRhs != ce->e2) {
CommaExp *newComma = static_cast<CommaExp *>(ce->copy());
@ -688,9 +687,8 @@ public:
PGO.setCurrentStmt(e);
// handle magic inline asm
if (e->e1->op == TOKvar) {
VarExp *ve = static_cast<VarExp *>(e->e1);
if (FuncDeclaration *fd = ve->var->isFuncDeclaration()) {
if (auto ve = e->e1->isVarExp()) {
if (auto fd = ve->var->isFuncDeclaration()) {
if (fd->llvmInternal == LLVMinline_asm) {
return DtoInlineAsmExpr(e->loc, fd, e->arguments, sretPointer);
}
@ -712,13 +710,12 @@ public:
// a similar hack.
VarDeclaration *delayedDtorVar = nullptr;
Expression *delayedDtorExp = nullptr;
if (e->f && e->f->isCtorDeclaration() && e->e1->op == TOKdotvar) {
DotVarExp *dve = static_cast<DotVarExp *>(e->e1);
if (dve->e1->op == TOKcomma) {
CommaExp *ce = static_cast<CommaExp *>(dve->e1);
if (ce->e1->op == TOKdeclaration && ce->e2->op == TOKvar) {
VarExp *ve = static_cast<VarExp *>(ce->e2);
if (VarDeclaration *vd = ve->var->isVarDeclaration()) {
if (e->f && e->f->isCtorDeclaration()) {
if (auto dve = e->e1->isDotVarExp())
if (auto ce = dve->e1->isCommaExp())
if (ce->e1->op == TOKdeclaration)
if (auto ve = ce->e2->isVarExp())
if (auto vd = ve->var->isVarDeclaration())
if (vd->needsScopeDtor()) {
Logger::println("Delaying edtor");
delayedDtorVar = vd;
@ -726,16 +723,13 @@ public:
vd->edtor = nullptr;
}
}
}
}
}
// get the callee value
DValue *fnval;
if (e->directcall) {
// TODO: Do this as an extra parameter to DotVarExp implementation.
assert(e->e1->op == TOKdotvar);
DotVarExp *dve = static_cast<DotVarExp *>(e->e1);
auto dve = e->e1->isDotVarExp();
assert(dve);
FuncDeclaration *fdecl = dve->var->isFuncDeclaration();
assert(fdecl);
DtoDeclareFunction(fdecl);
@ -1611,8 +1605,8 @@ public:
if (tc->sym->isInterfaceDeclaration()) {
DtoDeleteInterface(e->loc, dval);
onstack = true;
} else if (e->e1->op == TOKvar) {
if (auto vd = static_cast<VarExp *>(e->e1)->var->isVarDeclaration()) {
} else if (auto ve = e->e1->isVarExp()) {
if (auto vd = ve->var->isVarDeclaration()) {
if (vd->onstack) {
DtoFinalizeScopeClass(e->loc, DtoRVal(dval), vd->onstackWithDtor);
onstack = true;
@ -2610,9 +2604,8 @@ public:
// Array literals are assigned element-wise, other expressions are cast and
// splat across the vector elements. This is what DMD does.
if (e->e1->op == TOKarrayliteral) {
if (auto lit = e->e1->isArrayLiteralExp()) {
Logger::println("array literal expression");
ArrayLiteralExp *lit = static_cast<ArrayLiteralExp *>(e->e1);
assert(lit->elements->length == N &&
"Array literal vector initializer "
"length mismatch, should have been handled in frontend.");
@ -2803,15 +2796,13 @@ bool toInPlaceConstruction(DLValue *lhs, Expression *rhs) {
}
// skip over rhs casts only emitted because of differing constness
if (rhs->op == TOKcast) {
auto castSource = static_cast<CastExp *>(rhs)->e1;
if (auto ce = rhs->isCastExp()) {
auto castSource = ce->e1;
if (basetypesAreEqualWithoutModifiers(lhs->type, castSource->type))
rhs = castSource;
}
if (rhs->op == TOKcall) {
auto ce = static_cast<CallExp *>(rhs);
if (auto ce = rhs->isCallExp()) {
// Direct construction by rhs call via sret?
// E.g., `T v = foo();` if the callee `T foo()` uses sret.
// In this case, pass `&v` as hidden sret argument, i.e., let `foo()`
@ -2823,14 +2814,13 @@ bool toInPlaceConstruction(DLValue *lhs, Expression *rhs) {
}
// DMD issue 17457: detect structliteral.ctor(args)
if (ce->e1->op == TOKdotvar) {
auto dve = static_cast<DotVarExp *>(ce->e1);
if (auto dve = ce->e1->isDotVarExp()) {
auto fd = dve->var->isFuncDeclaration();
if (fd && fd->isCtorDeclaration() && dve->e1->op == TOKstructliteral) {
Logger::println(
"success, in-place-constructing struct literal and invoking ctor");
if (fd && fd->isCtorDeclaration()) {
if (auto sle = dve->e1->isStructLiteralExp()) {
Logger::println("success, in-place-constructing struct literal and "
"invoking ctor");
// emit the struct literal directly into the lhs lvalue...
auto sle = static_cast<StructLiteralExp *>(dve->e1);
auto lval = DtoLVal(lhs);
ToElemVisitor::emitStructLiteral(sle, lval);
// ... and invoke the ctor directly on it
@ -2841,23 +2831,24 @@ bool toInPlaceConstruction(DLValue *lhs, Expression *rhs) {
}
}
}
}
// emit struct literals directly into the lhs lvalue
if (rhs->op == TOKstructliteral) {
if (auto sle = rhs->isStructLiteralExp()) {
Logger::println("success, in-place-constructing struct literal");
auto sle = static_cast<StructLiteralExp *>(rhs);
ToElemVisitor::emitStructLiteral(sle, DtoLVal(lhs));
return true;
}
// static array literals too
Type *lhsBasetype = lhs->type->toBasetype();
if (rhs->op == TOKarrayliteral && lhsBasetype->ty == Tsarray) {
if (auto al = rhs->isArrayLiteralExp()) {
if (lhsBasetype->ty == Tsarray) {
Logger::println("success, in-place-constructing array literal");
auto al = static_cast<ArrayLiteralExp *>(rhs);
initializeArrayLiteral(gIR, al, DtoLVal(lhs));
return true;
}
}
// vector literals too
if (auto ve = rhs->isVectorExp()) {

View file

@ -127,12 +127,12 @@ sinteger_t getIntElem(StructLiteralExp *sle, size_t idx) {
}
llvm::StringRef getStringElem(StructLiteralExp *sle, size_t idx) {
auto arg = (*sle->elements)[idx];
if (arg && arg->op == TOKstring) {
auto strexp = static_cast<StringExp *>(arg);
if (auto arg = (*sle->elements)[idx]) {
if (auto strexp = arg->isStringExp()) {
DString str = strexp->peekString();
return {str.ptr, str.length};
}
}
// Default initialized element (arg->op == TOKnull)
return {};
}