//===- FunctionTest.cpp - Function 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/Function.h" #include "llvm/IR/Module.h" #include "gtest/gtest.h" using namespace llvm; namespace { TEST(FunctionTest, hasLazyArguments) { LLVMContext C; Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)}; FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false); // Functions start out with lazy arguments. std::unique_ptr F( Function::Create(FTy, GlobalValue::ExternalLinkage, "F")); EXPECT_TRUE(F->hasLazyArguments()); // Checking for empty or size shouldn't force arguments to be instantiated. EXPECT_FALSE(F->arg_empty()); EXPECT_TRUE(F->hasLazyArguments()); EXPECT_EQ(2u, F->arg_size()); EXPECT_TRUE(F->hasLazyArguments()); // The argument list should be populated at first access. (void)F->arg_begin(); EXPECT_FALSE(F->hasLazyArguments()); // Checking that getArg gets the arguments from F1 in the correct order. unsigned i = 0; for (Argument &A : F->args()) { EXPECT_EQ(&A, F->getArg(i)); ++i; } EXPECT_FALSE(F->hasLazyArguments()); } TEST(FunctionTest, stealArgumentListFrom) { LLVMContext C; Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)}; FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false); std::unique_ptr F1( Function::Create(FTy, GlobalValue::ExternalLinkage, "F1")); std::unique_ptr F2( Function::Create(FTy, GlobalValue::ExternalLinkage, "F1")); EXPECT_TRUE(F1->hasLazyArguments()); EXPECT_TRUE(F2->hasLazyArguments()); // Steal arguments before they've been accessed. Nothing should change; both // functions should still have lazy arguments. // // steal(empty); drop (empty) F1->stealArgumentListFrom(*F2); EXPECT_TRUE(F1->hasLazyArguments()); EXPECT_TRUE(F2->hasLazyArguments()); // Save arguments from F1 for later assertions. F1 won't have lazy arguments // anymore. SmallVector Args; for (Argument &A : F1->args()) Args.push_back(&A); EXPECT_EQ(2u, Args.size()); EXPECT_FALSE(F1->hasLazyArguments()); // Steal arguments from F1 to F2. F1's arguments should be lazy again. // // steal(real); drop (empty) F2->stealArgumentListFrom(*F1); EXPECT_TRUE(F1->hasLazyArguments()); EXPECT_FALSE(F2->hasLazyArguments()); unsigned I = 0; for (Argument &A : F2->args()) { EXPECT_EQ(Args[I], &A); I++; } EXPECT_EQ(2u, I); // Check that arguments in F1 don't have pointer equality with the saved ones. // This also instantiates F1's arguments. I = 0; for (Argument &A : F1->args()) { EXPECT_NE(Args[I], &A); I++; } EXPECT_EQ(2u, I); EXPECT_FALSE(F1->hasLazyArguments()); EXPECT_FALSE(F2->hasLazyArguments()); // Steal back from F2. F2's arguments should be lazy again. // // steal(real); drop (real) F1->stealArgumentListFrom(*F2); EXPECT_FALSE(F1->hasLazyArguments()); EXPECT_TRUE(F2->hasLazyArguments()); I = 0; for (Argument &A : F1->args()) { EXPECT_EQ(Args[I], &A); I++; } EXPECT_EQ(2u, I); // Steal from F2 a second time. Now both functions should have lazy // arguments. // // steal(empty); drop (real) F1->stealArgumentListFrom(*F2); EXPECT_TRUE(F1->hasLazyArguments()); EXPECT_TRUE(F2->hasLazyArguments()); } // Test setting and removing section information TEST(FunctionTest, setSection) { LLVMContext C; Module M("test", C); llvm::Function *F = Function::Create(llvm::FunctionType::get(llvm::Type::getVoidTy(C), false), llvm::GlobalValue::ExternalLinkage, "F", &M); F->setSection(".text.test"); EXPECT_TRUE(F->getSection() == ".text.test"); EXPECT_TRUE(F->hasSection()); F->setSection(""); EXPECT_FALSE(F->hasSection()); F->setSection(".text.test"); F->setSection(".text.test2"); EXPECT_TRUE(F->getSection() == ".text.test2"); EXPECT_TRUE(F->hasSection()); } TEST(FunctionTest, GetPointerAlignment) { LLVMContext Context; Type *VoidType(Type::getVoidTy(Context)); FunctionType *FuncType(FunctionType::get(VoidType, false)); std::unique_ptr Func(Function::Create( FuncType, GlobalValue::ExternalLinkage)); EXPECT_EQ(MaybeAlign(), Func->getPointerAlignment(DataLayout(""))); EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8"))); EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fn8"))); EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16"))); EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fn16"))); EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32"))); EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32"))); Func->setAlignment(Align(4)); EXPECT_EQ(MaybeAlign(), Func->getPointerAlignment(DataLayout(""))); EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8"))); EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn8"))); EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16"))); EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn16"))); EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32"))); EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32"))); } } // end namespace