Skip to content

Commit 88dddb8

Browse files
author
Daniel Neilson
committedJan 17, 2018
[Attributes] Fix crash when attempting to remove alignment from an attribute list/set
Summary: Discovered while working on a patch to move alignment in @llvm.memcpy/move/set from an arg into parameter attributes. The current implementations of AttributeSet::removeAttribute() and AttributeList::removeAttribute crash when attempting to remove the alignment attribute. Currently, these implementations add the to-be-removed attributes to an AttrBuilder and then remove the builder from the list/set. Alignment is special in that it must be added to a builder with an integer value for the alignment; attempts to add alignment to a builder without a value is an error. This change fixes the removeAttribute implementations for AttributeSet and AttributeList to make them able to remove the alignment, and other similar, attributes. Reviewers: rnk, chandlerc, pete, javed.absar, reames Reviewed By: rnk Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D41951 llvm-svn: 322735
1 parent 8c87a2e commit 88dddb8

File tree

2 files changed

+93
-24
lines changed

2 files changed

+93
-24
lines changed
 

‎llvm/lib/IR/Attributes.cpp

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -543,26 +543,21 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C,
543543
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
544544
Attribute::AttrKind Kind) const {
545545
if (!hasAttribute(Kind)) return *this;
546-
AttrBuilder B;
547-
B.addAttribute(Kind);
548-
return removeAttributes(C, B);
546+
AttrBuilder B(*this);
547+
B.removeAttribute(Kind);
548+
return get(C, B);
549549
}
550550

551551
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
552552
StringRef Kind) const {
553553
if (!hasAttribute(Kind)) return *this;
554-
AttrBuilder B;
555-
B.addAttribute(Kind);
556-
return removeAttributes(C, B);
554+
AttrBuilder B(*this);
555+
B.removeAttribute(Kind);
556+
return get(C, B);
557557
}
558558

559559
AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
560560
const AttrBuilder &Attrs) const {
561-
562-
// FIXME it is not obvious how this should work for alignment.
563-
// For now, say we can't pass in alignment, which no current use does.
564-
assert(!Attrs.hasAlignmentAttr() && "Attempt to change alignment!");
565-
566561
AttrBuilder B(*this);
567562
B.remove(Attrs);
568563
return get(C, B);
@@ -1098,17 +1093,27 @@ AttributeList AttributeList::addParamAttribute(LLVMContext &C,
10981093
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
10991094
Attribute::AttrKind Kind) const {
11001095
if (!hasAttribute(Index, Kind)) return *this;
1101-
AttrBuilder B;
1102-
B.addAttribute(Kind);
1103-
return removeAttributes(C, Index, B);
1096+
1097+
Index = attrIdxToArrayIdx(Index);
1098+
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1099+
assert(Index < AttrSets.size());
1100+
1101+
AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1102+
1103+
return getImpl(C, AttrSets);
11041104
}
11051105

11061106
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
11071107
StringRef Kind) const {
11081108
if (!hasAttribute(Index, Kind)) return *this;
1109-
AttrBuilder B;
1110-
B.addAttribute(Kind);
1111-
return removeAttributes(C, Index, B);
1109+
1110+
Index = attrIdxToArrayIdx(Index);
1111+
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
1112+
assert(Index < AttrSets.size());
1113+
1114+
AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
1115+
1116+
return getImpl(C, AttrSets);
11121117
}
11131118

11141119
AttributeList
@@ -1117,18 +1122,12 @@ AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
11171122
if (!pImpl)
11181123
return AttributeList();
11191124

1120-
// FIXME it is not obvious how this should work for alignment.
1121-
// For now, say we can't pass in alignment, which no current use does.
1122-
assert(!AttrsToRemove.hasAlignmentAttr() && "Attempt to change alignment!");
1123-
11241125
Index = attrIdxToArrayIdx(Index);
11251126
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
11261127
if (Index >= AttrSets.size())
11271128
AttrSets.resize(Index + 1);
11281129

1129-
AttrBuilder B(AttrSets[Index]);
1130-
B.remove(AttrsToRemove);
1131-
AttrSets[Index] = AttributeSet::get(C, B);
1130+
AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove);
11321131

11331132
return getImpl(C, AttrSets);
11341133
}

‎llvm/unittests/IR/AttributesTest.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,76 @@ TEST(Attributes, AddAttributes) {
6363
EXPECT_TRUE(AL.hasFnAttribute(Attribute::NoReturn));
6464
}
6565

