rogfer01 created this revision.
rogfer01 added a reviewer: rjmccall.

This is WIP and it is motivated by the suggestions in 
http://lists.llvm.org/pipermail/cfe-dev/2018-June/058263.html

First attempt, piggybacking the extend information in a structure where the 
bit-width of the integer represents the exact extension intended. There is a 
bit of overlapping with the original Extend but I'm not convinced we win 
anything from rewriting it into the new representation.

I plan to test this using unit tests but I can link a diff with the current 
usage in case it helps.


https://reviews.llvm.org/D48589

Files:
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp

Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1951,7 +1951,6 @@
 
   case ABIArgInfo::CoerceAndExpand:
     break;
-
   case ABIArgInfo::Expand:
     llvm_unreachable("Invalid ABI kind for return argument");
   }
@@ -1987,6 +1986,8 @@
         llvm::AttributeSet::get(getLLVMContext(), Attrs);
   }
 
+  SmallVector<llvm::AttrBuilder, 4> CoerceAndExpandAttrs(IRFunctionArgs.totalIRArgs());
+  bool CoerceAndExpandHasAttributes = false;
   unsigned ArgNo = 0;
   for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(),
                                           E = FI.arg_end();
@@ -2055,9 +2056,39 @@
     }
     case ABIArgInfo::Ignore:
     case ABIArgInfo::Expand:
-    case ABIArgInfo::CoerceAndExpand:
       break;
+    case ABIArgInfo::CoerceAndExpand:
+      if (AI.getExtendSeq()) {
+        // Handle extends in expanded items
+        unsigned FirstIRArg, NumIRArgs;
+        std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
+        llvm::StructType *CoercionType = AI.getCoerceAndExpandType();
+        for (unsigned I = 0, Ext = 0; I < NumIRArgs; I++) {
+          llvm::Type *EltType = CoercionType->getElementType(I);
+          if (ABIArgInfo::isPaddingForCoerceAndExpand(EltType))
+            continue;
 
+          llvm::Type *ExtendKind = AI.getExtendSeq()->getElementType(Ext++);
+          switch (ABIArgInfo::getExtendKind(ExtendKind)) {
+          case ABIArgInfo::ExtendKind::None:
+            break;
+          case ABIArgInfo::ExtendKind::SignExt: {
+            CoerceAndExpandHasAttributes = true;
+            CoerceAndExpandAttrs[FirstIRArg + I].addAttribute(
+                llvm::Attribute::SExt);
+            break;
+          }
+          case ABIArgInfo::ExtendKind::ZeroExt: {
+            CoerceAndExpandHasAttributes = true;
+            CoerceAndExpandAttrs[FirstIRArg + I].addAttribute(
+                llvm::Attribute::ZExt);
+            break;
+          }
+          }
+        }
+      }
+
+      break;
     case ABIArgInfo::InAlloca:
       // inalloca disables readnone and readonly.
       FuncAttrs.removeAttribute(llvm::Attribute::ReadOnly)
@@ -2112,12 +2143,16 @@
     if (FI.getExtParameterInfo(ArgNo).isNoEscape())
       Attrs.addAttribute(llvm::Attribute::NoCapture);
 
-    if (Attrs.hasAttributes()) {
+    if (Attrs.hasAttributes() || CoerceAndExpandHasAttributes) {
       unsigned FirstIRArg, NumIRArgs;
       std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
       for (unsigned i = 0; i < NumIRArgs; i++)
+      {
+        llvm::AttrBuilder CoerceAndExpandMergedAttrs(Attrs);
+        CoerceAndExpandMergedAttrs.merge(CoerceAndExpandAttrs[FirstIRArg + i]);
         ArgAttrs[FirstIRArg + i] =
-            llvm::AttributeSet::get(getLLVMContext(), Attrs);
+            llvm::AttributeSet::get(getLLVMContext(), CoerceAndExpandMergedAttrs);
+      }
     }
   }
   assert(ArgNo == FI.arg_size());
Index: include/clang/CodeGen/CGFunctionInfo.h
===================================================================
--- include/clang/CodeGen/CGFunctionInfo.h
+++ include/clang/CodeGen/CGFunctionInfo.h
@@ -25,6 +25,7 @@
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/Support/TrailingObjects.h"
 #include <cassert>
+#include <type_traits>
 
 namespace clang {
 namespace CodeGen {
@@ -76,16 +77,20 @@
     KindLast = InAlloca
   };
 
+  enum class ExtendKind : unsigned { None = 1, SignExt = 2, ZeroExt = 3 };
+
 private:
+
   llvm::Type *TypeData; // canHaveCoerceToType()
   union {
     llvm::Type *PaddingType; // canHavePaddingType()
     llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand()
   };
   union {
-    unsigned DirectOffset;     // isDirect() || isExtend()
-    unsigned IndirectAlign;    // isIndirect()
-    unsigned AllocaFieldIndex; // isInAlloca()
+    llvm::StructType *ExtendSeq; // isCoerceAndExpand()
+    unsigned DirectOffset;       // isDirect() || isExtend()
+    unsigned IndirectAlign;      // isIndirect()
+    unsigned AllocaFieldIndex;   // isInAlloca()
   };
   Kind TheKind;
   bool PaddingInReg : 1;
@@ -110,13 +115,16 @@
     UnpaddedCoerceAndExpandType = T;
   }
 
