diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index cda5fd0a38123..acf0e4afef27d 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2399,6 +2399,8 @@ class AssemblyWriter { void writeAllMDNodes(); void writeMDNode(unsigned Slot, const MDNode *Node); + void writeAttribute(const Attribute &Attr, bool InAttrGroup = false); + void writeAttributeSet(const AttributeSet &AttrSet, bool InAttrGroup = false); void writeAllAttributeGroups(); void printTypeIdentities(); @@ -2531,8 +2533,10 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, // Print the type TypePrinter.print(Operand->getType(), Out); // Print parameter attributes list - if (Attrs.hasAttributes()) - Out << ' ' << Attrs.getAsString(); + if (Attrs.hasAttributes()) { + Out << ' '; + writeAttributeSet(Attrs); + } Out << ' '; // Print the operand WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule); @@ -3462,8 +3466,10 @@ void AssemblyWriter::printFunction(const Function *F) { TypePrinter.print(FT->getParamType(I), Out); AttributeSet ArgAttrs = Attrs.getParamAttributes(I); - if (ArgAttrs.hasAttributes()) - Out << ' ' << ArgAttrs.getAsString(); + if (ArgAttrs.hasAttributes()) { + Out << ' '; + writeAttributeSet(ArgAttrs); + } } } else { // The arguments are meaningful here, print them in detail. @@ -3549,8 +3555,10 @@ void AssemblyWriter::printArgument(const Argument *Arg, AttributeSet Attrs) { TypePrinter.print(Arg->getType(), Out); // Output parameter attributes list - if (Attrs.hasAttributes()) - Out << ' ' << Attrs.getAsString(); + if (Attrs.hasAttributes()) { + Out << ' '; + writeAttributeSet(Attrs); + } // Output name, if available... if (Arg->hasName()) { @@ -4126,6 +4134,33 @@ void AssemblyWriter::printMDNodeBody(const MDNode *Node) { WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule); } +void AssemblyWriter::writeAttribute(const Attribute &Attr, bool InAttrGroup) { + if (!Attr.isTypeAttribute()) { + Out << Attr.getAsString(InAttrGroup); + return; + } + + assert(Attr.hasAttribute(Attribute::ByVal) && "unexpected type attr"); + + Out << "byval"; + if (Type *Ty = Attr.getValueAsType()) { + Out << '('; + TypePrinter.print(Ty, Out); + Out << ')'; + } +} + +void AssemblyWriter::writeAttributeSet(const AttributeSet &AttrSet, + bool InAttrGroup) { + bool FirstAttr = true; + for (const auto &Attr : AttrSet) { + if (!FirstAttr) + Out << ' '; + writeAttribute(Attr, InAttrGroup); + FirstAttr = false; + } +} + void AssemblyWriter::writeAllAttributeGroups() { std::vector> asVec; asVec.resize(Machine.as_size()); diff --git a/llvm/test/Assembler/byval-type-attr.ll b/llvm/test/Assembler/byval-type-attr.ll index c868885d2cc54..dd195a39651c0 100644 --- a/llvm/test/Assembler/byval-type-attr.ll +++ b/llvm/test/Assembler/byval-type-attr.ll @@ -29,3 +29,15 @@ fail: declare void @baz(%named_type* byval(%named_type)) declare i32 @__gxx_personality_v0(...) + +%0 = type opaque + +; CHECK: define void @anon({ %0* }* byval({ %0* }) %arg) +; CHECK: call void @anon_callee({ %0* }* byval({ %0* }) %arg) +define void @anon({ %0* }* byval({ %0* }) %arg) { + call void @anon_callee({ %0* }* byval({ %0* }) %arg) + ret void +} + +; CHECK: declare void @anon_callee({ %0* }* byval({ %0* })) +declare void @anon_callee({ %0* }* byval({ %0* }))