[llvm] r362128 - Reapply: IR: add optional type to 'byval' function parameters

Mikael Holmén via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 5 05:55:43 PDT 2019


Hi again,

I also noticed that if I run clang on a C program with -emit-llvm, then 
I don't get the optional byval argument in the output ll-file, but if I 
run with -emit-llvm-bc and then use llvm-dis on the bc-file, I do get it.

So

clang -S -Xclang -emit-llvm 'foo.c' -o './foo.nobc.ll'

and

clang -S -Xclang -emit-llvm-bc 'foo.c' -o './foo.bc'
llvm-dis foo.bc -o foo.bc.ll

are different with respect to the optional byval argument.

/Mikael

On 2019-06-05 11:52, Mikael Holmén wrote:
> 
> 
> On 2019-06-05 11:47, Mikael Holmén via llvm-commits wrote:
>> Hi Tim,
>>
>> If I do
>>
>> opt -S -o - bbi-29346_x86.ll -instcombine
> 
> And now I also attached the reproducer file :/
> /Mikael
> 
>>
>> I get
>>
>> Attribute 'byval' type does not match parameter!
>> in function f1
>> LLVM ERROR: Broken function found, compilation aborted!
>>
>> Just running the verifer works so I suppose the input is ok.
>>
>> If I add -debug I see the following:
>>
>> IC: Visiting:   call void (i8, ...) @f2(i8 undef, %t2* byval(%t2) %0)
>> IC: Mod =   call void (i8, ...) @f2(i8 undef, %t2* byval(%t2) %0)
>>       New =   call void (i8, ...) @f2(i8 undef, i8* nonnull byval(%t2) 
>> %tmp3)
>>
>> so I suppose instcombine misses to replace the optional type when it's
>> changed the type of the pointer.
>>
>> Regards,
>> Mikael
>>
>> On 2019-05-30 20:48, Tim Northover via llvm-commits wrote:
>>> Author: tnorthover
>>> Date: Thu May 30 11:48:23 2019
>>> New Revision: 362128
>>>
>>> URL: 
>>> https://protect2.fireeye.com/url?k=30ba9e3a-6c304b1c-30badea1-86aae6564056-4c7683e0fc1eca6a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%3Frev%3D362128%26view%3Drev 
>>>
>>> Log:
>>> Reapply: IR: add optional type to 'byval' function parameters
>>>
>>> When we switch to opaque pointer types we will need some way to describe
>>> how many bytes a 'byval' parameter should occupy on the stack. This adds
>>> a (for now) optional extra type parameter.
>>>
>>> If present, the type must match the pointee type of the argument.
>>>
>>> The original commit did not remap byval types when linking modules, 
>>> which broke
>>> LTO. This version fixes that.
>>>
>>> Note to front-end maintainers: if this causes test failures, it's 
>>> probably
>>> because the "byval" attribute is printed after attributes without any 
>>> parameter
>>> after this change.
>>>
>>> Added:
>>>       llvm/trunk/test/Assembler/byval-type-attr.ll
>>>       llvm/trunk/test/Assembler/invalid-byval-type1.ll
>>>       llvm/trunk/test/Assembler/invalid-byval-type2.ll
>>>       llvm/trunk/test/Assembler/invalid-byval-type3.ll
>>>       llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc   (with props)
>>>       llvm/trunk/test/Bitcode/byval-upgrade.test
>>>       llvm/trunk/test/CodeGen/AArch64/byval-type.ll
>>>       llvm/trunk/test/Linker/Inputs/byval-types-1.ll
>>>       llvm/trunk/test/Linker/byval-types.ll
>>> Modified:
>>>       llvm/trunk/docs/LangRef.rst
>>>       llvm/trunk/docs/ReleaseNotes.rst
>>>       llvm/trunk/include/llvm/CodeGen/TargetLowering.h
>>>       llvm/trunk/include/llvm/IR/Argument.h
>>>       llvm/trunk/include/llvm/IR/Attributes.h
>>>       llvm/trunk/include/llvm/IR/CallSite.h
>>>       llvm/trunk/include/llvm/IR/Function.h
>>>       llvm/trunk/include/llvm/IR/InstrTypes.h
>>>       llvm/trunk/lib/AsmParser/LLParser.cpp
>>>       llvm/trunk/lib/AsmParser/LLParser.h
>>>       llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>>>       llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>>>       llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
>>>       llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp
>>>       llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
>>>       llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>>>       llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>>>       llvm/trunk/lib/IR/AttributeImpl.h
>>>       llvm/trunk/lib/IR/Attributes.cpp
>>>       llvm/trunk/lib/IR/Function.cpp
>>>       llvm/trunk/lib/IR/Verifier.cpp
>>>       llvm/trunk/lib/Linker/IRMover.cpp
>>>       llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
>>>       llvm/trunk/test/Bitcode/attributes-3.3.ll
>>>       llvm/trunk/test/Bitcode/attributes.ll
>>>       llvm/trunk/test/Bitcode/compatibility-3.6.ll
>>>       llvm/trunk/test/Bitcode/compatibility-3.7.ll
>>>       llvm/trunk/test/Bitcode/compatibility-3.8.ll
>>>       llvm/trunk/test/Bitcode/compatibility-3.9.ll
>>>       llvm/trunk/test/Bitcode/compatibility-4.0.ll
>>>       llvm/trunk/test/Bitcode/compatibility-5.0.ll
>>>       llvm/trunk/test/Bitcode/compatibility-6.0.ll
>>>       llvm/trunk/test/Bitcode/compatibility.ll
>>>       llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll
>>>       llvm/trunk/test/Transforms/Inline/byval-tail-call.ll
>>>       llvm/trunk/unittests/IR/AttributesTest.cpp
>>>
>>> Modified: llvm/trunk/docs/LangRef.rst
>>> URL: 
>>> https://protect2.fireeye.com/url?k=80be4961-dc349c47-80be09fa-86aae6564056-ca2d521f90fc69e8&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Fdocs%2FLangRef.rst%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/docs/LangRef.rst (original)
>>> +++ llvm/trunk/docs/LangRef.rst Thu May 30 11:48:23 2019
>>> @@ -1017,7 +1017,7 @@ Currently, only the following parameter
>>>        opposed to memory, though some targets use it to distinguish 
>>> between
>>>        two different kinds of registers). Use of this attribute is
>>>        target-specific.
>>> -``byval``
>>> +``byval`` or ``byval(<ty>)``
>>>        This indicates that the pointer parameter should really be 
>>> passed by
>>>        value to the function. The attribute implies that a hidden 
>>> copy of
>>>        the pointee is made between the caller and the callee, so the 
>>> callee
>>> @@ -1029,6 +1029,9 @@ Currently, only the following parameter
>>>        ``byval`` parameters). This is not a valid attribute for return
>>>        values.
>>> +    The byval attribute also supports an optional type argument, 
>>> which must be
>>> +    the same as the pointee type of the argument.
>>> +
>>>        The byval attribute also supports specifying an alignment with 
>>> the
>>>        align attribute. It indicates the alignment of the stack slot to
>>>        form and the known alignment of the pointer specified to the call
>>>
>>> Modified: llvm/trunk/docs/ReleaseNotes.rst
>>> URL: 
>>> https://protect2.fireeye.com/url?k=3b7dcf53-67f71a75-3b7d8fc8-86aae6564056-d608315b8372659c&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Fdocs%2FReleaseNotes.rst%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/docs/ReleaseNotes.rst (original)
>>> +++ llvm/trunk/docs/ReleaseNotes.rst Thu May 30 11:48:23 2019
>>> @@ -67,6 +67,11 @@ Changes to the LLVM IR
>>>      type is now mandatory. Specify `i8* null` to migrate from the 
>>> obsoleted
>>>      2-field form.
>>> +* The ``byval`` attribute can now take a type parameter:
>>> +  ``byval(<ty>)``. If present it must be identical to the argument's
>>> +  pointee type. In the next release we intend to make this parameter
>>> +  mandatory in preparation for opaque pointer types.
>>> +
>>>    Changes to the ARM Backend
>>>    --------------------------
>>>
>>> Modified: llvm/trunk/include/llvm/CodeGen/TargetLowering.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=8dc30cbe-d149d998-8dc34c25-86aae6564056-e556e1b46b702783&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Finclude%2Fllvm%2FCodeGen%2FTargetLowering.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/include/llvm/CodeGen/TargetLowering.h (original)
>>> +++ llvm/trunk/include/llvm/CodeGen/TargetLowering.h Thu May 30 
>>> 11:48:23 2019
>>> @@ -188,6 +188,7 @@ public:
>>>        bool IsSwiftSelf : 1;
>>>        bool IsSwiftError : 1;
>>>        uint16_t Alignment = 0;
>>> +    Type *ByValType = nullptr;
>>>        ArgListEntry()
>>>            : IsSExt(false), IsZExt(false), IsInReg(false), 
>>> IsSRet(false),
>>>
>>> Modified: llvm/trunk/include/llvm/IR/Argument.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=34f5324e-687fe768-34f572d5-86aae6564056-ee0e5911219fedd8&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Finclude%2Fllvm%2FIR%2FArgument.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/include/llvm/IR/Argument.h (original)
>>> +++ llvm/trunk/include/llvm/IR/Argument.h Thu May 30 11:48:23 2019
>>> @@ -78,6 +78,9 @@ public:
>>>      /// If this is a byval or inalloca argument, return its alignment.
>>>      unsigned getParamAlignment() const;
>>> +  /// If this is a byval argument, return its type.
>>> +  Type *getParamByValType() const;
>>> +
>>>      /// Return true if this argument has the nest attribute.
>>>      bool hasNestAttr() const;
>>>
>>> Modified: llvm/trunk/include/llvm/IR/Attributes.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=0cb5ede2-503f38c4-0cb5ad79-86aae6564056-70dd7c0cbf70bc8a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Finclude%2Fllvm%2FIR%2FAttributes.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/include/llvm/IR/Attributes.h (original)
>>> +++ llvm/trunk/include/llvm/IR/Attributes.h Thu May 30 11:48:23 2019
>>> @@ -90,6 +90,7 @@ public:
>>>      static Attribute get(LLVMContext &Context, AttrKind Kind, 
>>> uint64_t Val = 0);
>>>      static Attribute get(LLVMContext &Context, StringRef Kind,
>>>                           StringRef Val = StringRef());
>>> +  static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty);
>>>      /// Return a uniquified Attribute object that has the specific
>>>      /// alignment set.
>>> @@ -102,6 +103,7 @@ public:
>>>      static Attribute getWithAllocSizeArgs(LLVMContext &Context,
>>>                                            unsigned ElemSizeArg,
>>>                                            const Optional<unsigned> 
>>> &NumElemsArg);
>>> +  static Attribute getWithByValType(LLVMContext &Context, Type *Ty);
>>>      
>>> //===--------------------------------------------------------------------===// 
>>>
>>>      // Attribute Accessors
>>> @@ -117,6 +119,9 @@ public:
>>>      /// attribute.
>>>      bool isStringAttribute() const;
>>> +  /// Return true if the attribute is a type attribute.
>>> +  bool isTypeAttribute() const;
>>> +
>>>      /// Return true if the attribute is present.
>>>      bool hasAttribute(AttrKind Val) const;
>>> @@ -139,6 +144,10 @@ public:
>>>      /// attribute to be a string attribute.
>>>      StringRef getValueAsString() const;
>>> +  /// Return the attribute's value as a Type. This requires the 
>>> attribute to be
>>> +  /// a type attribute.
>>> +  Type *getValueAsType() const;
>>> +
>>>      /// Returns the alignment field of an attribute as a byte alignment
>>>      /// value.
>>>      unsigned getAlignment() const;
>>> @@ -279,6 +288,7 @@ public:
>>>      unsigned getStackAlignment() const;
>>>      uint64_t getDereferenceableBytes() const;
>>>      uint64_t getDereferenceableOrNullBytes() const;
>>> +  Type *getByValType() const;
>>>      std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
>>>      std::string getAsString(bool InAttrGrp = false) const;
>>> @@ -598,6 +608,9 @@ public:
>>>      /// Return the alignment for the specified function parameter.
>>>      unsigned getParamAlignment(unsigned ArgNo) const;
>>> +  /// Return the byval type for the specified function parameter.
>>> +  Type *getParamByValType(unsigned ArgNo) const;
>>> +
>>>      /// Get the stack alignment.
>>>      unsigned getStackAlignment(unsigned Index) const;
>>> @@ -697,6 +710,7 @@ class AttrBuilder {
>>>      uint64_t DerefBytes = 0;
>>>      uint64_t DerefOrNullBytes = 0;
>>>      uint64_t AllocSizeArgs = 0;
>>> +  Type *ByValType = nullptr;
>>>    public:
>>>      AttrBuilder() = default;
>>> @@ -772,6 +786,9 @@ public:
>>>      /// dereferenceable_or_null attribute exists (zero is returned 
>>> otherwise).
>>>      uint64_t getDereferenceableOrNullBytes() const { return 
>>> DerefOrNullBytes; }
>>> +  /// Retrieve the byval type.
>>> +  Type *getByValType() const { return ByValType; }
>>> +
>>>      /// Retrieve the allocsize args, if the allocsize attribute 
>>> exists.  If it
>>>      /// doesn't exist, pair(0, 0) is returned.
>>>      std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
>>> @@ -796,6 +813,9 @@ public:
>>>      AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg,
>>>                                    const Optional<unsigned> 
>>> &NumElemsArg);
>>> +  /// This turns a byval type into the form used internally in 
>>> Attribute.
>>> +  AttrBuilder &addByValAttr(Type *Ty);
>>> +
>>>      /// Add an allocsize attribute, using the representation 
>>> returned by
>>>      /// Attribute.getIntValue().
>>>      AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t 
>>> RawAllocSizeRepr);
>>>
>>> Modified: llvm/trunk/include/llvm/IR/CallSite.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=bcff938f-e07546a9-bcffd314-86aae6564056-2d2f12ba2c401f85&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Finclude%2Fllvm%2FIR%2FCallSite.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/include/llvm/IR/CallSite.h (original)
>>> +++ llvm/trunk/include/llvm/IR/CallSite.h Thu May 30 11:48:23 2019
>>> @@ -415,6 +415,11 @@ public:
>>>        CALLSITE_DELEGATE_GETTER(getParamAlignment(ArgNo));
>>>      }
>>> +  /// Extract the byval type for a call or parameter (nullptr=unknown).
>>> +  Type *getParamByValType(unsigned ArgNo) const {
>>> +    CALLSITE_DELEGATE_GETTER(getParamByValType(ArgNo));
>>> +  }
>>> +
>>>      /// Extract the number of dereferenceable bytes for a call or 
>>> parameter
>>>      /// (0=unknown).
>>>      uint64_t getDereferenceableBytes(unsigned i) const {
>>>
>>> Modified: llvm/trunk/include/llvm/IR/Function.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=773cb7f1-2bb662d7-773cf76a-86aae6564056-b6093897bb78580a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Finclude%2Fllvm%2FIR%2FFunction.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/include/llvm/IR/Function.h (original)
>>> +++ llvm/trunk/include/llvm/IR/Function.h Thu May 30 11:48:23 2019
>>> @@ -431,6 +431,11 @@ public:
>>>        return AttributeSets.getParamAlignment(ArgNo);
>>>      }
>>> +  /// Extract the byval type for a parameter (nullptr=unknown).
>>> +  Type *getParamByValType(unsigned ArgNo) const {
>>> +    return AttributeSets.getParamByValType(ArgNo);
>>> +  }
>>> +
>>>      /// Extract the number of dereferenceable bytes for a call or
>>>      /// parameter (0=unknown).
>>>      /// @param i AttributeList index, referring to a return value or 
>>> argument.
>>>
>>> Modified: llvm/trunk/include/llvm/IR/InstrTypes.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=52438d7d-0ec9585b-5243cde6-86aae6564056-2896d1201528ec15&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Finclude%2Fllvm%2FIR%2FInstrTypes.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/include/llvm/IR/InstrTypes.h (original)
>>> +++ llvm/trunk/include/llvm/IR/InstrTypes.h Thu May 30 11:48:23 2019
>>> @@ -1560,6 +1560,11 @@ public:
>>>        return Attrs.getParamAlignment(ArgNo);
>>>      }
>>> +  /// Extract the byval type for a call or parameter (nullptr=unknown).
>>> +  Type *getParamByValType(unsigned ArgNo) const {
>>> +    return Attrs.getParamByValType(ArgNo);
>>> +  }
>>> +
>>>      /// Extract the number of dereferenceable bytes for a call or
>>>      /// parameter (0=unknown).
>>>      uint64_t getDereferenceableBytes(unsigned i) const {
>>>
>>> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=e712f6c1-bb9823e7-e712b65a-86aae6564056-f57d89981339b591&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FAsmParser%2FLLParser.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
>>> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Thu May 30 11:48:23 2019
>>> @@ -1601,7 +1601,13 @@ bool LLParser::ParseOptionalParamAttrs(A
>>>          B.addAlignmentAttr(Alignment);
>>>          continue;
>>>        }
>>> -    case lltok::kw_byval:           
>>> B.addAttribute(Attribute::ByVal); break;
>>> +    case lltok::kw_byval: {
>>> +      Type *Ty;
>>> +      if (ParseByValWithOptionalType(Ty))
>>> +        return true;
>>> +      B.addByValAttr(Ty);
>>> +      continue;
>>> +    }
>>>        case lltok::kw_dereferenceable: {
>>>          uint64_t Bytes;
>>>          if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable, 
>>> Bytes))
>>> @@ -2454,6 +2460,22 @@ bool LLParser::ParseParameterList(SmallV
>>>      return false;
>>>    }
>>> +/// ParseByValWithOptionalType
>>> +///   ::= byval
>>> +///   ::= byval(<ty>)
>>> +bool LLParser::ParseByValWithOptionalType(Type *&Result) {
>>> +  Result = nullptr;
>>> +  if (!EatIfPresent(lltok::kw_byval))
>>> +    return true;
>>> +  if (!EatIfPresent(lltok::lparen))
>>> +    return false;
>>> +  if (ParseType(Result))
>>> +    return true;
>>> +  if (!EatIfPresent(lltok::rparen))
>>> +    return Error(Lex.getLoc(), "expected ')'");
>>> +  return false;
>>> +}
>>> +
>>>    /// ParseOptionalOperandBundles
>>>    ///    ::= /*empty*/
>>>    ///    ::= '[' OperandBundle [, OperandBundle ]* ']'
>>>
>>> Modified: llvm/trunk/lib/AsmParser/LLParser.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=c99d4827-95179d01-c99d08bc-86aae6564056-6c5e3985988242a6&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FAsmParser%2FLLParser.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/AsmParser/LLParser.h (original)
>>> +++ llvm/trunk/lib/AsmParser/LLParser.h Thu May 30 11:48:23 2019
>>> @@ -339,6 +339,7 @@ namespace llvm {
>>>        bool ParseFnAttributeValuePairs(AttrBuilder &B,
>>>                                        std::vector<unsigned> 
>>> &FwdRefAttrGrps,
>>>                                        bool inAttrGrp, LocTy 
>>> &BuiltinLoc);
>>> +    bool ParseByValWithOptionalType(Type *&Result);
>>>        // Module Summary Index Parsing.
>>>        bool SkipModuleSummaryEntry();
>>>
>>> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=783b2315-24b1f633-783b638e-86aae6564056-a5f4e3ae9353e256&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FBitcode%2FReader%2FBitcodeReader.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
>>> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu May 30 
>>> 11:48:23 2019
>>> @@ -638,6 +638,10 @@ private:
>>>        return getFnValueByID(ValNo, Ty);
>>>      }
>>> +  /// Upgrades old-style typeless byval attributes by adding the 
>>> corresponding
>>> +  /// argument's pointee type.
>>> +  void propagateByValTypes(CallBase *CB);
>>> +
>>>      /// Converts alignment exponent (i.e. power of two (or zero)) to 
>>> the
>>>      /// corresponding alignment to use. If alignment is too large, 
>>> returns
>>>      /// a corresponding error code.
>>> @@ -1492,6 +1496,12 @@ Error BitcodeReader::parseAttributeGroup
>>>              if (Error Err = parseAttrKind(Record[++i], &Kind))
>>>                return Err;
>>> +          // Upgrade old-style byval attribute to one with a type, 
>>> even if it's
>>> +          // nullptr. We will have to insert the real type when we 
>>> associate
>>> +          // this AttributeList with a function.
>>> +          if (Kind == Attribute::ByVal)
>>> +            B.addByValAttr(nullptr);
>>> +
>>>              B.addAttribute(Kind);
>>>            } else if (Record[i] == 1) { // Integer attribute
>>>              Attribute::AttrKind Kind;
>>> @@ -1507,9 +1517,7 @@ Error BitcodeReader::parseAttributeGroup
>>>                B.addDereferenceableOrNullAttr(Record[++i]);
>>>              else if (Kind == Attribute::AllocSize)
>>>                B.addAllocSizeAttrFromRawRepr(Record[++i]);
>>> -        } else {                     // String attribute
>>> -          assert((Record[i] == 3 || Record[i] == 4) &&
>>> -                 "Invalid attribute group entry");
>>> +        } else if (Record[i] == 3 || Record[i] == 4) { // String 
>>> attribute
>>>              bool HasValue = (Record[i++] == 4);
>>>              SmallString<64> KindStr;
>>>              SmallString<64> ValStr;
>>> @@ -1527,6 +1535,15 @@ Error BitcodeReader::parseAttributeGroup
>>>              }
>>>              B.addAttribute(KindStr.str(), ValStr.str());
>>> +        } else {
>>> +          assert((Record[i] == 5 || Record[i] == 6) &&
>>> +                 "Invalid attribute group entry");
>>> +          bool HasType = Record[i] == 6;
>>> +          Attribute::AttrKind Kind;
>>> +          if (Error Err = parseAttrKind(Record[++i], &Kind))
>>> +            return Err;
>>> +          if (Kind == Attribute::ByVal)
>>> +            B.addByValAttr(HasType ? getTypeByID(Record[++i]) : 
>>> nullptr);
>>>            }
>>>          }
>>> @@ -3028,6 +3045,17 @@ Error BitcodeReader::parseFunctionRecord
>>>      Func->setLinkage(getDecodedLinkage(RawLinkage));
>>>      Func->setAttributes(getAttributes(Record[4]));
>>> +  // Upgrade any old-style byval without a type by propagating the 
>>> argument's
>>> +  // pointee type. There should be no opaque pointers where the 
>>> byval type is
>>> +  // implicit.
>>> +  for (auto &Arg : Func->args()) {
>>> +    if (Arg.hasByValAttr() && !Arg.getParamByValType()) {
>>> +      Arg.removeAttr(Attribute::ByVal);
>>> +      Arg.addAttr(Attribute::getWithByValType(
>>> +          Context, Arg.getType()->getPointerElementType()));
>>> +    }
>>> +  }
>>> +
>>>      unsigned Alignment;
>>>      if (Error Err = parseAlignmentValue(Record[5], Alignment))
>>>        return Err;
>>> @@ -3441,6 +3469,19 @@ Error BitcodeReader::typeCheckLoadStoreI
>>>      return Error::success();
>>>    }
>>> +void BitcodeReader::propagateByValTypes(CallBase *CB) {
>>> +  for (unsigned i = 0; i < CB->getNumArgOperands(); ++i) {
>>> +    if (CB->paramHasAttr(i, Attribute::ByVal) &&
>>> +        !CB->getAttribute(i, Attribute::ByVal).getValueAsType()) {
>>> +      CB->removeParamAttr(i, Attribute::ByVal);
>>> +      CB->addParamAttr(
>>> +          i, Attribute::getWithByValType(
>>> +                 Context,
>>> +                 
>>> CB->getArgOperand(i)->getType()->getPointerElementType()));
>>> +    }
>>> +  }
>>> +}
>>> +
>>>    /// Lazily parse the specified function body block.
>>>    Error BitcodeReader::parseFunctionBody(Function *F) {
>>>      if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
>>> @@ -4256,6 +4297,8 @@ Error BitcodeReader::parseFunctionBody(F
>>>          cast<InvokeInst>(I)->setCallingConv(
>>>              static_cast<CallingConv::ID>(CallingConv::MaxID & CCInfo));
>>>          cast<InvokeInst>(I)->setAttributes(PAL);
>>> +      propagateByValTypes(cast<CallBase>(I));
>>> +
>>>          break;
>>>        }
>>>        case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval]
>>> @@ -4731,6 +4774,7 @@ Error BitcodeReader::parseFunctionBody(F
>>>            TCK = CallInst::TCK_NoTail;
>>>          cast<CallInst>(I)->setTailCallKind(TCK);
>>>          cast<CallInst>(I)->setAttributes(PAL);
>>> +      propagateByValTypes(cast<CallBase>(I));
>>>          if (FMF.any()) {
>>>            if (!isa<FPMathOperator>(I))
>>>              return error("Fast-math-flags specified for call without "
>>>
>>> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=3562a936-69e87c10-3562e9ad-86aae6564056-0cef2abe54d48bc5&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FBitcode%2FWriter%2FBitcodeWriter.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
>>> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Thu May 30 
>>> 11:48:23 2019
>>> @@ -747,7 +747,7 @@ void ModuleBitcodeWriter::writeAttribute
>>>            Record.push_back(1);
>>>            Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
>>>            Record.push_back(Attr.getValueAsInt());
>>> -      } else {
>>> +      } else if (Attr.isStringAttribute()) {
>>>            StringRef Kind = Attr.getKindAsString();
>>>            StringRef Val = Attr.getValueAsString();
>>> @@ -758,6 +758,13 @@ void ModuleBitcodeWriter::writeAttribute
>>>              Record.append(Val.begin(), Val.end());
>>>              Record.push_back(0);
>>>            }
>>> +      } else {
>>> +        assert(Attr.isTypeAttribute());
>>> +        Type *Ty = Attr.getValueAsType();
>>> +        Record.push_back(Ty ? 6 : 5);
>>> +        Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
>>> +        if (Ty)
>>> +          Record.push_back(VE.getTypeID(Attr.getValueAsType()));
>>>          }
>>>        }
>>> @@ -4126,15 +4133,15 @@ void ModuleBitcodeWriter::write() {
>>>      // Emit blockinfo, which defines the standard abbreviations etc.
>>>      writeBlockInfo();
>>> +  // Emit information describing all of the types in the module.
>>> +  writeTypeTable();
>>> +
>>>      // Emit information about attribute groups.
>>>      writeAttributeGroupTable();
>>>      // Emit information about parameter attributes.
>>>      writeAttributeTable();
>>> -  // Emit information describing all of the types in the module.
>>> -  writeTypeTable();
>>> -
>>>      writeComdats();
>>>      // Emit top-level description of module, including target 
>>> triple, inline asm,
>>>
>>> Modified: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=cd8f51b6-91058490-cd8f112d-86aae6564056-ad2bbef4124fd65f&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FBitcode%2FWriter%2FValueEnumerator.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp (original)
>>> +++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Thu May 30 
>>> 11:48:23 2019
>>> @@ -949,9 +949,11 @@ void ValueEnumerator::incorporateFunctio
>>>      incorporateFunctionMetadata(F);
>>>      // Adding function arguments to the value table.
>>> -  for (const auto &I : F.args())
>>> +  for (const auto &I : F.args()) {
>>>        EnumerateValue(&I);
>>> -
>>> +    if (I.hasAttribute(Attribute::ByVal) && I.getParamByValType())
>>> +      EnumerateType(I.getParamByValType());
>>> +  }
>>>      FirstFuncConstantID = Values.size();
>>>      // Add all function-level constants to the value table.
>>>
>>> Modified: llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=9f3997b4-c3b34292-9f39d72f-86aae6564056-410217a70fd2050a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FCodeGen%2FGlobalISel%2FCallLowering.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp (original)
>>> +++ llvm/trunk/lib/CodeGen/GlobalISel/CallLowering.cpp Thu May 30 
>>> 11:48:23 2019
>>> @@ -87,7 +87,10 @@ void CallLowering::setArgFlags(CallLower
>>>      if (Arg.Flags.isByVal() || Arg.Flags.isInAlloca()) {
>>>        Type *ElementTy = cast<PointerType>(Arg.Ty)->getElementType();
>>> -    Arg.Flags.setByValSize(DL.getTypeAllocSize(ElementTy));
>>> +
>>> +    auto Ty = Attrs.getAttribute(OpIdx, 
>>> Attribute::ByVal).getValueAsType();
>>> +    Arg.Flags.setByValSize(DL.getTypeAllocSize(Ty ? Ty : ElementTy));
>>> +
>>>        // For ByVal, alignment should be passed from FE.  BE will 
>>> guess if
>>>        // this info is not there but there are cases it cannot get 
>>> right.
>>>        unsigned FrameAlign;
>>>
>>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=b87c4bb4-e4f69e92-b87c0b2f-86aae6564056-808605a16059f38f&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FCodeGen%2FSelectionDAG%2FFastISel.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
>>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Thu May 30 
>>> 11:48:23 2019
>>> @@ -1204,9 +1204,11 @@ bool FastISel::lowerCallTo(CallLoweringI
>>>        if (Arg.IsByVal || Arg.IsInAlloca) {
>>>          PointerType *Ty = cast<PointerType>(Arg.Ty);
>>>          Type *ElementTy = Ty->getElementType();
>>> -      unsigned FrameSize = DL.getTypeAllocSize(ElementTy);
>>> -      // For ByVal, alignment should come from FE. BE will guess if 
>>> this info is
>>> -      // not there, but there are cases it cannot get right.
>>> +      unsigned FrameSize =
>>> +          DL.getTypeAllocSize(Arg.ByValType ? Arg.ByValType : 
>>> ElementTy);
>>> +
>>> +      // For ByVal, alignment should come from FE. BE will guess if 
>>> this info
>>> +      // is not there, but there are cases it cannot get right.
>>>          unsigned FrameAlign = Arg.Alignment;
>>>          if (!FrameAlign)
>>>            FrameAlign = TLI.getByValTypeAlignment(ElementTy, DL);
>>>
>>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=0197369c-5d1de3ba-01977607-86aae6564056-f9cbae866faaba2f&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FCodeGen%2FSelectionDAG%2FSelectionDAGBuilder.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
>>> (original)
>>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Thu 
>>> May 30 11:48:23 2019
>>> @@ -9076,8 +9076,11 @@ TargetLowering::LowerCallTo(TargetLoweri
>>>          if (Args[i].IsByVal || Args[i].IsInAlloca) {
>>>            PointerType *Ty = cast<PointerType>(Args[i].Ty);
>>>            Type *ElementTy = Ty->getElementType();
>>> -        Flags.setByValSize(DL.getTypeAllocSize(ElementTy));
>>> -        // For ByVal, alignment should come from FE.  BE will guess 
>>> if this
>>> +
>>> +        unsigned FrameSize = DL.getTypeAllocSize(
>>> +            Args[i].ByValType ? Args[i].ByValType : ElementTy);
>>> +        Flags.setByValSize(FrameSize);
>>> +
>>>            // info is not there but there are cases it cannot get right.
>>>            unsigned FrameAlign;
>>>            if (Args[i].Alignment)
>>> @@ -9574,9 +9577,14 @@ void SelectionDAGISel::LowerArguments(co
>>>          if (Flags.isByVal() || Flags.isInAlloca()) {
>>>            PointerType *Ty = cast<PointerType>(Arg.getType());
>>>            Type *ElementTy = Ty->getElementType();
>>> -        Flags.setByValSize(DL.getTypeAllocSize(ElementTy));
>>> -        // For ByVal, alignment should be passed from FE.  BE will 
>>> guess if
>>> -        // this info is not there but there are cases it cannot get 
>>> right.
>>> +
>>> +        // For ByVal, size and alignment should be passed from FE.  
>>> BE will
>>> +        // guess if this info is not there but there are cases it 
>>> cannot get
>>> +        // right.
>>> +        unsigned FrameSize = DL.getTypeAllocSize(
>>> +            Arg.getParamByValType() ? Arg.getParamByValType() : 
>>> ElementTy);
>>> +        Flags.setByValSize(FrameSize);
>>> +
>>>            unsigned FrameAlign;
>>>            if (Arg.getParamAlignment())
>>>              FrameAlign = Arg.getParamAlignment();
>>>
>>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=0ad0600c-565ab52a-0ad02097-86aae6564056-dc0a1c4a6cc531be&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FCodeGen%2FSelectionDAG%2FTargetLowering.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
>>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Thu May 30 
>>> 11:48:23 2019
>>> @@ -112,6 +112,7 @@ void TargetLoweringBase::ArgListEntry::s
>>>      IsSwiftSelf = Call->paramHasAttr(ArgIdx, Attribute::SwiftSelf);
>>>      IsSwiftError = Call->paramHasAttr(ArgIdx, Attribute::SwiftError);
>>>      Alignment = Call->getParamAlignment(ArgIdx);
>>> +  ByValType = Call->getParamByValType(ArgIdx);
>>>    }
>>>    /// Generate a libcall taking the given operands as arguments and 
>>> returning a
>>>
>>> Modified: llvm/trunk/lib/IR/AttributeImpl.h
>>> URL: 
>>> https://protect2.fireeye.com/url?k=686d1347-34e7c661-686d53dc-86aae6564056-935d2b6c64799719&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FIR%2FAttributeImpl.h%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/IR/AttributeImpl.h (original)
>>> +++ llvm/trunk/lib/IR/AttributeImpl.h Thu May 30 11:48:23 2019
>>> @@ -29,6 +29,7 @@
>>>    namespace llvm {
>>>    class LLVMContext;
>>> +class Type;
>>>    
>>> //===----------------------------------------------------------------------===// 
>>>
>>>    /// \class
>>> @@ -41,7 +42,8 @@ protected:
>>>      enum AttrEntryKind {
>>>        EnumAttrEntry,
>>>        IntAttrEntry,
>>> -    StringAttrEntry
>>> +    StringAttrEntry,
>>> +    TypeAttrEntry,
>>>      };
>>>      AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {}
>>> @@ -56,6 +58,7 @@ public:
>>>      bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
>>>      bool isIntAttribute() const { return KindID == IntAttrEntry; }
>>>      bool isStringAttribute() const { return KindID == 
>>> StringAttrEntry; }
>>> +  bool isTypeAttribute() const { return KindID == TypeAttrEntry; }
>>>      bool hasAttribute(Attribute::AttrKind A) const;
>>>      bool hasAttribute(StringRef Kind) const;
>>> @@ -66,16 +69,20 @@ public:
>>>      StringRef getKindAsString() const;
>>>      StringRef getValueAsString() const;
>>> +  Type *getValueAsType() const;
>>> +
>>>      /// Used when sorting the attributes.
>>>      bool operator<(const AttributeImpl &AI) const;
>>>      void Profile(FoldingSetNodeID &ID) const {
>>>        if (isEnumAttribute())
>>> -      Profile(ID, getKindAsEnum(), 0);
>>> +      Profile(ID, getKindAsEnum(), static_cast<uint64_t>(0));
>>>        else if (isIntAttribute())
>>>          Profile(ID, getKindAsEnum(), getValueAsInt());
>>> -    else
>>> +    else if (isStringAttribute())
>>>          Profile(ID, getKindAsString(), getValueAsString());
>>> +    else
>>> +      Profile(ID, getKindAsEnum(), getValueAsType());
>>>      }
>>>      static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
>>> @@ -88,6 +95,12 @@ public:
>>>        ID.AddString(Kind);
>>>        if (!Values.empty()) ID.AddString(Values);
>>>      }
>>> +
>>> +  static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind,
>>> +                      Type *Ty) {
>>> +    ID.AddInteger(Kind);
>>> +    ID.AddPointer(Ty);
>>> +  }
>>>    };
>>>    
>>> //===----------------------------------------------------------------------===// 
>>>
>>> @@ -145,6 +158,18 @@ public:
>>>      StringRef getStringValue() const { return Val; }
>>>    };
>>> +class TypeAttributeImpl : public EnumAttributeImpl {
>>> +  virtual void anchor();
>>> +
>>> +  Type *Ty;
>>> +
>>> +public:
>>> +  TypeAttributeImpl(Attribute::AttrKind Kind, Type *Ty)
>>> +      : EnumAttributeImpl(TypeAttrEntry, Kind), Ty(Ty) {}
>>> +
>>> +  Type *getTypeValue() const { return Ty; }
>>> +};
>>> +
>>>    
>>> //===----------------------------------------------------------------------===// 
>>>
>>>    /// \class
>>>    /// This class represents a group of attributes that apply to one
>>> @@ -189,6 +214,7 @@ public:
>>>      uint64_t getDereferenceableOrNullBytes() const;
>>>      std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
>>>      std::string getAsString(bool InAttrGrp) const;
>>> +  Type *getByValType() const;
>>>      using iterator = const Attribute *;
>>>
>>> Modified: llvm/trunk/lib/IR/Attributes.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=2edd44c6-725791e0-2edd045d-86aae6564056-987bdbe9e669059e&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FIR%2FAttributes.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/IR/Attributes.cpp (original)
>>> +++ llvm/trunk/lib/IR/Attributes.cpp Thu May 30 11:48:23 2019
>>> @@ -121,6 +121,27 @@ Attribute Attribute::get(LLVMContext &Co
>>>      return Attribute(PA);
>>>    }
>>> +Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind 
>>> Kind,
>>> +                         Type *Ty) {
>>> +  LLVMContextImpl *pImpl = Context.pImpl;
>>> +  FoldingSetNodeID ID;
>>> +  ID.AddInteger(Kind);
>>> +  ID.AddPointer(Ty);
>>> +
>>> +  void *InsertPoint;
>>> +  AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, 
>>> InsertPoint);
>>> +
>>> +  if (!PA) {
>>> +    // If we didn't find any existing attributes of the same shape 
>>> then create a
>>> +    // new one and insert it.
>>> +    PA = new TypeAttributeImpl(Kind, Ty);
>>> +    pImpl->AttrsSet.InsertNode(PA, InsertPoint);
>>> +  }
>>> +
>>> +  // Return the Attribute that we found or created.
>>> +  return Attribute(PA);
>>> +}
>>> +
>>>    Attribute Attribute::getWithAlignment(LLVMContext &Context, 
>>> uint64_t Align) {
>>>      assert(isPowerOf2_32(Align) && "Alignment must be a power of 
>>> two.");
>>>      assert(Align <= 0x40000000 && "Alignment too large.");
>>> @@ -146,6 +167,10 @@ Attribute Attribute::getWithDereferencea
>>>      return get(Context, DereferenceableOrNull, Bytes);
>>>    }
>>> +Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
>>> +  return get(Context, ByVal, Ty);
>>> +}
>>> +
>>>    Attribute
>>>    Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned 
>>> ElemSizeArg,
>>>                                    const Optional<unsigned> 
>>> &NumElemsArg) {
>>> @@ -170,9 +195,13 @@ bool Attribute::isStringAttribute() cons
>>>      return pImpl && pImpl->isStringAttribute();
>>>    }
>>> +bool Attribute::isTypeAttribute() const {
>>> +  return pImpl && pImpl->isTypeAttribute();
>>> +}
>>> +
>>>    Attribute::AttrKind Attribute::getKindAsEnum() const {
>>>      if (!pImpl) return None;
>>> -  assert((isEnumAttribute() || isIntAttribute()) &&
>>> +  assert((isEnumAttribute() || isIntAttribute() || 
>>> isTypeAttribute()) &&
>>>             "Invalid attribute type to get the kind as an enum!");
>>>      return pImpl->getKindAsEnum();
>>>    }
>>> @@ -198,6 +227,14 @@ StringRef Attribute::getValueAsString()
>>>      return pImpl->getValueAsString();
>>>    }
>>> +Type *Attribute::getValueAsType() const {
>>> +  if (!pImpl) return {};
>>> +  assert(isTypeAttribute() &&
>>> +         "Invalid attribute type to get the value as a type!");
>>> +  return pImpl->getValueAsType();
>>> +}
>>> +
>>> +
>>>    bool Attribute::hasAttribute(AttrKind Kind) const {
>>>      return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind 
>>> == None);
>>>    }
>>> @@ -252,8 +289,6 @@ std::string Attribute::getAsString(bool
>>>        return "argmemonly";
>>>      if (hasAttribute(Attribute::Builtin))
>>>        return "builtin";
>>> -  if (hasAttribute(Attribute::ByVal))
>>> -    return "byval";
>>>      if (hasAttribute(Attribute::Convergent))
>>>        return "convergent";
>>>      if (hasAttribute(Attribute::SwiftError))
>>> @@ -353,6 +388,19 @@ std::string Attribute::getAsString(bool
>>>      if (hasAttribute(Attribute::ImmArg))
>>>        return "immarg";
>>> +  if (hasAttribute(Attribute::ByVal)) {
>>> +    std::string Result;
>>> +    Result += "byval";
>>> +    if (Type *Ty = getValueAsType()) {
>>> +      raw_string_ostream OS(Result);
>>> +      Result += '(';
>>> +      Ty->print(OS, false, true);
>>> +      OS.flush();
>>> +      Result += ')';
>>> +    }
>>> +    return Result;
>>> +  }
>>> +
>>>      // FIXME: These should be output like this:
>>>      //
>>>      //   align=4
>>> @@ -451,6 +499,8 @@ void IntAttributeImpl::anchor() {}
>>>    void StringAttributeImpl::anchor() {}
>>> +void TypeAttributeImpl::anchor() {}
>>> +
>>>    bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
>>>      if (isStringAttribute()) return false;
>>>      return getKindAsEnum() == A;
>>> @@ -462,7 +512,7 @@ bool AttributeImpl::hasAttribute(StringR
>>>    }
>>>    Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
>>> -  assert(isEnumAttribute() || isIntAttribute());
>>> +  assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
>>>      return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
>>>    }
>>> @@ -481,6 +531,11 @@ StringRef AttributeImpl::getValueAsStrin
>>>      return static_cast<const StringAttributeImpl 
>>> *>(this)->getStringValue();
>>>    }
>>> +Type *AttributeImpl::getValueAsType() const {
>>> +  assert(isTypeAttribute());
>>> +  return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
>>> +}
>>> +
>>>    bool AttributeImpl::operator<(const AttributeImpl &AI) const {
>>>      // This sorts the attributes with Attribute::AttrKinds coming 
>>> first (sorted
>>>      // relative to their enum value) and then strings.
>>> @@ -488,10 +543,23 @@ bool AttributeImpl::operator<(const Attr
>>>        if (AI.isEnumAttribute()) return getKindAsEnum() < 
>>> AI.getKindAsEnum();
>>>        if (AI.isIntAttribute()) return true;
>>>        if (AI.isStringAttribute()) return true;
>>> +    if (AI.isTypeAttribute()) return true;
>>> +  }
>>> +
>>> +  if (isTypeAttribute()) {
>>> +    if (AI.isEnumAttribute()) return false;
>>> +    if (AI.isTypeAttribute()) {
>>> +      assert(getKindAsEnum() != AI.getKindAsEnum() &&
>>> +             "Comparison of types would be unstable");
>>> +      return getKindAsEnum() < AI.getKindAsEnum();
>>> +    }
>>> +    if (AI.isIntAttribute()) return true;
>>> +    if (AI.isStringAttribute()) return true;
>>>      }
>>>      if (isIntAttribute()) {
>>>        if (AI.isEnumAttribute()) return false;
>>> +    if (AI.isTypeAttribute()) return false;
>>>        if (AI.isIntAttribute()) {
>>>          if (getKindAsEnum() == AI.getKindAsEnum())
>>>            return getValueAsInt() < AI.getValueAsInt();
>>> @@ -500,7 +568,9 @@ bool AttributeImpl::operator<(const Attr
>>>        if (AI.isStringAttribute()) return true;
>>>      }
>>> +  assert(isStringAttribute());
>>>      if (AI.isEnumAttribute()) return false;
>>> +  if (AI.isTypeAttribute()) return false;
>>>      if (AI.isIntAttribute()) return false;
>>>      if (getKindAsString() == AI.getKindAsString())
>>>        return getValueAsString() < AI.getValueAsString();
>>> @@ -608,6 +678,10 @@ uint64_t AttributeSet::getDereferenceabl
>>>      return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
>>>    }
>>> +Type *AttributeSet::getByValType() const {
>>> +  return SetNode ? SetNode->getByValType() : nullptr;
>>> +}
>>> +
>>>    std::pair<unsigned, Optional<unsigned>> 
>>> AttributeSet::getAllocSizeArgs() const {
>>>      return SetNode ? SetNode->getAllocSizeArgs()
>>>                     : std::pair<unsigned, Optional<unsigned>>(0, 0);
>>> @@ -691,6 +765,9 @@ AttributeSetNode *AttributeSetNode::get(
>>>        Attribute Attr;
>>>        switch (Kind) {
>>> +    case Attribute::ByVal:
>>> +      Attr = Attribute::getWithByValType(C, B.getByValType());
>>> +      break;
>>>        case Attribute::Alignment:
>>>          Attr = Attribute::getWithAlignment(C, B.getAlignment());
>>>          break;
>>> @@ -760,6 +837,13 @@ unsigned AttributeSetNode::getStackAlign
>>>      return 0;
>>>    }
>>> +Type *AttributeSetNode::getByValType() const {
>>> +  for (const auto I : *this)
>>> +    if (I.hasAttribute(Attribute::ByVal))
>>> +      return I.getValueAsType();
>>> +  return 0;
>>> +}
>>> +
>>>    uint64_t AttributeSetNode::getDereferenceableBytes() const {
>>>      for (const auto I : *this)
>>>        if (I.hasAttribute(Attribute::Dereferenceable))
>>> @@ -1258,6 +1342,11 @@ unsigned AttributeList::getParamAlignmen
>>>      return getAttributes(ArgNo + FirstArgIndex).getAlignment();
>>>    }
>>> +Type *AttributeList::getParamByValType(unsigned Index) const {
>>> +  return getAttributes(Index+FirstArgIndex).getByValType();
>>> +}
>>> +
>>> +
>>>    unsigned AttributeList::getStackAlignment(unsigned Index) const {
>>>      return getAttributes(Index).getStackAlignment();
>>>    }
>>> @@ -1336,6 +1425,7 @@ void AttrBuilder::clear() {
>>>      TargetDepAttrs.clear();
>>>      Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
>>>      AllocSizeArgs = 0;
>>> +  ByValType = nullptr;
>>>    }
>>>    AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
>>> @@ -1360,6 +1450,8 @@ AttrBuilder &AttrBuilder::addAttribute(A
>>>        Alignment = Attr.getAlignment();
>>>      else if (Kind == Attribute::StackAlignment)
>>>        StackAlignment = Attr.getStackAlignment();
>>> +  else if (Kind == Attribute::ByVal)
>>> +    ByValType = Attr.getValueAsType();
>>>      else if (Kind == Attribute::Dereferenceable)
>>>        DerefBytes = Attr.getDereferenceableBytes();
>>>      else if (Kind == Attribute::DereferenceableOrNull)
>>> @@ -1382,6 +1474,8 @@ AttrBuilder &AttrBuilder::removeAttribut
>>>        Alignment = 0;
>>>      else if (Val == Attribute::StackAlignment)
>>>        StackAlignment = 0;
>>> +  else if (Val == Attribute::ByVal)
>>> +    ByValType = nullptr;
>>>      else if (Val == Attribute::Dereferenceable)
>>>        DerefBytes = 0;
>>>      else if (Val == Attribute::DereferenceableOrNull)
>>> @@ -1464,6 +1558,12 @@ AttrBuilder &AttrBuilder::addAllocSizeAt
>>>      return *this;
>>>    }
>>> +AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
>>> +  Attrs[Attribute::ByVal] = true;
>>> +  ByValType = Ty;
>>> +  return *this;
>>> +}
>>> +
>>>    AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
>>>      // FIXME: What if both have alignments, but they don't match?!
>>>      if (!Alignment)
>>> @@ -1481,6 +1581,9 @@ AttrBuilder &AttrBuilder::merge(const At
>>>      if (!AllocSizeArgs)
>>>        AllocSizeArgs = B.AllocSizeArgs;
>>> +  if (!ByValType)
>>> +    ByValType = B.ByValType;
>>> +
>>>      Attrs |= B.Attrs;
>>>      for (auto I : B.td_attrs())
>>> @@ -1506,6 +1609,9 @@ AttrBuilder &AttrBuilder::remove(const A
>>>      if (B.AllocSizeArgs)
>>>        AllocSizeArgs = 0;
>>> +  if (B.ByValType)
>>> +    ByValType = nullptr;
>>> +
>>>      Attrs &= ~B.Attrs;
>>>      for (auto I : B.td_attrs())
>>> @@ -1565,7 +1671,7 @@ bool AttrBuilder::operator==(const AttrB
>>>          return false;
>>>      return Alignment == B.Alignment && StackAlignment == 
>>> B.StackAlignment &&
>>> -         DerefBytes == B.DerefBytes;
>>> +         DerefBytes == B.DerefBytes && ByValType == B.ByValType;
>>>    }
>>>    
>>> //===----------------------------------------------------------------------===// 
>>>
>>>
>>> Modified: llvm/trunk/lib/IR/Function.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=92f907b2-ce73d294-92f94729-86aae6564056-a1de1ac26a142128&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FIR%2FFunction.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/IR/Function.cpp (original)
>>> +++ llvm/trunk/lib/IR/Function.cpp Thu May 30 11:48:23 2019
>>> @@ -113,6 +113,11 @@ unsigned Argument::getParamAlignment() c
>>>      return getParent()->getParamAlignment(getArgNo());
>>>    }
>>> +Type *Argument::getParamByValType() const {
>>> +  assert(getType()->isPointerTy() && "Only pointers have byval types");
>>> +  return getParent()->getParamByValType(getArgNo());
>>> +}
>>> +
>>>    uint64_t Argument::getDereferenceableBytes() const {
>>>      assert(getType()->isPointerTy() &&
>>>             "Only pointers have dereferenceable bytes");
>>>
>>> Modified: llvm/trunk/lib/IR/Verifier.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=283528c5-74bffde3-2835685e-86aae6564056-e28bab8a0a065139&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FIR%2FVerifier.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/IR/Verifier.cpp (original)
>>> +++ llvm/trunk/lib/IR/Verifier.cpp Thu May 30 11:48:23 2019
>>> @@ -1695,6 +1695,11 @@ void Verifier::verifyParameterAttrs(Attr
>>>             "'noinline and alwaysinline' are incompatible!",
>>>             V);
>>> +  if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) {
>>> +    Assert(Attrs.getByValType() == 
>>> cast<PointerType>(Ty)->getElementType(),
>>> +           "Attribute 'byval' type does not match parameter!");
>>> +  }
>>> +
>>>      AttrBuilder IncompatibleAttrs = 
>>> AttributeFuncs::typeIncompatible(Ty);
>>>      Assert(!AttrBuilder(Attrs).overlaps(IncompatibleAttrs),
>>>             "Wrong types for attribute: " +
>>>
>>> Modified: llvm/trunk/lib/Linker/IRMover.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=885eda64-d4d40f42-885e9aff-86aae6564056-8c9bb9db8a71c26e&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FLinker%2FIRMover.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/Linker/IRMover.cpp (original)
>>> +++ llvm/trunk/lib/Linker/IRMover.cpp Thu May 30 11:48:23 2019
>>> @@ -489,6 +489,10 @@ class IRLinker {
>>>      void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src);
>>>      Error linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src);
>>> +  /// Replace all types in the source AttributeList with the
>>> +  /// corresponding destination type.
>>> +  AttributeList mapAttributeTypes(LLVMContext &C, AttributeList Attrs);
>>> +
>>>      /// Functions that take care of cloning a specific global value 
>>> type
>>>      /// into the destination module.
>>>      GlobalVariable *copyGlobalVariableProto(const GlobalVariable 
>>> *SGVar);
>>> @@ -628,6 +632,21 @@ GlobalVariable *IRLinker::copyGlobalVari
>>>      return NewDGV;
>>>    }
>>> +AttributeList IRLinker::mapAttributeTypes(LLVMContext &C, 
>>> AttributeList Attrs) {
>>> +  for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) {
>>> +    if (Attrs.hasAttribute(i, Attribute::ByVal)) {
>>> +      Type *Ty = Attrs.getAttribute(i, 
>>> Attribute::ByVal).getValueAsType();
>>> +      if (!Ty)
>>> +        continue;
>>> +
>>> +      Attrs = Attrs.removeAttribute(C, i, Attribute::ByVal);
>>> +      Attrs = Attrs.addAttribute(
>>> +          C, i, Attribute::getWithByValType(C, TypeMap.get(Ty)));
>>> +    }
>>> +  }
>>> +  return Attrs;
>>> +}
>>> +
>>>    /// Link the function in the source module into the destination 
>>> module if
>>>    /// needed, setting up mapping information.
>>>    Function *IRLinker::copyFunctionProto(const Function *SF) {
>>> @@ -637,6 +656,7 @@ Function *IRLinker::copyFunctionProto(co
>>>          Function::Create(TypeMap.get(SF->getFunctionType()),
>>>                           GlobalValue::ExternalLinkage, 
>>> SF->getName(), &DstM);
>>>      F->copyAttributesFrom(SF);
>>> +  F->setAttributes(mapAttributeTypes(F->getContext(), 
>>> F->getAttributes()));
>>>      return F;
>>>    }
>>>
>>> Modified: llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=59591798-05d3c2be-59595703-86aae6564056-c93b824e17a83570&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Flib%2FTransforms%2FUtils%2FValueMapper.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp Thu May 30 
>>> 11:48:23 2019
>>> @@ -913,6 +913,21 @@ void Mapper::remapInstruction(Instructio
>>>          Tys.push_back(TypeMapper->remapType(Ty));
>>>        CS.mutateFunctionType(FunctionType::get(
>>>            TypeMapper->remapType(I->getType()), Tys, FTy->isVarArg()));
>>> +
>>> +    LLVMContext &C = CS->getContext();
>>> +    AttributeList Attrs = CS.getAttributes();
>>> +    for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) {
>>> +      if (Attrs.hasAttribute(i, Attribute::ByVal)) {
>>> +        Type *Ty = Attrs.getAttribute(i, 
>>> Attribute::ByVal).getValueAsType();
>>> +        if (!Ty)
>>> +          continue;
>>> +
>>> +        Attrs = Attrs.removeAttribute(C, i, Attribute::ByVal);
>>> +        Attrs = Attrs.addAttribute(
>>> +            C, i, Attribute::getWithByValType(C, 
>>> TypeMapper->remapType(Ty)));
>>> +      }
>>> +    }
>>> +    CS.setAttributes(Attrs);
>>>        return;
>>>      }
>>>      if (auto *AI = dyn_cast<AllocaInst>(I))
>>>
>>> Added: llvm/trunk/test/Assembler/byval-type-attr.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=40eeed82-1c6438a4-40eead19-86aae6564056-cda8757957433cdd&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FAssembler%2Fbyval-type-attr.ll%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Assembler/byval-type-attr.ll (added)
>>> +++ llvm/trunk/test/Assembler/byval-type-attr.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -0,0 +1,31 @@
>>> +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
>>> +
>>> +; CHECK: define void @foo(i32* byval(i32) align 4)
>>> +define void @foo(i32* byval(i32) align 4) {
>>> +  ret void
>>> +}
>>> +
>>> +; CHECK: define void @bar({ i32*, i8 }* byval({ i32*, i8 }) align 4)
>>> +define void @bar({i32*, i8}* byval({i32*, i8}) align 4) {
>>> +  ret void
>>> +}
>>> +
>>> +define void @caller({ i32*, i8 }* %ptr) personality i8* bitcast (i32 
>>> (...)* @__gxx_personality_v0 to i8*) {
>>> +; CHECK: call void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)
>>> +; CHECK: invoke void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)
>>> +  call void @bar({i32*, i8}* byval %ptr)
>>> +  invoke void @bar({i32*, i8}* byval %ptr) to label %success unwind 
>>> label %fail
>>> +
>>> +success:
>>> +  ret void
>>> +
>>> +fail:
>>> +  landingpad { i8*, i32 } cleanup
>>> +  ret void
>>> +}
>>> +
>>> +; CHECK: declare void @baz([8 x i8]* byval([8 x i8]))
>>> +%named_type = type [8 x i8]
>>> +declare void @baz(%named_type* byval(%named_type))
>>> +
>>> +declare i32 @__gxx_personality_v0(...)
>>>
>>> Added: llvm/trunk/test/Assembler/invalid-byval-type1.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=4b95dd04-171f0822-4b959d9f-86aae6564056-e8a1feaf0a9f0d0a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FAssembler%2Finvalid-byval-type1.ll%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Assembler/invalid-byval-type1.ll (added)
>>> +++ llvm/trunk/test/Assembler/invalid-byval-type1.ll Thu May 30 
>>> 11:48:23 2019
>>> @@ -0,0 +1,4 @@
>>> +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
>>> +
>>> +; CHECK: Attribute 'byval' type does not match parameter!
>>> +declare void @foo(i32* byval(i8))
>>>
>>> Added: llvm/trunk/test/Assembler/invalid-byval-type2.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=e04c5f64-bcc68a42-e04c1fff-86aae6564056-c1225a1b96710580&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FAssembler%2Finvalid-byval-type2.ll%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Assembler/invalid-byval-type2.ll (added)
>>> +++ llvm/trunk/test/Assembler/invalid-byval-type2.ll Thu May 30 
>>> 11:48:23 2019
>>> @@ -0,0 +1,4 @@
>>> +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
>>> +
>>> +; CHECK: error: void type only allowed for function results
>>> +declare void @foo(i32* byval(void))
>>>
>>> Added: llvm/trunk/test/Assembler/invalid-byval-type3.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=56e048d4-0a6a9df2-56e0084f-86aae6564056-55d679135a7f7102&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FAssembler%2Finvalid-byval-type3.ll%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Assembler/invalid-byval-type3.ll (added)
>>> +++ llvm/trunk/test/Assembler/invalid-byval-type3.ll Thu May 30 
>>> 11:48:23 2019
>>> @@ -0,0 +1,4 @@
>>> +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
>>> +
>>> +; CHECK: Attributes 'byval' and 'inalloca' do not support unsized 
>>> types!
>>> +declare void @foo(void()* byval(void()))
>>>
>>> Added: llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc
>>> URL: 
>>> https://protect2.fireeye.com/url?k=f951a0a2-a5db7584-f951e039-86aae6564056-873727b011c76477&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2FInputs%2Fbyval-upgrade.bc%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> Binary file - no diff available.
>>>
>>> Propchange: llvm/trunk/test/Bitcode/Inputs/byval-upgrade.bc
>>> ------------------------------------------------------------------------------ 
>>>
>>>       svn:mime-type = application/octet-stream
>>>
>>> Modified: llvm/trunk/test/Bitcode/attributes-3.3.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=8f022b0f-d388fe29-8f026b94-86aae6564056-368605187761ac40&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fattributes-3.3.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/attributes-3.3.ll (original)
>>> +++ llvm/trunk/test/Bitcode/attributes-3.3.ll Thu May 30 11:48:23 2019
>>> @@ -48,7 +48,7 @@ define void @f7(i8* noalias)
>>>    }
>>>    define void @f8(i8* byval)
>>> -; CHECK: define void @f8(i8* byval)
>>> +; CHECK: define void @f8(i8* byval(i8))
>>>    {
>>>            ret void;
>>>    }
>>>
>>> Modified: llvm/trunk/test/Bitcode/attributes.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=43d5b9e0-1f5f6cc6-43d5f97b-86aae6564056-f078b53d24355cec&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fattributes.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/attributes.ll (original)
>>> +++ llvm/trunk/test/Bitcode/attributes.ll Thu May 30 11:48:23 2019
>>> @@ -45,7 +45,7 @@ define void @f7(i8* noalias)
>>>    }
>>>    define void @f8(i8* byval)
>>> -; CHECK: define void @f8(i8* byval)
>>> +; CHECK: define void @f8(i8* byval(i8))
>>>    {
>>>            ret void;
>>>    }
>>>
>>> Added: llvm/trunk/test/Bitcode/byval-upgrade.test
>>> URL: 
>>> https://protect2.fireeye.com/url?k=b01a4680-ec9093a6-b01a061b-86aae6564056-e81f110a5cc4c0d2&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fbyval-upgrade.test%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/byval-upgrade.test (added)
>>> +++ llvm/trunk/test/Bitcode/byval-upgrade.test Thu May 30 11:48:23 2019
>>> @@ -0,0 +1,7 @@
>>> +RUN: llvm-dis %p/Inputs/byval-upgrade.bc -o - | FileCheck %s
>>> +
>>> +Make sure we upgrade old-stile IntAttribute byval records to a fully 
>>> typed
>>> +version correctly.
>>> +
>>> +CHECK: call void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)
>>> +CHECK: invoke void @bar({ i32*, i8 }* byval({ i32*, i8 }) %ptr)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility-3.6.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=7c6a350c-20e0e02a-7c6a7597-86aae6564056-8faf5b41b6b30e43&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility-3.6.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility-3.6.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility-3.6.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -404,7 +404,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility-3.7.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=f634e842-aabe3d64-f634a8d9-86aae6564056-c194e084e9be497d&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility-3.7.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility-3.7.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility-3.7.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -410,7 +410,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility-3.8.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=80cf9578-dc45405e-80cfd5e3-86aae6564056-4e190a7df0d69d1e&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility-3.8.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility-3.8.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility-3.8.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -435,7 +435,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility-3.9.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=2ebadfbd-72300a9b-2eba9f26-86aae6564056-31c3483898ce070e&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility-3.9.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility-3.9.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility-3.9.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -504,7 +504,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility-4.0.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=c4fb0a29-9871df0f-c4fb4ab2-86aae6564056-4c8d82df98366c08&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility-4.0.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility-4.0.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility-4.0.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -504,7 +504,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility-5.0.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=3bcd9e65-67474b43-3bcddefe-86aae6564056-c4b7f7f8af5f6dd3&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility-5.0.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility-5.0.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility-5.0.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -508,7 +508,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility-6.0.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=cb6a4df4-97e098d2-cb6a0d6f-86aae6564056-908052f1f3804a58&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility-6.0.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility-6.0.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility-6.0.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -515,7 +515,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>>
>>> Modified: llvm/trunk/test/Bitcode/compatibility.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=b7298301-eba35627-b729c39a-86aae6564056-c348f06b60ed416a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2Fcompatibility.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/compatibility.ll (original)
>>> +++ llvm/trunk/test/Bitcode/compatibility.ll Thu May 30 11:48:23 2019
>>> @@ -529,7 +529,7 @@ declare void @f.param.signext(i8 signext
>>>    declare void @f.param.inreg(i8 inreg)
>>>    ; CHECK: declare void @f.param.inreg(i8 inreg)
>>>    declare void @f.param.byval({ i8, i8 }* byval)
>>> -; CHECK: declare void @f.param.byval({ i8, i8 }* byval)
>>> +; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
>>>    declare void @f.param.inalloca(i8* inalloca)
>>>    ; CHECK: declare void @f.param.inalloca(i8* inalloca)
>>>    declare void @f.param.sret(i8* sret)
>>> @@ -1735,6 +1735,15 @@ define i8** @constexpr() {
>>>    declare void @llvm.test.immarg.intrinsic(i32 immarg)
>>>    ; CHECK: declare void @llvm.test.immarg.intrinsic(i32 immarg)
>>> +; byval attribute with type
>>> +%named_type = type [8 x i8]
>>> +declare void @byval_type(i32* byval(i32) align 2)
>>> +declare void @byval_type2({ i8, i8* }* byval({ i8, i8* }))
>>> +declare void @byval_named_type(%named_type* byval(%named_type))
>>> +; CHECK: declare void @byval_type(i32* byval(i32) align 2)
>>> +; CHECK: declare void @byval_type2({ i8, i8* }* byval({ i8, i8* }))
>>> +; CHECK: declare void @byval_named_type([8 x i8]* byval([8 x i8]))
>>> +
>>>    ; CHECK: attributes #0 = { alignstack=4 }
>>>    ; CHECK: attributes #1 = { alignstack=8 }
>>>    ; CHECK: attributes #2 = { alwaysinline }
>>>
>>> Modified: llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=ad25bb7d-f1f1b3d4-ad25fbe6-865b3b1e120b-0f81f645fa641211&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FBitcode%2FhighLevelStructure.3.2.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll (original)
>>> +++ llvm/trunk/test/Bitcode/highLevelStructure.3.2.ll Thu May 30 
>>> 11:48:23 2019
>>> @@ -41,7 +41,7 @@ declare void @ParamAttr3(i8* sret)
>>>    declare void @ParamAttr4(i8 signext)
>>>    ; CHECK: declare void @ParamAttr5(i8* inreg)
>>>    declare void @ParamAttr5(i8* inreg)
>>> -; CHECK: declare void @ParamAttr6(i8* byval)
>>> +; CHECK: declare void @ParamAttr6(i8* byval(i8))
>>>    declare void @ParamAttr6(i8* byval)
>>>    ; CHECK: declare void @ParamAttr7(i8* noalias)
>>>    declare void @ParamAttr7(i8* noalias)
>>> @@ -51,7 +51,7 @@ declare void @ParamAttr8(i8* nocapture)
>>>    declare void @ParamAttr9(i8* nest noalias nocapture)
>>>    ; CHECK: declare void @ParamAttr10{{[(i8* sret noalias nocapture) 
>>> | (i8* noalias nocapture sret)]}}
>>>    declare void @ParamAttr10(i8* sret noalias nocapture)
>>> -;CHECK: declare void @ParamAttr11{{[(i8* byval noalias nocapture) | 
>>> (i8* noalias nocapture byval)]}}
>>> +;CHECK: declare void @ParamAttr11{{[(i8* byval(i8) noalias 
>>> nocapture) | (i8* noalias nocapture byval(i8))]}}
>>>    declare void @ParamAttr11(i8* byval noalias nocapture)
>>>    ;CHECK: declare void @ParamAttr12{{[(i8* inreg noalias nocapture) 
>>> | (i8* noalias nocapture inreg)]}}
>>>    declare void @ParamAttr12(i8* inreg noalias nocapture)
>>>
>>> Added: llvm/trunk/test/CodeGen/AArch64/byval-type.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=aa14732a-f6c07b83-aa1433b1-865b3b1e120b-8c5b95c42c95483e&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FCodeGen%2FAArch64%2Fbyval-type.ll%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/CodeGen/AArch64/byval-type.ll (added)
>>> +++ llvm/trunk/test/CodeGen/AArch64/byval-type.ll Thu May 30 11:48:23 
>>> 2019
>>> @@ -0,0 +1,37 @@
>>> +; RUN: llc -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s
>>> +
>>> +define i8 @byval_match(i8* byval(i8) align 1, i8* byval %ptr) {
>>> +; CHECK-LABEL: byval_match:
>>> +; CHECK: ldrb w0, [sp, #8]
>>> +  %res = load i8, i8* %ptr
>>> +  ret i8 %res
>>> +}
>>> +
>>> +define void @caller_match(i8* %p0, i8* %p1) {
>>> +; CHECK-LABEL: caller_match:
>>> +; CHECK: ldrb [[P1:w[0-9]+]], [x1]
>>> +; CHECK: strb [[P1]], [sp, #8]
>>> +; CHECK: ldrb [[P0:w[0-9]+]], [x0]
>>> +; CHECK: strb [[P0]], [sp]
>>> +; CHECK: bl byval_match
>>> +  call i8 @byval_match(i8* byval(i8) align 1 %p0, i8* byval %p1)
>>> +  ret void
>>> +}
>>> +
>>> +define i8 @byval_large([3 x i64]* byval([3 x i64]) align 8, i8* 
>>> byval %ptr) {
>>> +; CHECK-LABEL: byval_large:
>>> +; CHECK: ldrb w0, [sp, #24]
>>> +  %res = load i8, i8* %ptr
>>> +  ret i8 %res
>>> +}
>>> +
>>> +define void @caller_large([3 x i64]* %p0, i8* %p1) {
>>> +; CHECK-LABEL: caller_large:
>>> +; CHECK: ldr [[P0HI:x[0-9]+]], [x0, #16]
>>> +; CHECK: ldr [[P0LO:q[0-9]+]], [x0]
>>> +; CHECK: str [[P0HI]], [sp, #16]
>>> +; CHECK: str [[P0LO]], [sp]
>>> +; CHECK: bl byval_large
>>> +  call i8 @byval_large([3 x i64]* byval([3 x i64]) align 8 %p0, i8* 
>>> byval %p1)
>>> +  ret void
>>> +}
>>>
>>> Added: llvm/trunk/test/Linker/Inputs/byval-types-1.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=f514e744-a9c0efed-f514a7df-865b3b1e120b-c07dd599e5504ceb&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FLinker%2FInputs%2Fbyval-types-1.ll%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Linker/Inputs/byval-types-1.ll (added)
>>> +++ llvm/trunk/test/Linker/Inputs/byval-types-1.ll Thu May 30 
>>> 11:48:23 2019
>>> @@ -0,0 +1,8 @@
>>> +%struct = type {i32, i8}
>>> +
>>> +declare void @baz(%struct* byval(%struct))
>>> +
>>> +define void @foo(%struct* byval(%struct) %a) {
>>> +  call void @baz(%struct* byval(%struct) %a)
>>> +  ret void
>>> +}
>>>
>>> Added: llvm/trunk/test/Linker/byval-types.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=e0f1450a-bc254da3-e0f10591-865b3b1e120b-6ee662016850763c&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FLinker%2Fbyval-types.ll%3Frev%3D362128%26view%3Dauto 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Linker/byval-types.ll (added)
>>> +++ llvm/trunk/test/Linker/byval-types.ll Thu May 30 11:48:23 2019
>>> @@ -0,0 +1,17 @@
>>> +; RUN: llvm-link %s %p/Inputs/byval-types-1.ll -S | FileCheck %s
>>> +
>>> +%struct = type {i32, i8}
>>> +
>>> +declare void @foo(%struct* byval(%struct) %a)
>>> +
>>> +define void @bar() {
>>> +  %ptr = alloca %struct
>>> +; CHECK: call void @foo(%struct* byval(%struct) %ptr)
>>> +  call void @foo(%struct* byval(%struct) %ptr)
>>> +  ret void
>>> +}
>>> +
>>> +; CHECK: define void @foo(%struct* byval(%struct) %a)
>>> +; CHECK-NEXT:   call void @baz(%struct* byval(%struct) %a)
>>> +
>>> +; CHECK: declare void @baz(%struct* byval(%struct))
>>>
>>> Modified: llvm/trunk/test/Transforms/Inline/byval-tail-call.ll
>>> URL: 
>>> https://protect2.fireeye.com/url?k=42110dc4-1ec5056d-42114d5f-865b3b1e120b-9210ad011f28de9a&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Ftest%2FTransforms%2FInline%2Fbyval-tail-call.ll%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/test/Transforms/Inline/byval-tail-call.ll (original)
>>> +++ llvm/trunk/test/Transforms/Inline/byval-tail-call.ll Thu May 30 
>>> 11:48:23 2019
>>> @@ -56,7 +56,7 @@ define void @foobar(i32* %x) {
>>>    ; CHECK: %[[POS:.*]] = alloca i32
>>>    ; CHECK: %[[VAL:.*]] = load i32, i32* %x
>>>    ; CHECK: store i32 %[[VAL]], i32* %[[POS]]
>>> -; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]
>>> +; CHECK: tail call void @ext2(i32* nonnull byval %[[POS]]
>>>    ; CHECK: ret void
>>>      tail call void @bar2(i32* byval %x)
>>>      ret void
>>> @@ -67,7 +67,7 @@ define void @barfoo() {
>>>    ; CHECK: %[[POS:.*]] = alloca i32
>>>    ; CHECK: %[[VAL:.*]] = load i32, i32* %x
>>>    ; CHECK: store i32 %[[VAL]], i32* %[[POS]]
>>> -; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]
>>> +; CHECK: tail call void @ext2(i32* nonnull byval %[[POS]]
>>>    ; CHECK: ret void
>>>      %x = alloca i32
>>>      tail call void @bar2(i32* byval %x)
>>>
>>> Modified: llvm/trunk/unittests/IR/AttributesTest.cpp
>>> URL: 
>>> https://protect2.fireeye.com/url?k=1a35cf2f-46e1c786-1a358fb4-865b3b1e120b-a6d5ff92c1791b13&q=1&u=http%3A%2F%2Fllvm.org%2Fviewvc%2Fllvm-project%2Fllvm%2Ftrunk%2Funittests%2FIR%2FAttributesTest.cpp%3Frev%3D362128%26r1%3D362127%26r2%3D362128%26view%3Ddiff 
>>>
>>> ============================================================================== 
>>>
>>> --- llvm/trunk/unittests/IR/AttributesTest.cpp (original)
>>> +++ llvm/trunk/unittests/IR/AttributesTest.cpp Thu May 30 11:48:23 2019
>>> @@ -8,6 +8,7 @@
>>>    #include "llvm/IR/Attributes.h"
>>>    #include "llvm/IR/LLVMContext.h"
>>> +#include "llvm/IR/DerivedTypes.h"
>>>    #include "gtest/gtest.h"
>>>    using namespace llvm;
>>> @@ -40,6 +41,10 @@ TEST(Attributes, Ordering) {
>>>      EXPECT_TRUE(Align4 < Deref5);
>>>      EXPECT_TRUE(Align5 < Deref4);
>>> +  Attribute ByVal = Attribute::get(C, Attribute::ByVal, 
>>> Type::getInt32Ty(C));
>>> +  EXPECT_FALSE(ByVal < Attribute::get(C, Attribute::ZExt));
>>> +  EXPECT_TRUE(ByVal < Align4);
>>> +
>>>      AttributeList ASs[] = {AttributeList::get(C, 2, Attribute::ZExt),
>>>                             AttributeList::get(C, 1, Attribute::SExt)};
>>> @@ -166,4 +171,19 @@ TEST(Attributes, OverflowGet) {
>>>      EXPECT_EQ(2U, AL.getNumAttrSets());
>>>    }
>>> +TEST(Attributes, StringRepresentation) {
>>> +  LLVMContext C;
>>> +  StructType *Ty = StructType::create(Type::getInt32Ty(C), "mystruct");
>>> +
>>> +  // Insufficiently careful printing can result in byval(%mystruct = 
>>> { i32 })
>>> +  Attribute A = Attribute::getWithByValType(C, Ty);
>>> +  EXPECT_EQ(A.getAsString(), "byval(%mystruct)");
>>> +
>>> +  A = Attribute::getWithByValType(C, nullptr);
>>> +  EXPECT_EQ(A.getAsString(), "byval");
>>> +
>>> +  A = Attribute::getWithByValType(C, Type::getInt32Ty(C));
>>> +  EXPECT_EQ(A.getAsString(), "byval(i32)");
>>> +}
>>> +
>>>    } // end anonymous namespace
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at lists.llvm.org
>>> https://protect2.fireeye.com/url?k=fd44213e-a1902997-fd4461a5-865b3b1e120b-56ba281e6150cc0c&q=1&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-commits 
>>>
>>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://protect2.fireeye.com/url?k=2eca32f6-7240e7d0-2eca726d-86aae6564056-fbc34a934d3c8281&q=1&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-commits 
>>
>>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: foo.c
Type: text/x-csrc
Size: 108 bytes
Desc: foo.c
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190605/cdff5805/attachment-0001.c>


More information about the llvm-commits mailing list