Imported Upstream version 5.18.0.207

Former-commit-id: 3b152f462918d427ce18620a2cbe4f8b79650449
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-11-17 08:23:10 +00:00
parent 8e12397d70
commit eb85e2fc17
28480 changed files with 72 additions and 3866936 deletions

View File

@ -1,54 +0,0 @@
//===- llvm/unittest/IR/AsmWriter.cpp - AsmWriter tests -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
TEST(AsmWriterTest, DebugPrintDetachedInstruction) {
// PR24852: Ensure that an instruction can be printed even when it
// has metadata attached but no parent.
LLVMContext Ctx;
auto Ty = Type::getInt32Ty(Ctx);
auto Undef = UndefValue::get(Ty);
std::unique_ptr<BinaryOperator> Add(BinaryOperator::CreateAdd(Undef, Undef));
Add->setMetadata(
"", MDNode::get(Ctx, {ConstantAsMetadata::get(ConstantInt::get(Ty, 1))}));
std::string S;
raw_string_ostream OS(S);
Add->print(OS);
std::size_t r = OS.str().find("<badref> = add i32 undef, undef, !<empty");
EXPECT_TRUE(r != std::string::npos);
}
TEST(AsmWriterTest, DumpDIExpression) {
LLVMContext Ctx;
uint64_t Ops[] = {
dwarf::DW_OP_constu, 4,
dwarf::DW_OP_minus,
dwarf::DW_OP_deref,
};
DIExpression *Expr = DIExpression::get(Ctx, Ops);
std::string S;
raw_string_ostream OS(S);
Expr->print(OS);
EXPECT_EQ("!DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_deref)",
OS.str());
}
}

View File

@ -1,92 +0,0 @@
//===- llvm/unittest/IR/AttributesTest.cpp - Attributes unit tests --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Attributes.h"
#include "llvm/IR/LLVMContext.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);
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, 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());
}
} // end anonymous namespace

View File

@ -1,81 +0,0 @@
//===- llvm/unittest/IR/BasicBlockTest.cpp - BasicBlock unit tests --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/BasicBlock.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/NoFolder.h"
#include "gmock/gmock-matchers.h"
#include "gtest/gtest.h"
#include <memory>
namespace llvm {
namespace {
TEST(BasicBlockTest, PhiRange) {
LLVMContext Context;
// Create the main block.
std::unique_ptr<BasicBlock> BB(BasicBlock::Create(Context));
// Create some predecessors of it.
std::unique_ptr<BasicBlock> BB1(BasicBlock::Create(Context));
BranchInst::Create(BB.get(), BB1.get());
std::unique_ptr<BasicBlock> BB2(BasicBlock::Create(Context));
BranchInst::Create(BB.get(), BB2.get());
// Make sure this doesn't crash if there are no phis.
for (auto &PN : BB->phis()) {
(void)PN;
EXPECT_TRUE(false) << "empty block should have no phis";
}
// Make it a cycle.
auto *BI = BranchInst::Create(BB.get(), BB.get());
// Now insert some PHI nodes.
auto *Int32Ty = Type::getInt32Ty(Context);
auto *P1 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.1", BI);
auto *P2 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.2", BI);
auto *P3 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.3", BI);
// Some non-PHI nodes.
auto *Sum = BinaryOperator::CreateAdd(P1, P2, "sum", BI);
// Now wire up the incoming values that are interesting.
P1->addIncoming(P2, BB.get());
P2->addIncoming(P1, BB.get());
P3->addIncoming(Sum, BB.get());
// Finally, let's iterate them, which is the thing we're trying to test.
// We'll use this to wire up the rest of the incoming values.
for (auto &PN : BB->phis()) {
PN.addIncoming(UndefValue::get(Int32Ty), BB1.get());
PN.addIncoming(UndefValue::get(Int32Ty), BB2.get());
}
// Test that we can use const iterators and generally that the iterators
// behave like iterators.
BasicBlock::const_phi_iterator CI;
CI = BB->phis().begin();
EXPECT_NE(CI, BB->phis().end());
// And iterate a const range.
for (const auto &PN : const_cast<const BasicBlock *>(BB.get())->phis()) {
EXPECT_EQ(BB.get(), PN.getIncomingBlock(0));
EXPECT_EQ(BB1.get(), PN.getIncomingBlock(1));
EXPECT_EQ(BB2.get(), PN.getIncomingBlock(2));
}
}
} // End anonymous namespace.
} // End llvm namespace.

View File

@ -1,269 +0,0 @@
//===- llvm/Testing/Support/CFGBuilder.cpp --------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CFGBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/TypeBuilder.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
#define DEBUG_TYPE "cfg-builder"
using namespace llvm;
CFGHolder::CFGHolder(StringRef ModuleName, StringRef FunctionName)
: Context(llvm::make_unique<LLVMContext>()),
M(llvm::make_unique<Module>(ModuleName, *Context)) {
FunctionType *FTy = TypeBuilder<void(), false>::get(*Context);
F = cast<Function>(M->getOrInsertFunction(FunctionName, FTy));
}
CFGHolder::~CFGHolder() = default;
CFGBuilder::CFGBuilder(Function *F, const std::vector<Arc> &InitialArcs,
std::vector<Update> Updates)
: F(F), Updates(std::move(Updates)) {
assert(F);
buildCFG(InitialArcs);
}
static void ConnectBlocks(BasicBlock *From, BasicBlock *To) {
DEBUG(dbgs() << "Creating BB arc " << From->getName() << " -> "
<< To->getName() << "\n";
dbgs().flush());
auto *IntTy = IntegerType::get(From->getContext(), 32);
if (isa<UnreachableInst>(From->getTerminator()))
From->getTerminator()->eraseFromParent();
if (!From->getTerminator()) {
IRBuilder<> IRB(From);
IRB.CreateSwitch(ConstantInt::get(IntTy, 0), To);
return;
}
SwitchInst *SI = cast<SwitchInst>(From->getTerminator());
const auto Last = SI->getNumCases();
auto *IntVal = ConstantInt::get(IntTy, Last);
SI->addCase(IntVal, To);
}
static void DisconnectBlocks(BasicBlock *From, BasicBlock *To) {
DEBUG(dbgs() << "Deleting BB arc " << From->getName() << " -> "
<< To->getName() << "\n";
dbgs().flush());
SwitchInst *SI = cast<SwitchInst>(From->getTerminator());
if (SI->getNumCases() == 0) {
SI->eraseFromParent();
IRBuilder<> IRB(From);
IRB.CreateUnreachable();
return;
}
if (SI->getDefaultDest() == To) {
auto FirstC = SI->case_begin();
SI->setDefaultDest(FirstC->getCaseSuccessor());
SI->removeCase(FirstC);
return;
}
for (auto CIt = SI->case_begin(); CIt != SI->case_end(); ++CIt)
if (CIt->getCaseSuccessor() == To) {
SI->removeCase(CIt);
return;
}
}
BasicBlock *CFGBuilder::getOrAddBlock(StringRef BlockName) {
auto BIt = NameToBlock.find(BlockName);
if (BIt != NameToBlock.end())
return BIt->second;
auto *BB = BasicBlock::Create(F->getParent()->getContext(), BlockName, F);
IRBuilder<> IRB(BB);
IRB.CreateUnreachable();
NameToBlock[BlockName] = BB;
return BB;
}
bool CFGBuilder::connect(const Arc &A) {
BasicBlock *From = getOrAddBlock(A.From);
BasicBlock *To = getOrAddBlock(A.To);
if (Arcs.count(A) != 0)
return false;
Arcs.insert(A);
ConnectBlocks(From, To);
return true;
}
bool CFGBuilder::disconnect(const Arc &A) {
assert(NameToBlock.count(A.From) != 0 && "No block to disconnect (From)");
assert(NameToBlock.count(A.To) != 0 && "No block to disconnect (To)");
if (Arcs.count(A) == 0)
return false;
BasicBlock *From = getOrAddBlock(A.From);
BasicBlock *To = getOrAddBlock(A.To);
Arcs.erase(A);
DisconnectBlocks(From, To);
return true;
}
void CFGBuilder::buildCFG(const std::vector<Arc> &NewArcs) {
for (const auto &A : NewArcs) {
const bool Connected = connect(A);
(void)Connected;
assert(Connected);
}
}
Optional<CFGBuilder::Update> CFGBuilder::getNextUpdate() const {
if (UpdateIdx == Updates.size())
return None;
return Updates[UpdateIdx];
}
Optional<CFGBuilder::Update> CFGBuilder::applyUpdate() {
if (UpdateIdx == Updates.size())
return None;
Update NextUpdate = Updates[UpdateIdx++];
if (NextUpdate.Action == ActionKind::Insert)
connect(NextUpdate.Edge);
else
disconnect(NextUpdate.Edge);
return NextUpdate;
}
void CFGBuilder::dump(raw_ostream &OS) const {
OS << "Arcs:\n";
size_t i = 0;
for (const auto &A : Arcs)
OS << " " << i++ << ":\t" << A.From << " -> " << A.To << "\n";
OS << "Updates:\n";
i = 0;
for (const auto &U : Updates) {
OS << (i + 1 == UpdateIdx ? "->" : " ") << i
<< ((U.Action == ActionKind::Insert) ? "\tIns " : "\tDel ")
<< U.Edge.From << " -> " << U.Edge.To << "\n";
++i;
}
}
//---- CFGBuilder tests ---------------------------------------------------===//
TEST(CFGBuilder, Construction) {
CFGHolder Holder;
std::vector<CFGBuilder::Arc> Arcs = {{"entry", "a"}, {"a", "b"}, {"a", "c"},
{"c", "d"}, {"d", "b"}, {"d", "e"},
{"d", "f"}, {"e", "f"}};
CFGBuilder B(Holder.F, Arcs, {});
EXPECT_TRUE(B.getOrAddBlock("entry") == &Holder.F->getEntryBlock());
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("entry")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("a")->getTerminator()));
EXPECT_TRUE(isa<UnreachableInst>(B.getOrAddBlock("b")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("d")->getTerminator()));
auto *DSwitch = cast<SwitchInst>(B.getOrAddBlock("d")->getTerminator());
// d has 3 successors, but one of them if going to be a default case
EXPECT_EQ(DSwitch->getNumCases(), 2U);
EXPECT_FALSE(B.getNextUpdate()); // No updates to apply.
}
TEST(CFGBuilder, Insertions) {
CFGHolder Holder;
const auto Insert = CFGBuilder::ActionKind::Insert;
std::vector<CFGBuilder::Update> Updates = {
{Insert, {"entry", "a"}}, {Insert, {"a", "b"}}, {Insert, {"a", "c"}},
{Insert, {"c", "d"}}, {Insert, {"d", "b"}}, {Insert, {"d", "e"}},
{Insert, {"d", "f"}}, {Insert, {"e", "f"}}};
const size_t NumUpdates = Updates.size();
CFGBuilder B(Holder.F, {}, Updates);
size_t i = 0;
while (B.applyUpdate())
++i;
EXPECT_EQ(i, NumUpdates);
EXPECT_TRUE(B.getOrAddBlock("entry") == &Holder.F->getEntryBlock());
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("entry")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("a")->getTerminator()));
EXPECT_TRUE(isa<UnreachableInst>(B.getOrAddBlock("b")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("d")->getTerminator()));
auto *DSwitch = cast<SwitchInst>(B.getOrAddBlock("d")->getTerminator());
// d has 3 successors, but one of them if going to be a default case
EXPECT_EQ(DSwitch->getNumCases(), 2U);
EXPECT_FALSE(B.getNextUpdate()); // No updates to apply.
}
TEST(CFGBuilder, Deletions) {
CFGHolder Holder;
std::vector<CFGBuilder::Arc> Arcs = {
{"entry", "a"}, {"a", "b"}, {"a", "c"}, {"c", "d"}, {"d", "b"}};
const auto Delete = CFGBuilder::ActionKind::Delete;
std::vector<CFGBuilder::Update> Updates = {
{Delete, {"c", "d"}}, {Delete, {"a", "c"}}, {Delete, {"entry", "a"}},
};
const size_t NumUpdates = Updates.size();
CFGBuilder B(Holder.F, Arcs, Updates);
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("entry")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("a")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("c")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("d")->getTerminator()));
auto UpdateC = B.applyUpdate();
EXPECT_TRUE(UpdateC);
EXPECT_EQ(UpdateC->Action, CFGBuilder::ActionKind::Delete);
EXPECT_EQ(UpdateC->Edge.From, "c");
EXPECT_EQ(UpdateC->Edge.To, "d");
EXPECT_TRUE(isa<UnreachableInst>(B.getOrAddBlock("c")->getTerminator()));
size_t i = 1;
while (B.applyUpdate())
++i;
EXPECT_EQ(i, NumUpdates);
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("a")->getTerminator()));
EXPECT_TRUE(isa<UnreachableInst>(B.getOrAddBlock("entry")->getTerminator()));
}
TEST(CFGBuilder, Rebuild) {
CFGHolder Holder;
std::vector<CFGBuilder::Arc> Arcs = {
{"entry", "a"}, {"a", "b"}, {"a", "c"}, {"c", "d"}, {"d", "b"}};
const auto Insert = CFGBuilder::ActionKind::Insert;
const auto Delete = CFGBuilder::ActionKind::Delete;
std::vector<CFGBuilder::Update> Updates = {
{Delete, {"c", "d"}}, {Delete, {"a", "c"}}, {Delete, {"entry", "a"}},
{Insert, {"c", "d"}}, {Insert, {"a", "c"}}, {Insert, {"entry", "a"}},
};
const size_t NumUpdates = Updates.size();
CFGBuilder B(Holder.F, Arcs, Updates);
size_t i = 0;
while (B.applyUpdate())
++i;
EXPECT_EQ(i, NumUpdates);
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("entry")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("a")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("c")->getTerminator()));
EXPECT_TRUE(isa<SwitchInst>(B.getOrAddBlock("d")->getTerminator()));
}

View File

@ -1,94 +0,0 @@
//===- CFGBuilder.h - CFG building and updating utility ----------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// CFGBuilders provides utilities fo building and updating CFG for testing
/// purposes.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_UNITTESTS_CFG_BUILDER_H
#define LLVM_UNITTESTS_CFG_BUILDER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Debug.h"
#include <memory>
#include <set>
#include <tuple>
#include <vector>
namespace llvm {
class LLVMContext;
class Module;
class Function;
class BasicBlock;
class raw_ostream;
struct CFGHolder {
std::unique_ptr<LLVMContext> Context;
std::unique_ptr<Module> M;
Function *F;
CFGHolder(StringRef ModuleName = "m", StringRef FunctionName = "foo");
~CFGHolder(); // Defined in the .cpp file so we can use forward declarations.
};
/// \brief
/// CFGBuilder builds IR with specific CFG, based on the supplied list of arcs.
/// It's able to apply the provided updates and automatically modify the IR.
///
/// Internally it makes every basic block end with either SwitchInst or with
/// UnreachableInst. When all arc to a BB are deleted, the BB remains in the
/// function and doesn't get deleted.
///
class CFGBuilder {
public:
struct Arc {
StringRef From;
StringRef To;
friend bool operator<(const Arc &LHS, const Arc &RHS) {
return std::tie(LHS.From, LHS.To) <
std::tie(RHS.From, RHS.To);
}
};
enum class ActionKind { Insert, Delete };
struct Update {
ActionKind Action;
Arc Edge;
};
CFGBuilder(Function *F, const std::vector<Arc> &InitialArcs,
std::vector<Update> Updates);
BasicBlock *getOrAddBlock(StringRef BlockName);
Optional<Update> getNextUpdate() const;
Optional<Update> applyUpdate();
void dump(raw_ostream &OS = dbgs()) const;
private:
void buildCFG(const std::vector<Arc> &Arcs);
bool connect(const Arc &A);
bool disconnect(const Arc &A);
Function *F;
unsigned UpdateIdx = 0;
StringMap<BasicBlock *> NameToBlock;
std::set<Arc> Arcs;
std::vector<Update> Updates;
};
} // namespace llvm
#endif

View File

