mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 03:16:05 +03:00
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:
parent
ec1c37a5a4
commit
26673c174f
10 changed files with 112 additions and 132 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) ) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,10 +47,11 @@ 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);
|
||||
res = i->isBool(true);
|
||||
return true;
|
||||
if (auto i = e->isIntegerExp()) {
|
||||
if (e->type->equals(Type::tbool)) {
|
||||
res = i->isBool(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -172,10 +172,11 @@ 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) {
|
||||
e->error("cannot `switch` on strings in `@compute` code");
|
||||
stop = true;
|
||||
if (auto ce = e->condition->isCallExp()) {
|
||||
if (ce->f->ident == Id::__switch) {
|
||||
e->error("cannot `switch` on strings in `@compute` code");
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -196,10 +196,10 @@ 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 (ve->var->isResult())
|
||||
doPostblit = false;
|
||||
if (doPostblit) {
|
||||
if (auto ve = stmt->exp->isVarExp())
|
||||
if (ve->var->isResult())
|
||||
doPostblit = false;
|
||||
}
|
||||
|
||||
DtoAssign(stmt->loc, &returnValue, e, TOKblit);
|
||||
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
125
gen/toir.cpp
125
gen/toir.cpp
|
@ -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,11 +525,13 @@ 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))
|
||||
return;
|
||||
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,30 +710,26 @@ 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 (vd->needsScopeDtor()) {
|
||||
Logger::println("Delaying edtor");
|
||||
delayedDtorVar = vd;
|
||||
delayedDtorExp = vd->edtor;
|
||||
vd->edtor = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
delayedDtorExp = vd->edtor;
|
||||
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,40 +2814,40 @@ 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");
|
||||
// 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
|
||||
DtoDeclareFunction(fd);
|
||||
auto fnval = new DFuncValue(fd, DtoCallee(fd), lval);
|
||||
DtoCallFunction(ce->loc, ce->type, fnval, ce->arguments);
|
||||
return true;
|
||||
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 lval = DtoLVal(lhs);
|
||||
ToElemVisitor::emitStructLiteral(sle, lval);
|
||||
// ... and invoke the ctor directly on it
|
||||
DtoDeclareFunction(fd);
|
||||
auto fnval = new DFuncValue(fd, DtoCallee(fd), lval);
|
||||
DtoCallFunction(ce->loc, ce->type, fnval, ce->arguments);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
Logger::println("success, in-place-constructing array literal");
|
||||
auto al = static_cast<ArrayLiteralExp *>(rhs);
|
||||
initializeArrayLiteral(gIR, al, DtoLVal(lhs));
|
||||
return true;
|
||||
if (auto al = rhs->isArrayLiteralExp()) {
|
||||
if (lhsBasetype->ty == Tsarray) {
|
||||
Logger::println("success, in-place-constructing array literal");
|
||||
initializeArrayLiteral(gIR, al, DtoLVal(lhs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// vector literals too
|
||||
|
|
10
gen/uda.cpp
10
gen/uda.cpp
|
@ -127,11 +127,11 @@ 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);
|
||||
DString str = strexp->peekString();
|
||||
return {str.ptr, str.length};
|
||||
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 {};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue