diff gen/functions.cpp @ 217:0806379a5eca trunk

[svn r233] Added: -oq command line option for writing fully qualified object names. Added: started support for x86 80bit floating point. Changed: aggregates passed by value now use the llvm 'byval' parameter attribute, also lays ground work for using other attributes. Changed: eliminated a lot more std::vectorS, these showed up pretty much at the top when profiling! Changed: performed other misc. cleanups. Changed: halt expression now call the new llvm trap intrinsic instead of an assert(0). Changed: dstress suite now passes -O0 by default, this only eliminates unreferenced globals, which speeds up linking quite a bit.
author lindquist
date Thu, 05 Jun 2008 06:38:36 +0200
parents a58d8f4b84df
children 74701ba40398
line wrap: on
line diff
--- a/gen/functions.cpp	Tue Jun 03 22:32:59 2008 +0200
+++ b/gen/functions.cpp	Thu Jun 05 06:38:36 2008 +0200
@@ -51,7 +51,7 @@
     else {
         assert(rt);
         Type* rtfin = DtoDType(rt);
-        if (DtoIsPassedByRef(rt)) {
+        if (DtoIsReturnedInArg(rt)) {
             rettype = getPtrToType(DtoType(rt));
             actualRettype = llvm::Type::VoidTy;
             f->llvmRetInPtr = retinptr = true;
@@ -94,22 +94,30 @@
 
     size_t n = Argument::dim(f->parameters);
 
+    int nbyval = 0;
+
+    llvm::PAListPtr palist;
+
     for (int i=0; i < n; ++i) {
         Argument* arg = Argument::getNth(f->parameters, i);
         // ensure scalar
         Type* argT = DtoDType(arg->type);
         assert(argT);
 
+        bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
+
         const LLType* at = DtoType(argT);
         if (isaStruct(at)) {
             Logger::println("struct param");
             paramvec.push_back(getPtrToType(at));
+            arg->llvmByVal = !refOrOut;
         }
         else if (isaArray(at)) {
             Logger::println("sarray param");
             assert(argT->ty == Tsarray);
             //paramvec.push_back(getPtrToType(at->getContainedType(0)));
             paramvec.push_back(getPtrToType(at));
+            arg->llvmByVal = !refOrOut;
         }
         else if (llvm::isa<llvm::OpaqueType>(at)) {
             Logger::println("opaque param");
@@ -117,7 +125,7 @@
             paramvec.push_back(getPtrToType(at));
         }
         else {
-            if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
+            if (refOrOut) {
                 Logger::println("by ref param");
                 at = getPtrToType(at);
             }
@@ -126,8 +134,13 @@
             }
             paramvec.push_back(at);
         }
+
+        if (arg->llvmByVal)
+            nbyval++;
     }
 
+    //warning("set %d byval args for type: %s", nbyval, f->toChars());
+
     // construct function type
     bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
     llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
@@ -135,10 +148,7 @@
     f->llvmRetInPtr = retinptr;
     f->llvmUsesThis = usesthis;
 
-    //if (!f->ir.type)
-        f->ir.type = new llvm::PATypeHolder(functype);
-    //else
-        //assert(functype == f->ir.type->get());
+    f->ir.type = new llvm::PATypeHolder(functype);
 
     return functype;
 }
@@ -378,6 +388,43 @@
     fdecl->ir.irFunc->func = func;
     assert(llvm::isa<llvm::FunctionType>(f->ir.type->get()));
 
+    // parameter attributes
+    if (f->parameters)
+    {
+        int llidx = 1;
+        if (f->llvmRetInPtr) ++llidx;
+        if (f->llvmUsesThis) ++llidx;
+        if (f->linkage == LINKd && f->varargs == 1)
+            llidx += 2;
+
+        int funcNumArgs = func->getArgumentList().size();
+        std::vector<llvm::ParamAttrsWithIndex> attrs;
+        int k = 0;
+
+        int nbyval = 0;
+
+        for (; llidx <= funcNumArgs && f->parameters->dim > k; ++llidx,++k)
+        {
+            Argument* fnarg = (Argument*)f->parameters->data[k];
+            assert(fnarg);
+            if (fnarg->llvmByVal)
+            {
+                llvm::ParamAttrsWithIndex PAWI;
+                PAWI.Index = llidx;
+                PAWI.Attrs = llvm::ParamAttr::ByVal;
+                attrs.push_back(PAWI);
+                nbyval++;
+            }
+        }
+
+        //warning("set %d byval args for function: %s", nbyval, func->getName().c_str());
+
+        if (nbyval) {
+            llvm::PAListPtr palist = llvm::PAListPtr::get(attrs.begin(), attrs.end());
+            func->setParamAttrs(palist);
+        }
+    }
+
     // main
     if (fdecl->isMain()) {
         gIR->mainFunc = func;
@@ -775,19 +822,14 @@
         else
             arg = new DImValue(argexp->type, arg->getRVal(), false);
     }
-    // aggregate arg
-    else if (DtoIsPassedByRef(argexp->type))
+    // byval arg, but expr has no storage yet
+    else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
     {
         LLValue* alloc = new llvm::AllocaInst(DtoType(argexp->type), "tmpparam", gIR->topallocapoint());
         DVarValue* vv = new DVarValue(argexp->type, alloc, true);
         DtoAssign(vv, arg);
         arg = vv;
     }
-    // normal arg (basic/value type)
-    else
-    {
-        // nothing to do
-    }
 
     return arg;
 }