@ -1,50 +0,0 @@
set(LLVM_LINK_COMPONENTS
Analysis
AsmParser
Core
Support
Passes
)
set(IRSources
AsmWriterTest.cpp
AttributesTest.cpp
BasicBlockTest.cpp
CFGBuilder.cpp
ConstantRangeTest.cpp
ConstantsTest.cpp
DebugInfoTest.cpp
DebugTypeODRUniquingTest.cpp
DominatorTreeTest.cpp
DominatorTreeBatchUpdatesTest.cpp
FunctionTest.cpp
PassBuilderCallbacksTest.cpp
IRBuilderTest.cpp
InstructionsTest.cpp
IntrinsicsTest.cpp
LegacyPassManagerTest.cpp
MDBuilderTest.cpp
MetadataTest.cpp
ModuleTest.cpp
PassManagerTest.cpp
PatternMatch.cpp
TypeBuilderTest.cpp
TypesTest.cpp
UseTest.cpp
UserTest.cpp
ValueHandleTest.cpp
ValueMapTest.cpp
ValueTest.cpp
VerifierTest.cpp
WaymarkTest.cpp
)
# HACK: Declare a couple of source files as optionally compiled to satisfy the
# missing-file-checker in LLVM's weird CMake build.
set(LLVM_OPTIONAL_SOURCES
ValueMapTest.cpp
)
add_llvm_unittest(IRTests
${IRSources}
)

File diff suppressed because it is too large Load Diff

View File

@ -1,481 +0,0 @@
//===- llvm/unittest/IR/ConstantsTest.cpp - Constants unit tests ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Constants.h"
#include "llvm-c/Core.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
namespace llvm {
namespace {
TEST(ConstantsTest, Integer_i1) {
LLVMContext Context;
IntegerType *Int1 = IntegerType::get(Context, 1);
Constant* One = ConstantInt::get(Int1, 1, true);
Constant* Zero = ConstantInt::get(Int1, 0);
Constant* NegOne = ConstantInt::get(Int1, static_cast<uint64_t>(-1), true);
EXPECT_EQ(NegOne, ConstantInt::getSigned(Int1, -1));
Constant* Undef = UndefValue::get(Int1);
// Input: @b = constant i1 add(i1 1 , i1 1)
// Output: @b = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getAdd(One, One));
// @c = constant i1 add(i1 -1, i1 1)
// @c = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getAdd(NegOne, One));
// @d = constant i1 add(i1 -1, i1 -1)
// @d = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getAdd(NegOne, NegOne));
// @e = constant i1 sub(i1 -1, i1 1)
// @e = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getSub(NegOne, One));
// @f = constant i1 sub(i1 1 , i1 -1)
// @f = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getSub(One, NegOne));
// @g = constant i1 sub(i1 1 , i1 1)
// @g = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getSub(One, One));
// @h = constant i1 shl(i1 1 , i1 1) ; undefined
// @h = constant i1 undef
EXPECT_EQ(Undef, ConstantExpr::getShl(One, One));
// @i = constant i1 shl(i1 1 , i1 0)
// @i = constant i1 true
EXPECT_EQ(One, ConstantExpr::getShl(One, Zero));
// @j = constant i1 lshr(i1 1, i1 1) ; undefined
// @j = constant i1 undef
EXPECT_EQ(Undef, ConstantExpr::getLShr(One, One));
// @m = constant i1 ashr(i1 1, i1 1) ; undefined
// @m = constant i1 undef
EXPECT_EQ(Undef, ConstantExpr::getAShr(One, One));
// @n = constant i1 mul(i1 -1, i1 1)
// @n = constant i1 true
EXPECT_EQ(One, ConstantExpr::getMul(NegOne, One));
// @o = constant i1 sdiv(i1 -1, i1 1) ; overflow
// @o = constant i1 true
EXPECT_EQ(One, ConstantExpr::getSDiv(NegOne, One));
// @p = constant i1 sdiv(i1 1 , i1 -1); overflow
// @p = constant i1 true
EXPECT_EQ(One, ConstantExpr::getSDiv(One, NegOne));
// @q = constant i1 udiv(i1 -1, i1 1)
// @q = constant i1 true
EXPECT_EQ(One, ConstantExpr::getUDiv(NegOne, One));
// @r = constant i1 udiv(i1 1, i1 -1)
// @r = constant i1 true
EXPECT_EQ(One, ConstantExpr::getUDiv(One, NegOne));
// @s = constant i1 srem(i1 -1, i1 1) ; overflow
// @s = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getSRem(NegOne, One));
// @t = constant i1 urem(i1 -1, i1 1)
// @t = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getURem(NegOne, One));
// @u = constant i1 srem(i1 1, i1 -1) ; overflow
// @u = constant i1 false
EXPECT_EQ(Zero, ConstantExpr::getSRem(One, NegOne));
}
TEST(ConstantsTest, IntSigns) {
LLVMContext Context;
IntegerType *Int8Ty = Type::getInt8Ty(Context);
EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, false)->getSExtValue());
EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, true)->getSExtValue());
EXPECT_EQ(100, ConstantInt::getSigned(Int8Ty, 100)->getSExtValue());
EXPECT_EQ(-50, ConstantInt::get(Int8Ty, 206)->getSExtValue());
EXPECT_EQ(-50, ConstantInt::getSigned(Int8Ty, -50)->getSExtValue());
EXPECT_EQ(206U, ConstantInt::getSigned(Int8Ty, -50)->getZExtValue());
// Overflow is handled by truncation.
EXPECT_EQ(0x3b, ConstantInt::get(Int8Ty, 0x13b)->getSExtValue());
}
TEST(ConstantsTest, FP128Test) {
LLVMContext Context;
Type *FP128Ty = Type::getFP128Ty(Context);
IntegerType *Int128Ty = Type::getIntNTy(Context, 128);
Constant *Zero128 = Constant::getNullValue(Int128Ty);
Constant *X = ConstantExpr::getUIToFP(Zero128, FP128Ty);
EXPECT_TRUE(isa<ConstantFP>(X));
}
TEST(ConstantsTest, PointerCast) {
LLVMContext C;
Type *Int8PtrTy = Type::getInt8PtrTy(C);
Type *Int32PtrTy = Type::getInt32PtrTy(C);
Type *Int64Ty = Type::getInt64Ty(C);
VectorType *Int8PtrVecTy = VectorType::get(Int8PtrTy, 4);
VectorType *Int32PtrVecTy = VectorType::get(Int32PtrTy, 4);
VectorType *Int64VecTy = VectorType::get(Int64Ty, 4);
// ptrtoint i8* to i64
EXPECT_EQ(Constant::getNullValue(Int64Ty),
ConstantExpr::getPointerCast(
Constant::getNullValue(Int8PtrTy), Int64Ty));
// bitcast i8* to i32*
EXPECT_EQ(Constant::getNullValue(Int32PtrTy),
ConstantExpr::getPointerCast(
Constant::getNullValue(Int8PtrTy), Int32PtrTy));
// ptrtoint <4 x i8*> to <4 x i64>
EXPECT_EQ(Constant::getNullValue(Int64VecTy),
ConstantExpr::getPointerCast(
Constant::getNullValue(Int8PtrVecTy), Int64VecTy));
// bitcast <4 x i8*> to <4 x i32*>
EXPECT_EQ(Constant::getNullValue(Int32PtrVecTy),
ConstantExpr::getPointerCast(
Constant::getNullValue(Int8PtrVecTy), Int32PtrVecTy));
Type *Int32Ptr1Ty = Type::getInt32PtrTy(C, 1);
ConstantInt *K = ConstantInt::get(Type::getInt64Ty(C), 1234);
// Make sure that addrspacecast of inttoptr is not folded away.
EXPECT_NE(K,
ConstantExpr::getAddrSpaceCast(
ConstantExpr::getIntToPtr(K, Int32PtrTy), Int32Ptr1Ty));
EXPECT_NE(K,
ConstantExpr::getAddrSpaceCast(
ConstantExpr::getIntToPtr(K, Int32Ptr1Ty), Int32PtrTy));
Constant *NullInt32Ptr0 = Constant::getNullValue(Int32PtrTy);
Constant *NullInt32Ptr1 = Constant::getNullValue(Int32Ptr1Ty);
// Make sure that addrspacecast of null is not folded away.
EXPECT_NE(Constant::getNullValue(Int32PtrTy),
ConstantExpr::getAddrSpaceCast(NullInt32Ptr0, Int32Ptr1Ty));
EXPECT_NE(Constant::getNullValue(Int32Ptr1Ty),
ConstantExpr::getAddrSpaceCast(NullInt32Ptr1, Int32PtrTy));
}
#define CHECK(x, y) \
{ \
std::string __s; \
raw_string_ostream __o(__s); \
Instruction *__I = cast<ConstantExpr>(x)->getAsInstruction(); \
__I->print(__o); \
__I->deleteValue(); \
__o.flush(); \
EXPECT_EQ(std::string(" <badref> = " y), __s); \
}
TEST(ConstantsTest, AsInstructionsTest) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
Type *Int64Ty = Type::getInt64Ty(Context);
Type *Int32Ty = Type::getInt32Ty(Context);
Type *Int16Ty = Type::getInt16Ty(Context);
Type *Int1Ty = Type::getInt1Ty(Context);
Type *FloatTy = Type::getFloatTy(Context);
Type *DoubleTy = Type::getDoubleTy(Context);
Constant *Global = M->getOrInsertGlobal("dummy",
PointerType::getUnqual(Int32Ty));
Constant *Global2 = M->getOrInsertGlobal("dummy2",
PointerType::getUnqual(Int32Ty));
Constant *P0 = ConstantExpr::getPtrToInt(Global, Int32Ty);
Constant *P1 = ConstantExpr::getUIToFP(P0, FloatTy);
Constant *P2 = ConstantExpr::getUIToFP(P0, DoubleTy);
Constant *P3 = ConstantExpr::getTrunc(P0, Int1Ty);
Constant *P4 = ConstantExpr::getPtrToInt(Global2, Int32Ty);
Constant *P5 = ConstantExpr::getUIToFP(P4, FloatTy);
Constant *P6 = ConstantExpr::getBitCast(P4, VectorType::get(Int16Ty, 2));
Constant *One = ConstantInt::get(Int32Ty, 1);
Constant *Two = ConstantInt::get(Int64Ty, 2);
Constant *Big = ConstantInt::get(Context, APInt{256, uint64_t(-1), true});
Constant *Elt = ConstantInt::get(Int16Ty, 2015);
Constant *Undef16 = UndefValue::get(Int16Ty);
Constant *Undef64 = UndefValue::get(Int64Ty);
Constant *UndefV16 = UndefValue::get(P6->getType());
#define P0STR "ptrtoint (i32** @dummy to i32)"
#define P1STR "uitofp (i32 ptrtoint (i32** @dummy to i32) to float)"
#define P2STR "uitofp (i32 ptrtoint (i32** @dummy to i32) to double)"
#define P3STR "ptrtoint (i32** @dummy to i1)"
#define P4STR "ptrtoint (i32** @dummy2 to i32)"
#define P5STR "uitofp (i32 ptrtoint (i32** @dummy2 to i32) to float)"
#define P6STR "bitcast (i32 ptrtoint (i32** @dummy2 to i32) to <2 x i16>)"
CHECK(ConstantExpr::getNeg(P0), "sub i32 0, " P0STR);
CHECK(ConstantExpr::getFNeg(P1), "fsub float -0.000000e+00, " P1STR);
CHECK(ConstantExpr::getNot(P0), "xor i32 " P0STR ", -1");
CHECK(ConstantExpr::getAdd(P0, P0), "add i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getAdd(P0, P0, false, true), "add nsw i32 " P0STR ", "
P0STR);
CHECK(ConstantExpr::getAdd(P0, P0, true, true), "add nuw nsw i32 " P0STR ", "
P0STR);
CHECK(ConstantExpr::getFAdd(P1, P1), "fadd float " P1STR ", " P1STR);
CHECK(ConstantExpr::getSub(P0, P0), "sub i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getFSub(P1, P1), "fsub float " P1STR ", " P1STR);
CHECK(ConstantExpr::getMul(P0, P0), "mul i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getFMul(P1, P1), "fmul float " P1STR ", " P1STR);
CHECK(ConstantExpr::getUDiv(P0, P0), "udiv i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getSDiv(P0, P0), "sdiv i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getFDiv(P1, P1), "fdiv float " P1STR ", " P1STR);
CHECK(ConstantExpr::getURem(P0, P0), "urem i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getSRem(P0, P0), "srem i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getFRem(P1, P1), "frem float " P1STR ", " P1STR);
CHECK(ConstantExpr::getAnd(P0, P0), "and i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getOr(P0, P0), "or i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getXor(P0, P0), "xor i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getShl(P0, P0), "shl i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getShl(P0, P0, true), "shl nuw i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getShl(P0, P0, false, true), "shl nsw i32 " P0STR ", "
P0STR);
CHECK(ConstantExpr::getLShr(P0, P0, false), "lshr i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getLShr(P0, P0, true), "lshr exact i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getAShr(P0, P0, false), "ashr i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getAShr(P0, P0, true), "ashr exact i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getSExt(P0, Int64Ty), "sext i32 " P0STR " to i64");
CHECK(ConstantExpr::getZExt(P0, Int64Ty), "zext i32 " P0STR " to i64");
CHECK(ConstantExpr::getFPTrunc(P2, FloatTy), "fptrunc double " P2STR
" to float");
CHECK(ConstantExpr::getFPExtend(P1, DoubleTy), "fpext float " P1STR
" to double");
CHECK(ConstantExpr::getExactUDiv(P0, P0), "udiv exact i32 " P0STR ", " P0STR);
CHECK(ConstantExpr::getSelect(P3, P0, P4), "select i1 " P3STR ", i32 " P0STR
", i32 " P4STR);
CHECK(ConstantExpr::getICmp(CmpInst::ICMP_EQ, P0, P4), "icmp eq i32 " P0STR
", " P4STR);
CHECK(ConstantExpr::getFCmp(CmpInst::FCMP_ULT, P1, P5), "fcmp ult float "
P1STR ", " P5STR);
std::vector<Constant*> V;
V.push_back(One);
// FIXME: getGetElementPtr() actually creates an inbounds ConstantGEP,
// not a normal one!
//CHECK(ConstantExpr::getGetElementPtr(Global, V, false),
// "getelementptr i32*, i32** @dummy, i32 1");
CHECK(ConstantExpr::getInBoundsGetElementPtr(PointerType::getUnqual(Int32Ty),
Global, V),
"getelementptr inbounds i32*, i32** @dummy, i32 1");
CHECK(ConstantExpr::getExtractElement(P6, One), "extractelement <2 x i16> "
P6STR ", i32 1");
EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Two));
EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Big));
EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Undef64));
EXPECT_EQ(Elt, ConstantExpr::getExtractElement(
ConstantExpr::getInsertElement(P6, Elt, One), One));
EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Two));
EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Big));
EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Undef64));
}
#ifdef GTEST_HAS_DEATH_TEST
#ifndef NDEBUG
TEST(ConstantsTest, ReplaceWithConstantTest) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
Type *Int32Ty = Type::getInt32Ty(Context);
Constant *One = ConstantInt::get(Int32Ty, 1);
Constant *Global =
M->getOrInsertGlobal("dummy", PointerType::getUnqual(Int32Ty));
Constant *GEP = ConstantExpr::getGetElementPtr(
PointerType::getUnqual(Int32Ty), Global, One);
EXPECT_DEATH(Global->replaceAllUsesWith(GEP),
"this->replaceAllUsesWith\\(expr\\(this\\)\\) is NOT valid!");
}
#endif
#endif
#undef CHECK
TEST(ConstantsTest, ConstantArrayReplaceWithConstant) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
Type *IntTy = Type::getInt8Ty(Context);
ArrayType *ArrayTy = ArrayType::get(IntTy, 2);
Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0),
ConstantInt::get(IntTy, 1)};
Constant *A01 = ConstantArray::get(ArrayTy, A01Vals);
Constant *Global = new GlobalVariable(*M, IntTy, false,
GlobalValue::ExternalLinkage, nullptr);
Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy);
Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt};
Constant *A0G = ConstantArray::get(ArrayTy, A0GVals);
ASSERT_NE(A01, A0G);
GlobalVariable *RefArray =
new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G);
ASSERT_EQ(A0G, RefArray->getInitializer());
GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1));
ASSERT_EQ(A01, RefArray->getInitializer());
}
TEST(ConstantsTest, ConstantExprReplaceWithConstant) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
Type *IntTy = Type::getInt8Ty(Context);
Constant *G1 = new GlobalVariable(*M, IntTy, false,
GlobalValue::ExternalLinkage, nullptr);
Constant *G2 = new GlobalVariable(*M, IntTy, false,
GlobalValue::ExternalLinkage, nullptr);
ASSERT_NE(G1, G2);
Constant *Int1 = ConstantExpr::getPtrToInt(G1, IntTy);
Constant *Int2 = ConstantExpr::getPtrToInt(G2, IntTy);
ASSERT_NE(Int1, Int2);
GlobalVariable *Ref =
new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, Int1);
ASSERT_EQ(Int1, Ref->getInitializer());
G1->replaceAllUsesWith(G2);
ASSERT_EQ(Int2, Ref->getInitializer());
}
TEST(ConstantsTest, GEPReplaceWithConstant) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
Type *IntTy = Type::getInt32Ty(Context);
Type *PtrTy = PointerType::get(IntTy, 0);
auto *C1 = ConstantInt::get(IntTy, 1);
auto *Placeholder = new GlobalVariable(
*M, IntTy, false, GlobalValue::ExternalWeakLinkage, nullptr);
auto *GEP = ConstantExpr::getGetElementPtr(IntTy, Placeholder, C1);
ASSERT_EQ(GEP->getOperand(0), Placeholder);
auto *Ref =
new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP);
ASSERT_EQ(GEP, Ref->getInitializer());
auto *Global = new GlobalVariable(*M, PtrTy, false,
GlobalValue::ExternalLinkage, nullptr);
auto *Alias = GlobalAlias::create(IntTy, 0, GlobalValue::ExternalLinkage,
"alias", Global, M.get());
Placeholder->replaceAllUsesWith(Alias);
ASSERT_EQ(GEP, Ref->getInitializer());
ASSERT_EQ(GEP->getOperand(0), Alias);
}
TEST(ConstantsTest, AliasCAPI) {
LLVMContext Context;
SMDiagnostic Error;
std::unique_ptr<Module> M =
parseAssemblyString("@g = global i32 42", Error, Context);
GlobalVariable *G = M->getGlobalVariable("g");
Type *I16Ty = Type::getInt16Ty(Context);
Type *I16PTy = PointerType::get(I16Ty, 0);
Constant *Aliasee = ConstantExpr::getBitCast(G, I16PTy);
LLVMValueRef AliasRef =
LLVMAddAlias(wrap(M.get()), wrap(I16PTy), wrap(Aliasee), "a");
ASSERT_EQ(unwrap<GlobalAlias>(AliasRef)->getAliasee(), Aliasee);
}
static std::string getNameOfType(Type *T) {
std::string S;
raw_string_ostream RSOS(S);
T->print(RSOS);
return S;
}
TEST(ConstantsTest, BuildConstantDataArrays) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
for (Type *T : {Type::getInt8Ty(Context), Type::getInt16Ty(Context),
Type::getInt32Ty(Context), Type::getInt64Ty(Context)}) {
ArrayType *ArrayTy = ArrayType::get(T, 2);
Constant *Vals[] = {ConstantInt::get(T, 0), ConstantInt::get(T, 1)};
Constant *CDV = ConstantArray::get(ArrayTy, Vals);
ASSERT_TRUE(dyn_cast<ConstantDataArray>(CDV) != nullptr)
<< " T = " << getNameOfType(T);
}
for (Type *T : {Type::getHalfTy(Context), Type::getFloatTy(Context),
Type::getDoubleTy(Context)}) {
ArrayType *ArrayTy = ArrayType::get(T, 2);
Constant *Vals[] = {ConstantFP::get(T, 0), ConstantFP::get(T, 1)};
Constant *CDV = ConstantArray::get(ArrayTy, Vals);
ASSERT_TRUE(dyn_cast<ConstantDataArray>(CDV) != nullptr)
<< " T = " << getNameOfType(T);
}
}
TEST(ConstantsTest, BuildConstantDataVectors) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
for (Type *T : {Type::getInt8Ty(Context), Type::getInt16Ty(Context),
Type::getInt32Ty(Context), Type::getInt64Ty(Context)}) {
Constant *Vals[] = {ConstantInt::get(T, 0), ConstantInt::get(T, 1)};
Constant *CDV = ConstantVector::get(Vals);
ASSERT_TRUE(dyn_cast<ConstantDataVector>(CDV) != nullptr)
<< " T = " << getNameOfType(T);
}
for (Type *T : {Type::getHalfTy(Context), Type::getFloatTy(Context),
Type::getDoubleTy(Context)}) {
Constant *Vals[] = {ConstantFP::get(T, 0), ConstantFP::get(T, 1)};
Constant *CDV = ConstantVector::get(Vals);
ASSERT_TRUE(dyn_cast<ConstantDataVector>(CDV) != nullptr)
<< " T = " << getNameOfType(T);
}
}
TEST(ConstantsTest, BitcastToGEP) {
LLVMContext Context;
std::unique_ptr<Module> M(new Module("MyModule", Context));
auto *i32 = Type::getInt32Ty(Context);
auto *U = StructType::create(Context, "Unsized");
Type *EltTys[] = {i32, U};
auto *S = StructType::create(EltTys);
auto *G = new GlobalVariable(*M, S, false,
GlobalValue::ExternalLinkage, nullptr);
auto *PtrTy = PointerType::get(i32, 0);
auto *C = ConstantExpr::getBitCast(G, PtrTy);
ASSERT_EQ(dyn_cast<ConstantExpr>(C)->getOpcode(),
Instruction::BitCast);
}
} // end anonymous namespace
} // end namespace llvm

