changeset 1248:01909bd1132c

Merge.
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Tue, 21 Apr 2009 17:54:43 +0200
parents a16b587aab58 (diff) 2a92c115461d (current diff)
children 4b0b470bb2f9
files gen/functions.cpp gen/toir.cpp
diffstat 3 files changed, 102 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/gen/functions.cpp	Fri Apr 17 17:16:55 2009 +0200
+++ b/gen/functions.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -45,8 +45,9 @@
         gABI->newFunctionType(f);
     }
 
-    // start new ir funcTy
-    f->fty.reset();
+    // Do not modify f->fty yet; this function may be called recursively if any
+    // of the argument types refer to this type.
+    IrFuncTy fty;
 
     // llvm idx counter
     size_t lidx = 0;
@@ -54,7 +55,7 @@
     // main needs a little special handling
     if (ismain)
     {
-        f->fty.ret = new IrFuncTyArg(Type::tint32, false);
+        fty.ret = new IrFuncTyArg(Type::tint32, false);
     }
     // sane return value
     else
@@ -65,7 +66,7 @@
         if (f->linkage != LINKintrinsic)
             if (gABI->returnInArg(f))
             {
-                f->fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture);
+                fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture);
                 rt = Type::tvoid;
                 lidx++;
             }
@@ -74,7 +75,7 @@
             {
                 a = se;
             }
-        f->fty.ret = new IrFuncTyArg(rt, false, a);
+        fty.ret = new IrFuncTyArg(rt, false, a);
     }
     lidx++;
 
@@ -82,14 +83,14 @@
     if (thistype)
     {
         bool toref = (thistype->toBasetype()->ty == Tstruct);
-        f->fty.arg_this = new IrFuncTyArg(thistype, toref);
+        fty.arg_this = new IrFuncTyArg(thistype, toref);
         lidx++;
     }
 
     // and nested functions
     else if (nesttype)
     {
-        f->fty.arg_nest = new IrFuncTyArg(nesttype, false);
+        fty.arg_nest = new IrFuncTyArg(nesttype, false);
         lidx++;
     }
 
@@ -103,16 +104,16 @@
             if (f->varargs == 1)
             {
                 // _arguments
-                f->fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
+                fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
                 lidx++;
                 // _argptr
-                f->fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture);
+                fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture);
                 lidx++;
             }
         }
         else if (f->linkage == LINKc)
         {
-            f->fty.c_vararg = true;
+            fty.c_vararg = true;
         }
         else
         {
@@ -127,7 +128,7 @@
     if (ismain && nargs == 0)
     {
         Type* mainargs = Type::tchar->arrayOf()->arrayOf();
-        f->fty.args.push_back(new IrFuncTyArg(mainargs, false));
+        fty.args.push_back(new IrFuncTyArg(mainargs, false));
         lidx++;
     }
     // add explicit parameters
@@ -163,10 +164,34 @@
             a |= DtoShouldExtend(argtype);
         }
 
-        f->fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
+        fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
         lidx++;
     }
 
