166 lines
5.4 KiB
C++
166 lines
5.4 KiB
C++
//===- 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<Function> 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<Function> F1(
|
|
Function::Create(FTy, GlobalValue::ExternalLinkage, "F1"));
|
|
std::unique_ptr<Function> 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<Argument *, 4> 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<Function> Func(Function::Create(
|
|
FuncType, GlobalValue::ExternalLinkage));
|
|
EXPECT_EQ(Align(1), 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(Align(1), 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
|