View File

@ -1,83 +0,0 @@
//===- llvm/unittest/IR/DebugInfo.cpp - DebugInfo tests -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/DebugInfoMetadata.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
TEST(DINodeTest, getFlag) {
// Some valid flags.
EXPECT_EQ(DINode::FlagPublic, DINode::getFlag("DIFlagPublic"));
EXPECT_EQ(DINode::FlagProtected, DINode::getFlag("DIFlagProtected"));
EXPECT_EQ(DINode::FlagPrivate, DINode::getFlag("DIFlagPrivate"));
EXPECT_EQ(DINode::FlagVector, DINode::getFlag("DIFlagVector"));
EXPECT_EQ(DINode::FlagRValueReference,
DINode::getFlag("DIFlagRValueReference"));
// FlagAccessibility shouldn't work.
EXPECT_EQ(0u, DINode::getFlag("DIFlagAccessibility"));
// Some other invalid strings.
EXPECT_EQ(0u, DINode::getFlag("FlagVector"));
EXPECT_EQ(0u, DINode::getFlag("Vector"));
EXPECT_EQ(0u, DINode::getFlag("other things"));
EXPECT_EQ(0u, DINode::getFlag("DIFlagOther"));
}
TEST(DINodeTest, getFlagString) {
// Some valid flags.
EXPECT_EQ(StringRef("DIFlagPublic"),
DINode::getFlagString(DINode::FlagPublic));
EXPECT_EQ(StringRef("DIFlagProtected"),
DINode::getFlagString(DINode::FlagProtected));
EXPECT_EQ(StringRef("DIFlagPrivate"),
DINode::getFlagString(DINode::FlagPrivate));
EXPECT_EQ(StringRef("DIFlagVector"),
DINode::getFlagString(DINode::FlagVector));
EXPECT_EQ(StringRef("DIFlagRValueReference"),
DINode::getFlagString(DINode::FlagRValueReference));
// FlagAccessibility actually equals FlagPublic.
EXPECT_EQ(StringRef("DIFlagPublic"),
DINode::getFlagString(DINode::FlagAccessibility));
// Some other invalid flags.
EXPECT_EQ(StringRef(),
DINode::getFlagString(DINode::FlagPublic | DINode::FlagVector));
EXPECT_EQ(StringRef(), DINode::getFlagString(DINode::FlagFwdDecl |
DINode::FlagArtificial));
EXPECT_EQ(StringRef(),
DINode::getFlagString(static_cast<DINode::DIFlags>(0xffff)));
}
TEST(DINodeTest, splitFlags) {
// Some valid flags.
#define CHECK_SPLIT(FLAGS, VECTOR, REMAINDER) \
{ \
SmallVector<DINode::DIFlags, 8> V; \
EXPECT_EQ(REMAINDER, DINode::splitFlags(FLAGS, V)); \
EXPECT_TRUE(makeArrayRef(V).equals(VECTOR)); \
}
CHECK_SPLIT(DINode::FlagPublic, {DINode::FlagPublic}, DINode::FlagZero);
CHECK_SPLIT(DINode::FlagProtected, {DINode::FlagProtected}, DINode::FlagZero);
CHECK_SPLIT(DINode::FlagPrivate, {DINode::FlagPrivate}, DINode::FlagZero);
CHECK_SPLIT(DINode::FlagVector, {DINode::FlagVector}, DINode::FlagZero);
CHECK_SPLIT(DINode::FlagRValueReference, {DINode::FlagRValueReference},
DINode::FlagZero);
DINode::DIFlags Flags[] = {DINode::FlagFwdDecl, DINode::FlagVector};
CHECK_SPLIT(DINode::FlagFwdDecl | DINode::FlagVector, Flags,
DINode::FlagZero);
CHECK_SPLIT(DINode::FlagZero, {}, DINode::FlagZero);
#undef CHECK_SPLIT
}
} // end namespace

