diff 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
line wrap: on
line diff
--- a/gen/toir.cpp	Wed Aug 20 19:03:28 2008 +0200
+++ b/gen/toir.cpp	Thu Aug 21 15:19:45 2008 +0200
@@ -1569,30 +1569,56 @@
     Logger::print("AssertExp::toElem: %s\n", toChars());
     LOG_SCOPE;
 
+    if(!global.params.useAssert)
+        return NULL;
+
     // condition
     DValue* cond = e1->toElem(p);
-
-    // create basic blocks
-    llvm::BasicBlock* oldend = p->scopeend();
-    llvm::BasicBlock* assertbb = llvm::BasicBlock::Create("assert", p->topfunc(), oldend);
-    llvm::BasicBlock* endbb = llvm::BasicBlock::Create("noassert", p->topfunc(), oldend);
-
-    // test condition
-    LLValue* condval = DtoBoolean(loc, cond);
-
-    // branch
-    llvm::BranchInst::Create(endbb, assertbb, condval, p->scopebb());
-
-    // call assert runtime functions
-    p->scope() = IRScope(assertbb,endbb);
-    DtoAssert(&loc, msg ? msg->toElem(p) : NULL);
-
-    // assert inserts unreachable terminator
-//     if (!gIR->scopereturned())
-//         llvm::BranchInst::Create(endbb, p->scopebb());
-
-    // rewrite the scope
-    p->scope() = IRScope(endbb,oldend);
+    Type* condty = e1->type->toBasetype();
+
+    InvariantDeclaration* invdecl;
+
+    // class invariants
+    if(
+        global.params.useInvariants && 
+        condty->ty == Tclass &&
+        !((TypeClass*)condty)->sym->isInterfaceDeclaration())
+    {
+        Logger::print("calling class invariant");
+        llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_invariant");
+        LLValue* arg = DtoBitCast(cond->getRVal(), fn->getFunctionType()->getParamType(0));
+        gIR->CreateCallOrInvoke(fn, arg);
+    }
+    // struct invariants
+    else if(
+        global.params.useInvariants && 
+        condty->ty == Tpointer && condty->next->ty == Tstruct &&
+        (invdecl = ((TypeStruct*)condty->next)->sym->inv) != NULL)
+    {
+        Logger::print("calling struct invariant");
+        DFuncValue invfunc(invdecl, invdecl->ir.irFunc->func, cond->getRVal());
+        DtoCallFunction(loc, NULL, &invfunc, NULL);
+    }
+    else
+    {
+        // create basic blocks
+        llvm::BasicBlock* oldend = p->scopeend();
+        llvm::BasicBlock* assertbb = llvm::BasicBlock::Create("assert", p->topfunc(), oldend);
+        llvm::BasicBlock* endbb = llvm::BasicBlock::Create("noassert", p->topfunc(), oldend);
+
+        // test condition
+        LLValue* condval = DtoBoolean(loc, cond);
+
+        // branch
+        llvm::BranchInst::Create(endbb, assertbb, condval, p->scopebb());
+
+        // call assert runtime functions
+        p->scope() = IRScope(assertbb,endbb);
+        DtoAssert(&loc, msg ? msg->toElem(p) : NULL);
+
+        // rewrite the scope
+        p->scope() = IRScope(endbb,oldend);
+    }
 
     // no meaningful return value
     return NULL;