mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
42e839cbcd
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. llvm-svn: 362128
190 lines
7.1 KiB
C++
190 lines
7.1 KiB
C++
//===- llvm/unittest/IR/AttributesTest.cpp - Attributes unit tests --------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/Attributes.h"
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "gtest/gtest.h"
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
TEST(Attributes, Uniquing) {
|
|
LLVMContext C;
|
|
|
|
Attribute AttrA = Attribute::get(C, Attribute::AlwaysInline);
|
|
Attribute AttrB = Attribute::get(C, Attribute::AlwaysInline);
|
|
EXPECT_EQ(AttrA, AttrB);
|
|
|
|
AttributeList ASs[] = {AttributeList::get(C, 1, Attribute::ZExt),
|
|
AttributeList::get(C, 2, Attribute::SExt)};
|
|
|
|
AttributeList SetA = AttributeList::get(C, ASs);
|
|
AttributeList SetB = AttributeList::get(C, ASs);
|
|
EXPECT_EQ(SetA, SetB);
|
|
}
|
|
|
|
TEST(Attributes, Ordering) {
|
|
LLVMContext C;
|
|
|
|
Attribute Align4 = Attribute::get(C, Attribute::Alignment, 4);
|
|
Attribute Align5 = Attribute::get(C, Attribute::Alignment, 5);
|
|
Attribute Deref4 = Attribute::get(C, Attribute::Dereferenceable, 4);
|
|
Attribute Deref5 = Attribute::get(C, Attribute::Dereferenceable, 5);
|
|
EXPECT_TRUE(Align4 < Align5);
|
|
EXPECT_TRUE(Align4 < Deref4);
|
|
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)};
|
|
|
|
AttributeList SetA = AttributeList::get(C, ASs);
|
|
AttributeList SetB = SetA.removeAttributes(C, 1, ASs[1].getAttributes(1));
|
|
EXPECT_NE(SetA, SetB);
|
|
}
|
|
|
|
TEST(Attributes, AddAttributes) {
|
|
LLVMContext C;
|
|
AttributeList AL;
|
|
AttrBuilder B;
|
|
B.addAttribute(Attribute::NoReturn);
|
|
AL = AL.addAttributes(C, AttributeList::FunctionIndex, AttributeSet::get(C, B));
|
|
EXPECT_TRUE(AL.hasFnAttribute(Attribute::NoReturn));
|
|
B.clear();
|
|
B.addAttribute(Attribute::SExt);
|
|
AL = AL.addAttributes(C, AttributeList::ReturnIndex, B);
|
|
EXPECT_TRUE(AL.hasAttribute(AttributeList::ReturnIndex, Attribute::SExt));
|
|
EXPECT_TRUE(AL.hasFnAttribute(Attribute::NoReturn));
|
|
}
|
|
|
|
TEST(Attributes, RemoveAlign) {
|
|
LLVMContext C;
|
|
|
|
Attribute AlignAttr = Attribute::getWithAlignment(C, 8);
|
|
Attribute StackAlignAttr = Attribute::getWithStackAlignment(C, 32);
|
|
AttrBuilder B_align_readonly;
|
|
B_align_readonly.addAttribute(AlignAttr);
|
|
B_align_readonly.addAttribute(Attribute::ReadOnly);
|
|
AttrBuilder B_align;
|
|
B_align.addAttribute(AlignAttr);
|
|
AttrBuilder B_stackalign_optnone;
|
|
B_stackalign_optnone.addAttribute(StackAlignAttr);
|
|
B_stackalign_optnone.addAttribute(Attribute::OptimizeNone);
|
|
AttrBuilder B_stackalign;
|
|
B_stackalign.addAttribute(StackAlignAttr);
|
|
|
|
AttributeSet AS = AttributeSet::get(C, B_align_readonly);
|
|
EXPECT_TRUE(AS.getAlignment() == 8);
|
|
EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly));
|
|
AS = AS.removeAttribute(C, Attribute::Alignment);
|
|
EXPECT_FALSE(AS.hasAttribute(Attribute::Alignment));
|
|
EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly));
|
|
AS = AttributeSet::get(C, B_align_readonly);
|
|
AS = AS.removeAttributes(C, B_align);
|
|
EXPECT_TRUE(AS.getAlignment() == 0);
|
|
EXPECT_TRUE(AS.hasAttribute(Attribute::ReadOnly));
|
|
|
|
AttributeList AL;
|
|
AL = AL.addParamAttributes(C, 0, B_align_readonly);
|
|
AL = AL.addAttributes(C, 0, B_stackalign_optnone);
|
|
EXPECT_TRUE(AL.hasAttributes(0));
|
|
EXPECT_TRUE(AL.hasAttribute(0, Attribute::StackAlignment));
|
|
EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone));
|
|
EXPECT_TRUE(AL.getStackAlignment(0) == 32);
|
|
EXPECT_TRUE(AL.hasParamAttrs(0));
|
|
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::Alignment));
|
|
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly));
|
|
EXPECT_TRUE(AL.getParamAlignment(0) == 8);
|
|
|
|
AL = AL.removeParamAttribute(C, 0, Attribute::Alignment);
|
|
EXPECT_FALSE(AL.hasParamAttr(0, Attribute::Alignment));
|
|
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly));
|
|
EXPECT_TRUE(AL.hasAttribute(0, Attribute::StackAlignment));
|
|
EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone));
|
|
EXPECT_TRUE(AL.getStackAlignment(0) == 32);
|
|
|
|
AL = AL.removeAttribute(C, 0, Attribute::StackAlignment);
|
|
EXPECT_FALSE(AL.hasParamAttr(0, Attribute::Alignment));
|
|
EXPECT_TRUE(AL.hasParamAttr(0, Attribute::ReadOnly));
|
|
EXPECT_FALSE(AL.hasAttribute(0, Attribute::StackAlignment));
|
|
EXPECT_TRUE(AL.hasAttribute(0, Attribute::OptimizeNone));
|
|
|
|
AttributeList AL2;
|
|
AL2 = AL2.addParamAttributes(C, 0, B_align_readonly);
|
|
AL2 = AL2.addAttributes(C, 0, B_stackalign_optnone);
|
|
|
|
AL2 = AL2.removeParamAttributes(C, 0, B_align);
|
|
EXPECT_FALSE(AL2.hasParamAttr(0, Attribute::Alignment));
|
|
EXPECT_TRUE(AL2.hasParamAttr(0, Attribute::ReadOnly));
|
|
EXPECT_TRUE(AL2.hasAttribute(0, Attribute::StackAlignment));
|
|
EXPECT_TRUE(AL2.hasAttribute(0, Attribute::OptimizeNone));
|
|
EXPECT_TRUE(AL2.getStackAlignment(0) == 32);
|
|
|
|
AL2 = AL2.removeAttributes(C, 0, B_stackalign);
|
|
EXPECT_FALSE(AL2.hasParamAttr(0, Attribute::Alignment));
|
|
EXPECT_TRUE(AL2.hasParamAttr(0, Attribute::ReadOnly));
|
|
EXPECT_FALSE(AL2.hasAttribute(0, Attribute::StackAlignment));
|
|
EXPECT_TRUE(AL2.hasAttribute(0, Attribute::OptimizeNone));
|
|
}
|
|
|
|
TEST(Attributes, AddMatchingAlignAttr) {
|
|
LLVMContext C;
|
|
AttributeList AL;
|
|
AL = AL.addAttribute(C, AttributeList::FirstArgIndex,
|
|
Attribute::getWithAlignment(C, 8));
|
|
AL = AL.addAttribute(C, AttributeList::FirstArgIndex + 1,
|
|
Attribute::getWithAlignment(C, 32));
|
|
EXPECT_EQ(8U, AL.getParamAlignment(0));
|
|
EXPECT_EQ(32U, AL.getParamAlignment(1));
|
|
|
|
AttrBuilder B;
|
|
B.addAttribute(Attribute::NonNull);
|
|
B.addAlignmentAttr(8);
|
|
AL = AL.addAttributes(C, AttributeList::FirstArgIndex, B);
|
|
EXPECT_EQ(8U, AL.getParamAlignment(0));
|
|
EXPECT_EQ(32U, AL.getParamAlignment(1));
|
|
EXPECT_TRUE(AL.hasParamAttribute(0, Attribute::NonNull));
|
|
}
|
|
|
|
TEST(Attributes, EmptyGet) {
|
|
LLVMContext C;
|
|
AttributeList EmptyLists[] = {AttributeList(), AttributeList()};
|
|
AttributeList AL = AttributeList::get(C, EmptyLists);
|
|
EXPECT_TRUE(AL.isEmpty());
|
|
}
|
|
|
|
TEST(Attributes, OverflowGet) {
|
|
LLVMContext C;
|
|
std::pair<unsigned, Attribute> Attrs[] = { { AttributeList::ReturnIndex, Attribute::get(C, Attribute::SExt) },
|
|
{ AttributeList::FunctionIndex, Attribute::get(C, Attribute::ReadOnly) } };
|
|
AttributeList AL = AttributeList::get(C, Attrs);
|
|
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
|