View File

@ -1,159 +0,0 @@
//===- DebugTypeODRUniquingTest.cpp - Debug type ODR uniquing tests -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/LLVMContext.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
TEST(DebugTypeODRUniquingTest, enableDebugTypeODRUniquing) {
LLVMContext Context;
EXPECT_FALSE(Context.isODRUniquingDebugTypes());
Context.enableDebugTypeODRUniquing();
EXPECT_TRUE(Context.isODRUniquingDebugTypes());
Context.disableDebugTypeODRUniquing();
EXPECT_FALSE(Context.isODRUniquingDebugTypes());
}
TEST(DebugTypeODRUniquingTest, getODRType) {
LLVMContext Context;
MDString &UUID = *MDString::get(Context, "string");
// Without a type map, this should return null.
EXPECT_FALSE(DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr));
// Enable the mapping. There still shouldn't be a type.
Context.enableDebugTypeODRUniquing();
EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
// Create some ODR-uniqued type.
auto &CT = *DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr);
EXPECT_EQ(UUID.getString(), CT.getIdentifier());
// Check that we get it back, even if we change a field.
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr));
EXPECT_EQ(&CT,
DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type,
MDString::get(Context, "name"), nullptr, 0, nullptr, nullptr, 0,
0, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr));
// Check that it's discarded with the type map.
Context.disableDebugTypeODRUniquing();
EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
// And it shouldn't magically reappear...
Context.enableDebugTypeODRUniquing();
EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
}
TEST(DebugTypeODRUniquingTest, buildODRType) {
LLVMContext Context;
Context.enableDebugTypeODRUniquing();
// Build an ODR type that's a forward decl.
MDString &UUID = *MDString::get(Context, "Type");
auto &CT = *DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with another forward decl. This should be a no-op.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with a definition. This time we should see a change.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr,
nullptr, 0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero,
nullptr, 0, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
// Further updates should be ignored.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr, 0,
nullptr, nullptr));
EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
}
TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
LLVMContext Context;
Context.enableDebugTypeODRUniquing();
// Build an ODR type that's a forward decl with no other fields set.
MDString &UUID = *MDString::get(Context, "UUID");
auto &CT = *DICompositeType::buildODRType(
Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
// Create macros for running through all the fields except Identifier and Flags.
#define FOR_EACH_MDFIELD() \
DO_FOR_FIELD(Name) \
DO_FOR_FIELD(File) \
DO_FOR_FIELD(Scope) \
DO_FOR_FIELD(BaseType) \
DO_FOR_FIELD(Elements) \
DO_FOR_FIELD(VTableHolder) \
DO_FOR_FIELD(TemplateParams)
#define FOR_EACH_INLINEFIELD() \
DO_FOR_FIELD(Tag) \
DO_FOR_FIELD(Line) \
DO_FOR_FIELD(SizeInBits) \
DO_FOR_FIELD(AlignInBits) \
DO_FOR_FIELD(OffsetInBits) \
DO_FOR_FIELD(RuntimeLang)
// Create all the fields.
#define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X);
FOR_EACH_MDFIELD();
#undef DO_FOR_FIELD
unsigned NonZeroInit = 0;
#define DO_FOR_FIELD(X) auto X = ++NonZeroInit;
FOR_EACH_INLINEFIELD();
#undef DO_FOR_FIELD
// Replace all the fields with new values that are distinct from each other.
EXPECT_EQ(&CT,
DICompositeType::buildODRType(
Context, UUID, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
Elements, RuntimeLang, VTableHolder, TemplateParams));
// Confirm that all the right fields got updated.
#define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());
FOR_EACH_MDFIELD();
#undef DO_FOR_FIELD
#undef FOR_EACH_MDFIELD
#define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.get##X());
FOR_EACH_INLINEFIELD();
#undef DO_FOR_FIELD
#undef FOR_EACH_INLINEFIELD
EXPECT_EQ(DINode::FlagArtificial, CT.getFlags());
EXPECT_EQ(&UUID, CT.getRawIdentifier());
}
} // end namespace

View File

