<div dir="ltr">Hey Tim,<br><br>Sorry about this, but Google-internal build testing is tripping over this change when it comes to bootstrapping compiler-rt (with some "Attribute 'byval' type does not match parameter!"). Did you happen to test a bootstrap? (that'd help me narrow this down to an internal-only issue, versus an external issue - though I guess if it's an external issue you'll be getting email from bootstrap buildbots soon enough?) Reckon it's worth reverting while I investigate on my side? (or if you think the chances are good it's only a Google internal issue, that's fair & I can just try to figure out what's off with our internal build system)<br><br>- Dave</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, May 29, 2019 at 12:09 PM Tim Northover via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: tnorthover<br>
Date: Wed May 29 12:12:48 2019<br>
New Revision: 362012<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=362012&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=362012&view=rev</a><br>
Log:<br>
IR: add optional type to 'byval' function parameters<br>
<br>
When we switch to opaque pointer types we will need some way to describe<br>
how many bytes a 'byval' parameter should occupy on the stack. This adds<br>
a (for now) optional extra type parameter.<br>
<br>
If present, the type must match the pointee type of the argument.<br>
<br>
Note to front-end maintainers: if this causes test failures, it's probably<br>
because the "byval" attribute is printed after attributes without any parameter<br>
after this change.<br>
<br>
Added:<br>
    llvm/trunk/test/Assembler/byval-type-attr.ll<br>
    llvm/trunk/test/Assembler/invalid-byval-type1.ll<br>
    llvm/trunk/test/Assembler/invalid-byval-type2.ll<br>
    llvm/trunk/test/Assembler/invalid-byval-type3.ll<br>
    llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc   (with props)<br>
    llvm/trunk/test/Bitcode/byval-upgrade.test<br>
    llvm/trunk/test/CodeGen/AArch64/byval-type.ll<br>
Modified:<br>
    llvm/trunk/docs/LangRef.rst<br>
    llvm/trunk/include/llvm/CodeGen/TargetLowering.h<br>
    llvm/trunk/include/llvm/IR/Argument.h<br>
    llvm/trunk/include/llvm/IR/Attributes.h<br>
    llvm/trunk/include/llvm/IR/CallSite.h<br>
    llvm/trunk/include/llvm/IR/Function.h<br>
    llvm/trunk/include/llvm/IR/InstrTypes.h<br>
    llvm/trunk/lib/AsmParser/LLParser.cpp<br>
    llvm/trunk/lib/AsmParser/LLParser.h<br>
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp<br>
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
    llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp<br>
    llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp<br>
    llvm/trunk/lib/IR/AttributeImpl.h<br>
    llvm/trunk/lib/IR/Attributes.cpp<br>
    llvm/trunk/lib/IR/Function.cpp<br>
    llvm/trunk/lib/IR/Verifier.cpp<br>
    llvm/trunk/test/Bitcode/attributes-3.3.ll<br>
    llvm/trunk/test/Bitcode/attributes.ll<br>
    llvm/trunk/test/Bitcode/compatibility-3.6.ll<br>
    llvm/trunk/test/Bitcode/compatibility-3.7.ll<br>
    llvm/trunk/test/Bitcode/compatibility-3.8.ll<br>
    llvm/trunk/test/Bitcode/compatibility-3.9.ll<br>
    llvm/trunk/test/Bitcode/compatibility-4.0.ll<br>
    llvm/trunk/test/Bitcode/compatibility-5.0.ll<br>
    llvm/trunk/test/Bitcode/compatibility-6.0.ll<br>
    llvm/trunk/test/Bitcode/compatibility.ll<br>
    llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll<br>
    llvm/trunk/test/Transforms/Inline/byval-tail-call.ll<br>
    llvm/trunk/unittests/IR/AttributesTest.cpp<br>
<br>
Modified: llvm/trunk/docs/LangRef.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/docs/LangRef.rst (original)<br>
+++ llvm/trunk/docs/LangRef.rst Wed May 29 12:12:48 2019<br>
@@ -1017,7 +1017,7 @@ Currently, only the following parameter<br>
     opposed to memory, though some targets use it to distinguish between<br>
     two different kinds of registers). Use of this attribute is<br>
     target-specific.<br>
-``byval``<br>
+``byval`` or ``byval(<ty>)``<br>
     This indicates that the pointer parameter should really be passed by<br>
     value to the function. The attribute implies that a hidden copy of<br>
     the pointee is made between the caller and the callee, so the callee<br>
@@ -1029,6 +1029,9 @@ Currently, only the following parameter<br>
     ``byval`` parameters). This is not a valid attribute for return<br>
     values.<br>
<br>
+    The byval attribute also supports an optional type argument, which must be<br>
+    the same as the pointee type of the argument.<br>
+<br>
     The byval attribute also supports specifying an alignment with the<br>
     align attribute. It indicates the alignment of the stack slot to<br>
     form and the known alignment of the pointer specified to the call<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/TargetLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLowering.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLowering.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/TargetLowering.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGen/TargetLowering.h Wed May 29 12:12:48 2019<br>
@@ -188,6 +188,7 @@ public:<br>
     bool IsSwiftSelf : 1;<br>
     bool IsSwiftError : 1;<br>
     uint16_t Alignment = 0;<br>
+    Type *ByValType = nullptr;<br>
<br>
     ArgListEntry()<br>
         : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false),<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Argument.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Argument.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Argument.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/Argument.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Argument.h Wed May 29 12:12:48 2019<br>
@@ -78,6 +78,9 @@ public:<br>
   /// If this is a byval or inalloca argument, return its alignment.<br>
   unsigned getParamAlignment() const;<br>
<br>
+  /// If this is a byval argument, return its type.<br>
+  Type *getParamByValType() const;<br>
+<br>
   /// Return true if this argument has the nest attribute.<br>
   bool hasNestAttr() const;<br>
<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Attributes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/Attributes.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Attributes.h Wed May 29 12:12:48 2019<br>
@@ -90,6 +90,7 @@ public:<br>
   static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0);<br>
   static Attribute get(LLVMContext &Context, StringRef Kind,<br>
                        StringRef Val = StringRef());<br>
+  static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty);<br>
<br>
   /// Return a uniquified Attribute object that has the specific<br>
   /// alignment set.<br>
@@ -102,6 +103,7 @@ public:<br>
   static Attribute getWithAllocSizeArgs(LLVMContext &Context,<br>
                                         unsigned ElemSizeArg,<br>
                                         const Optional<unsigned> &NumElemsArg);<br>
+  static Attribute getWithByValType(LLVMContext &Context, Type *Ty);<br>
<br>
   //===--------------------------------------------------------------------===//<br>
   // Attribute Accessors<br>
@@ -117,6 +119,9 @@ public:<br>
   /// attribute.<br>
   bool isStringAttribute() const;<br>
<br>
+  /// Return true if the attribute is a type attribute.<br>
+  bool isTypeAttribute() const;<br>
+<br>
   /// Return true if the attribute is present.<br>
   bool hasAttribute(AttrKind Val) const;<br>
<br>
@@ -139,6 +144,10 @@ public:<br>
   /// attribute to be a string attribute.<br>
   StringRef getValueAsString() const;<br>
<br>
+  /// Return the attribute's value as a Type. This requires the attribute to be<br>
+  /// a type attribute.<br>
+  Type *getValueAsType() const;<br>
+<br>
   /// Returns the alignment field of an attribute as a byte alignment<br>
   /// value.<br>
   unsigned getAlignment() const;<br>
