2013-04-12 16:33:11 +08:00
|
|
|
//===- llvm/unittest/IR/ValueTest.cpp - Value unit tests ------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-01-07 20:34:26 +08:00
|
|
|
#include "llvm/AsmParser/Parser.h"
|
2013-04-12 16:33:11 +08:00
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
2015-06-27 08:38:26 +08:00
|
|
|
#include "llvm/IR/ModuleSlotTracker.h"
|
2013-04-12 16:33:11 +08:00
|
|
|
#include "llvm/IR/Value.h"
|
|
|
|
#include "llvm/Support/SourceMgr.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
TEST(ValueTest, UsedInBasicBlock) {
|
|
|
|
LLVMContext C;
|
|
|
|
|
|
|
|
const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
|
|
|
|
"bb0:\n"
|
|
|
|
" %y1 = add i32 %y, 1\n"
|
|
|
|
" %y2 = add i32 %y, 1\n"
|
|
|
|
" %y3 = add i32 %y, 1\n"
|
|
|
|
" %y4 = add i32 %y, 1\n"
|
|
|
|
" %y5 = add i32 %y, 1\n"
|
|
|
|
" %y6 = add i32 %y, 1\n"
|
|
|
|
" %y7 = add i32 %y, 1\n"
|
|
|
|
" %y8 = add i32 %x, 1\n"
|
|
|
|
" ret void\n"
|
|
|
|
"}\n";
|
|
|
|
SMDiagnostic Err;
|
2014-08-20 00:58:54 +08:00
|
|
|
std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
|
2013-04-12 16:33:11 +08:00
|
|
|
|
|
|
|
Function *F = M->getFunction("f");
|
|
|
|
|
2015-10-21 02:30:20 +08:00
|
|
|
EXPECT_FALSE(F->isUsedInBasicBlock(&F->front()));
|
Remove getArgumentList() in favor of arg_begin(), args(), etc
Users often call getArgumentList().size(), which is a linear way to get
the number of function arguments. arg_size(), on the other hand, is
constant time.
In general, the fact that arguments are stored in an iplist is an
implementation detail, so I've removed it from the Function interface
and moved all other users to the argument container APIs (arg_begin(),
arg_end(), args(), arg_size()).
Reviewed By: chandlerc
Differential Revision: https://reviews.llvm.org/D31052
llvm-svn: 298010
2017-03-17 06:59:15 +08:00
|
|
|
EXPECT_TRUE(std::next(F->arg_begin())->isUsedInBasicBlock(&F->front()));
|
2015-10-21 02:30:20 +08:00
|
|
|
EXPECT_TRUE(F->arg_begin()->isUsedInBasicBlock(&F->front()));
|
2013-04-12 16:33:11 +08:00
|
|
|
}
|
|
|
|
|
2013-10-01 05:23:03 +08:00
|
|
|
TEST(GlobalTest, CreateAddressSpace) {
|
2016-04-15 05:59:01 +08:00
|
|
|
LLVMContext Ctx;
|
2014-03-06 13:51:42 +08:00
|
|
|
std::unique_ptr<Module> M(new Module("TestModule", Ctx));
|
2013-10-01 05:23:03 +08:00
|
|
|
Type *Int8Ty = Type::getInt8Ty(Ctx);
|
|
|
|
Type *Int32Ty = Type::getInt32Ty(Ctx);
|
|
|
|
|
|
|
|
GlobalVariable *Dummy0
|
|
|
|
= new GlobalVariable(*M,
|
|
|
|
Int32Ty,
|
|
|
|
true,
|
|
|
|
GlobalValue::ExternalLinkage,
|
|
|
|
Constant::getAllOnesValue(Int32Ty),
|
|
|
|
"dummy",
|
2014-06-09 06:29:17 +08:00
|
|
|
nullptr,
|
2013-10-01 05:23:03 +08:00
|
|
|
GlobalVariable::NotThreadLocal,
|
|
|
|
1);
|
|
|
|
|
2014-10-23 22:45:19 +08:00
|
|
|
EXPECT_TRUE(Value::MaximumAlignment == 536870912U);
|
|
|
|
Dummy0->setAlignment(536870912U);
|
|
|
|
EXPECT_EQ(Dummy0->getAlignment(), 536870912U);
|
|
|
|
|
2013-10-01 05:23:03 +08:00
|
|
|
// Make sure the address space isn't dropped when returning this.
|
|
|
|
Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty);
|
|
|
|
EXPECT_EQ(Dummy0, Dummy1);
|
|
|
|
EXPECT_EQ(1u, Dummy1->getType()->getPointerAddressSpace());
|
|
|
|
|
|
|
|
|
|
|
|
// This one requires a bitcast, but the address space must also stay the same.
|
|
|
|
GlobalVariable *DummyCast0
|
|
|
|
= new GlobalVariable(*M,
|
|
|
|
Int32Ty,
|
|
|
|
true,
|
|
|
|
GlobalValue::ExternalLinkage,
|
|
|
|
Constant::getAllOnesValue(Int32Ty),
|
|
|
|
"dummy_cast",
|
2014-06-09 06:29:17 +08:00
|
|
|
nullptr,
|
2013-10-01 05:23:03 +08:00
|
|
|
GlobalVariable::NotThreadLocal,
|
|
|
|
1);
|
|
|
|
|
|
|
|
// Make sure the address space isn't dropped when returning this.
|
|
|
|
Constant *DummyCast1 = M->getOrInsertGlobal("dummy_cast", Int8Ty);
|
|
|
|
EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace());
|
|
|
|
EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1;
|
|
|
|
}
|
2014-10-23 22:45:19 +08:00
|
|
|
|
|
|
|
#ifdef GTEST_HAS_DEATH_TEST
|
|
|
|
#ifndef NDEBUG
|
|
|
|
TEST(GlobalTest, AlignDeath) {
|
2016-04-15 05:59:01 +08:00
|
|
|
LLVMContext Ctx;
|
2014-10-23 22:45:19 +08:00
|
|
|
std::unique_ptr<Module> M(new Module("TestModule", Ctx));
|
|
|
|
Type *Int32Ty = Type::getInt32Ty(Ctx);
|
|
|
|
GlobalVariable *Var =
|
|
|
|
new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage,
|
|
|
|
Constant::getAllOnesValue(Int32Ty), "var", nullptr,
|
|
|
|
GlobalVariable::NotThreadLocal, 1);
|
|
|
|
|
|
|
|
EXPECT_DEATH(Var->setAlignment(536870913U), "Alignment is not a power of 2");
|
|
|
|
EXPECT_DEATH(Var->setAlignment(1073741824U),
|
|
|
|
"Alignment is greater than MaximumAlignment");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2015-06-27 08:38:26 +08:00
|
|
|
TEST(ValueTest, printSlots) {
|
|
|
|
// Check that Value::print() and Value::printAsOperand() work with and
|
|
|
|
// without a slot tracker.
|
|
|
|
LLVMContext C;
|
|
|
|
|
|
|
|
const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
|
|
|
|
"entry:\n"
|
|
|
|
" %0 = add i32 %y, 1\n"
|
|
|
|
" %1 = add i32 %y, 1\n"
|
|
|
|
" ret void\n"
|
|
|
|
"}\n";
|
|
|
|
SMDiagnostic Err;
|
|
|
|
std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
|
|
|
|
|
|
|
|
Function *F = M->getFunction("f");
|
|
|
|
ASSERT_TRUE(F);
|
|
|
|
ASSERT_FALSE(F->empty());
|
|
|
|
BasicBlock &BB = F->getEntryBlock();
|
|
|
|
ASSERT_EQ(3u, BB.size());
|
|
|
|
|
2015-10-21 02:30:20 +08:00
|
|
|
Instruction *I0 = &*BB.begin();
|
2015-06-27 08:38:26 +08:00
|
|
|
ASSERT_TRUE(I0);
|
2015-10-21 02:30:20 +08:00
|
|
|
Instruction *I1 = &*++BB.begin();
|
2015-06-27 08:38:26 +08:00
|
|
|
ASSERT_TRUE(I1);
|
|
|
|
|
|
|
|
ModuleSlotTracker MST(M.get());
|
|
|
|
|
|
|
|
#define CHECK_PRINT(INST, STR) \
|
|
|
|
do { \
|
|
|
|
{ \
|
|
|
|
std::string S; \
|
|
|
|
raw_string_ostream OS(S); \
|
|
|
|
INST->print(OS); \
|
|
|
|
EXPECT_EQ(STR, OS.str()); \
|
|
|
|
} \
|
|
|
|
{ \
|
|
|
|
std::string S; \
|
|
|
|
raw_string_ostream OS(S); \
|
|
|
|
INST->print(OS, MST); \
|
|
|
|
EXPECT_EQ(STR, OS.str()); \
|
|
|
|
} \
|
|
|
|
} while (false)
|
|
|
|
CHECK_PRINT(I0, " %0 = add i32 %y, 1");
|
|
|
|
CHECK_PRINT(I1, " %1 = add i32 %y, 1");
|
|
|
|
#undef CHECK_PRINT
|
|
|
|
|
|
|
|
#define CHECK_PRINT_AS_OPERAND(INST, TYPE, STR) \
|
|
|
|
do { \
|
|
|
|
{ \
|
|
|
|
std::string S; \
|
|
|
|
raw_string_ostream OS(S); \
|
|
|
|
INST->printAsOperand(OS, TYPE); \
|
|
|
|
EXPECT_EQ(StringRef(STR), StringRef(OS.str())); \
|
|
|
|
} \
|
|
|
|
{ \
|
|
|
|
std::string S; \
|
|
|
|
raw_string_ostream OS(S); \
|
|
|
|
INST->printAsOperand(OS, TYPE, MST); \
|
|
|
|
EXPECT_EQ(StringRef(STR), StringRef(OS.str())); \
|
|
|
|
} \
|
|
|
|
} while (false)
|
|
|
|
CHECK_PRINT_AS_OPERAND(I0, false, "%0");
|
|
|
|
CHECK_PRINT_AS_OPERAND(I1, false, "%1");
|
|
|
|
CHECK_PRINT_AS_OPERAND(I0, true, "i32 %0");
|
|
|
|
CHECK_PRINT_AS_OPERAND(I1, true, "i32 %1");
|
|
|
|
#undef CHECK_PRINT_AS_OPERAND
|
|
|
|
}
|
|
|
|
|
2015-07-28 06:31:04 +08:00
|
|
|
TEST(ValueTest, getLocalSlots) {
|
|
|
|
// Verify that the getLocalSlot method returns the correct slot numbers.
|
|
|
|
LLVMContext C;
|
|
|
|
const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
|
|
|
|
"entry:\n"
|
|
|
|
" %0 = add i32 %y, 1\n"
|
|
|
|
" %1 = add i32 %y, 1\n"
|
|
|
|
" br label %2\n"
|
|
|
|
"\n"
|
|
|
|
" ret void\n"
|
|
|
|
"}\n";
|
|
|
|
SMDiagnostic Err;
|
|
|
|
std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
|
|
|
|
|
|
|
|
Function *F = M->getFunction("f");
|
|
|
|
ASSERT_TRUE(F);
|
|
|
|
ASSERT_FALSE(F->empty());
|
|
|
|
BasicBlock &EntryBB = F->getEntryBlock();
|
|
|
|
ASSERT_EQ(3u, EntryBB.size());
|
2015-10-21 02:30:20 +08:00
|
|
|
BasicBlock *BB2 = &*++F->begin();
|
2015-07-28 06:31:04 +08:00
|
|
|
ASSERT_TRUE(BB2);
|
|
|
|
|
2015-10-21 02:30:20 +08:00
|
|
|
Instruction *I0 = &*EntryBB.begin();
|
2015-07-28 06:31:04 +08:00
|
|
|
ASSERT_TRUE(I0);
|
2015-10-21 02:30:20 +08:00
|
|
|
Instruction *I1 = &*++EntryBB.begin();
|
2015-07-28 06:31:04 +08:00
|
|
|
ASSERT_TRUE(I1);
|
|
|
|
|
|
|
|
ModuleSlotTracker MST(M.get());
|
|
|
|
MST.incorporateFunction(*F);
|
|
|
|
EXPECT_EQ(MST.getLocalSlot(I0), 0);
|
|
|
|
EXPECT_EQ(MST.getLocalSlot(I1), 1);
|
|
|
|
EXPECT_EQ(MST.getLocalSlot(&EntryBB), -1);
|
|
|
|
EXPECT_EQ(MST.getLocalSlot(BB2), 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
|
|
|
|
TEST(ValueTest, getLocalSlotDeath) {
|
|
|
|
LLVMContext C;
|
|
|
|
const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
|
|
|
|
"entry:\n"
|
|
|
|
" %0 = add i32 %y, 1\n"
|
|
|
|
" %1 = add i32 %y, 1\n"
|
|
|
|
" br label %2\n"
|
|
|
|
"\n"
|
|
|
|
" ret void\n"
|
|
|
|
"}\n";
|
|
|
|
SMDiagnostic Err;
|
|
|
|
std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
|
|
|
|
|
|
|
|
Function *F = M->getFunction("f");
|
|
|
|
ASSERT_TRUE(F);
|
|
|
|
ASSERT_FALSE(F->empty());
|
2015-10-21 02:30:20 +08:00
|
|
|
BasicBlock *BB2 = &*++F->begin();
|
2015-07-28 06:31:04 +08:00
|
|
|
ASSERT_TRUE(BB2);
|
|
|
|
|
|
|
|
ModuleSlotTracker MST(M.get());
|
|
|
|
EXPECT_DEATH(MST.getLocalSlot(BB2), "No function incorporated");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-04-12 16:33:11 +08:00
|
|
|
} // end anonymous namespace
|