Home | History | Annotate | Download | only in IR
      1 //===- DebugTypeODRUniquingTest.cpp - Debug type ODR uniquing tests -------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/IR/LLVMContext.h"
     11 #include "llvm/IR/DebugInfoMetadata.h"
     12 #include "gtest/gtest.h"
     13 using namespace llvm;
     14 
     15 namespace {
     16 
     17 TEST(DebugTypeODRUniquingTest, enableDebugTypeODRUniquing) {
     18   LLVMContext Context;
     19   EXPECT_FALSE(Context.isODRUniquingDebugTypes());
     20   Context.enableDebugTypeODRUniquing();
     21   EXPECT_TRUE(Context.isODRUniquingDebugTypes());
     22   Context.disableDebugTypeODRUniquing();
     23   EXPECT_FALSE(Context.isODRUniquingDebugTypes());
     24 }
     25 
     26 TEST(DebugTypeODRUniquingTest, getODRType) {
     27   LLVMContext Context;
     28   MDString &UUID = *MDString::get(Context, "string");
     29 
     30   // Without a type map, this should return null.
     31   EXPECT_FALSE(DICompositeType::getODRType(
     32       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
     33       nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr));
     34 
     35   // Enable the mapping.  There still shouldn't be a type.
     36   Context.enableDebugTypeODRUniquing();
     37   EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
     38 
     39   // Create some ODR-uniqued type.
     40   auto &CT = *DICompositeType::getODRType(
     41       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
     42       nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr);
     43   EXPECT_EQ(UUID.getString(), CT.getIdentifier());
     44 
     45   // Check that we get it back, even if we change a field.
     46   EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
     47   EXPECT_EQ(
     48       &CT, DICompositeType::getODRType(Context, UUID, dwarf::DW_TAG_class_type,
     49                                        nullptr, nullptr, 0, nullptr, nullptr, 0,
     50                                        0, 0, 0, nullptr, 0, nullptr, nullptr));
     51   EXPECT_EQ(&CT, DICompositeType::getODRType(
     52                      Context, UUID, dwarf::DW_TAG_class_type,
     53                      MDString::get(Context, "name"), nullptr, 0, nullptr,
     54                      nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr));
     55 
     56   // Check that it's discarded with the type map.
     57   Context.disableDebugTypeODRUniquing();
     58   EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
     59 
     60   // And it shouldn't magically reappear...
     61   Context.enableDebugTypeODRUniquing();
     62   EXPECT_FALSE(DICompositeType::getODRTypeIfExists(Context, UUID));
     63 }
     64 
     65 TEST(DebugTypeODRUniquingTest, buildODRType) {
     66   LLVMContext Context;
     67   Context.enableDebugTypeODRUniquing();
     68 
     69   // Build an ODR type that's a forward decl.
     70   MDString &UUID = *MDString::get(Context, "Type");
     71   auto &CT = *DICompositeType::buildODRType(
     72       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
     73       nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
     74   EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
     75   EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
     76 
     77   // Update with another forward decl.  This should be a no-op.
     78   EXPECT_EQ(&CT, DICompositeType::buildODRType(
     79       Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
     80       nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
     81   EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
     82 
     83   // Update with a definition.  This time we should see a change.
     84   EXPECT_EQ(&CT, DICompositeType::buildODRType(
     85       Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
     86       nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr));
     87   EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
     88 
     89   // Further updates should be ignored.
     90   EXPECT_EQ(&CT, DICompositeType::buildODRType(
     91       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
     92       nullptr, 0, 0, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr));
     93   EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
     94   EXPECT_EQ(&CT, DICompositeType::buildODRType(
     95       Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
     96       nullptr, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr));
     97   EXPECT_EQ(dwarf::DW_TAG_structure_type, CT.getTag());
     98 }
     99 
    100 TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
    101   LLVMContext Context;
    102   Context.enableDebugTypeODRUniquing();
    103 
    104   // Build an ODR type that's a forward decl with no other fields set.
    105   MDString &UUID = *MDString::get(Context, "UUID");
    106   auto &CT = *DICompositeType::buildODRType(
    107       Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0,
    108       DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr);
    109 
    110 // Create macros for running through all the fields except Identifier and Flags.
    111 #define FOR_EACH_MDFIELD()                                                     \
    112   DO_FOR_FIELD(Name)                                                           \
    113   DO_FOR_FIELD(File)                                                           \
    114   DO_FOR_FIELD(Scope)                                                          \
    115   DO_FOR_FIELD(BaseType)                                                       \
    116   DO_FOR_FIELD(Elements)                                                       \
    117   DO_FOR_FIELD(VTableHolder)                                                   \
    118   DO_FOR_FIELD(TemplateParams)
    119 #define FOR_EACH_INLINEFIELD()                                                 \
    120   DO_FOR_FIELD(Tag)                                                            \
    121   DO_FOR_FIELD(Line)                                                           \
    122   DO_FOR_FIELD(SizeInBits)                                                     \
    123   DO_FOR_FIELD(AlignInBits)                                                    \
    124   DO_FOR_FIELD(OffsetInBits)                                                   \
    125   DO_FOR_FIELD(RuntimeLang)
    126 
    127 // Create all the fields.
    128 #define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X);
    129   FOR_EACH_MDFIELD();
    130 #undef DO_FOR_FIELD
    131   unsigned NonZeroInit = 0;
    132 #define DO_FOR_FIELD(X) auto X = ++NonZeroInit;
    133   FOR_EACH_INLINEFIELD();
    134 #undef DO_FOR_FIELD
    135 
    136   // Replace all the fields with new values that are distinct from each other.
    137   EXPECT_EQ(&CT,
    138             DICompositeType::buildODRType(
    139                 Context, UUID, Tag, Name, File, Line, Scope, BaseType,
    140                 SizeInBits, AlignInBits, OffsetInBits, DINode::FlagArtificial,
    141                 Elements, RuntimeLang, VTableHolder, TemplateParams));
    142 
    143   // Confirm that all the right fields got updated.
    144 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());
    145   FOR_EACH_MDFIELD();
    146 #undef DO_FOR_FIELD
    147 #undef FOR_EACH_MDFIELD
    148 #define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.get##X());
    149   FOR_EACH_INLINEFIELD();
    150 #undef DO_FOR_FIELD
    151 #undef FOR_EACH_INLINEFIELD
    152   EXPECT_EQ(DINode::FlagArtificial, CT.getFlags());
    153   EXPECT_EQ(&UUID, CT.getRawIdentifier());
    154 }
    155 
    156 } // end namespace
    157