Mercurial > projects > ldc
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 |