changeset 720:e177ae483f8e

Added inreg attribute where appropriate on x86 to follow ABI docs. Removed now unnecessary temporary variable in StringExp.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Thu, 23 Oct 2008 00:34:46 +0200
parents 7261ff0f95ff
children 51797efb6975
files dmd/mtype.c dmd/mtype.h gen/functions.cpp gen/tocall.cpp gen/toir.cpp
diffstat 5 files changed, 51 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/mtype.c	Wed Oct 22 21:50:08 2008 +0200
+++ b/dmd/mtype.c	Thu Oct 23 00:34:46 2008 +0200
@@ -2672,6 +2672,7 @@
     this->usesThis = false;
     this->usesNest = false;
     this->retAttrs = 0;
+    this->thisAttrs = 0;
 }
 
 Type *TypeFunction::syntaxCopy()
@@ -2683,6 +2684,7 @@
     t->usesThis = usesThis;
     t->usesNest = usesNest;
     t->retAttrs = retAttrs;
+    t->thisAttrs = thisAttrs;
     return t;
 }
 
--- a/dmd/mtype.h	Wed Oct 22 21:50:08 2008 +0200
+++ b/dmd/mtype.h	Thu Oct 23 00:34:46 2008 +0200
@@ -439,6 +439,7 @@
     bool usesThis;
     bool usesNest;
     unsigned retAttrs;
+    unsigned thisAttrs; // also used for nest
 };
 
 struct TypeDelegate : Type
--- a/gen/functions.cpp	Wed Oct 22 21:50:08 2008 +0200
+++ b/gen/functions.cpp	Thu Oct 23 00:34:46 2008 +0200
@@ -171,6 +171,39 @@
     bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
     llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
 
+    // tell first param to be passed in a register if we can
+    // ONLY extern(D) functions !
+    if ((n > 0 || usesthis || usesnest) && f->linkage == LINKd)
+    {
+        // FIXME: Only x86 right now ...
+        if (global.params.cpu == ARCHx86)
+        {
+            // pass first param in EAX if it fits, is not floating point and is not a 3 byte struct.
+            // FIXME: struct are not passed in EAX yet
+
+            // if there is a implicit context parameter, pass it in EAX
+            if (usesthis || usesnest)
+            {
+                f->thisAttrs |= llvm::Attribute::InReg;
+            }
+            // otherwise check the first formal parameter
+            else
+            {
+                Argument* arg = Argument::getNth(f->parameters, 0);
+                Type* t = arg->type->toBasetype();
+
+                // 32bit ints, pointers, classes and static arrays are candidate for being passed in EAX
+                if ((arg->storageClass & STCin) &&
+                    ((t->isscalar() && !t->isfloating()) || t->ty == Tclass || t->ty == Tsarray) &&
+                    (t->size() <= PTRSIZE))
+                {
+                    arg->llvmAttrs |= llvm::Attribute::InReg;
+                }
+            }
+        }
+    }
+
+    // done
     f->retInPtr = retinptr;
     f->usesThis = usesthis;
     f->usesNest = usesnest;
@@ -350,6 +383,14 @@
         attrs.push_back(PAWI);
     }
 
+    // set this/nest param attrs
+    if (f->thisAttrs)
+    {
+        PAWI.Index = f->retInPtr ? 2 : 1;
+        PAWI.Attrs = f->thisAttrs;
+        attrs.push_back(PAWI);
+    }
+
     // set attrs on the rest of the arguments
     for (; llidx <= funcNumArgs && Argument::dim(f->parameters) > k; ++llidx,++k)
     {
--- a/gen/tocall.cpp	Wed Oct 22 21:50:08 2008 +0200
+++ b/gen/tocall.cpp	Thu Oct 23 00:34:46 2008 +0200
@@ -257,6 +257,8 @@
         LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp");
         ++argiter;
         args.push_back(retvar);
+
+        // add attrs for hidden ptr
         palist = palist.addAttr(1, llvm::Attribute::StructRet);
     }
 
@@ -299,6 +301,10 @@
             error(loc, "Context argument required but none given");
             fatal();
         }
+
+        // add attributes for context argument
+        if (tf->thisAttrs)
+            palist = palist.addAttr(retinptr?2:1, tf->thisAttrs);
     }
 
     // handle the rest of the arguments based on param passing style
--- a/gen/toir.cpp	Wed Oct 22 21:50:08 2008 +0200
+++ b/gen/toir.cpp	Thu Oct 23 00:34:46 2008 +0200
@@ -373,9 +373,7 @@
 
     if (dtype->ty == Tarray) {
         LLConstant* clen = llvm::ConstantInt::get(DtoSize_t(),len,false);
-        LLValue* tmpmem = DtoAlloca(DtoType(dtype),"tempstring");
-        DtoSetArray(tmpmem, clen, arrptr);
-        return new DVarValue(type, tmpmem);
+        return new DImValue(type, DtoConstSlice(clen, arrptr));
     }
     else if (dtype->ty == Tsarray) {
         const LLType* dstType = getPtrToType(LLArrayType::get(ct, len));