@@ -279,6 +288,7 @@ public:<br>
   unsigned getStackAlignment() const;<br>
   uint64_t getDereferenceableBytes() const;<br>
   uint64_t getDereferenceableOrNullBytes() const;<br>
+  Type *getByValType() const;<br>
   std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;<br>
   std::string getAsString(bool InAttrGrp = false) const;<br>
<br>
@@ -598,6 +608,9 @@ public:<br>
   /// Return the alignment for the specified function parameter.<br>
   unsigned getParamAlignment(unsigned ArgNo) const;<br>
<br>
+  /// Return the byval type for the specified function parameter.<br>
+  Type *getParamByValType(unsigned ArgNo) const;<br>
+<br>
   /// Get the stack alignment.<br>
   unsigned getStackAlignment(unsigned Index) const;<br>
<br>
@@ -697,6 +710,7 @@ class AttrBuilder {<br>
   uint64_t DerefBytes = 0;<br>
   uint64_t DerefOrNullBytes = 0;<br>
   uint64_t AllocSizeArgs = 0;<br>
+  Type *ByValType = nullptr;<br>
<br>
 public:<br>
   AttrBuilder() = default;<br>
@@ -772,6 +786,9 @@ public:<br>
   /// dereferenceable_or_null attribute exists (zero is returned otherwise).<br>
   uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; }<br>
<br>
+  /// Retrieve the byval type.<br>
+  Type *getByValType() const { return ByValType; }<br>
+<br>
   /// Retrieve the allocsize args, if the allocsize attribute exists.  If it<br>
   /// doesn't exist, pair(0, 0) is returned.<br>
   std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;<br>
@@ -796,6 +813,9 @@ public:<br>
   AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg,<br>
                                 const Optional<unsigned> &NumElemsArg);<br>
<br>
+  /// This turns a byval type into the form used internally in Attribute.<br>
+  AttrBuilder &addByValAttr(Type *Ty);<br>
+<br>
   /// Add an allocsize attribute, using the representation returned by<br>
   /// Attribute.getIntValue().<br>
   AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr);<br>
<br>
Modified: llvm/trunk/include/llvm/IR/CallSite.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/CallSite.h (original)<br>
+++ llvm/trunk/include/llvm/IR/CallSite.h Wed May 29 12:12:48 2019<br>
@@ -415,6 +415,11 @@ public:<br>
     CALLSITE_DELEGATE_GETTER(getParamAlignment(ArgNo));<br>
   }<br>
<br>
+  /// Extract the byval type for a call or parameter (nullptr=unknown).<br>
+  Type *getParamByValType(unsigned ArgNo) const {<br>
+    CALLSITE_DELEGATE_GETTER(getParamByValType(ArgNo));<br>
+  }<br>
+<br>
   /// Extract the number of dereferenceable bytes for a call or parameter<br>
   /// (0=unknown).<br>
   uint64_t getDereferenceableBytes(unsigned i) const {<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Function.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Function.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Function.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/Function.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Function.h Wed May 29 12:12:48 2019<br>
@@ -431,6 +431,11 @@ public:<br>
     return AttributeSets.getParamAlignment(ArgNo);<br>
   }<br>
<br>
+  /// Extract the byval type for a parameter (nullptr=unknown).<br>
+  Type *getParamByValType(unsigned ArgNo) const {<br>
+    return AttributeSets.getParamByValType(ArgNo);<br>
+  }<br>
+<br>
   /// Extract the number of dereferenceable bytes for a call or<br>
   /// parameter (0=unknown).<br>
   /// @param i AttributeList index, referring to a return value or argument.<br>
<br>
Modified: llvm/trunk/include/llvm/IR/InstrTypes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InstrTypes.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InstrTypes.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/InstrTypes.h (original)<br>
+++ llvm/trunk/include/llvm/IR/InstrTypes.h Wed May 29 12:12:48 2019<br>
@@ -1560,6 +1560,11 @@ public:<br>
     return Attrs.getParamAlignment(ArgNo);<br>
   }<br>
<br>
+  /// Extract the byval type for a call or parameter (nullptr=unknown).<br>
+  Type *getParamByValType(unsigned ArgNo) const {<br>
+    return Attrs.getParamByValType(ArgNo);<br>
+  }<br>
+<br>
   /// Extract the number of dereferenceable bytes for a call or<br>
   /// parameter (0=unknown).<br>
   uint64_t getDereferenceableBytes(unsigned i) const {<br>
<br>
Modified: llvm/trunk/lib/AsmParser/LLParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)<br>
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Wed May 29 12:12:48 2019<br>
@@ -1601,7 +1601,13 @@ bool LLParser::ParseOptionalParamAttrs(A<br>
       B.addAlignmentAttr(Alignment);<br>
       continue;<br>
     }<br>
-    case lltok::kw_byval:           B.addAttribute(Attribute::ByVal); break;<br>
+    case lltok::kw_byval: {<br>
+      Type *Ty;<br>
+      if (ParseByValWithOptionalType(Ty))<br>
+        return true;<br>
+      B.addByValAttr(Ty);<br>
+      continue;<br>
+    }<br>
     case lltok::kw_dereferenceable: {<br>
       uint64_t Bytes;<br>
       if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes))<br>
@@ -2454,6 +2460,22 @@ bool LLParser::ParseParameterList(SmallV<br>
   return false;<br>
 }<br>
<br>
+/// ParseByValWithOptionalType<br>
+///   ::= byval<br>
+///   ::= byval(<ty>)<br>
+bool LLParser::ParseByValWithOptionalType(Type *&Result) {<br>
+  Result = nullptr;<br>
+  if (!EatIfPresent(lltok::kw_byval))<br>
+    return true;<br>
+  if (!EatIfPresent(lltok::lparen))<br>
+    return false;<br>
+  if (ParseType(Result))<br>
+    return true;<br>
+  if (!EatIfPresent(lltok::rparen))<br>
+    return Error(Lex.getLoc(), "expected ')'");<br>
+  return false;<br>
+}<br>
+<br>
 /// ParseOptionalOperandBundles<br>
 ///    ::= /*empty*/<br>
 ///    ::= '[' OperandBundle [, OperandBundle ]* ']'<br>
<br>
Modified: llvm/trunk/lib/AsmParser/LLParser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/AsmParser/LLParser.h (original)<br>
+++ llvm/trunk/lib/AsmParser/LLParser.h Wed May 29 12:12:48 2019<br>
@@ -339,6 +339,7 @@ namespace llvm {<br>
     bool ParseFnAttributeValuePairs(AttrBuilder &B,<br>
                                     std::vector<unsigned> &FwdRefAttrGrps,<br>
                                     bool inAttrGrp, LocTy &BuiltinLoc);<br>
+    bool ParseByValWithOptionalType(Type *&Result);<br>
<br>
     // Module Summary Index Parsing.<br>
     bool SkipModuleSummaryEntry();<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Wed May 29 12:12:48 2019<br>
@@ -638,6 +638,10 @@ private:<br>
     return getFnValueByID(ValNo, Ty);<br>
   }<br>
<br>
+  /// Upgrades old-style typeless byval attributes by adding the corresponding<br>
+  /// argument's pointee type.<br>
+  void propagateByValTypes(CallBase *CB);<br>
+<br>
   /// Converts alignment exponent (i.e. power of two (or zero)) to the<br>
   /// corresponding alignment to use. If alignment is too large, returns<br>
   /// a corresponding error code.<br>
