From f1f0486b6e5744d8f234d767fd6eb3cdda924ceb Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 28 Dec 2012 03:36:56 +0100 Subject: [PATCH] Implement ordered delegate comparisons. GitHub: Fixes #256. --- gen/toir.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++ tests/d2/dmd-testsuite | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index ad7eff0e..0b97ff9d 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1772,6 +1772,50 @@ DValue* CmpExp::toElem(IRState* p) { eval = LLConstantInt::getFalse(gIR->context()); } + else if (t->ty == Tdelegate) + { + llvm::ICmpInst::Predicate icmpPred; + tokToIcmpPred(op, isLLVMUnsigned(t), &icmpPred, &eval); + + if (!eval) + { + // First compare the function pointers, then the context ones. This is + // what DMD does. + llvm::Value* lhs = l->getRVal(); + llvm::Value* rhs = r->getRVal(); + + llvm::BasicBlock* oldend = p->scopeend(); + llvm::BasicBlock* fptreq = llvm::BasicBlock::Create( + gIR->context(), "fptreq", gIR->topfunc(), oldend); + llvm::BasicBlock* fptrneq = llvm::BasicBlock::Create( + gIR->context(), "fptrneq", gIR->topfunc(), oldend); + llvm::BasicBlock* dgcmpend = llvm::BasicBlock::Create( + gIR->context(), "dgcmpend", gIR->topfunc(), oldend); + + llvm::Value* lfptr = p->ir->CreateExtractValue(lhs, 1, ".lfptr"); + llvm::Value* rfptr = p->ir->CreateExtractValue(rhs, 1, ".rfptr"); + + llvm::Value* fptreqcmp = p->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ, + lfptr, rfptr, ".fptreqcmp"); + llvm::BranchInst::Create(fptreq, fptrneq, fptreqcmp, p->scopebb()); + + p->scope() = IRScope(fptreq, fptrneq); + llvm::Value* lctx = p->ir->CreateExtractValue(lhs, 0, ".lctx"); + llvm::Value* rctx = p->ir->CreateExtractValue(rhs, 0, ".rctx"); + llvm::Value* ctxcmp = p->ir->CreateICmp(icmpPred, lctx, rctx, ".ctxcmp"); + llvm::BranchInst::Create(dgcmpend,p->scopebb()); + + p->scope() = IRScope(fptrneq, dgcmpend); + llvm::Value* fptrcmp = p->ir->CreateICmp(icmpPred, lfptr, rfptr, ".fptrcmp"); + llvm::BranchInst::Create(dgcmpend,p->scopebb()); + + p->scope() = IRScope(dgcmpend, oldend); + llvm::PHINode* phi = p->ir->CreatePHI(ctxcmp->getType(), 2, ".dgcmp"); + phi->addIncoming(ctxcmp, fptreq); + phi->addIncoming(fptrcmp, fptrneq); + eval = phi; + } + } else { assert(0 && "Unsupported CmpExp type"); diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index a520eae7..910e0198 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit a520eae7edb7be92fd3e3370256d5bc01fe5e62e +Subproject commit 910e0198ae0be3c04370c84f33dcac36577ed390