[cfe-commits] r63292 - /cfe/trunk/lib/CodeGen/CGCall.cpp

Daniel Dunbar daniel at zuster.org
Thu Jan 29 00:13:58 PST 2009


Author: ddunbar
Date: Thu Jan 29 02:13:58 2009
New Revision: 63292

URL: http://llvm.org/viewvc/llvm-project?rev=63292&view=rev
Log:
x86_64 ABI: Implement classification for records.
 - This is my best initial guess at what the "spec" means, although it is not
   particularly clear on a number of points. Will refine through testing.

Modified:
    cfe/trunk/lib/CodeGen/CGCall.cpp

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=63292&r1=63291&r2=63292&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Jan 29 02:13:58 2009
@@ -19,6 +19,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/RecordLayout.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Attributes.h"
 #include "llvm/Support/CommandLine.h"
@@ -482,6 +483,108 @@
       Lo = Hi = SSE;
     else if (ET == Context.LongDoubleTy)
       Lo = ComplexX87;
+  } else if (const RecordType *RT = Ty->getAsRecordType()) {
+    unsigned Size = Context.getTypeSize(Ty);
+    
+    // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
+    // than two eightbytes, ..., it has class MEMORY.
+    if (Size > 128)
+      return;
+
+    const RecordDecl *RD = RT->getDecl();
+
+    // Assume variable sized types are passed in memory.
+    if (RD->hasFlexibleArrayMember())
+      return;
+
+    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+    
+    // Reset Lo class, this will be recomputed.
+    Lo = NoClass;
+    unsigned idx = 0;
+    for (RecordDecl::field_iterator i = RD->field_begin(), 
+           e = RD->field_end(); i != e; ++i, ++idx) {
+      unsigned Offset = Layout.getFieldOffset(idx);
+
+      //  AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
+      //  fields, it has class MEMORY.
+      if (Offset % Context.getTypeAlign(i->getType())) {
+        Lo = Memory;
+        return;
+      }
+
+      // Determine which half of the structure we are classifying.
+      //
+      // AMD64-ABI 3.2.3p2: Rule 3. f the size of the aggregate
+      // exceeds a single eightbyte, each is classified
+      // separately. Each eightbyte gets initialized to class
+      // NO_CLASS.
+      Class &Target = Offset < 64 ? Lo : Hi;
+
+      // Classify this field.
+      Class FieldLo, FieldHi;
+      classify(i->getType(), Context, FieldLo, FieldHi);
+      
+      // Merge the lo field classifcation.
+      //
+      // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is
+      // classified recursively so that always two fields are
+      // considered. The resulting class is calculated according to
+      // the classes of the fields in the eightbyte:
+      //
+      // (a) If both classes are equal, this is the resulting class.
+      //
+      // (b) If one of the classes is NO_CLASS, the resulting class is
+      // the other class.
+      //
+      // (c) If one of the classes is MEMORY, the result is the MEMORY
+      // class.
+      //
+      // (d) If one of the classes is INTEGER, the result is the
+      // INTEGER.
+      //
+      // (e) If one of the classes is X87, X87UP, COMPLEX_X87 class,
+      // MEMORY is used as class.
+      //
+      // (f) Otherwise class SSE is used.
+      if (Target == FieldLo || FieldLo == NoClass) ;
+      else if (Target == NoClass)
+        Target = FieldLo;
+      else if (FieldLo == Memory) {
+        // Memory is never over-ridden, just bail.
+        Lo = Memory;
+        return;
+      } 
+      else if (Target == Integer || FieldLo == Integer) 
+        Target = Integer;
+      else if (FieldLo == X87 || FieldLo == X87Up || FieldLo == ComplexX87) {
+        // As before, just bail once we generate a memory class.
+        Lo = Memory;
+        return;
+      } else
+        Target = SSE;
+
+      // It isn't clear from the ABI spec what the role of the high
+      // classification is here, but since this should only happen
+      // when we have a struct with a two eightbyte member, we can
+      // just push the field high class into the overall high class.
+      if (FieldHi != NoClass)
+        Hi = FieldHi;
+    }
+
+    // AMD64-ABI 3.2.3p2: Rule 5. Then a post merger cleanup is done:
+    //
+    // (a) If one of the classes is MEMORY, the whole argument is
+    // passed in memory.
+    //
+    // (b) If SSEUP is not preceeded by SSE, it is converted to SSE.
+
+    // The first of these conditions is guaranteed by how we implement
+    // the merge (just bail). I don't believe the second is actually
+    // possible at all.
+    assert(Lo != Memory && "Unexpected memory classification.");
+    if (Hi == SSEUp && Lo != SSE)
+        Hi = SSE;
   }
 }
 





More information about the cfe-commits mailing list