@ -1,355 +0,0 @@
//===- llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <random>
#include "CFGBuilder.h"
#include "gtest/gtest.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/Dominators.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
#define DEBUG_TYPE "batch-update-tests"
using namespace llvm;
namespace {
const auto CFGInsert = CFGBuilder::ActionKind::Insert;
const auto CFGDelete = CFGBuilder::ActionKind::Delete;
struct PostDomTree : PostDomTreeBase<BasicBlock> {
PostDomTree(Function &F) { recalculate(F); }
};
using DomUpdate = DominatorTree::UpdateType;
static_assert(
std::is_same<DomUpdate, PostDomTree::UpdateType>::value,
"Trees differing only in IsPostDom should have the same update types");
using DomSNCA = DomTreeBuilder::SemiNCAInfo<DomTreeBuilder::BBDomTree>;
using PostDomSNCA = DomTreeBuilder::SemiNCAInfo<DomTreeBuilder::BBPostDomTree>;
const auto Insert = DominatorTree::Insert;
const auto Delete = DominatorTree::Delete;
std::vector<DomUpdate> ToDomUpdates(CFGBuilder &B,
std::vector<CFGBuilder::Update> &In) {
std::vector<DomUpdate> Res;
Res.reserve(In.size());
for (const auto &CFGU : In)
Res.push_back({CFGU.Action == CFGInsert ? Insert : Delete,
B.getOrAddBlock(CFGU.Edge.From),
B.getOrAddBlock(CFGU.Edge.To)});
return Res;
}
} // namespace
TEST(DominatorTreeBatchUpdates, LegalizeDomUpdates) {
CFGHolder Holder;
CFGBuilder Builder(Holder.F, {{"A", "B"}}, {});
BasicBlock *A = Builder.getOrAddBlock("A");
BasicBlock *B = Builder.getOrAddBlock("B");
BasicBlock *C = Builder.getOrAddBlock("C");
BasicBlock *D = Builder.getOrAddBlock("D");
std::vector<DomUpdate> Updates = {
{Insert, B, C}, {Insert, C, D}, {Delete, B, C}, {Insert, B, C},
{Insert, B, D}, {Delete, C, D}, {Delete, A, B}};
SmallVector<DomUpdate, 4> Legalized;
DomSNCA::LegalizeUpdates(Updates, Legalized);
DEBUG(dbgs() << "Legalized updates:\t");
DEBUG(for (auto &U : Legalized) dbgs() << U << ", ");
DEBUG(dbgs() << "\n");
EXPECT_EQ(Legalized.size(), 3UL);
EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, B, C}), Legalized.end());
EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, B, D}), Legalized.end());
EXPECT_NE(llvm::find(Legalized, DomUpdate{Delete, A, B}), Legalized.end());
}
TEST(DominatorTreeBatchUpdates, LegalizePostDomUpdates) {
CFGHolder Holder;
CFGBuilder Builder(Holder.F, {{"A", "B"}}, {});
BasicBlock *A = Builder.getOrAddBlock("A");
BasicBlock *B = Builder.getOrAddBlock("B");
BasicBlock *C = Builder.getOrAddBlock("C");
BasicBlock *D = Builder.getOrAddBlock("D");
std::vector<DomUpdate> Updates = {
{Insert, B, C}, {Insert, C, D}, {Delete, B, C}, {Insert, B, C},
{Insert, B, D}, {Delete, C, D}, {Delete, A, B}};
SmallVector<DomUpdate, 4> Legalized;
PostDomSNCA::LegalizeUpdates(Updates, Legalized);
DEBUG(dbgs() << "Legalized postdom updates:\t");
DEBUG(for (auto &U : Legalized) dbgs() << U << ", ");
DEBUG(dbgs() << "\n");
EXPECT_EQ(Legalized.size(), 3UL);
EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, C, B}), Legalized.end());
EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, D, B}), Legalized.end());
EXPECT_NE(llvm::find(Legalized, DomUpdate{Delete, B, A}), Legalized.end());
}
TEST(DominatorTreeBatchUpdates, SingleInsertion) {
CFGHolder Holder;
CFGBuilder Builder(Holder.F, {{"A", "B"}}, {{CFGInsert, {"B", "C"}}});
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(DT.verify());
BasicBlock *B = Builder.getOrAddBlock("B");
BasicBlock *C = Builder.getOrAddBlock("C");
std::vector<DomUpdate> Updates = {{Insert, B, C}};
ASSERT_TRUE(Builder.applyUpdate());
DT.applyUpdates(Updates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(Updates);
EXPECT_TRUE(PDT.verify());
}
TEST(DominatorTreeBatchUpdates, SingleDeletion) {
CFGHolder Holder;
CFGBuilder Builder(Holder.F, {{"A", "B"}, {"B", "C"}},
{{CFGDelete, {"B", "C"}}});
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(DT.verify());
BasicBlock *B = Builder.getOrAddBlock("B");
BasicBlock *C = Builder.getOrAddBlock("C");
std::vector<DomUpdate> Updates = {{Delete, B, C}};
ASSERT_TRUE(Builder.applyUpdate());
DT.applyUpdates(Updates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(Updates);
EXPECT_TRUE(PDT.verify());
}
TEST(DominatorTreeBatchUpdates, FewInsertion) {
std::vector<CFGBuilder::Update> CFGUpdates = {{CFGInsert, {"B", "C"}},
{CFGInsert, {"C", "B"}},
{CFGInsert, {"C", "D"}},
{CFGInsert, {"D", "E"}}};
CFGHolder Holder;
CFGBuilder Builder(Holder.F, {{"A", "B"}}, CFGUpdates);
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(PDT.verify());
BasicBlock *B = Builder.getOrAddBlock("B");
BasicBlock *C = Builder.getOrAddBlock("C");
BasicBlock *D = Builder.getOrAddBlock("D");
BasicBlock *E = Builder.getOrAddBlock("E");
std::vector<DomUpdate> Updates = {
{Insert, B, C}, {Insert, C, B}, {Insert, C, D}, {Insert, D, E}};
while (Builder.applyUpdate())
;
DT.applyUpdates(Updates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(Updates);
EXPECT_TRUE(PDT.verify());
}
TEST(DominatorTreeBatchUpdates, FewDeletions) {
std::vector<CFGBuilder::Update> CFGUpdates = {{CFGDelete, {"B", "C"}},
{CFGDelete, {"C", "B"}},
{CFGDelete, {"B", "D"}},
{CFGDelete, {"D", "E"}}};
CFGHolder Holder;
CFGBuilder Builder(
Holder.F, {{"A", "B"}, {"B", "C"}, {"B", "D"}, {"D", "E"}, {"C", "B"}},
CFGUpdates);
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(PDT.verify());
auto Updates = ToDomUpdates(Builder, CFGUpdates);
while (Builder.applyUpdate())
;
DT.applyUpdates(Updates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(Updates);
EXPECT_TRUE(PDT.verify());
}
TEST(DominatorTreeBatchUpdates, InsertDelete) {
std::vector<CFGBuilder::Arc> Arcs = {
{"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
{"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
std::vector<CFGBuilder::Update> Updates = {
{CFGInsert, {"2", "4"}}, {CFGInsert, {"12", "10"}},
{CFGInsert, {"10", "9"}}, {CFGInsert, {"7", "6"}},
{CFGInsert, {"7", "5"}}, {CFGDelete, {"3", "8"}},
{CFGInsert, {"10", "7"}}, {CFGInsert, {"2", "8"}},
{CFGDelete, {"3", "4"}}, {CFGDelete, {"8", "9"}},
{CFGDelete, {"11", "12"}}};
CFGHolder Holder;
CFGBuilder B(Holder.F, Arcs, Updates);
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(PDT.verify());
while (B.applyUpdate())
;
auto DomUpdates = ToDomUpdates(B, Updates);
DT.applyUpdates(DomUpdates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(DomUpdates);
EXPECT_TRUE(PDT.verify());
}
TEST(DominatorTreeBatchUpdates, InsertDeleteExhaustive) {
std::vector<CFGBuilder::Arc> Arcs = {
{"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"},
{"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}};
std::vector<CFGBuilder::Update> Updates = {
{CFGInsert, {"2", "4"}}, {CFGInsert, {"12", "10"}},
{CFGInsert, {"10", "9"}}, {CFGInsert, {"7", "6"}},
{CFGInsert, {"7", "5"}}, {CFGDelete, {"3", "8"}},
{CFGInsert, {"10", "7"}}, {CFGInsert, {"2", "8"}},
{CFGDelete, {"3", "4"}}, {CFGDelete, {"8", "9"}},
{CFGDelete, {"11", "12"}}};
std::mt19937 Generator(0);
for (unsigned i = 0; i < 16; ++i) {
std::shuffle(Updates.begin(), Updates.end(), Generator);
CFGHolder Holder;
CFGBuilder B(Holder.F, Arcs, Updates);
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(PDT.verify());
while (B.applyUpdate())
;
auto DomUpdates = ToDomUpdates(B, Updates);
DT.applyUpdates(DomUpdates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(DomUpdates);
EXPECT_TRUE(PDT.verify());
}
}
// These are some odd flowgraphs, usually generated from csmith cases,
// which are difficult on post dom trees.
TEST(DominatorTreeBatchUpdates, InfiniteLoop) {
std::vector<CFGBuilder::Arc> Arcs = {
{"1", "2"},
{"2", "3"},
{"3", "6"}, {"3", "5"},
{"4", "5"},
{"5", "2"},
{"6", "3"}, {"6", "4"}};
// SplitBlock on 3 -> 5
std::vector<CFGBuilder::Update> Updates = {
{CFGInsert, {"N", "5"}}, {CFGInsert, {"3", "N"}}, {CFGDelete, {"3", "5"}}};
CFGHolder Holder;
CFGBuilder B(Holder.F, Arcs, Updates);
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(PDT.verify());
while (B.applyUpdate())
;
auto DomUpdates = ToDomUpdates(B, Updates);
DT.applyUpdates(DomUpdates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(DomUpdates);
EXPECT_TRUE(PDT.verify());
}
TEST(DominatorTreeBatchUpdates, DeadBlocks) {
std::vector<CFGBuilder::Arc> Arcs = {
{"1", "2"},
{"2", "3"},
{"3", "4"}, {"3", "7"},
{"4", "4"},
{"5", "6"}, {"5", "7"},
{"6", "7"},
{"7", "2"}, {"7", "8"}};
// Remove dead 5 and 7,
// plus SplitBlock on 7 -> 8
std::vector<CFGBuilder::Update> Updates = {
{CFGDelete, {"6", "7"}}, {CFGDelete, {"5", "7"}}, {CFGDelete, {"5", "6"}},
{CFGInsert, {"N", "8"}}, {CFGInsert, {"7", "N"}}, {CFGDelete, {"7", "8"}}};
CFGHolder Holder;
CFGBuilder B(Holder.F, Arcs, Updates);
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(PDT.verify());
while (B.applyUpdate())
;
auto DomUpdates = ToDomUpdates(B, Updates);
DT.applyUpdates(DomUpdates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(DomUpdates);
EXPECT_TRUE(PDT.verify());
}
TEST(DominatorTreeBatchUpdates, InfiniteLoop2) {
std::vector<CFGBuilder::Arc> Arcs = {
{"1", "2"},
{"2", "6"}, {"2", "3"},
{"3", "4"},
{"4", "5"}, {"4", "6"},
{"5", "4"},
{"6", "2"}};
// SplitBlock on 4 -> 6
std::vector<CFGBuilder::Update> Updates = {
{CFGInsert, {"N", "6"}}, {CFGInsert, {"4", "N"}}, {CFGDelete, {"4", "6"}}};
CFGHolder Holder;
CFGBuilder B(Holder.F, Arcs, Updates);
DominatorTree DT(*Holder.F);
EXPECT_TRUE(DT.verify());
PostDomTree PDT(*Holder.F);
EXPECT_TRUE(PDT.verify());
while (B.applyUpdate())
;
auto DomUpdates = ToDomUpdates(B, Updates);
DT.applyUpdates(DomUpdates);
EXPECT_TRUE(DT.verify());
PDT.applyUpdates(DomUpdates);
EXPECT_TRUE(PDT.verify());
}

File diff suppressed because it is too large Load Diff

View File

@ -1,133 +0,0 @@
//===- FunctionTest.cpp - Function unit tests -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#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());
}
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());
}
} // end namespace

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
//===- llvm/unittest/IR/IntrinsicsTest.cpp - ------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/IntrinsicInst.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
static const char *const NameTable1[] = {
"llvm.foo",
"llvm.foo.a",
"llvm.foo.b",
"llvm.foo.b.a",
"llvm.foo.c",
};
TEST(IntrinNameLookup, Basic) {
int I = Intrinsic::lookupLLVMIntrinsicByName(NameTable1, "llvm.foo");
EXPECT_EQ(0, I);
I = Intrinsic::lookupLLVMIntrinsicByName(NameTable1, "llvm.foo.f64");
EXPECT_EQ(0, I);
I = Intrinsic::lookupLLVMIntrinsicByName(NameTable1, "llvm.foo.b");
EXPECT_EQ(2, I);
I = Intrinsic::lookupLLVMIntrinsicByName(NameTable1, "llvm.foo.b.a");
EXPECT_EQ(3, I);
I = Intrinsic::lookupLLVMIntrinsicByName(NameTable1, "llvm.foo.c");
EXPECT_EQ(4, I);
I = Intrinsic::lookupLLVMIntrinsicByName(NameTable1, "llvm.foo.c.f64");
EXPECT_EQ(4, I);
}
} // end namespace

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +0,0 @@
//===- llvm/unittests/MDBuilderTest.cpp - MDBuilder unit tests ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Operator.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
class MDBuilderTest : public testing::Test {
protected:
LLVMContext Context;
};
TEST_F(MDBuilderTest, createString) {
MDBuilder MDHelper(Context);
MDString *Str0 = MDHelper.createString("");
MDString *Str1 = MDHelper.createString("string");
EXPECT_EQ(Str0->getString(), StringRef(""));
EXPECT_EQ(Str1->getString(), StringRef("string"));
}
TEST_F(MDBuilderTest, createFPMath) {
MDBuilder MDHelper(Context);
MDNode *MD0 = MDHelper.createFPMath(0.0);
MDNode *MD1 = MDHelper.createFPMath(1.0);
EXPECT_EQ(MD0, (MDNode *)nullptr);
EXPECT_NE(MD1, (MDNode *)nullptr);
EXPECT_EQ(MD1->getNumOperands(), 1U);
Metadata *Op = MD1->getOperand(0);
EXPECT_TRUE(mdconst::hasa<ConstantFP>(Op));
ConstantFP *Val = mdconst::extract<ConstantFP>(Op);
EXPECT_TRUE(Val->getType()->isFloatingPointTy());
EXPECT_TRUE(Val->isExactlyValue(1.0));
}
TEST_F(MDBuilderTest, createRangeMetadata) {
MDBuilder MDHelper(Context);
APInt A(8, 1), B(8, 2);
MDNode *R0 = MDHelper.createRange(A, A);
MDNode *R1 = MDHelper.createRange(A, B);
EXPECT_EQ(R0, (MDNode *)nullptr);
EXPECT_NE(R1, (MDNode *)nullptr);
EXPECT_EQ(R1->getNumOperands(), 2U);
EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(0)));
EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(1)));
ConstantInt *C0 = mdconst::extract<ConstantInt>(R1->getOperand(0));
ConstantInt *C1 = mdconst::extract<ConstantInt>(R1->getOperand(1));
EXPECT_EQ(C0->getValue(), A);
EXPECT_EQ(C1->getValue(), B);
}
TEST_F(MDBuilderTest, createAnonymousTBAARoot) {
MDBuilder MDHelper(Context);
MDNode *R0 = MDHelper.createAnonymousTBAARoot();
MDNode *R1 = MDHelper.createAnonymousTBAARoot();
EXPECT_NE(R0, R1);
EXPECT_GE(R0->getNumOperands(), 1U);
EXPECT_GE(R1->getNumOperands(), 1U);
EXPECT_EQ(R0->getOperand(0), R0);
EXPECT_EQ(R1->getOperand(0), R1);
EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == nullptr);
EXPECT_TRUE(R1->getNumOperands() == 1 || R1->getOperand(1) == nullptr);
}
TEST_F(MDBuilderTest, createTBAARoot) {
MDBuilder MDHelper(Context);
MDNode *R0 = MDHelper.createTBAARoot("Root");
MDNode *R1 = MDHelper.createTBAARoot("Root");
EXPECT_EQ(R0, R1);
EXPECT_GE(R0->getNumOperands(), 1U);
EXPECT_TRUE(isa<MDString>(R0->getOperand(0)));
EXPECT_EQ(cast<MDString>(R0->getOperand(0))->getString(), "Root");
EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == nullptr);
}
TEST_F(MDBuilderTest, createTBAANode) {
MDBuilder MDHelper(Context);
MDNode *R = MDHelper.createTBAARoot("Root");
MDNode *N0 = MDHelper.createTBAANode("Node", R);
MDNode *N1 = MDHelper.createTBAANode("edoN", R);
MDNode *N2 = MDHelper.createTBAANode("Node", R, true);
MDNode *N3 = MDHelper.createTBAANode("Node", R);
EXPECT_EQ(N0, N3);
EXPECT_NE(N0, N1);
EXPECT_NE(N0, N2);
EXPECT_GE(N0->getNumOperands(), 2U);
EXPECT_GE(N1->getNumOperands(), 2U);
EXPECT_GE(N2->getNumOperands(), 3U);
EXPECT_TRUE(isa<MDString>(N0->getOperand(0)));
EXPECT_TRUE(isa<MDString>(N1->getOperand(0)));
EXPECT_TRUE(isa<MDString>(N2->getOperand(0)));
EXPECT_EQ(cast<MDString>(N0->getOperand(0))->getString(), "Node");
EXPECT_EQ(cast<MDString>(N1->getOperand(0))->getString(), "edoN");
EXPECT_EQ(cast<MDString>(N2->getOperand(0))->getString(), "Node");
EXPECT_EQ(N0->getOperand(1), R);
EXPECT_EQ(N1->getOperand(1), R);
EXPECT_EQ(N2->getOperand(1), R);
EXPECT_TRUE(mdconst::hasa<ConstantInt>(N2->getOperand(2)));
EXPECT_EQ(mdconst::extract<ConstantInt>(N2->getOperand(2))->getZExtValue(),
1U);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
//===- unittests/IR/ModuleTest.cpp - Module unit tests --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Module.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/Support/RandomNumberGenerator.h"
#include "gtest/gtest.h"
#include <random>
using namespace llvm;
namespace {
bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {
return L.getName() < R.getName();
}
bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {
return sortByName(R, L);
}
TEST(ModuleTest, sortGlobalsByName) {
LLVMContext Context;
for (auto compare : {&sortByName, &sortByNameReverse}) {
Module M("M", Context);
Type *T = Type::getInt8Ty(Context);
GlobalValue::LinkageTypes L = GlobalValue::ExternalLinkage;
(void)new GlobalVariable(M, T, false, L, nullptr, "A");
(void)new GlobalVariable(M, T, false, L, nullptr, "F");
(void)new GlobalVariable(M, T, false, L, nullptr, "G");
(void)new GlobalVariable(M, T, false, L, nullptr, "E");
(void)new GlobalVariable(M, T, false, L, nullptr, "B");
(void)new GlobalVariable(M, T, false, L, nullptr, "H");
(void)new GlobalVariable(M, T, false, L, nullptr, "C");
(void)new GlobalVariable(M, T, false, L, nullptr, "D");
// Sort the globals by name.
EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare));
M.getGlobalList().sort(compare);
EXPECT_TRUE(std::is_sorted(M.global_begin(), M.global_end(), compare));
}
}
TEST(ModuleTest, randomNumberGenerator) {
LLVMContext Context;
static char ID;
struct DummyPass : ModulePass {
DummyPass() : ModulePass(ID) {}
bool runOnModule(Module &) { return true; }
} DP;
Module M("R", Context);
std::uniform_int_distribution<int> dist;
const size_t NBCheck = 10;
std::array<int, NBCheck> RandomStreams[2];
for (auto &RandomStream : RandomStreams) {
std::unique_ptr<RandomNumberGenerator> RNG = M.createRNG(&DP);
std::generate(RandomStream.begin(), RandomStream.end(),
[&]() { return dist(*RNG); });
}
EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(),
RandomStreams[1].begin()));
}
} // end namespace

Some files were not shown because too many files have changed in this diff Show More