@@ -1492,6 +1496,12 @@ Error BitcodeReader::parseAttributeGroup<br>
           if (Error Err = parseAttrKind(Record[++i], &Kind))<br>
             return Err;<br>
<br>
+          // Upgrade old-style byval attribute to one with a type, even if it's<br>
+          // nullptr. We will have to insert the real type when we associate<br>
+          // this AttributeList with a function.<br>
+          if (Kind == Attribute::ByVal)<br>
+            B.addByValAttr(nullptr);<br>
+<br>
           B.addAttribute(Kind);<br>
         } else if (Record[i] == 1) { // Integer attribute<br>
           Attribute::AttrKind Kind;<br>
@@ -1507,9 +1517,7 @@ Error BitcodeReader::parseAttributeGroup<br>
             B.addDereferenceableOrNullAttr(Record[++i]);<br>
           else if (Kind == Attribute::AllocSize)<br>
             B.addAllocSizeAttrFromRawRepr(Record[++i]);<br>
-        } else {                     // String attribute<br>
-          assert((Record[i] == 3 || Record[i] == 4) &&<br>
-                 "Invalid attribute group entry");<br>
+        } else if (Record[i] == 3 || Record[i] == 4) { // String attribute<br>
           bool HasValue = (Record[i++] == 4);<br>
           SmallString<64> KindStr;<br>
           SmallString<64> ValStr;<br>
@@ -1527,6 +1535,15 @@ Error BitcodeReader::parseAttributeGroup<br>
           }<br>
<br>
           B.addAttribute(KindStr.str(), ValStr.str());<br>
+        } else {<br>
+          assert((Record[i] == 5 || Record[i] == 6) &&<br>
+                 "Invalid attribute group entry");<br>
+          bool HasType = Record[i] == 6;<br>
+          Attribute::AttrKind Kind;<br>
+          if (Error Err = parseAttrKind(Record[++i], &Kind))<br>
+            return Err;<br>
+          if (Kind == Attribute::ByVal)<br>
+            B.addByValAttr(HasType ? getTypeByID(Record[++i]) : nullptr);<br>
         }<br>
       }<br>
<br>
@@ -3028,6 +3045,17 @@ Error BitcodeReader::parseFunctionRecord<br>
   Func->setLinkage(getDecodedLinkage(RawLinkage));<br>
   Func->setAttributes(getAttributes(Record[4]));<br>
<br>
+  // Upgrade any old-style byval without a type by propagating the argument's<br>
+  // pointee type. There should be no opaque pointers where the byval type is<br>
+  // implicit.<br>
+  for (auto &Arg : Func->args()) {<br>
+    if (Arg.hasByValAttr() && !Arg.getParamByValType()) {<br>
+      Arg.removeAttr(Attribute::ByVal);<br>
+      Arg.addAttr(Attribute::getWithByValType(<br>
+          Context, Arg.getType()->getPointerElementType()));<br>
+    }<br>
+  }<br>
+<br>
   unsigned Alignment;<br>
   if (Error Err = parseAlignmentValue(Record[5], Alignment))<br>
     return Err;<br>
@@ -3441,6 +3469,19 @@ Error BitcodeReader::typeCheckLoadStoreI<br>
   return Error::success();<br>
 }<br>
<br>
+void BitcodeReader::propagateByValTypes(CallBase *CB) {<br>
+  for (unsigned i = 0; i < CB->getNumArgOperands(); ++i) {<br>
+    if (CB->paramHasAttr(i, Attribute::ByVal) &&<br>
+        !CB->getAttribute(i, Attribute::ByVal).getValueAsType()) {<br>
+      CB->removeParamAttr(i, Attribute::ByVal);<br>
+      CB->addParamAttr(<br>
+          i, Attribute::getWithByValType(<br>
+                 Context,<br>
+                 CB->getArgOperand(i)->getType()->getPointerElementType()));<br>
+    }<br>
+  }<br>
+}<br>
+<br>
 /// Lazily parse the specified function body block.<br>
 Error BitcodeReader::parseFunctionBody(Function *F) {<br>
   if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))<br>
@@ -4256,6 +4297,8 @@ Error BitcodeReader::parseFunctionBody(F<br>
       cast<InvokeInst>(I)->setCallingConv(<br>
           static_cast<CallingConv::ID>(CallingConv::MaxID & CCInfo));<br>
       cast<InvokeInst>(I)->setAttributes(PAL);<br>
+      propagateByValTypes(cast<CallBase>(I));<br>
+<br>
       break;<br>
     }<br>
     case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval]<br>
@@ -4731,6 +4774,7 @@ Error BitcodeReader::parseFunctionBody(F<br>
         TCK = CallInst::TCK_NoTail;<br>
       cast<CallInst>(I)->setTailCallKind(TCK);<br>
       cast<CallInst>(I)->setAttributes(PAL);<br>
+      propagateByValTypes(cast<CallBase>(I));<br>
       if (FMF.any()) {<br>
         if (!isa<FPMathOperator>(I))<br>
           return error("Fast-math-flags specified for call without "<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Wed May 29 12:12:48 2019<br>
@@ -747,7 +747,7 @@ void ModuleBitcodeWriter::writeAttribute<br>
         Record.push_back(1);<br>
         Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));<br>
         Record.push_back(Attr.getValueAsInt());<br>
-      } else {<br>
+      } else if (Attr.isStringAttribute()) {<br>
         StringRef Kind = Attr.getKindAsString();<br>
         StringRef Val = Attr.getValueAsString();<br>
<br>
@@ -758,6 +758,13 @@ void ModuleBitcodeWriter::writeAttribute<br>
           Record.append(Val.begin(), Val.end());<br>
           Record.push_back(0);<br>
         }<br>
+      } else {<br>
+        assert(Attr.isTypeAttribute());<br>
+        Type *Ty = Attr.getValueAsType();<br>
+        Record.push_back(Ty ? 6 : 5);<br>
+        Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));<br>
+        if (Ty)<br>
+          Record.push_back(VE.getTypeID(Attr.getValueAsType()));<br>
       }<br>
     }<br>
