mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 23:48:56 +00:00
d33fbe4f07
Add a new method, DICompositeType::buildODRType, that will create or mutate the DICompositeType for a given ODR identifier, and use it in LLParser and BitcodeReader instead of DICompositeType::getODRType. The logic is as follows: - If there's no node, create one with the given arguments. - Else, if the current node is a forward declaration and the new arguments would create a definition, mutate the node to match the new arguments. - Else, return the old node. This adds a missing feature supported by the current DITypeIdentifierMap (which I'm slowly making redudant). The only remaining difference is that the DITypeIdentifierMap has a "the-last-one-wins" rule, whereas DICompositeType::buildODRType has a "the-first-one-wins" rule. For now I'm leaving behind DICompositeType::getODRType since it has obvious, low-level semantics that are convenient for unit testing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266786 91177308-0d34-0410-b5e6-96231b3b80d8
157 lines
6.7 KiB
C++
157 lines
6.7 KiB
C++
//===- 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/LLVMContext.h"
|
|
#include "llvm/IR/DebugInfoMetadata.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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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
|