-  ABIArgInfo(Kind K)
-      : TheKind(K), PaddingInReg(false), InReg(false) {
+  void setExtendSet(llvm::StructType *ES) {
+    assert(isCoerceAndExpand());
+    ExtendSeq = ES;
   }
 
+  ABIArgInfo(Kind K) : TheKind(K), PaddingInReg(false), InReg(false) {}
+
 public:
   ABIArgInfo()
-      : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
+      : TypeData(nullptr), PaddingType(nullptr), ExtendSeq(nullptr),
         TheKind(Direct), PaddingInReg(false), InReg(false) {}
 
   static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
@@ -210,8 +218,15 @@
   /// \param unpaddedCoerceToType The coerce-to type with padding elements
   ///   removed, canonicalized to a single element if it would otherwise
   ///   have exactly one element.
-  static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType,
-                                       llvm::Type *unpaddedCoerceToType) {
+  /// \param extendSet The extension to be applied to the expanded type. It is
+  //    represented by a struct of integers of bit-width one of the values
+  //    of ExtendKind. If null no extension is applied. If not null it has
+  //    as many elements as unpaddedCoerceToType. Only integral-types can have
+  //    an extension other than None.
+  static ABIArgInfo
+  getCoerceAndExpand(llvm::StructType *coerceToType,
+                     llvm::Type *unpaddedCoerceToType,
+                     llvm::StructType *extendSet = nullptr) {
 #ifndef NDEBUG
     // Sanity checks on unpaddedCoerceToType.
 
@@ -238,11 +253,44 @@
     } else {
       assert(unpaddedIndex == 1);
     }
+
+    if (extendSet) {
+      // Assert that the size of the extend struct agrees with the unpadded
+      // struct and it only attempts to extend integral types.
+      if (unpaddedStruct) {
+        assert(extendSet->getNumElements() == unpaddedStruct->getNumElements());
+        unsigned Idx = 0;
+        for (auto EltType : unpaddedStruct->elements()) {
+          llvm::Type *ExtendType = extendSet->getElementType(Idx);
+          assert((ExtendType->isIntegerTy(
+                      static_cast<unsigned>(ExtendKind::None)) ||
+                  ((ExtendType->isIntegerTy(
+                        static_cast<unsigned>(ExtendKind::ZeroExt)) ||
+                    ExtendType->isIntegerTy(
+                        static_cast<unsigned>(ExtendKind::SignExt))) &&
+                   EltType->isIntegerTy())) &&
+                 "Invalid extend applied to non-integral type");
+          Idx++;
+        }
+      } else {
+        assert(extendSet->getNumElements() == 1);
+        llvm::Type *ExtendType = extendSet->getElementType(0);
+        assert(
+            (ExtendType->isIntegerTy(static_cast<unsigned>(ExtendKind::None)) ||
+             ((ExtendType->isIntegerTy(
+                   static_cast<unsigned>(ExtendKind::ZeroExt)) ||
+               ExtendType->isIntegerTy(
+                   static_cast<unsigned>(ExtendKind::SignExt))) &&
+              unpaddedCoerceToType->isIntegerTy())) &&
+            "Invalid extend applied to non-integral type");
+      }
+    }
 #endif
 
     auto AI = ABIArgInfo(CoerceAndExpand);
     AI.setCoerceToType(coerceToType);
     AI.setUnpaddedCoerceToType(unpaddedCoerceToType);
+    AI.setExtendSet(extendSet);
     return AI;
   }
 
@@ -255,6 +303,16 @@
     }
   }
 
+  static ExtendKind getExtendKind(llvm::Type *T) {
+    unsigned S = cast<llvm::IntegerType>(T)->getBitWidth();
+    ExtendKind EK = static_cast<ExtendKind>(S);
+    if (EK == ExtendKind::None || EK == ExtendKind::SignExt ||
+        EK == ExtendKind::ZeroExt) {
+      return EK;
+    }
+    llvm_unreachable("Unexpected integer kind");
+  }
+
   Kind getKind() const { return TheKind; }
   bool isDirect() const { return TheKind == Direct; }
   bool isInAlloca() const { return TheKind == InAlloca; }
@@ -318,6 +376,11 @@
     return UnpaddedCoerceAndExpandType;
   }
 
+  llvm::StructType *getExtendSeq() const {
+    assert(isCoerceAndExpand());
+    return ExtendSeq;
+  }
+
   ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const {
     assert(isCoerceAndExpand());
     if (auto structTy =
@@ -409,6 +472,10 @@
   void dump() const;
 };
 
+static_assert(std::is_trivially_copyable<ABIArgInfo>::value,
+    "ABIArgInfo must be trivially copyable as it is embedded as trailing "
+    "data of CGFunctionInfo");
+
 /// A class for recording the number of arguments that a function
 /// signature requires.
 class RequiredArgs {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to