<br>
@@ -4126,15 +4133,15 @@ void ModuleBitcodeWriter::write() {<br>
   // Emit blockinfo, which defines the standard abbreviations etc.<br>
   writeBlockInfo();<br>
<br>
+  // Emit information describing all of the types in the module.<br>
+  writeTypeTable();<br>
+<br>
   // Emit information about attribute groups.<br>
   writeAttributeGroupTable();<br>
<br>
   // Emit information about parameter attributes.<br>
   writeAttributeTable();<br>
<br>
-  // Emit information describing all of the types in the module.<br>
-  writeTypeTable();<br>
-<br>
   writeComdats();<br>
<br>
   // Emit top-level description of module, including target triple, inline asm,<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Wed May 29 12:12:48 2019<br>
@@ -949,9 +949,11 @@ void ValueEnumerator::incorporateFunctio<br>
   incorporateFunctionMetadata(F);<br>
<br>
   // Adding function arguments to the value table.<br>
-  for (const auto &I : F.args())<br>
+  for (const auto &I : F.args()) {<br>
     EnumerateValue(&I);<br>
-<br>
+    if (I.hasAttribute(Attribute::ByVal) && I.getParamByValType())<br>
+      EnumerateType(I.getParamByValType());<br>
+  }<br>
   FirstFuncConstantID = Values.size();<br>
<br>
   // Add all function-level constants to the value table.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp Wed May 29 12:12:48 2019<br>
@@ -87,7 +87,10 @@ void CallLowering::setArgFlags(CallLower<br>
<br>
   if (Arg.Flags.isByVal() || Arg.Flags.isInAlloca()) {<br>
     Type *ElementTy = cast<PointerType>(Arg.Ty)->getElementType();<br>
-    Arg.Flags.setByValSize(DL.getTypeAllocSize(ElementTy));<br>
+<br>
+    auto Ty = Attrs.getAttribute(OpIdx, Attribute::ByVal).getValueAsType();<br>
+    Arg.Flags.setByValSize(DL.getTypeAllocSize(Ty ? Ty : ElementTy));<br>
+<br>
     // For ByVal, alignment should be passed from FE.  BE will guess if<br>
     // this info is not there but there are cases it cannot get right.<br>
     unsigned FrameAlign;<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Wed May 29 12:12:48 2019<br>
@@ -1204,9 +1204,11 @@ bool FastISel::lowerCallTo(CallLoweringI<br>
     if (Arg.IsByVal || Arg.IsInAlloca) {<br>
       PointerType *Ty = cast<PointerType>(Arg.Ty);<br>
       Type *ElementTy = Ty->getElementType();<br>
-      unsigned FrameSize = DL.getTypeAllocSize(ElementTy);<br>
-      // For ByVal, alignment should come from FE. BE will guess if this info is<br>
-      // not there, but there are cases it cannot get right.<br>
+      unsigned FrameSize =<br>
+          DL.getTypeAllocSize(Arg.ByValType ? Arg.ByValType : ElementTy);<br>
+<br>
+      // For ByVal, alignment should come from FE. BE will guess if this info<br>
+      // is not there, but there are cases it cannot get right.<br>
       unsigned FrameAlign = Arg.Alignment;<br>
       if (!FrameAlign)<br>
         FrameAlign = TLI.getByValTypeAlignment(ElementTy, DL);<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed May 29 12:12:48 2019<br>
@@ -9076,8 +9076,11 @@ TargetLowering::LowerCallTo(TargetLoweri<br>
       if (Args[i].IsByVal || Args[i].IsInAlloca) {<br>
         PointerType *Ty = cast<PointerType>(Args[i].Ty);<br>
         Type *ElementTy = Ty->getElementType();<br>
-        Flags.setByValSize(DL.getTypeAllocSize(ElementTy));<br>
-        // For ByVal, alignment should come from FE.  BE will guess if this<br>
+<br>
+        unsigned FrameSize = DL.getTypeAllocSize(<br>
+            Args[i].ByValType ? Args[i].ByValType : ElementTy);<br>
+        Flags.setByValSize(FrameSize);<br>
+<br>
         // info is not there but there are cases it cannot get right.<br>
         unsigned FrameAlign;<br>
         if (Args[i].Alignment)<br>
@@ -9574,9 +9577,14 @@ void SelectionDAGISel::LowerArguments(co<br>
       if (Flags.isByVal() || Flags.isInAlloca()) {<br>
         PointerType *Ty = cast<PointerType>(Arg.getType());<br>
         Type *ElementTy = Ty->getElementType();<br>
-        Flags.setByValSize(DL.getTypeAllocSize(ElementTy));<br>
-        // For ByVal, alignment should be passed from FE.  BE will guess if<br>
-        // this info is not there but there are cases it cannot get right.<br>
+<br>
+        // For ByVal, size and alignment should be passed from FE.  BE will<br>
+        // guess if this info is not there but there are cases it cannot get<br>
+        // right.<br>
+        unsigned FrameSize = DL.getTypeAllocSize(<br>
+            Arg.getParamByValType() ? Arg.getParamByValType() : ElementTy);<br>
+        Flags.setByValSize(FrameSize);<br>
+<br>
         unsigned FrameAlign;<br>
         if (Arg.getParamAlignment())<br>
           FrameAlign = Arg.getParamAlignment();<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Wed May 29 12:12:48 2019<br>
@@ -112,6 +112,7 @@ void TargetLoweringBase::ArgListEntry::s<br>
   IsSwiftSelf = Call->paramHasAttr(ArgIdx, Attribute::SwiftSelf);<br>
   IsSwiftError = Call->paramHasAttr(ArgIdx, Attribute::SwiftError);<br>
   Alignment = Call->getParamAlignment(ArgIdx);<br>
+  ByValType = Call->getParamByValType(ArgIdx);<br>
 }<br>
<br>
 /// Generate a libcall taking the given operands as arguments and returning a<br>
<br>
Modified: llvm/trunk/lib/IR/AttributeImpl.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AttributeImpl.h?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AttributeImpl.h?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/AttributeImpl.h (original)<br>
+++ llvm/trunk/lib/IR/AttributeImpl.h Wed May 29 12:12:48 2019<br>
@@ -29,6 +29,7 @@<br>
 namespace llvm {<br>
<br>
 class LLVMContext;<br>
+class Type;<br>
<br>
 //===----------------------------------------------------------------------===//<br>
 /// \class<br>
@@ -41,7 +42,8 @@ protected:<br>
   enum AttrEntryKind {<br>
     EnumAttrEntry,<br>
     IntAttrEntry,<br>
-    StringAttrEntry<br>
+    StringAttrEntry,<br>
+    TypeAttrEntry,<br>
   };<br>
<br>
   AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}<br>
@@ -56,6 +58,7 @@ public:<br>
   bool isEnumAttribute() const { return KindID == EnumAttrEntry; }<br>
   bool isIntAttribute() const { return KindID == IntAttrEntry; }<br>
   bool isStringAttribute() const { return KindID == StringAttrEntry; }<br>
+  bool isTypeAttribute() const { return KindID == TypeAttrEntry; }<br>
<br>
   bool hasAttribute(Attribute::AttrKind A) const;<br>
   bool hasAttribute(StringRef Kind) const;<br>
@@ -66,16 +69,20 @@ public:<br>
   StringRef getKindAsString() const;<br>
   StringRef getValueAsString() const;<br>
<br>
+  Type *getValueAsType() const;<br>
+<br>
   /// Used when sorting the attributes.<br>
   bool operator<(const AttributeImpl &AI) const;<br>
<br>
   void Profile(FoldingSetNodeID &ID) const {<br>
     if (isEnumAttribute())<br>
-      Profile(ID, getKindAsEnum(), 0);<br>
+      Profile(ID, getKindAsEnum(), static_cast<uint64_t>(0));<br>
     else if (isIntAttribute())<br>
       Profile(ID, getKindAsEnum(), getValueAsInt());<br>
-    else<br>
+    else if (isStringAttribute())<br>
       Profile(ID, getKindAsString(), getValueAsString());<br>
+    else<br>
+      Profile(ID, getKindAsEnum(), getValueAsType());<br>
   }<br>
<br>
   static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,<br>
@@ -88,6 +95,12 @@ public:<br>
     ID.AddString(Kind);<br>
     if (!Values.empty()) ID.AddString(Values);<br>
   }<br>
+<br>
+  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,<br>
+                      Type *Ty) {<br>
+    ID.AddInteger(Kind);<br>
+    ID.AddPointer(Ty);<br>
+  }<br>
 };<br>
<br>
 //===----------------------------------------------------------------------===//<br>
@@ -145,6 +158,18 @@ public:<br>
   StringRef getStringValue() const { return Val; }<br>
 };<br>
<br>
+class TypeAttributeImpl : public EnumAttributeImpl {<br>
+  virtual void anchor();<br>
+<br>
+  Type *Ty;<br>
+<br>
+public:<br>
+  TypeAttributeImpl(Attribute::AttrKind Kind, Type *Ty)<br>
+      : EnumAttributeImpl(TypeAttrEntry, Kind), Ty(Ty) {}<br>
+<br>
+  Type *getTypeValue() const { return Ty; }<br>
+};<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 /// \class<br>
 /// This class represents a group of attributes that apply to one<br>
@@ -189,6 +214,7 @@ public:<br>
   uint64_t getDereferenceableOrNullBytes() const;<br>
   std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;<br>
   std::string getAsString(bool InAttrGrp) const;<br>
+  Type *getByValType() const;<br>
<br>
   using iterator = const Attribute *;<br>
<br>
<br>
Modified: llvm/trunk/lib/IR/Attributes.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/Attributes.cpp (original)<br>
+++ llvm/trunk/lib/IR/Attributes.cpp Wed May 29 12:12:48 2019<br>
@@ -121,6 +121,27 @@ Attribute Attribute::get(LLVMContext &Co<br>
   return Attribute(PA);<br>
 }<br>
<br>
+Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,<br>
+                         Type *Ty) {<br>
+  LLVMContextImpl *pImpl = Context.pImpl;<br>
+  FoldingSetNodeID ID;<br>
+  ID.AddInteger(Kind);<br>
+  ID.AddPointer(Ty);<br>
+<br>
+  void *InsertPoint;<br>
+  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);<br>
+<br>
+  if (!PA) {<br>
+    // If we didn't find any existing attributes of the same shape then create a<br>
+    // new one and insert it.<br>
+    PA = new TypeAttributeImpl(Kind, Ty);<br>
+    pImpl->AttrsSet.InsertNode(PA, InsertPoint);<br>
+  }<br>
+<br>
+  // Return the Attribute that we found or created.<br>
+  return Attribute(PA);<br>
+}<br>
+<br>
 Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) {<br>
   assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");<br>
   assert(Align <= 0x40000000 && "Alignment too large.");<br>
@@ -146,6 +167,10 @@ Attribute Attribute::getWithDereferencea<br>
   return get(Context, DereferenceableOrNull, Bytes);<br>
 }<br>
<br>
+Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {<br>
+  return get(Context, ByVal, Ty);<br>
+}<br>
+<br>
 Attribute<br>
 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,<br>
                                 const Optional<unsigned> &NumElemsArg) {<br>
@@ -170,9 +195,13 @@ bool Attribute::isStringAttribute() cons<br>
   return pImpl && pImpl->isStringAttribute();<br>
 }<br>
