comparison gen/toir.cpp @ 530:d30c40f1128d

Make class invariants work.
author Christian Kamm <kamm incasoftware de>
date Thu, 21 Aug 2008 15:19:45 +0200
parents b18b6135e54b
children d19e29194c13
comparison
equal deleted inserted replaced
529:cef0cbcf7d22 530:d30c40f1128d
1567 DValue* AssertExp::toElem(IRState* p) 1567 DValue* AssertExp::toElem(IRState* p)
1568 { 1568 {
1569 Logger::print("AssertExp::toElem: %s\n", toChars()); 1569 Logger::print("AssertExp::toElem: %s\n", toChars());
1570 LOG_SCOPE; 1570 LOG_SCOPE;
1571 1571
1572 if(!global.params.useAssert)
1573 return NULL;
1574
1572 // condition 1575 // condition
1573 DValue* cond = e1->toElem(p); 1576 DValue* cond = e1->toElem(p);
1574 1577 Type* condty = e1->type->toBasetype();
1575 // create basic blocks 1578
1576 llvm::BasicBlock* oldend = p->scopeend(); 1579 InvariantDeclaration* invdecl;
1577 llvm::BasicBlock* assertbb = llvm::BasicBlock::Create("assert", p->topfunc(), oldend); 1580
1578 llvm::BasicBlock* endbb = llvm::BasicBlock::Create("noassert", p->topfunc(), oldend); 1581 // class invariants
1579 1582 if(
1580 // test condition 1583 global.params.useInvariants &&
1581 LLValue* condval = DtoBoolean(loc, cond); 1584 condty->ty == Tclass &&
1582 1585 !((TypeClass*)condty)->sym->isInterfaceDeclaration())
1583 // branch 1586 {
1584 llvm::BranchInst::Create(endbb, assertbb, condval, p->scopebb()); 1587 Logger::print("calling class invariant");
1585 1588 llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_invariant");
1586 // call assert runtime functions 1589 LLValue* arg = DtoBitCast(cond->getRVal(), fn->getFunctionType()->getParamType(0));
1587 p->scope() = IRScope(assertbb,endbb); 1590 gIR->CreateCallOrInvoke(fn, arg);
1588 DtoAssert(&loc, msg ? msg->toElem(p) : NULL); 1591 }
1589 1592 // struct invariants
1590 // assert inserts unreachable terminator 1593 else if(
1591 // if (!gIR->scopereturned()) 1594 global.params.useInvariants &&
1592 // llvm::BranchInst::Create(endbb, p->scopebb()); 1595 condty->ty == Tpointer && condty->next->ty == Tstruct &&
1593 1596 (invdecl = ((TypeStruct*)condty->next)->sym->inv) != NULL)
1594 // rewrite the scope 1597 {
1595 p->scope() = IRScope(endbb,oldend); 1598 Logger::print("calling struct invariant");
1599 DFuncValue invfunc(invdecl, invdecl->ir.irFunc->func, cond->getRVal());
1600 DtoCallFunction(loc, NULL, &invfunc, NULL);
1601 }
1602 else
1603 {
1604 // create basic blocks
1605 llvm::BasicBlock* oldend = p->scopeend();
1606 llvm::BasicBlock* assertbb = llvm::BasicBlock::Create("assert", p->topfunc(), oldend);
1607 llvm::BasicBlock* endbb = llvm::BasicBlock::Create("noassert", p->topfunc(), oldend);
1608
1609 // test condition
1610 LLValue* condval = DtoBoolean(loc, cond);
1611
1612 // branch
1613 llvm::BranchInst::Create(endbb, assertbb, condval, p->scopebb());
1614
1615 // call assert runtime functions
1616 p->scope() = IRScope(assertbb,endbb);
1617 DtoAssert(&loc, msg ? msg->toElem(p) : NULL);
1618
1619 // rewrite the scope
1620 p->scope() = IRScope(endbb,oldend);
1621 }
1596 1622
1597 // no meaningful return value 1623 // no meaningful return value
1598 return NULL; 1624 return NULL;
1599 } 1625 }
1600 1626