1 //===- llvm/unittest/IR/AttributesTest.cpp - Attributes unit tests --------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/IR/Attributes.h" 10 #include "llvm/IR/LLVMContext.h" 11 #include "llvm/IR/DerivedTypes.h" 12 #include "gtest/gtest.h" 13 using namespace llvm; 14 15 namespace { 16 17 TEST(Attributes, Uniquing) { 18 LLVMContext C; 19 20 Attribute AttrA = Attribute::get(C, Attribute::AlwaysInline); 21 Attribute AttrB = Attribute::get(C, Attribute::AlwaysInline); 22 EXPECT_EQ(AttrA, AttrB); 23 24 AttributeList ASs[] = {AttributeList::get(C, 1, Attribute::ZExt), 25 AttributeList::get(C, 2, Attribute::SExt)}; 26 27 AttributeList SetA = AttributeList::get(C, ASs); 28 AttributeList SetB = AttributeList::get(C, ASs); 29 EXPECT_EQ(SetA, SetB); 30 } 31 32 TEST(Attributes, Ordering) { 33 LLVMContext C; 34 35 Attribute Align4 = Attribute::get(C, Attribute::Alignment, 4); 36 Attribute Align5 = Attribute::get(C, Attribute::Alignment, 5); 37 Attribute Deref4 = Attribute::get(C, Attribute::Dereferenceable, 4); 38 Attribute Deref5 = Attribute::get(C, Attribute::Dereferenceable, 5); 39 EXPECT_TRUE(Align4 < Align5); 40 EXPECT_TRUE(Align4 < Deref4); 41 EXPECT_TRUE(Align4 < Deref5); 42 EXPECT_TRUE(Align5 < Deref4); 43 44 Attribute ByVal = Attribute::get(C, Attribute::ByVal, Type::getInt32Ty(C)); 45 EXPECT_FALSE(ByVal < Attribute::get(C, Attribute::ZExt)); 46 EXPECT_TRUE(ByVal < Align4); 47 48 AttributeList ASs[] = {AttributeList::get(C, 2, Attribute::ZExt), 49 AttributeList::get(C, 1, Attribute::SExt)}; 50 51 AttributeList SetA = AttributeList::get(C, ASs); 52 AttributeList SetB = SetA.removeAttributes(C, 1, ASs[1].getAttributes(1)); 53 EXPECT_NE(SetA, SetB); 54 } 55 56 TEST(Attributes, AddAttributes) { 57 LLVMContext C; 58 AttributeList AL; 59 AttrBuilder B; 60 B.addAttribute(Attribute::NoReturn); 61 AL = AL.addAttributes(C, AttributeList::FunctionIndex, AttributeSet::get(C, B)); 62 EXPECT_TRUE(AL.hasFnAttribute(Attribute::NoReturn)); 63 B.clear(); 64 B.addAttribute(Attribute::SExt); 65 AL = AL.addAttributes(C, AttributeList::ReturnIndex, B); 66 EXPECT_TRUE(AL.hasAttribute(AttributeList::ReturnIndex, Attribute::SExt)); 67 EXPECT_TRUE(AL.hasFnAttribute(Attribute::NoReturn)); 68 } 69 70 TEST(Attributes, RemoveAlign) { 71 LLVMContext C; 72 73 Attribute AlignAttr = Attribute::getWithAlignment(C, Align(8)); 74 Attribute StackAlignAttr = Attribute::getWithStackAlignment(C, Align(32)); 75 AttrBuilder B_align_readonly; 76 B_align_readonly.addAttribute(AlignAttr); 77 B_align_readonly.addAttribute(Attribute::ReadOnly); 78 AttrBuilder B_align; 79 B_align.addAttribute(AlignAttr); 80 AttrBuilder B_stackalign_optnone; 81 B_stackalign_optnone.addAttribute(StackAlignAttr); 82 B_stackalign_optnone.addAttribute(Attribute::OptimizeNone); 83 AttrBuilder B_stackalign; 84 B_stackalign.addAttribute(StackAlignAttr); 85 86 AttributeSet AS = AttributeSet::get(C, B_align_readonly); 87 EXPECT_TRUE(AS.getAlignment() == 8); 88 EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly)); 89 AS = AS.removeAttribute(C, Attribute::Alignment); 90 EXPECT_FALSE(AS.hasAttribute(Attribute::Alignment)); 91 EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly)); 92 AS = AttributeSet::get(C, B_align_readonly); 93 AS = AS.removeAttributes(C, B_align); 94 EXPECT_TRUE(AS.getAlignment() == 0); 95 EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly)); 96 97 AttributeList AL; 98 AL = AL.addParamAttributes(C, 0, B_align_readonly); 99 AL = AL.addAttributes(C, 0, B_stackalign_optnone); 100 EXPECT_TRUE(AL.hasAttributes(0)); 101 EXPECT_TRUE(AL.hasAttribute(0, Attribute::StackAlignment)); 102 EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone)); 103 EXPECT_TRUE(AL.getStackAlignment(0) == 32); 104 EXPECT_TRUE(AL.hasParamAttrs(0)); 105 EXPECT_TRUE(AL.hasParamAttr(0, Attribute::Alignment)); 106 EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly)); 107 EXPECT_TRUE(AL.getParamAlignment(0) == 8); 108 109 AL = AL.removeParamAttribute(C, 0, Attribute::Alignment); 110 EXPECT_FALSE(AL.hasParamAttr(0, Attribute::Alignment)); 111 EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly)); 112 EXPECT_TRUE(AL.hasAttribute(0, Attribute::StackAlignment)); 113 EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone)); 114 EXPECT_TRUE(AL.getStackAlignment(0) == 32); 115 116 AL = AL.removeAttribute(C, 0, Attribute::StackAlignment); 117 EXPECT_FALSE(AL.hasParamAttr(0, Attribute::Alignment)); 118 EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly)); 119 EXPECT_FALSE(AL.hasAttribute(0, Attribute::StackAlignment)); 120 EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone)); 121 122 AttributeList AL2; 123 AL2 = AL2.addParamAttributes(C, 0, B_align_readonly); 124 AL2 = AL2.addAttributes(C, 0, B_stackalign_optnone); 125 126 AL2 = AL2.removeParamAttributes(C, 0, B_align); 127 EXPECT_FALSE(AL2.hasParamAttr(0, Attribute::Alignment)); 128 EXPECT_TRUE(AL2.hasParamAttr(0, Attribute::ReadOnly)); 129 EXPECT_TRUE(AL2.hasAttribute(0, Attribute::StackAlignment)); 130 EXPECT_TRUE(AL2.hasAttribute(0, Attribute::OptimizeNone)); 131 EXPECT_TRUE(AL2.getStackAlignment(0) == 32); 132 133 AL2 = AL2.removeAttributes(C, 0, B_stackalign); 134 EXPECT_FALSE(AL2.hasParamAttr(0, Attribute::Alignment)); 135 EXPECT_TRUE(AL2.hasParamAttr(0, Attribute::ReadOnly)); 136 EXPECT_FALSE(AL2.hasAttribute(0, Attribute::StackAlignment)); 137 EXPECT_TRUE(AL2.hasAttribute(0, Attribute::OptimizeNone)); 138 } 139 140 TEST(Attributes, AddMatchingAlignAttr) { 141 LLVMContext C; 142 AttributeList AL; 143 AL = AL.addAttribute(C, AttributeList::FirstArgIndex, 144 Attribute::getWithAlignment(C, Align(8))); 145 AL = AL.addAttribute(C, AttributeList::FirstArgIndex + 1, 146 Attribute::getWithAlignment(C, Align(32))); 147 EXPECT_EQ(8U, AL.getParamAlignment(0)); 148 EXPECT_EQ(32U, AL.getParamAlignment(1)); 149 150 AttrBuilder B; 151 B.addAttribute(Attribute::NonNull); 152 B.addAlignmentAttr(8); 153 AL = AL.addAttributes(C, AttributeList::FirstArgIndex, B); 154 EXPECT_EQ(8U, AL.getParamAlignment(0)); 155 EXPECT_EQ(32U, AL.getParamAlignment(1)); 156 EXPECT_TRUE(AL.hasParamAttribute(0, Attribute::NonNull)); 157 } 158 159 TEST(Attributes, EmptyGet) { 160 LLVMContext C; 161 AttributeList EmptyLists[] = {AttributeList(), AttributeList()}; 162 AttributeList AL = AttributeList::get(C, EmptyLists); 163 EXPECT_TRUE(AL.isEmpty()); 164 } 165 166 TEST(Attributes, OverflowGet) { 167 LLVMContext C; 168 std::pair<unsigned, Attribute> Attrs[] = { { AttributeList::ReturnIndex, Attribute::get(C, Attribute::SExt) }, 169 { AttributeList::FunctionIndex, Attribute::get(C, Attribute::ReadOnly) } }; 170 AttributeList AL = AttributeList::get(C, Attrs); 171 EXPECT_EQ(2U, AL.getNumAttrSets()); 172 } 173 174 TEST(Attributes, StringRepresentation) { 175 LLVMContext C; 176 StructType *Ty = StructType::create(Type::getInt32Ty(C), "mystruct"); 177 178 // Insufficiently careful printing can result in byval(%mystruct = { i32 }) 179 Attribute A = Attribute::getWithByValType(C, Ty); 180 EXPECT_EQ(A.getAsString(), "byval(%mystruct)"); 181 182 A = Attribute::getWithByValType(C, nullptr); 183 EXPECT_EQ(A.getAsString(), "byval"); 184 185 A = Attribute::getWithByValType(C, Type::getInt32Ty(C)); 186 EXPECT_EQ(A.getAsString(), "byval(i32)"); 187 } 188 189 } // end anonymous namespace 190