<br>
+bool Attribute::isTypeAttribute() const {<br>
+  return pImpl && pImpl->isTypeAttribute();<br>
+}<br>
+<br>
 Attribute::AttrKind Attribute::getKindAsEnum() const {<br>
   if (!pImpl) return None;<br>
-  assert((isEnumAttribute() || isIntAttribute()) &&<br>
+  assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&<br>
          "Invalid attribute type to get the kind as an enum!");<br>
   return pImpl->getKindAsEnum();<br>
 }<br>
@@ -198,6 +227,14 @@ StringRef Attribute::getValueAsString()<br>
   return pImpl->getValueAsString();<br>
 }<br>
<br>
+Type *Attribute::getValueAsType() const {<br>
+  if (!pImpl) return {};<br>
+  assert(isTypeAttribute() &&<br>
+         "Invalid attribute type to get the value as a type!");<br>
+  return pImpl->getValueAsType();<br>
+}<br>
+<br>
+<br>
 bool Attribute::hasAttribute(AttrKind Kind) const {<br>
   return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);<br>
 }<br>
@@ -252,8 +289,6 @@ std::string Attribute::getAsString(bool<br>
     return "argmemonly";<br>
   if (hasAttribute(Attribute::Builtin))<br>
     return "builtin";<br>
-  if (hasAttribute(Attribute::ByVal))<br>
-    return "byval";<br>
   if (hasAttribute(Attribute::Convergent))<br>
     return "convergent";<br>
   if (hasAttribute(Attribute::SwiftError))<br>
@@ -353,6 +388,19 @@ std::string Attribute::getAsString(bool<br>
   if (hasAttribute(Attribute::ImmArg))<br>
     return "immarg";<br>
<br>
+  if (hasAttribute(Attribute::ByVal)) {<br>
+    std::string Result;<br>
+    Result += "byval";<br>
+    if (Type *Ty = getValueAsType()) {<br>
+      raw_string_ostream OS(Result);<br>
+      Result += '(';<br>
+      Ty->print(OS, false, true);<br>
+      OS.flush();<br>
+      Result += ')';<br>
+    }<br>
+    return Result;<br>
+  }<br>
+<br>
   // FIXME: These should be output like this:<br>
   //<br>
   //   align=4<br>
@@ -451,6 +499,8 @@ void IntAttributeImpl::anchor() {}<br>
<br>
 void StringAttributeImpl::anchor() {}<br>
<br>
+void TypeAttributeImpl::anchor() {}<br>
+<br>
 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {<br>
   if (isStringAttribute()) return false;<br>
   return getKindAsEnum() == A;<br>
@@ -462,7 +512,7 @@ bool AttributeImpl::hasAttribute(StringR<br>
 }<br>
<br>
 Attribute::AttrKind AttributeImpl::getKindAsEnum() const {<br>
-  assert(isEnumAttribute() || isIntAttribute());<br>
+  assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());<br>
   return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();<br>
 }<br>
<br>
@@ -481,6 +531,11 @@ StringRef AttributeImpl::getValueAsStrin<br>
   return static_cast<const StringAttributeImpl *>(this)->getStringValue();<br>
 }<br>
<br>
+Type *AttributeImpl::getValueAsType() const {<br>
+  assert(isTypeAttribute());<br>
+  return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();<br>
+}<br>
+<br>
 bool AttributeImpl::operator<(const AttributeImpl &AI) const {<br>
   // This sorts the attributes with Attribute::AttrKinds coming first (sorted<br>
   // relative to their enum value) and then strings.<br>
@@ -488,10 +543,23 @@ bool AttributeImpl::operator<(const Attr<br>
     if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();<br>
     if (AI.isIntAttribute()) return true;<br>
     if (AI.isStringAttribute()) return true;<br>
+    if (AI.isTypeAttribute()) return true;<br>
+  }<br>
+<br>
+  if (isTypeAttribute()) {<br>
+    if (AI.isEnumAttribute()) return false;<br>
+    if (AI.isTypeAttribute()) {<br>
+      assert(getKindAsEnum() != AI.getKindAsEnum() &&<br>
+             "Comparison of types would be unstable");<br>
+      return getKindAsEnum() < AI.getKindAsEnum();<br>
+    }<br>
+    if (AI.isIntAttribute()) return true;<br>
+    if (AI.isStringAttribute()) return true;<br>
   }<br>
<br>
   if (isIntAttribute()) {<br>
     if (AI.isEnumAttribute()) return false;<br>
+    if (AI.isTypeAttribute()) return false;<br>
     if (AI.isIntAttribute()) {<br>
       if (getKindAsEnum() == AI.getKindAsEnum())<br>
         return getValueAsInt() < AI.getValueAsInt();<br>
@@ -500,7 +568,9 @@ bool AttributeImpl::operator<(const Attr<br>
     if (AI.isStringAttribute()) return true;<br>
   }<br>
<br>
+  assert(isStringAttribute());<br>
   if (AI.isEnumAttribute()) return false;<br>
+  if (AI.isTypeAttribute()) return false;<br>
   if (AI.isIntAttribute()) return false;<br>
   if (getKindAsString() == AI.getKindAsString())<br>
     return getValueAsString() < AI.getValueAsString();<br>
@@ -608,6 +678,10 @@ uint64_t AttributeSet::getDereferenceabl<br>
   return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;<br>
 }<br>
<br>
+Type *AttributeSet::getByValType() const {<br>
+  return SetNode ? SetNode->getByValType() : nullptr;<br>
+}<br>
+<br>
 std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {<br>
   return SetNode ? SetNode->getAllocSizeArgs()<br>
                  : std::pair<unsigned, Optional<unsigned>>(0, 0);<br>
@@ -691,6 +765,9 @@ AttributeSetNode *AttributeSetNode::get(<br>
<br>
     Attribute Attr;<br>
     switch (Kind) {<br>
+    case Attribute::ByVal:<br>
+      Attr = Attribute::getWithByValType(C, B.getByValType());<br>
+      break;<br>
     case Attribute::Alignment:<br>
       Attr = Attribute::getWithAlignment(C, B.getAlignment());<br>
       break;<br>
@@ -760,6 +837,13 @@ unsigned AttributeSetNode::getStackAlign<br>
   return 0;<br>
 }<br>
<br>
+Type *AttributeSetNode::getByValType() const {<br>
+  for (const auto I : *this)<br>
+    if (I.hasAttribute(Attribute::ByVal))<br>
+      return I.getValueAsType();<br>
+  return 0;<br>
+}<br>
+<br>
 uint64_t AttributeSetNode::getDereferenceableBytes() const {<br>
   for (const auto I : *this)<br>
     if (I.hasAttribute(Attribute::Dereferenceable))<br>
@@ -1258,6 +1342,11 @@ unsigned AttributeList::getParamAlignmen<br>
   return getAttributes(ArgNo + FirstArgIndex).getAlignment();<br>
 }<br>
<br>
+Type *AttributeList::getParamByValType(unsigned Index) const {<br>
+  return getAttributes(Index+FirstArgIndex).getByValType();<br>
+}<br>
+<br>
+<br>
 unsigned AttributeList::getStackAlignment(unsigned Index) const {<br>
   return getAttributes(Index).getStackAlignment();<br>
 }<br>
@@ -1336,6 +1425,7 @@ void AttrBuilder::clear() {<br>
   TargetDepAttrs.clear();<br>
   Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;<br>
   AllocSizeArgs = 0;<br>
+  ByValType = nullptr;<br>
 }<br>
<br>
 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {<br>
@@ -1360,6 +1450,8 @@ AttrBuilder &AttrBuilder::addAttribute(A<br>
     Alignment = Attr.getAlignment();<br>
   else if (Kind == Attribute::StackAlignment)<br>
     StackAlignment = Attr.getStackAlignment();<br>
+  else if (Kind == Attribute::ByVal)<br>
+    ByValType = Attr.getValueAsType();<br>
   else if (Kind == Attribute::Dereferenceable)<br>
     DerefBytes = Attr.getDereferenceableBytes();<br>
   else if (Kind == Attribute::DereferenceableOrNull)<br>
@@ -1382,6 +1474,8 @@ AttrBuilder &AttrBuilder::removeAttribut<br>
     Alignment = 0;<br>
   else if (Val == Attribute::StackAlignment)<br>
     StackAlignment = 0;<br>
+  else if (Val == Attribute::ByVal)<br>
+    ByValType = nullptr;<br>
   else if (Val == Attribute::Dereferenceable)<br>
     DerefBytes = 0;<br>
   else if (Val == Attribute::DereferenceableOrNull)<br>
@@ -1464,6 +1558,12 @@ AttrBuilder &AttrBuilder::addAllocSizeAt<br>
   return *this;<br>
 }<br>
<br>
+AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {<br>
+  Attrs[Attribute::ByVal] = true;<br>
+  ByValType = Ty;<br>
+  return *this;<br>
+}<br>
+<br>
 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {<br>
   // FIXME: What if both have alignments, but they don't match?!<br>
   if (!Alignment)<br>
<br>
Modified: llvm/trunk/lib/IR/Function.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Function.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Function.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/Function.cpp (original)<br>
+++ llvm/trunk/lib/IR/Function.cpp Wed May 29 12:12:48 2019<br>
@@ -113,6 +113,11 @@ unsigned Argument::getParamAlignment() c<br>
   return getParent()->getParamAlignment(getArgNo());<br>
 }<br>
<br>
+Type *Argument::getParamByValType() const {<br>
+  assert(getType()->isPointerTy() && "Only pointers have byval types");<br>
+  return getParent()->getParamByValType(getArgNo());<br>
+}<br>
+<br>
 uint64_t Argument::getDereferenceableBytes() const {<br>
   assert(getType()->isPointerTy() &&<br>
          "Only pointers have dereferenceable bytes");<br>
<br>
Modified: llvm/trunk/lib/IR/Verifier.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/Verifier.cpp (original)<br>
+++ llvm/trunk/lib/IR/Verifier.cpp Wed May 29 12:12:48 2019<br>
@@ -1695,6 +1695,11 @@ void Verifier::verifyParameterAttrs(Attr<br>
          "'noinline and alwaysinline' are incompatible!",<br>
          V);<br>
<br>
+  if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) {<br>
+    Assert(Attrs.getByValType() == cast<PointerType>(Ty)->getElementType(),<br>
+           "Attribute 'byval' type does not match parameter!");<br>
+  }<br>
+<br>
   AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty);<br>
   Assert(!AttrBuilder(Attrs).overlaps(IncompatibleAttrs),<br>
          "Wrong types for attribute: " +<br>
<br>
Added: llvm/trunk/test/Assembler/byval-type-attr.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/byval-type-attr.ll?rev=362012&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/byval-type-attr.ll?rev=362012&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Assembler/byval-type-attr.ll (added)<br>
+++ llvm/trunk/test/Assembler/byval-type-attr.ll Wed May 29 12:12:48 2019<br>
@@ -0,0 +1,31 @@<br>
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s<br>
+<br>
+; CHECK: define void @foo(i32* byval(i32) align 4)<br>
+define void @foo(i32* byval(i32) align 4) {<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK: define void @bar({ i32*, i8 }* byval({ i32*, i8 }) align 4)<br>
+define void @bar({i32*, i8}* byval({i32*, i8}) align 4) {<br>
+  ret void<br>
+}<br>
+<br>
+define void @caller({ i32*, i8 }* %ptr) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {<br>
+; CHECK: call void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)<br>
+; CHECK: invoke void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)<br>
+  call void @bar({i32*, i8}* byval %ptr)<br>
+  invoke void @bar({i32*, i8}* byval %ptr) to label %success unwind label %fail<br>
+<br>
+success:<br>
+  ret void<br>
+<br>
+fail:<br>
+  landingpad { i8*, i32 } cleanup<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK: declare void @baz([8 x i8]* byval([8 x i8]))<br>
+%named_type = type [8 x i8]<br>
+declare void @baz(%named_type* byval(%named_type))<br>
+<br>
+declare i32 @__gxx_personality_v0(...)<br>
<br>
Added: llvm/trunk/test/Assembler/invalid-byval-type1.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-byval-type1.ll?rev=362012&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-byval-type1.ll?rev=362012&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Assembler/invalid-byval-type1.ll (added)<br>
+++ llvm/trunk/test/Assembler/invalid-byval-type1.ll Wed May 29 12:12:48 2019<br>
@@ -0,0 +1,4 @@<br>
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s<br>
+<br>
+; CHECK: Attribute 'byval' type does not match parameter!<br>
+declare void @foo(i32* byval(i8))<br>
<br>
Added: llvm/trunk/test/Assembler/invalid-byval-type2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-byval-type2.ll?rev=362012&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-byval-type2.ll?rev=362012&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Assembler/invalid-byval-type2.ll (added)<br>
+++ llvm/trunk/test/Assembler/invalid-byval-type2.ll Wed May 29 12:12:48 2019<br>
@@ -0,0 +1,4 @@<br>
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s<br>
+<br>
+; CHECK: error: void type only allowed for function results<br>
+declare void @foo(i32* byval(void))<br>
<br>
Added: llvm/trunk/test/Assembler/invalid-byval-type3.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-byval-type3.ll?rev=362012&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-byval-type3.ll?rev=362012&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Assembler/invalid-byval-type3.ll (added)<br>
+++ llvm/trunk/test/Assembler/invalid-byval-type3.ll Wed May 29 12:12:48 2019<br>
@@ -0,0 +1,4 @@<br>
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s<br>
+<br>
+; CHECK: Attributes 'byval' and 'inalloca' do not support unsized types!<br>
+declare void @foo(void()* byval(void()))<br>
<br>
Added: llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc?rev=362012&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc?rev=362012&view=auto</a><br>
==============================================================================<br>
Binary file - no diff available.<br>
<br>
Propchange: llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc<br>
------------------------------------------------------------------------------<br>
    svn:mime-type = application/octet-stream<br>
<br>
Modified: llvm/trunk/test/Bitcode/attributes-3.3.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes-3.3.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes-3.3.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/attributes-3.3.ll (original)<br>
+++ llvm/trunk/test/Bitcode/attributes-3.3.ll Wed May 29 12:12:48 2019<br>
@@ -48,7 +48,7 @@ define void @f7(i8* noalias)<br>
 }<br>
<br>
 define void @f8(i8* byval)<br>
-; CHECK: define void @f8(i8* byval)<br>
+; CHECK: define void @f8(i8* byval(i8))<br>
 {<br>
         ret void;<br>
 }<br>
<br>
Modified: llvm/trunk/test/Bitcode/attributes.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/attributes.ll (original)<br>
+++ llvm/trunk/test/Bitcode/attributes.ll Wed May 29 12:12:48 2019<br>
@@ -45,7 +45,7 @@ define void @f7(i8* noalias)<br>
 }<br>
<br>
 define void @f8(i8* byval)<br>
-; CHECK: define void @f8(i8* byval)<br>
+; CHECK: define void @f8(i8* byval(i8))<br>
 {<br>
         ret void;<br>
 }<br>
<br>
Added: llvm/trunk/test/Bitcode/byval-upgrade.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/byval-upgrade.test?rev=362012&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/byval-upgrade.test?rev=362012&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/byval-upgrade.test (added)<br>
+++ llvm/trunk/test/Bitcode/byval-upgrade.test Wed May 29 12:12:48 2019<br>
@@ -0,0 +1,7 @@<br>
+RUN: llvm-dis %p/Inputs/byval-upgrade.bc -o - | FileCheck %s<br>
+<br>
+Make sure we upgrade old-stile IntAttribute byval records to a fully typed<br>
+version correctly.<br>
+<br>
+CHECK: call void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)<br>
+CHECK: invoke void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility-3.6.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.6.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.6.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility-3.6.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility-3.6.ll Wed May 29 12:12:48 2019<br>
@@ -404,7 +404,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility-3.7.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.7.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.7.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility-3.7.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility-3.7.ll Wed May 29 12:12:48 2019<br>
@@ -410,7 +410,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility-3.8.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.8.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.8.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility-3.8.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility-3.8.ll Wed May 29 12:12:48 2019<br>
@@ -435,7 +435,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility-3.9.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.9.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-3.9.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility-3.9.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility-3.9.ll Wed May 29 12:12:48 2019<br>
@@ -504,7 +504,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility-4.0.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-4.0.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-4.0.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility-4.0.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility-4.0.ll Wed May 29 12:12:48 2019<br>
@@ -504,7 +504,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility-5.0.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-5.0.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-5.0.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility-5.0.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility-5.0.ll Wed May 29 12:12:48 2019<br>
@@ -508,7 +508,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility-6.0.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-6.0.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility-6.0.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility-6.0.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility-6.0.ll Wed May 29 12:12:48 2019<br>
@@ -515,7 +515,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
<br>
Modified: llvm/trunk/test/Bitcode/compatibility.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/compatibility.ll (original)<br>
+++ llvm/trunk/test/Bitcode/compatibility.ll Wed May 29 12:12:48 2019<br>
@@ -529,7 +529,7 @@ declare void @f.param.signext(i8 signext<br>
 declare void @f.param.inreg(i8 inreg)<br>
 ; CHECK: declare void @f.param.inreg(i8 inreg)<br>
 declare void @f.param.byval({ i8, i8 }* byval)<br>
-; CHECK: declare void @f.param.byval({ i8, i8 }* byval)<br>
+; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))<br>
 declare void @f.param.inalloca(i8* inalloca)<br>
 ; CHECK: declare void @f.param.inalloca(i8* inalloca)<br>
 declare void @f.param.sret(i8* sret)<br>
@@ -1735,6 +1735,15 @@ define i8** @constexpr() {<br>
 declare void @llvm.test.immarg.intrinsic(i32 immarg)<br>
 ; CHECK: declare void @llvm.test.immarg.intrinsic(i32 immarg)<br>
<br>
+; byval attribute with type<br>
+%named_type = type [8 x i8]<br>
+declare void @byval_type(i32* byval(i32) align 2)<br>
+declare void @byval_type2({ i8, i8* }* byval({ i8, i8* }))<br>
+declare void @byval_named_type(%named_type* byval(%named_type))<br>
+; CHECK: declare void @byval_type(i32* byval(i32) align 2)<br>
+; CHECK: declare void @byval_type2({ i8, i8* }* byval({ i8, i8* }))<br>
+; CHECK: declare void @byval_named_type([8 x i8]* byval([8 x i8]))<br>
+<br>
 ; CHECK: attributes #0 = { alignstack=4 }<br>
 ; CHECK: attributes #1 = { alignstack=8 }<br>
 ; CHECK: attributes #2 = { alwaysinline }<br>
<br>
Modified: llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll (original)<br>
+++ llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll Wed May 29 12:12:48 2019<br>
@@ -41,7 +41,7 @@ declare void @ParamAttr3(i8* sret)<br>
 declare void @ParamAttr4(i8 signext)<br>
 ; CHECK: declare void @ParamAttr5(i8* inreg)<br>
 declare void @ParamAttr5(i8* inreg)<br>
-; CHECK: declare void @ParamAttr6(i8* byval)<br>
+; CHECK: declare void @ParamAttr6(i8* byval(i8))<br>
 declare void @ParamAttr6(i8* byval)<br>
 ; CHECK: declare void @ParamAttr7(i8* noalias)<br>
 declare void @ParamAttr7(i8* noalias)<br>
@@ -51,7 +51,7 @@ declare void @ParamAttr8(i8* nocapture)<br>
 declare void @ParamAttr9(i8* nest noalias nocapture)<br>
 ; CHECK: declare void @ParamAttr10{{[(i8* sret noalias nocapture) | (i8* noalias nocapture sret)]}}<br>
 declare void @ParamAttr10(i8* sret noalias nocapture)<br>
-;CHECK: declare void @ParamAttr11{{[(i8* byval noalias nocapture) | (i8* noalias nocapture byval)]}}<br>
+;CHECK: declare void @ParamAttr11{{[(i8* byval(i8) noalias nocapture) | (i8* noalias nocapture byval(i8))]}}<br>
 declare void @ParamAttr11(i8* byval noalias nocapture)<br>
 ;CHECK: declare void @ParamAttr12{{[(i8* inreg noalias nocapture) | (i8* noalias nocapture inreg)]}}<br>
 declare void @ParamAttr12(i8* inreg noalias nocapture)<br>
<br>
Added: llvm/trunk/test/CodeGen/AArch64/byval-type.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/byval-type.ll?rev=362012&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/byval-type.ll?rev=362012&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/AArch64/byval-type.ll (added)<br>
+++ llvm/trunk/test/CodeGen/AArch64/byval-type.ll Wed May 29 12:12:48 2019<br>
@@ -0,0 +1,37 @@<br>
+; RUN: llc -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s<br>
+<br>
+define i8 @byval_match(i8* byval(i8) align 1, i8* byval %ptr) {<br>
+; CHECK-LABEL: byval_match:<br>
+; CHECK: ldrb w0, [sp, #8]<br>
+  %res = load i8, i8* %ptr<br>
+  ret i8 %res<br>
+}<br>
+<br>
+define void @caller_match(i8* %p0, i8* %p1) {<br>
+; CHECK-LABEL: caller_match:<br>
+; CHECK: ldrb [[P1:w[0-9]+]], [x1]<br>
+; CHECK: strb [[P1]], [sp, #8]<br>
+; CHECK: ldrb [[P0:w[0-9]+]], [x0]<br>
+; CHECK: strb [[P0]], [sp]<br>
+; CHECK: bl byval_match<br>
+  call i8 @byval_match(i8* byval(i8) align 1 %p0, i8* byval %p1)<br>
+  ret void<br>
+}<br>
+<br>
+define i8 @byval_large([3 x i64]* byval([3 x i64]) align 8, i8* byval %ptr) {<br>
+; CHECK-LABEL: byval_large:<br>
+; CHECK: ldrb w0, [sp, #24]<br>
+  %res = load i8, i8* %ptr<br>
+  ret i8 %res<br>
+}<br>
+<br>
+define void @caller_large([3 x i64]* %p0, i8* %p1) {<br>
+; CHECK-LABEL: caller_large:<br>
+; CHECK: ldr [[P0HI:x[0-9]+]], [x0, #16]<br>
+; CHECK: ldr [[P0LO:q[0-9]+]], [x0]<br>
+; CHECK: str [[P0HI]], [sp, #16]<br>
+; CHECK: str [[P0LO]], [sp]<br>
+; CHECK: bl byval_large<br>
+  call i8 @byval_large([3 x i64]* byval([3 x i64]) align 8 %p0, i8* byval %p1)<br>
+  ret void<br>
+}<br>
<br>
Modified: llvm/trunk/test/Transforms/Inline/byval-tail-call.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/byval-tail-call.ll?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/byval-tail-call.ll?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/Inline/byval-tail-call.ll (original)<br>
+++ llvm/trunk/test/Transforms/Inline/byval-tail-call.ll Wed May 29 12:12:48 2019<br>
@@ -56,7 +56,7 @@ define void @foobar(i32* %x) {<br>
 ; CHECK: %[[POS:.*]] = alloca i32<br>
 ; CHECK: %[[VAL:.*]] = load i32, i32* %x<br>
 ; CHECK: store i32 %[[VAL]], i32* %[[POS]]<br>
-; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]<br>
+; CHECK: tail call void @ext2(i32* nonnull byval %[[POS]]<br>
 ; CHECK: ret void<br>
   tail call void @bar2(i32* byval %x)<br>
   ret void<br>
@@ -67,7 +67,7 @@ define void @barfoo() {<br>
 ; CHECK: %[[POS:.*]] = alloca i32<br>
 ; CHECK: %[[VAL:.*]] = load i32, i32* %x<br>
 ; CHECK: store i32 %[[VAL]], i32* %[[POS]]<br>
-; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]<br>
+; CHECK: tail call void @ext2(i32* nonnull byval %[[POS]]<br>
 ; CHECK: ret void<br>
   %x = alloca i32<br>
   tail call void @bar2(i32* byval %x)<br>
<br>
Modified: llvm/trunk/unittests/IR/AttributesTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/AttributesTest.cpp?rev=362012&r1=362011&r2=362012&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/AttributesTest.cpp?rev=362012&r1=362011&r2=362012&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/IR/AttributesTest.cpp (original)<br>
+++ llvm/trunk/unittests/IR/AttributesTest.cpp Wed May 29 12:12:48 2019<br>
@@ -8,6 +8,7 @@<br>
<br>
 #include "llvm/IR/Attributes.h"<br>
 #include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/IR/DerivedTypes.h"<br>
 #include "gtest/gtest.h"<br>
 using namespace llvm;<br>
<br>
@@ -40,6 +41,10 @@ TEST(Attributes, Ordering) {<br>
   EXPECT_TRUE(Align4 < Deref5);<br>
   EXPECT_TRUE(Align5 < Deref4);<br>
<br>
+  Attribute ByVal = Attribute::get(C, Attribute::ByVal, Type::getInt32Ty(C));<br>
+  EXPECT_FALSE(ByVal < Attribute::get(C, Attribute::ZExt));<br>
+  EXPECT_TRUE(ByVal < Align4);<br>
+<br>
   AttributeList ASs[] = {AttributeList::get(C, 2, Attribute::ZExt),<br>
                          AttributeList::get(C, 1, Attribute::SExt)};<br>
<br>
@@ -166,4 +171,19 @@ TEST(Attributes, OverflowGet) {<br>
   EXPECT_EQ(2U, AL.getNumAttrSets());<br>
 }<br>
<br>
+TEST(Attributes, StringRepresentation) {<br>
+  LLVMContext C;<br>
+  StructType *Ty = StructType::create(Type::getInt32Ty(C), "mystruct");<br>
+<br>
+  // Insufficiently careful printing can result in byval(%mystruct = { i32 })<br>
+  Attribute A = Attribute::getWithByValType(C, Ty);<br>
+  EXPECT_EQ(A.getAsString(), "byval(%mystruct)");<br>
+<br>
+  A = Attribute::getWithByValType(C, nullptr);<br>
+  EXPECT_EQ(A.getAsString(), "byval");<br>
+<br>
+  A = Attribute::getWithByValType(C, Type::getInt32Ty(C));<br>
+  EXPECT_EQ(A.getAsString(), "byval(i32)");<br>
+}<br>
+<br>
 } // end anonymous namespace<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>