+    // If the function type was forward referenced by one of the parameter types,
+    // it has now been set.
+    if (f->ir.type) {
+        // Notify ABI that we won't be needing it for this function type anymore.
+        gABI->doneWithFunctionType();
+        
+        // Some cleanup of memory we won't use
+        delete fty.ret;
+        delete fty.arg_sret;
+        delete fty.arg_this;
+        delete fty.arg_nest;
+        delete fty.arg_arguments;
+        delete fty.arg_argptr;
+        for (IrFuncTy::ArgIter It = fty.args.begin(), E = fty.args.end(); It != E; ++It) {
+            delete *It;
+        }
+
+        Logger::cout() << "Final function type: " << **f->ir.type << '\n';
+        return llvm::cast<LLFunctionType>(*f->ir.type);
+    }
+
+    // Now we can modify f->fty safely.
+    f->fty = fty;
+
     if (f->linkage != LINKintrinsic) {
         // let the abi rewrite the types as necesary
         gABI->rewriteFunctionType(f);
--- a/gen/nested.cpp	Fri Apr 17 17:16:55 2009 +0200
+++ b/gen/nested.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -426,10 +426,14 @@
                 vd->ir.irLocal->nestedDepth = depth;
                 if (vd->isParameter()) {
                     // Parameters already have storage associated with them (to handle byref etc.),
-                    // so handle specially for now by storing a pointer instead of a value.
+                    // so handle those cases specially by storing a pointer instead of a value.
                     assert(vd->ir.irLocal->value);
-                    // FIXME: don't do this for normal parameters?
-                    types.push_back(vd->ir.irLocal->value->getType());
+                    LLValue* value = vd->ir.irLocal->value;
+                    const LLType* type = value->getType();
+                    if (llvm::isa<llvm::AllocaInst>(value->getUnderlyingObject()))
+                        // This will be copied to the nesting frame.
+                        type = type->getContainedType(0);
+                    types.push_back(type);
                 } else if (vd->isRef() || vd->isOut()) {
                     // Foreach variables can also be by reference, for instance.
                     types.push_back(DtoType(vd->type->pointerTo()));
@@ -453,6 +457,8 @@
             
             // Create frame for current function and append to frames list
             // FIXME: For D2, this should be a gc_malloc (or similar) call, not alloca
+            //        (Note that it'd also require more aggressive copying of
+            //        by-value parameters instead of just alloca'd ones)
             LLValue* frame = DtoAlloca(frameType, ".frame");
             
             // copy parent frames into beginning
@@ -491,8 +497,26 @@
                 LLValue* gep = DtoGEPi(frame, 0, vd->ir.irLocal->nestedIndex, vd->toChars());
                 if (vd->isParameter()) {
                     Logger::println("nested param: %s", vd->toChars());
-                    DtoAlignedStore(vd->ir.irLocal->value, gep);
-                    vd->ir.irLocal->byref = true;
+                    LOG_SCOPE
+                    LLValue* value = vd->ir.irLocal->value;
+                    if (llvm::isa<llvm::AllocaInst>(value->getUnderlyingObject())) {
+                        Logger::println("Copying to nested frame");
+                        // The parameter value is an alloca'd stack slot.
+                        // Copy to the nesting frame and leave the alloca for
+                        // the optimizers to clean up.
+                        DtoStore(DtoLoad(value), gep);
+                        gep->takeName(value);
+                        vd->ir.irLocal->value = gep;
+                        vd->ir.irLocal->byref = false;
+                    } else {
+                        Logger::println("Adding pointer to nested frame");
+                        // The parameter value is something else, such as a
+                        // passed-in pointer (for 'ref' or 'out' parameters) or
+                        // a pointer arg with byval attribute.
+                        // Store the address into the frame and set the byref flag.
+                        DtoAlignedStore(vd->ir.irLocal->value, gep);
+                        vd->ir.irLocal->byref = true;
+                    }
                 } else if (vd->isRef() || vd->isOut()) {
                     // This slot is initialized in DtoNestedInit, to handle things like byref foreach variables
                     // which move around in memory.
--- a/gen/toir.cpp	Fri Apr 17 17:16:55 2009 +0200
+++ b/gen/toir.cpp	Tue Apr 21 17:54:43 2009 +0200
@@ -1825,10 +1825,6 @@
     Logger::print("AndAndExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    // allocate a temporary for the final result. failed to come up with a better way :/
-    LLValue* resval = 0;
-    resval = DtoAlloca(LLType::Int1Ty,"andandtmp");
-
     DValue* u = e1->toElem(p);
 
     llvm::BasicBlock* oldend = p->scopeend();
@@ -1836,23 +1832,36 @@
     llvm::BasicBlock* andandend = llvm::BasicBlock::Create("andandend", gIR->topfunc(), oldend);
 
     LLValue* ubool = DtoCast(loc, u, Type::tbool)->getRVal();
-    DtoStore(ubool,resval);
+
+    llvm::BasicBlock* oldblock = p->scopebb();
     llvm::BranchInst::Create(andand,andandend,ubool,p->scopebb());
 
     p->scope() = IRScope(andand, andandend);
     DValue* v = e2->toElem(p);
 
+    LLValue* vbool = 0;
     if (!v->isFunc() && v->getType() != Type::tvoid)
     {
-        LLValue* vbool = DtoCast(loc, v, Type::tbool)->getRVal();
-        LLValue* uandvbool = llvm::BinaryOperator::Create(llvm::BinaryOperator::And, ubool, vbool,"tmp",p->scopebb());
-        DtoStore(uandvbool,resval);
+        vbool = DtoCast(loc, v, Type::tbool)->getRVal();
     }
 
+    llvm::BasicBlock* newblock = p->scopebb();
     llvm::BranchInst::Create(andandend,p->scopebb());
     p->scope() = IRScope(andandend, oldend);
 
-    resval = DtoLoad(resval);
+    LLValue* resval = 0;
+    if (ubool == vbool || !vbool) {
+        // No need to create a PHI node.
+        resval = ubool;
+    } else {
+        llvm::PHINode* phi = p->ir->CreatePHI(LLType::Int1Ty, "andandval");
+        // If we jumped over evaluation of the right-hand side,
+        // the result is false. Otherwise it's the value of the right-hand side.
+        phi->addIncoming(LLConstantInt::getFalse(), oldblock);
+        phi->addIncoming(vbool, newblock);
+        resval = phi;
+    }
+
     return new DImValue(type, resval);
 }
 
@@ -1863,10 +1872,6 @@
     Logger::print("OrOrExp::toElem: %s @ %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    // allocate a temporary for the final result. failed to come up with a better way :/
-    LLValue* resval = 0;
-    resval = DtoAlloca(LLType::Int1Ty,"orortmp");
-
     DValue* u = e1->toElem(p);
 
     llvm::BasicBlock* oldend = p->scopeend();
@@ -1874,22 +1879,36 @@
     llvm::BasicBlock* ororend = llvm::BasicBlock::Create("ororend", gIR->topfunc(), oldend);
 
     LLValue* ubool = DtoCast(loc, u, Type::tbool)->getRVal();
-    DtoStore(ubool,resval);
+
+    llvm::BasicBlock* oldblock = p->scopebb();
     llvm::BranchInst::Create(ororend,oror,ubool,p->scopebb());
 
     p->scope() = IRScope(oror, ororend);
     DValue* v = e2->toElem(p);
 
+    LLValue* vbool = 0;
     if (!v->isFunc() && v->getType() != Type::tvoid)
     {
-        LLValue* vbool = DtoCast(loc, v, Type::tbool)->getRVal();
-        DtoStore(vbool,resval);
+        vbool = DtoCast(loc, v, Type::tbool)->getRVal();
     }
 
+    llvm::BasicBlock* newblock = p->scopebb();
     llvm::BranchInst::Create(ororend,p->scopebb());
     p->scope() = IRScope(ororend, oldend);
 
-    resval = DtoLoad(resval);
+    LLValue* resval = 0;
+    if (ubool == vbool || !vbool) {
+        // No need to create a PHI node.
+        resval = ubool;
+    } else {
+        llvm::PHINode* phi = p->ir->CreatePHI(LLType::Int1Ty, "ororval");
+        // If we jumped over evaluation of the right-hand side,
+        // the result is true. Otherwise, it's the value of the right-hand side.
+        phi->addIncoming(LLConstantInt::getTrue(), oldblock);
+        phi->addIncoming(vbool, newblock);
+        resval = phi;
+    }
+
     return new DImValue(type, resval);
 }