Skip to content

Commit 3cf6156

Browse files
committed
Fix operand load order for binary comparison/equality/identity expressions
Fixes ldc-developers#4651.
1 parent 59c0c60 commit 3cf6156

File tree

2 files changed

+59
-49
lines changed

2 files changed

+59
-49
lines changed

gen/toir.cpp

Lines changed: 38 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,8 +1322,8 @@ class ToElemVisitor : public Visitor {
13221322
auto &PGO = gIR->funcGen().pgo;
13231323
PGO.setCurrentStmt(e);
13241324

1325-
DValue *l = toElem(e->e1);
1326-
DValue *r = toElem(e->e2);
1325+
LLValue *l = DtoRVal(e->e1);
1326+
LLValue *r = DtoRVal(e->e2);
13271327

13281328
Type *t = e->e1->type->toBasetype();
13291329

@@ -1334,16 +1334,14 @@ class ToElemVisitor : public Visitor {
13341334
tokToICmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
13351335

13361336
if (!eval) {
1337-
LLValue *a = DtoRVal(l);
1338-
LLValue *b = DtoRVal(r);
13391337
IF_LOG {
1340-
Logger::cout() << "type 1: " << *a << '\n';
1341-
Logger::cout() << "type 2: " << *b << '\n';
1338+
Logger::cout() << "type 1: " << *l << '\n';
1339+
Logger::cout() << "type 2: " << *r << '\n';
13421340
}
1343-
if (a->getType() != b->getType()) {
1344-
b = DtoBitCast(b, a->getType());
1341+
if (l->getType() != r->getType()) {
1342+
r = DtoBitCast(r, l->getType());
13451343
}
1346-
eval = p->ir->CreateICmp(icmpPred, a, b);
1344+
eval = p->ir->CreateICmp(icmpPred, l, r);
13471345
}
13481346
} else if (t->isfloating()) {
13491347
llvm::FCmpInst::Predicate cmpop;
@@ -1364,7 +1362,7 @@ class ToElemVisitor : public Visitor {
13641362
default:
13651363
llvm_unreachable("Unsupported floating point comparison operator.");
13661364
}
1367-
eval = p->ir->CreateFCmp(cmpop, DtoRVal(l), DtoRVal(r));
1365+
eval = p->ir->CreateFCmp(cmpop, l, r);
13681366
} else if (t->ty == TY::Taarray) {
13691367
eval = LLConstantInt::getFalse(gIR->context());
13701368
} else if (t->ty == TY::Tdelegate) {
@@ -1374,23 +1372,21 @@ class ToElemVisitor : public Visitor {
13741372
if (!eval) {
13751373
// First compare the function pointers, then the context ones. This is
13761374
// what DMD does.
1377-
llvm::Value *lhs = DtoRVal(l);
1378-
llvm::Value *rhs = DtoRVal(r);
13791375

13801376
llvm::BasicBlock *fptreq = p->insertBB("fptreq");
13811377
llvm::BasicBlock *fptrneq = p->insertBBAfter(fptreq, "fptrneq");
13821378
llvm::BasicBlock *dgcmpend = p->insertBBAfter(fptrneq, "dgcmpend");
13831379

1384-
llvm::Value *lfptr = p->ir->CreateExtractValue(lhs, 1, ".lfptr");
1385-
llvm::Value *rfptr = p->ir->CreateExtractValue(rhs, 1, ".rfptr");
1380+
llvm::Value *lfptr = p->ir->CreateExtractValue(l, 1, ".lfptr");
1381+
llvm::Value *rfptr = p->ir->CreateExtractValue(r, 1, ".rfptr");
13861382

13871383
llvm::Value *fptreqcmp = p->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,
13881384
lfptr, rfptr, ".fptreqcmp");
13891385
llvm::BranchInst::Create(fptreq, fptrneq, fptreqcmp, p->scopebb());
13901386

13911387
p->ir->SetInsertPoint(fptreq);
1392-
llvm::Value *lctx = p->ir->CreateExtractValue(lhs, 0, ".lctx");
1393-
llvm::Value *rctx = p->ir->CreateExtractValue(rhs, 0, ".rctx");
1388+
llvm::Value *lctx = p->ir->CreateExtractValue(l, 0, ".lctx");
1389+
llvm::Value *rctx = p->ir->CreateExtractValue(r, 0, ".rctx");
13941390
llvm::Value *ctxcmp =
13951391
p->ir->CreateICmp(icmpPred, lctx, rctx, ".ctxcmp");
13961392
llvm::BranchInst::Create(dgcmpend, p->scopebb());
@@ -1423,10 +1419,10 @@ class ToElemVisitor : public Visitor {
14231419
auto &PGO = gIR->funcGen().pgo;
14241420
PGO.setCurrentStmt(e);
14251421

1426-
DValue *l = toElem(e->e1);
1427-
DValue *r = toElem(e->e2);
1422+
Expression *l = e->e1;
1423+
Expression *r = e->e2;
14281424

1429-
Type *t = e->e1->type->toBasetype();
1425+
Type *t = l->type->toBasetype();
14301426

14311427
LLValue *eval = nullptr;
14321428

@@ -1457,20 +1453,22 @@ class ToElemVisitor : public Visitor {
14571453
}
14581454
eval = p->ir->CreateICmp(cmpop, lv, rv);
14591455
} else if (t->isfloating()) { // includes iscomplex
1460-
eval = DtoBinNumericEquals(e->loc, l, r, e->op);
1456+
eval = DtoBinNumericEquals(e->loc, toElem(l)->getRVal(),
1457+
toElem(r)->getRVal(), e->op);
14611458
} else if (t->ty == TY::Tsarray || t->ty == TY::Tarray) {
14621459
Logger::println("static or dynamic array");
1463-
eval = DtoArrayEquals(e->loc, e->op, l, r);
1460+
eval = DtoArrayEquals(e->loc, e->op, toElem(l), toElem(r));
14641461
} else if (t->ty == TY::Taarray) {
14651462
Logger::println("associative array");
1466-
eval = DtoAAEquals(e->loc, e->op, l, r);
1463+
eval = DtoAAEquals(e->loc, e->op, toElem(l)->getRVal(),
1464+
toElem(r)->getRVal());
14671465
} else if (t->ty == TY::Tdelegate) {
14681466
Logger::println("delegate");
14691467
eval = DtoDelegateEquals(e->op, DtoRVal(l), DtoRVal(r));
14701468
} else if (t->ty == TY::Tstruct) {
14711469
Logger::println("struct");
14721470
// when this is reached it means there is no opEquals overload.
1473-
eval = DtoStructEquals(e->op, l, r);
1471+
eval = DtoStructEquals(e->op, toElem(l), toElem(r));
14741472
} else {
14751473
llvm_unreachable("Unsupported EqualExp type.");
14761474
}
@@ -2028,45 +2026,35 @@ class ToElemVisitor : public Visitor {
20282026
e->type->toChars());
20292027
LOG_SCOPE;
20302028

2031-
DValue *l = toElem(e->e1);
2032-
DValue *r = toElem(e->e2);
2033-
2034-
Type *t1 = e->e1->type->toBasetype();
2029+
Expression *l = e->e1;
2030+
Expression *r = e->e2;
20352031

2036-
// handle dynarray specially
2037-
if (t1->ty == TY::Tarray) {
2038-
result = zextBool(DtoDynArrayIs(e->op, l, r), e->type);
2039-
return;
2040-
}
2041-
// also structs
2042-
if (t1->ty == TY::Tstruct) {
2043-
result = zextBool(DtoStructEquals(e->op, l, r), e->type);
2044-
return;
2045-
}
2032+
Type *t1 = l->type->toBasetype();
20462033

2047-
// FIXME this stuff isn't pretty
20482034
LLValue *eval = nullptr;
20492035

2050-
if (t1->ty == TY::Tdelegate) {
2036+
if (t1->ty == TY::Tarray) {
2037+
eval = DtoDynArrayIs(e->op, toElem(l), toElem(r));
2038+
} else if (t1->ty == TY::Tstruct) {
2039+
eval = DtoStructEquals(e->op, toElem(l), toElem(r));
2040+
} else if (t1->ty == TY::Tdelegate) {
20512041
LLValue *lv = DtoRVal(l);
2042+
DValue *rhs = toElem(r);
2043+
20522044
LLValue *rv = nullptr;
2053-
if (!r->isNull()) {
2054-
rv = DtoRVal(r);
2045+
if (!rhs->isNull()) {
2046+
rv = DtoRVal(rhs);
20552047
assert(lv->getType() == rv->getType());
20562048
}
2049+
20572050
eval = DtoDelegateEquals(e->op, lv, rv);
20582051
} else if (t1->isfloating()) { // includes iscomplex
2059-
eval = DtoBinNumericEquals(e->loc, l, r, e->op);
2052+
eval = DtoBinNumericEquals(e->loc, toElem(l)->getRVal(),
2053+
toElem(r)->getRVal(), e->op);
20602054
} else if (t1->ty == TY::Tpointer || t1->ty == TY::Tclass) {
20612055
LLValue *lv = DtoRVal(l);
20622056
LLValue *rv = DtoRVal(r);
2063-
if (lv->getType() != rv->getType()) {
2064-
if (r->isNull()) {
2065-
rv = llvm::ConstantPointerNull::get(isaPointer(lv));
2066-
} else {
2067-
rv = DtoBitCast(rv, lv->getType());
2068-
}
2069-
}
2057+
rv = DtoBitCast(rv, lv->getType());
20702058
eval = (e->op == EXP::identity) ? p->ir->CreateICmpEQ(lv, rv)
20712059
: p->ir->CreateICmpNE(lv, rv);
20722060
} else if (t1->ty == TY::Tsarray) {
@@ -2086,6 +2074,7 @@ class ToElemVisitor : public Visitor {
20862074
: EXP::notEqual);
20872075
}
20882076
}
2077+
20892078
result = zextBool(eval, e->type);
20902079
}
20912080

tests/codegen/gh4651.d

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %ldc -run %s
2+
3+
void main()
4+
{
5+
int x;
6+
7+
assert(!(++x < x++)); // CmpExp: !(1 < 1)
8+
assert(x == 2);
9+
10+
assert(!(++x > x++)); // CmpExp: !(3 > 3)
11+
assert(x == 4);
12+
13+
assert(++x == x++); // EqualExp: 5 == 5
14+
assert(x == 6);
15+
16+
assert(++x is x++); // IdentityExp: 7 is 7
17+
assert(x == 8);
18+
19+
assert(x++ !is x); // IdentityExp: 8 !is 9
20+
assert(x == 9);
21+
}

0 commit comments

Comments
 (0)