#include "llvm/BinaryFormat/Dwarf.h"
#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");
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, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr));
Context.enableDebugTypeODRUniquing();
EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
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, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(UUID.getString(), CT.getIdentifier());
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, nullptr, nullptr, nullptr, nullptr, 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, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr));
Context.disableDebugTypeODRUniquing();
EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
Context.enableDebugTypeODRUniquing();
EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
}
TEST(DebugTypeODRUniquingTest, buildODRType) {
LLVMContext Context;
Context.enableDebugTypeODRUniquing();
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,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
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, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr));
EXPECT_FALSE(DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
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, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr));
EXPECT_FALSE(CT.isForwardDecl());
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, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr));
EXPECT_FALSE(CT.isForwardDecl());
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
111u, nullptr, nullptr, 0, 0, 0, DINode::FlagZero, nullptr,
0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr));
EXPECT_NE(111u, CT.getLine());
}
TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
LLVMContext Context;
Context.enableDebugTypeODRUniquing();
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, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr);
#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(Line) \
DO_FOR_FIELD(SizeInBits) \
DO_FOR_FIELD(AlignInBits) \
DO_FOR_FIELD(OffsetInBits) \
DO_FOR_FIELD(RuntimeLang)
#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
EXPECT_EQ(&CT,
DICompositeType::buildODRType(
Context, UUID, 0, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, DINode::FlagArtificial, Elements,
RuntimeLang, VTableHolder, TemplateParams, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr));
#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());
}
}