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

Daniel Dunbar daniel at zuster.org
Sat Jan 24 00:32:22 PST 2009


Author: ddunbar
Date: Sat Jan 24 02:32:22 2009
New Revision: 62915

URL: http://llvm.org/viewvc/llvm-project?rev=62915&view=rev
Log:
Start filling in x86_64 ABI implementation.
 - No functionality change, moved behind -use-x86_64-abi option until
   it becomes non-experimental.

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=62915&r1=62914&r2=62915&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Sat Jan 24 02:32:22 2009
@@ -21,9 +21,15 @@
 #include "clang/AST/DeclObjC.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Attributes.h"
+#include "llvm/Support/CommandLine.h"
 using namespace clang;
 using namespace CodeGen;
 
+static llvm::cl::opt<bool>
+UseX86_64ABI("use-x86_64-abi",
+           llvm::cl::desc("Enable use of experimental x86_64 ABI."),
+           llvm::cl::init(false));
+
 /***/
 
 // FIXME: Use iterator and sidestep silly type array creation.
@@ -303,17 +309,6 @@
   virtual ABIArgInfo classifyArgumentType(QualType RetTy,
                                           ASTContext &Context) const;
 };
-
-
-/// X86_32ABIInfo - The X86_64 ABI information.
-class X86_64ABIInfo : public ABIInfo {
-public:
-  virtual ABIArgInfo classifyReturnType(QualType RetTy, 
-                                        ASTContext &Context) const;
-
-  virtual ABIArgInfo classifyArgumentType(QualType RetTy,
-                                          ASTContext &Context) const;
-};
 }
 
 ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
@@ -389,9 +384,159 @@
   }
 }
 
+namespace {
+/// X86_32ABIInfo - The X86_64 ABI information.
+class X86_64ABIInfo : public ABIInfo {
+  enum Class {
+    Integer = 0,
+    SSE,
+    SSEUp,
+    X87,
+    X87Up,
+    ComplexX87,
+    NoClass,
+    Memory
+  };
+
+  /// classify - Determine the x86_64 register classes in which the
+  /// given type T should be passed.
+  ///
+  /// \param Lo - The classification for the low word of the type.
+  /// \param Hi - The classification for the high word of the type.
+  ///
+  /// If a word is unused its result will be NoClass; if a type should
+  /// be passed in Memory then at least the classification of \arg Lo
+  /// will be Memory.
+  ///
+  /// The \arg Lo class will be NoClass iff the argument is ignored.
+  ///
+  /// If the \arg Lo class is ComplexX87, then the \arg Hi class will
+  /// be NoClass.
+  void classify(QualType T, ASTContext &Context,
+                Class &Lo, Class &Hi) const;
+
+public:
+  virtual ABIArgInfo classifyReturnType(QualType RetTy, 
+                                        ASTContext &Context) const;
+
+  virtual ABIArgInfo classifyArgumentType(QualType RetTy,
+                                          ASTContext &Context) const;
+};
+}
+
+void X86_64ABIInfo::classify(QualType Ty,
+                             ASTContext &Context,
+                             Class &Lo, Class &Hi) const {
+  Lo = Memory;
+  Hi = NoClass;
+  if (const BuiltinType *BT = Ty->getAsBuiltinType()) {
+    BuiltinType::Kind k = BT->getKind();
+
+    if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
+      Lo = Integer;
+    } else if (k == BuiltinType::Float || k == BuiltinType::Double) {
+      Lo = SSE;
+    } else if (k == BuiltinType::LongDouble) {
+      Lo = X87;
+      Hi = X87Up;
+    }
+    // FIXME: _Decimal32, _Decimal64, and __m64 are SSE.
+    // FIXME: _float128, _Decimal128, and __m128 are (SSE, SSEUp).
+    // FIXME: __int128 is (Integer, Integer).
+  } else if (Ty->isPointerLikeType() || Ty->isBlockPointerType() ||
+             Ty->isObjCQualifiedInterfaceType()) {
+    Lo = Integer;
+  } else if (const ComplexType *CT = Ty->getAsComplexType()) {
+    QualType ET = CT->getElementType();
+    
+    if (ET == Context.FloatTy) 
+      Lo = SSE;
+    else if (ET == Context.DoubleTy)
+      Lo = Hi = SSE;
+    else if (ET == Context.LongDoubleTy)
+      Lo = ComplexX87;
+  }
+}
+
 ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy,
                                             ASTContext &Context) const {
-  return ABIArgInfo::getDefault();
+  // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
+  // classification algorithm.
+  X86_64ABIInfo::Class Lo, Hi;
+  classify(RetTy, Context, Lo, Hi);
+
+  const llvm::Type *ResType = 0;
+  switch (Lo) {
+  case NoClass:
+    assert(0 && "FIXME: Handle ignored return values.");
+
+  case SSEUp:
+  case X87Up:
+    assert(0 && "Invalid classification for lo word.");
+
+  // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via
+  // hidden argument, i.e. structret.
+  case Memory:
+    return ABIArgInfo::getStructRet();
+
+    // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next
+    // available register of the sequence %rax, %rdx is used.
+  case Integer:
+    ResType = llvm::Type::Int64Ty; break;
+
+    // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next
+    // available SSE register of the sequence %xmm0, %xmm1 is used.
+  case SSE:
+    ResType = llvm::Type::DoubleTy; break;
+
+    // AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is
+    // returned on the X87 stack in %st0 as 80-bit x87 number.
+  case X87:
+    ResType = llvm::Type::X86_FP80Ty; break;
+
+  // AMD64-ABI 3.2.3p4: Rule 8. If the class is COMPLEX_X87, the real
+  // part of the value is returned in %st0 and the imaginary part in
+  // %st1.
+  case ComplexX87:
+    assert(Hi == NoClass && "Unexpected ComplexX87 classification.");
+    ResType = llvm::VectorType::get(llvm::Type::X86_FP80Ty, 2);
+    break;    
+  }
+
+  switch (Hi) {
+    // Memory was handled previously, and ComplexX87 and X87 should
+    // never occur as hi classes.
+  case Memory:
+  case X87:
+  case ComplexX87:
+    assert(0 && "Invalid classification for hi word.");
+
+  case NoClass: break;
+  case Integer:
+    assert(0 && "FIXME: Implement MRV"); break;
+  case SSE:    
+    assert(0 && "FIXME: Implement MRV"); break;
+
+    // AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte
+    // is passed in the upper half of the last used SSE register.
+    //
+    // SSEUP should always be preceeded by SSE, just widen.
+  case SSEUp:
+    assert(Lo == SSE && "Unexpected SSEUp classification.");
+    ResType = llvm::VectorType::get(llvm::Type::DoubleTy, 2);
+    break;
+
+    // AMD64-ABI 3.2.3p4: Rule 7. If the class is X87UP, the value is
+    // returned together with the previos X87 value in %st0.
+    //
+    // X87UP should always be preceeded by X87, so we don't need to do
+    // anything here.
+  case X87Up:
+    assert(Lo == X87 && "Unexpected X87Up classification.");
+    break;
+  }
+
+  return ABIArgInfo::getCoerce(ResType);
 }
 
 ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
@@ -421,7 +566,8 @@
     case 32:
       return *(TheABIInfo = new X86_32ABIInfo());
     case 64:
-      return *(TheABIInfo = new X86_64ABIInfo());
+      if (UseX86_64ABI)
+        return *(TheABIInfo = new X86_64ABIInfo());
     }
   }
 





More information about the cfe-commits mailing list