66+
TEST(Attributes, RemoveAlign) {
67+
LLVMContext C;
68+
69+
Attribute AlignAttr = Attribute::getWithAlignment(C, 8);
70+
Attribute StackAlignAttr = Attribute::getWithStackAlignment(C, 32);
71+
AttrBuilder B_align_readonly;
72+
B_align_readonly.addAttribute(AlignAttr);
73+
B_align_readonly.addAttribute(Attribute::ReadOnly);
74+
AttrBuilder B_align;
75+
B_align.addAttribute(AlignAttr);
76+
AttrBuilder B_stackalign_optnone;
77+
B_stackalign_optnone.addAttribute(StackAlignAttr);
78+
B_stackalign_optnone.addAttribute(Attribute::OptimizeNone);
79+
AttrBuilder B_stackalign;
80+
B_stackalign.addAttribute(StackAlignAttr);
81+
82+
AttributeSet AS = AttributeSet::get(C, B_align_readonly);
83+
EXPECT_TRUE(AS.getAlignment() == 8);
84+
EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly));
85+
AS = AS.removeAttribute(C, Attribute::Alignment);
86+
EXPECT_FALSE(AS.hasAttribute(Attribute::Alignment));
87+
EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly));
88+
AS = AttributeSet::get(C, B_align_readonly);
89+
AS = AS.removeAttributes(C, B_align);
90+
EXPECT_TRUE(AS.getAlignment() == 0);
91+
EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly));
92+
93+
AttributeList AL;
94+
AL = AL.addParamAttributes(C, 0, B_align_readonly);
95+
AL = AL.addAttributes(C, 0, B_stackalign_optnone);
96+
EXPECT_TRUE(AL.hasAttributes(0));
97+
EXPECT_TRUE(AL.hasAttribute(0, Attribute::StackAlignment));
98+
EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone));
99+
EXPECT_TRUE(AL.getStackAlignment(0) == 32);
100+
EXPECT_TRUE(AL.hasParamAttrs(0));
101+
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::Alignment));
102+
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly));
103+
EXPECT_TRUE(AL.getParamAlignment(0) == 8);
104+
105+
AL = AL.removeParamAttribute(C, 0, Attribute::Alignment);
106+
EXPECT_FALSE(AL.hasParamAttr(0, Attribute::Alignment));
107+
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly));
108+
EXPECT_TRUE(AL.hasAttribute(0, Attribute::StackAlignment));
109+
EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone));
110+
EXPECT_TRUE(AL.getStackAlignment(0) == 32);
111+
112+
AL = AL.removeAttribute(C, 0, Attribute::StackAlignment);
113+
EXPECT_FALSE(AL.hasParamAttr(0, Attribute::Alignment));
114+
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly));
115+
EXPECT_FALSE(AL.hasAttribute(0, Attribute::StackAlignment));
116+
EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone));
117+
118+
AttributeList AL2;
119+
AL2 = AL2.addParamAttributes(C, 0, B_align_readonly);
120+
AL2 = AL2.addAttributes(C, 0, B_stackalign_optnone);
121+
122+
AL2 = AL2.removeParamAttributes(C, 0, B_align);
123+
EXPECT_FALSE(AL2.hasParamAttr(0, Attribute::Alignment));
124+
EXPECT_TRUE(AL2.hasParamAttr(0, Attribute::ReadOnly));
125+
EXPECT_TRUE(AL2.hasAttribute(0, Attribute::StackAlignment));
126+
EXPECT_TRUE(AL2.hasAttribute(0, Attribute::OptimizeNone));
127+
EXPECT_TRUE(AL2.getStackAlignment(0) == 32);
128+
129+
AL2 = AL2.removeAttributes(C, 0, B_stackalign);
130+
EXPECT_FALSE(AL2.hasParamAttr(0, Attribute::Alignment));
131+
EXPECT_TRUE(AL2.hasParamAttr(0, Attribute::ReadOnly));
132+
EXPECT_FALSE(AL2.hasAttribute(0, Attribute::StackAlignment));
133+
EXPECT_TRUE(AL2.hasAttribute(0, Attribute::OptimizeNone));
134+
}
135+
66136
TEST(Attributes, AddMatchingAlignAttr) {
67137
LLVMContext C;
68138
AttributeList AL;

0 commit comments

Comments
 (0)
Please sign in to comment.