diff gen/statements.cpp @ 94:61615fa85940 trunk

[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca"). Added support for array .sort and .reverse properties. Fixed some bugs with pointer arithmetic. Disabled some DMD AST optimizations that was messing things up, destroying valuable information. Added a KDevelop project file, this is what I use for coding LLVMDC now :) Other minor stuff.
author lindquist
date Mon, 12 Nov 2007 06:32:46 +0100
parents fd32135dca3e
children ce7ed8f59b99
line wrap: on
line diff
--- a/gen/statements.cpp	Thu Nov 08 19:21:05 2007 +0100
+++ b/gen/statements.cpp	Mon Nov 12 06:32:46 2007 +0100
@@ -7,7 +7,6 @@
 #include <iostream>
 
 #include "gen/llvm.h"
-#include "llvm/Transforms/Utils/Cloning.h"
 
 #include "total.h"
 #include "init.h"
@@ -39,8 +38,7 @@
         if (s)
             s->toIR(p);
         else {
-            Logger::println("*** ATTENTION: null statement found in CompoundStatement");
-            //assert(0);
+            Logger::println("??? null statement found in CompoundStatement");
         }
     }
 }
@@ -133,8 +131,8 @@
     Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars());
     LOG_SCOPE;
 
-    if (global.params.symdebug)
-        DtoDwarfStopPoint(loc.linnum);
+//     if (global.params.symdebug)
+//         DtoDwarfStopPoint(loc.linnum);
 
     if (exp != 0) {
         elem* e = exp->toElem(p);
@@ -255,8 +253,10 @@
     // rewrite scope
     gIR->scope() = IRScope(whilebodybb,endbb);
 
-    // do while body code
+    // while body code
+    p->loopbbs.push_back(IRScope(whilebb,endbb));
     body->toIR(p);
+    p->loopbbs.pop_back();
 
     // loop
     new llvm::BranchInst(whilebb, gIR->scopebegin());
@@ -284,7 +284,7 @@
     // replace current scope
     gIR->scope() = IRScope(dowhilebb,endbb);
 
-    // do do-while body code
+    // do-while body code
     body->toIR(p);
 
     // create the condition
@@ -363,8 +363,7 @@
 
 void BreakStatement::toIR(IRState* p)
 {
-    static int wsi = 0;
-    Logger::println("BreakStatement::toIR(%d): %s", wsi++, toChars());
+    Logger::println("BreakStatement::toIR(): %s", toChars());
     LOG_SCOPE;
 
     if (ident != 0) {
@@ -380,8 +379,7 @@
 
 void ContinueStatement::toIR(IRState* p)
 {
-    static int wsi = 0;
-    Logger::println("ContinueStatement::toIR(%d): %s", wsi++, toChars());
+    Logger::println("ContinueStatement::toIR(): %s", toChars());
     LOG_SCOPE;
 
     if (ident != 0) {
@@ -397,8 +395,7 @@
 
 void OnScopeStatement::toIR(IRState* p)
 {
-    static int wsi = 0;
-    Logger::println("OnScopeStatement::toIR(%d): %s", wsi++, toChars());
+    Logger::println("OnScopeStatement::toIR(): %s", toChars());
     LOG_SCOPE;
 
     assert(statement);
@@ -407,10 +404,6 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-static void replaceFinallyBBs(std::vector<llvm::BasicBlock*>& a, std::vector<llvm::BasicBlock*>& b)
-{
-}
-
 void TryFinallyStatement::toIR(IRState* p)
 {
     Logger::println("TryFinallyStatement::toIR(): %s", toChars());
@@ -495,7 +488,7 @@
     Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars());
     LOG_SCOPE;
 
-    Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted.");
+    Logger::attention("try-catch is not yet fully implemented, only the try block will be emitted.");
 
     assert(body);
     body->toIR(p);
@@ -516,10 +509,9 @@
     Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars());
     LOG_SCOPE;
 
-    Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);");
+    Logger::attention("throw is not yet implemented, replacing expression with assert(0);");
 
-    llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
-    DtoAssert(NULL, line, NULL);
+    DtoAssert(NULL, &loc, NULL);
 
     /*
     assert(exp);
@@ -657,42 +649,62 @@
     //Logger::println("Argument is %s", arg->toChars());
 
     Logger::println("aggr = %s", aggr->toChars());
-    Logger::println("func = %s", func->toChars());
 
-    DValue* arr = aggr->toElem(p);
-    llvm::Value* val = 0;
-    if (!arr->isSlice()) {
-        val = arr->getRVal();
-        Logger::cout() << "aggr2llvm = " << *val << '\n';
-    }
-
-    llvm::Value* numiters = 0;
-
+    // key
     const llvm::Type* keytype = key ? DtoType(key->type) : DtoSize_t();
     llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
     if (key) key->llvmValue = keyvar;
+    llvm::Value* zerokey = llvm::ConstantInt::get(keytype,0,false);
 
+    // value
     const llvm::Type* valtype = DtoType(value->type);
-    llvm::Value* valvar = !(value->isRef() || value->isOut()) ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL;
+    llvm::Value* valvar = NULL;
+    if (!value->isRef() && !value->isOut())
+        valvar = new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint());
 
+    // what to iterate
+    DValue* aggrval = aggr->toElem(p);
     Type* aggrtype = DtoDType(aggr->type);
+
+    // get length and pointer
+    llvm::Value* val = 0;
+    llvm::Value* niters = 0;
+
+    // static array
     if (aggrtype->ty == Tsarray)
     {
+        Logger::println("foreach over static array");
+        val = aggrval->getRVal();
         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); 
+        size_t nelems = llvm::cast<llvm::ArrayType>(val->getType()->getContainedType(0))->getNumElements();
+        assert(nelems > 0);
+        niters = llvm::ConstantInt::get(keytype,nelems,false);
     }
+    // dynamic array
     else if (aggrtype->ty == Tarray)
     {
-        if (DSliceValue* slice = arr->isSlice()) {
-            numiters = slice->len;
+        if (DSliceValue* slice = aggrval->isSlice()) {
+            Logger::println("foreach over slice");
+            niters = slice->len;
+            assert(niters);
+            if (llvm::isa<llvm::ConstantInt>(niters)) {
+                llvm::ConstantInt* ci = llvm::cast<llvm::ConstantInt>(niters);
+                Logger::println("const num iters: %u", ci);
+            }
+            else {
+                Logger::cout() << "numiters: " << *niters <<'\n';
+            }
             val = slice->ptr;
+            assert(val);
         }
         else {
-            numiters = p->ir->CreateLoad(DtoGEPi(val,0,0,"tmp",p->scopebb()));
-            val = p->ir->CreateLoad(DtoGEPi(val,0,1,"tmp",p->scopebb()));
+            Logger::println("foreach over dynamic array");
+            val = aggrval->getRVal();
+            niters = DtoGEPi(val,0,0,"tmp",p->scopebb());
+            niters = p->ir->CreateLoad(niters, "numiterations");
+            val = DtoGEPi(val,0,1,"tmp",p->scopebb());
+            val = p->ir->CreateLoad(val, "collection");
         }
     }
     else
@@ -700,41 +712,39 @@
         assert(0 && "aggregate type is not Tarray or Tsarray");
     }
 
+    llvm::Constant* delta = 0;
     if (op == TOKforeach) {
-        new llvm::StoreInst(llvm::ConstantInt::get(keytype,0,false), keyvar, p->scopebb());
+        new llvm::StoreInst(zerokey, 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 {
+        new llvm::StoreInst(niters, keyvar, p->scopebb());
     }
 
-    delete arr;
-
     llvm::BasicBlock* oldend = gIR->scopeend();
-    llvm::BasicBlock* nexbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend);
-    llvm::BasicBlock* begbb = new llvm::BasicBlock("foreachbegin", p->topfunc(), oldend);
+    llvm::BasicBlock* condbb = new llvm::BasicBlock("foreachcond", p->topfunc(), oldend);
+    llvm::BasicBlock* bodybb = new llvm::BasicBlock("foreachbody", p->topfunc(), oldend);
+    llvm::BasicBlock* nextbb = new llvm::BasicBlock("foreachnext", p->topfunc(), oldend);
     llvm::BasicBlock* endbb = new llvm::BasicBlock("foreachend", p->topfunc(), oldend);
 
-    new llvm::BranchInst(begbb, p->scopebb());
+    new llvm::BranchInst(condbb, p->scopebb());
 
-    // next
-    p->scope() = IRScope(nexbb,begbb);
+    // condition
+    p->scope() = IRScope(condbb,bodybb);
+
     llvm::Value* done = 0;
     llvm::Value* load = new llvm::LoadInst(keyvar, "tmp", p->scopebb());
     if (op == TOKforeach) {
-        load = llvm::BinaryOperator::createAdd(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
-        new llvm::StoreInst(load, keyvar, p->scopebb());
-        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, numiters, "tmp", p->scopebb());
+        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_ULT, load, niters, "tmp", p->scopebb());
     }
     else if (op == TOKforeach_reverse) {
-        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, llvm::ConstantInt::get(keytype, 0, false), "tmp", p->scopebb());
+        done = new llvm::ICmpInst(llvm::ICmpInst::ICMP_UGT, load, zerokey, "tmp", p->scopebb());
         load = llvm::BinaryOperator::createSub(load,llvm::ConstantInt::get(keytype, 1, false),"tmp",p->scopebb());
         new llvm::StoreInst(load, keyvar, p->scopebb());
     }
-    new llvm::BranchInst(begbb, endbb, done, p->scopebb());
+    new llvm::BranchInst(bodybb, endbb, done, p->scopebb());
 
-    // begin
-    p->scope() = IRScope(begbb,nexbb);
+    // body
+    p->scope() = IRScope(bodybb,nextbb);
 
     // get value for this iteration
     llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false);
@@ -754,13 +764,21 @@
     }
 
     // body
-    p->scope() = IRScope(p->scopebb(),endbb);
-    p->loopbbs.push_back(IRScope(nexbb,endbb));
+    p->loopbbs.push_back(IRScope(nextbb,endbb));
     body->toIR(p);
     p->loopbbs.pop_back();
 
     if (!p->scopereturned())
-        new llvm::BranchInst(nexbb, p->scopebb());
+        new llvm::BranchInst(nextbb, p->scopebb());
+
+    // next
+    p->scope() = IRScope(nextbb,endbb);
+    if (op == TOKforeach) {
+        llvm::Value* load = DtoLoad(keyvar);
+        load = p->ir->CreateAdd(load, llvm::ConstantInt::get(keytype, 1, false), "tmp");
+        DtoStore(load, keyvar);
+    }
+    new llvm::BranchInst(condbb, p->scopebb());
 
     // end
     p->scope() = IRScope(endbb,oldend);
@@ -828,13 +846,25 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+void SynchronizedStatement::toIR(IRState* p)
+{
+    Logger::println("SynchronizedStatement::toIR(): %s", toChars());
+    LOG_SCOPE;
+
+    Logger::attention("synchronized is currently ignored. only the body will be emitted");
+
+    body->toIR(p);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
 //////////////////////////////////////////////////////////////////////////////
 
 #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();}
 //STUBST(BreakStatement);
 //STUBST(ForStatement);
 //STUBST(WithStatement);
-STUBST(SynchronizedStatement);
+//STUBST(SynchronizedStatement);
 //STUBST(ReturnStatement);
 //STUBST(ContinueStatement);
 STUBST(DefaultStatement);