changeset 32:a86fe7496b58 trunk

[svn r36] * Fixed a bug where passing a regular argument to a ref argument did not allocate storage
author lindquist
date Thu, 04 Oct 2007 18:24:05 +0200
parents 2841234d2aea
children bc641b23a714
files gen/statements.c gen/toir.c test/bug6.d
diffstat 3 files changed, 107 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/gen/statements.c	Thu Oct 04 16:44:07 2007 +0200
+++ b/gen/statements.c	Thu Oct 04 18:24:05 2007 +0200
@@ -616,6 +616,90 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+void ForeachStatement::toIR(IRState* p)
+{
+    Logger::println("ForeachStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    //assert(arguments->dim == 1);
+    assert(key == 0);
+    assert(value != 0);
+    assert(body != 0);
+    assert(aggr != 0);
+    assert(func != 0);
+
+    //Argument* arg = (Argument*)arguments->data[0];
+    //Logger::println("Argument is %s", arg->toChars());
+
+    Logger::println("aggr = %s", aggr->toChars());
+    Logger::println("func = %s", func->toChars());
+
+    elem* arr = aggr->toElem(p);
+    llvm::Value* val = arr->getValue();
+    Logger::cout() << "aggr2llvm = " << *val << '\n';
+
+    llvm::Value* numiters = 0;
+
+    const llvm::Type* keytype = key ? LLVM_DtoType(key->type) : LLVM_DtoSize_t();
+    llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
+
+    const llvm::Type* valtype = LLVM_DtoType(value->type);
+    llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint());
+
+    if (aggr->type->ty == Tsarray)
+    {
+        assert(llvm::isa<llvm::PointerType>(val->getType()));
+        assert(llvm::isa<llvm::ArrayType>(val->getType()->getContainedType(0)));
+        size_t n = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements();
+        assert(n > 0);
+        numiters = llvm::ConstantInt::get(keytype,n,false); 
+    }
+    else
+    {
+        assert(0);
+    }
+
+    if (op == TOKforeach)
+    {
+        new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb());
+    }
+    else if (op == TOKforeach_reverse)
+    {
+        llvm::Value* v = llvm::BinaryOperator::createSub(numiters, llvm::ConstantInt::get(keytype,1,false),"tmp",p->scopebb());
+        new llvm::StoreInst(v, keyvar, p->scopebb());
+    }
+    else
+    assert(0);
+
+    delete arr;
+
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend);
+    llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend);
+    llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend);
+
+    new llvm::BranchInst(begbb, p->scopebb());
+
+    // begin
+    p->scope() = IRScope(begbb,nexbb);
+
+    value->llvmValue = LLVM_DtoGEP(val,llvm::ConstantInt::get(keytype,0,false),keyvar,"tmp",p->scopebb());
+
+    // body
+    body->toIR(p);
+
+    // next
+    p->scope() = IRScope(nexbb,endbb);
+    new llvm::BranchInst(endbb, p->scopebb());
+
+    // end
+    if (!p->scope().returned)
+        new llvm::BranchInst(endbb, p->scopebb());
+    p->scope() = IRScope(endbb,oldend);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
 //////////////////////////////////////////////////////////////////////////////
 
 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
@@ -631,7 +715,7 @@
 STUBST(SwitchErrorStatement);
 STUBST(Statement);
 //STUBST(IfStatement);
-STUBST(ForeachStatement);
+//STUBST(ForeachStatement);
 //STUBST(DoStatement);
 //STUBST(WhileStatement);
 //STUBST(ExpStatement);
--- a/gen/toir.c	Thu Oct 04 16:44:07 2007 +0200
+++ b/gen/toir.c	Thu Oct 04 18:24:05 2007 +0200
@@ -986,6 +986,13 @@
         else {
             Logger::println("as ptr arg");
             llargs[j] = arg->mem ? arg->mem : arg->val;
+            if (llargs[j]->getType() != llfnty->getParamType(j))
+            {
+                assert(llargs[j]->getType() == llfnty->getParamType(j)->getContainedType(0));
+                LLVM_DtoGiveArgumentStorage(arg);
+                new llvm::StoreInst(llargs[j], arg->mem, p->scopebb());
+                llargs[j] = arg->mem;
+            }
             assert(llargs[j] != 0);
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug6.d	Thu Oct 04 18:24:05 2007 +0200
@@ -0,0 +1,15 @@
+module bug6;
+class wrong { }
+void bark(ref wrong s) { s = new wrong; }
+void foo(wrong tree) {
+    auto old = tree;
+    bark(tree);
+    assert(old !is tree);
+}
+void main()
+{
+    auto w = new wrong;
+    auto old = w;
+    foo(w);
+    assert(w is old);
+}