Fix abi diffing to incporporate changes in type graphs.

We now need to convert from type ids to type names while adding a diff
message, since types don't have type names as references anymore.

Bug: 71486971

Test: tests/test.py test updation CL; all tests pass.

Test: tests/gen_all.py; manually diff between libcpp_gold.so.lsdump and
      libcpp_gold_member_diff.so.lsdump, diff is visually the same as
      before.

Test: build android source tree for aosp_arm64_ab; create reference
      dumps; rebuild; confirm no errors or warnings.

Change-Id: I17a3a1a02c5c2312e543a930ae3a1d9037e683b8
This commit is contained in:
Jayant Chowdhary
2018-01-22 12:50:40 -08:00
parent 3dc86c5263
commit 29738b5c14
7 changed files with 291 additions and 78 deletions

View File

@@ -46,34 +46,16 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::GenerateCompatibilityReport() {
return status; return status;
} }
template <typename KeyGetter, typename ValueGetter>
static void AddTypesToMap(AbiElementMap<const abi_util::TypeIR *> *dst,
const abi_util::TextFormatToIRReader *tu,
KeyGetter get_key, ValueGetter get_value) {
AddToMap(dst, tu->GetRecordTypes(), get_key, get_value);
AddToMap(dst, tu->GetEnumTypes(), get_key, get_value);
AddToMap(dst, tu->GetPointerTypes(), get_key, get_value);
AddToMap(dst, tu->GetBuiltinTypes(), get_key, get_value);
AddToMap(dst, tu->GetArrayTypes(), get_key, get_value);
AddToMap(dst, tu->GetLvalueReferenceTypes(), get_key, get_value);
AddToMap(dst, tu->GetRvalueReferenceTypes(), get_key, get_value);
AddToMap(dst, tu->GetQualifiedTypes(), get_key, get_value);
}
abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs( abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
const abi_util::TextFormatToIRReader *old_tu, const abi_util::TextFormatToIRReader *old_tu,
const abi_util::TextFormatToIRReader *new_tu, const abi_util::TextFormatToIRReader *new_tu,
abi_util::IRDiffDumper *ir_diff_dumper) { abi_util::IRDiffDumper *ir_diff_dumper) {
// Collect all old and new types in maps, so that we can refer to them by // Collect all old and new types in maps, so that we can refer to them by
// type name / linker_set_key later. // type name / linker_set_key later.
AbiElementMap<const abi_util::TypeIR *> old_types; const AbiElementMap<const abi_util::TypeIR *> old_types =
AbiElementMap<const abi_util::TypeIR *> new_types; old_tu->GetTypeGraph();
AddTypesToMap(&old_types, old_tu, const AbiElementMap<const abi_util::TypeIR *> new_types =
[](auto e) {return e->first;}, new_tu->GetTypeGraph();
[](auto e) {return &(e->second);});
AddTypesToMap(&new_types, new_tu,
[](auto e) {return e->first;},
[](auto e) {return &(e->second);});
// Collect fills in added, removed ,unsafe and safe function diffs. // Collect fills in added, removed ,unsafe and safe function diffs.
if (!CollectDynsymExportables(old_tu->GetFunctions(), new_tu->GetFunctions(), if (!CollectDynsymExportables(old_tu->GetFunctions(), new_tu->GetFunctions(),
@@ -108,42 +90,68 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
return combined_status; return combined_status;
} }
std::pair<AbiElementMap<const abi_util::EnumTypeIR *>,
AbiElementMap<const abi_util::RecordTypeIR *>>
HeaderAbiDiff::ExtractUserDefinedTypes(
const abi_util::TextFormatToIRReader *tu) {
AbiElementMap<const abi_util::EnumTypeIR *> enum_types;
AbiElementMap<const abi_util::RecordTypeIR *> record_types;
// Iterate through the ODRListMap, if there is more than 1 element in the
// list, we cannot really unique the type by name, so skip it. If not, add a
// map entry ODRListMapKey -> const Record(Enum)TypeIR *.
for (auto &it : tu->GetODRListMap()) {
auto &odr_list = it.second;
if (odr_list.size() != 1) {
continue;
}
const abi_util::TypeIR *type = *(odr_list.begin());
switch (type->GetKind()) {
case abi_util::RecordTypeKind:
record_types.emplace(type->GetLinkerSetKey(),
static_cast<const abi_util::RecordTypeIR *>(type));
break;
case abi_util::EnumTypeKind:
enum_types.emplace(type->GetLinkerSetKey(),
static_cast<const abi_util::EnumTypeIR *>(type));
break;
default:
// Only user defined types should have ODR list entries.
assert(0);
}
}
return std::make_pair(std::move(enum_types), std::move(record_types));
}
bool HeaderAbiDiff::CollectUserDefinedTypes( bool HeaderAbiDiff::CollectUserDefinedTypes(
const abi_util::TextFormatToIRReader *old_tu, const abi_util::TextFormatToIRReader *old_tu,
const abi_util::TextFormatToIRReader *new_tu, const abi_util::TextFormatToIRReader *new_tu,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map, const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map, const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper) { abi_util::IRDiffDumper *ir_diff_dumper) {
auto old_enums_and_records_extracted = ExtractUserDefinedTypes(old_tu);
auto new_enums_and_records_extracted = ExtractUserDefinedTypes(new_tu);
return CollectUserDefinedTypesInternal( return CollectUserDefinedTypesInternal(
old_tu->GetRecordTypes(), new_tu->GetRecordTypes(), old_types_map, old_enums_and_records_extracted.second,
new_enums_and_records_extracted.second, old_types_map,
new_types_map, ir_diff_dumper) && new_types_map, ir_diff_dumper) &&
CollectUserDefinedTypesInternal(old_tu->GetEnumTypes(), CollectUserDefinedTypesInternal(old_enums_and_records_extracted.first,
new_tu->GetEnumTypes(), old_types_map, new_enums_and_records_extracted.first,
new_types_map, ir_diff_dumper); old_types_map, new_types_map,
ir_diff_dumper);
} }
template <typename T> template <typename T>
bool HeaderAbiDiff::CollectUserDefinedTypesInternal( bool HeaderAbiDiff::CollectUserDefinedTypesInternal(
const AbiElementMap<T> &old_ud_types, const AbiElementMap<const T*> &old_ud_types_map,
const AbiElementMap<T> &new_ud_types, const AbiElementMap<const T*> &new_ud_types_map,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map, const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map, const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper) { abi_util::IRDiffDumper *ir_diff_dumper) {
// No elf information for records and enums.
AbiElementMap<const T *> old_ud_types_map;
AbiElementMap<const T *> new_ud_types_map;
abi_util::AddToMap(&old_ud_types_map, old_ud_types,
[](auto e) { return e->first;},
[](auto e) {return &(e->second);});
abi_util::AddToMap(&new_ud_types_map, new_ud_types,
[](auto e) { return e->first;},
[](auto e) {return &(e->second);});
return Collect(old_ud_types_map, new_ud_types_map, nullptr, nullptr, return Collect(old_ud_types_map, new_ud_types_map, nullptr, nullptr,
ir_diff_dumper) && ir_diff_dumper, old_types_map, new_types_map) &&
PopulateCommonElements(old_ud_types_map, new_ud_types_map, old_types_map, PopulateCommonElements(old_ud_types_map, new_ud_types_map, old_types_map,
new_types_map, ir_diff_dumper, new_types_map, ir_diff_dumper,
abi_util::DiffMessageIR::Unreferenced); abi_util::DiffMessageIR::Unreferenced);
@@ -182,7 +190,7 @@ bool HeaderAbiDiff::CollectDynsymExportables(
if (!Collect(old_exportables_map, if (!Collect(old_exportables_map,
new_exportables_map, &old_elf_symbol_map, &new_elf_symbol_map, new_exportables_map, &old_elf_symbol_map, &new_elf_symbol_map,
ir_diff_dumper) || ir_diff_dumper, old_types_map, new_types_map) ||
!CollectElfSymbols(old_elf_symbol_map, new_elf_symbol_map, !CollectElfSymbols(old_elf_symbol_map, new_elf_symbol_map,
ir_diff_dumper) || ir_diff_dumper) ||
!PopulateCommonElements(old_exportables_map, new_exportables_map, !PopulateCommonElements(old_exportables_map, new_exportables_map,
@@ -206,13 +214,16 @@ bool HeaderAbiDiff::Collect(
const AbiElementMap<const T*> &new_elements_map, const AbiElementMap<const T*> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
abi_util::IRDiffDumper *ir_diff_dumper) { abi_util::IRDiffDumper *ir_diff_dumper,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map) {
if (!PopulateRemovedElements( if (!PopulateRemovedElements(
old_elements_map, new_elements_map, new_elf_map, ir_diff_dumper, old_elements_map, new_elements_map, new_elf_map, ir_diff_dumper,
abi_util::DiffMessageIR::Removed) || abi_util::DiffMessageIR::Removed, old_types_map) ||
!PopulateRemovedElements(new_elements_map, old_elements_map, old_elf_map, !PopulateRemovedElements(new_elements_map, old_elements_map, old_elf_map,
ir_diff_dumper, ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind::Added)) { abi_util::IRDiffDumper::DiffKind::Added,
new_types_map)) {
llvm::errs() << "Populating functions in report failed\n"; llvm::errs() << "Populating functions in report failed\n";
return false; return false;
} }
@@ -253,10 +264,12 @@ bool HeaderAbiDiff::PopulateRemovedElements(
const AbiElementMap<const T*> &new_elements_map, const AbiElementMap<const T*> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper, abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind) { abi_util::IRDiffDumper::DiffKind diff_kind,
const AbiElementMap<const abi_util::TypeIR *> &removed_types_map) {
std::vector<const T *> removed_elements = std::vector<const T *> removed_elements =
abi_util::FindRemovedElements(old_elements_map, new_elements_map); abi_util::FindRemovedElements(old_elements_map, new_elements_map);
if (!DumpLoneElements(removed_elements, elf_map, ir_diff_dumper, diff_kind)) { if (!DumpLoneElements(removed_elements, elf_map, ir_diff_dumper, diff_kind,
removed_types_map)) {
llvm::errs() << "Dumping added / removed element to report failed\n"; llvm::errs() << "Dumping added / removed element to report failed\n";
return false; return false;
} }
@@ -289,7 +302,8 @@ bool HeaderAbiDiff::DumpLoneElements(
std::vector<const T *> &elements, std::vector<const T *> &elements,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper, abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind) { abi_util::IRDiffDumper::DiffKind diff_kind,
const AbiElementMap<const abi_util::TypeIR *> &types_map) {
// If the record / enum has source file information, skip it. // If the record / enum has source file information, skip it.
std::smatch source_file_match; std::smatch source_file_match;
std::regex source_file_regex(" at "); std::regex source_file_regex(" at ");
@@ -310,7 +324,9 @@ bool HeaderAbiDiff::DumpLoneElements(
source_file_regex)) { source_file_regex)) {
continue; continue;
} }
if (!ir_diff_dumper->AddLinkableMessageIR(element, diff_kind)) { auto element_copy = *element;
ReplaceTypeIdsWithTypeNames(types_map, &element_copy);
if (!ir_diff_dumper->AddLinkableMessageIR(&element_copy, diff_kind)) {
llvm::errs() << "Couldn't dump added /removed element\n"; llvm::errs() << "Couldn't dump added /removed element\n";
return false; return false;
} }

View File

@@ -60,7 +60,9 @@ class HeaderAbiDiff {
const AbiElementMap<const T *> &new_elements_map, const AbiElementMap<const T *> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
abi_util::IRDiffDumper *ir_diff_dumper); abi_util::IRDiffDumper *ir_diff_dumper,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map);
bool CollectElfSymbols( bool CollectElfSymbols(
const AbiElementMap<const abi_util::ElfSymbolIR *> &old_symbols, const AbiElementMap<const abi_util::ElfSymbolIR *> &old_symbols,
@@ -78,7 +80,8 @@ class HeaderAbiDiff {
const AbiElementMap<const T *> &new_elements_map, const AbiElementMap<const T *> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper, abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind); abi_util::IRDiffDumper::DiffKind diff_kind,
const AbiElementMap<const abi_util::TypeIR *> &types_map);
template <typename T> template <typename T>
bool PopulateCommonElements( bool PopulateCommonElements(
@@ -102,7 +105,12 @@ class HeaderAbiDiff {
std::vector<const T *> &elements, std::vector<const T *> &elements,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map, const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper, abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind); abi_util::IRDiffDumper::DiffKind diff_kind,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map);
std::pair<AbiElementMap<const abi_util::EnumTypeIR *>,
AbiElementMap<const abi_util::RecordTypeIR *>>
ExtractUserDefinedTypes(const abi_util::TextFormatToIRReader *tu);
bool CollectUserDefinedTypes( bool CollectUserDefinedTypes(
const abi_util::TextFormatToIRReader *old_tu, const abi_util::TextFormatToIRReader *old_tu,
@@ -113,8 +121,8 @@ class HeaderAbiDiff {
template <typename T> template <typename T>
bool CollectUserDefinedTypesInternal( bool CollectUserDefinedTypesInternal(
const AbiElementMap<T> &old_ud_types, const AbiElementMap<const T*> &old_ud_types_map,
const AbiElementMap<T> &new_ud_types, const AbiElementMap<const T*> &new_ud_types_map,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map, const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map, const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper); abi_util::IRDiffDumper *ir_diff_dumper);

View File

@@ -65,7 +65,12 @@ bool DiffWrapper<abi_util::GlobalVarIR>::DumpDiff(
DiffStatus access_diff = (oldp_->GetAccess() == newp_->GetAccess()) ? DiffStatus access_diff = (oldp_->GetAccess() == newp_->GetAccess()) ?
DiffStatus::no_diff : DiffStatus::direct_diff; DiffStatus::no_diff : DiffStatus::direct_diff;
if ((type_diff | access_diff) & DiffStatus::direct_diff) { if ((type_diff | access_diff) & DiffStatus::direct_diff) {
abi_util::GlobalVarDiffIR global_var_diff_ir(oldp_, newp_); abi_util::GlobalVarIR old_global_var = *oldp_;
abi_util::GlobalVarIR new_global_var = *newp_;
ReplaceTypeIdsWithTypeNames(old_types_, &old_global_var);
ReplaceTypeIdsWithTypeNames(new_types_, &new_global_var);
abi_util::GlobalVarDiffIR global_var_diff_ir(&old_global_var,
&new_global_var);
global_var_diff_ir.SetName(oldp_->GetName()); global_var_diff_ir.SetName(oldp_->GetName());
return ir_diff_dumper_->AddDiffMessageIR(&global_var_diff_ir, return ir_diff_dumper_->AddDiffMessageIR(&global_var_diff_ir,
Unwind(&type_queue), diff_kind); Unwind(&type_queue), diff_kind);
@@ -92,7 +97,11 @@ bool DiffWrapper<abi_util::FunctionIR>::DumpDiff(
if ((param_diffs == DiffStatus::direct_diff || if ((param_diffs == DiffStatus::direct_diff ||
return_type_diff == DiffStatus::direct_diff) || return_type_diff == DiffStatus::direct_diff) ||
(oldp_->GetAccess() != newp_->GetAccess())) { (oldp_->GetAccess() != newp_->GetAccess())) {
abi_util::FunctionDiffIR function_diff_ir(oldp_, newp_); abi_util::FunctionIR old_function = *oldp_;
abi_util::FunctionIR new_function = *newp_;
ReplaceTypeIdsWithTypeNames(old_types_, &old_function);
ReplaceTypeIdsWithTypeNames(new_types_, &new_function);
abi_util::FunctionDiffIR function_diff_ir(&old_function, &new_function);
function_diff_ir.SetName(oldp_->GetName()); function_diff_ir.SetName(oldp_->GetName());
return ir_diff_dumper_->AddDiffMessageIR(&function_diff_ir, return ir_diff_dumper_->AddDiffMessageIR(&function_diff_ir,
Unwind(&type_queue), diff_kind); Unwind(&type_queue), diff_kind);

View File

@@ -36,6 +36,7 @@ static bool IgnoreSymbol(const T *element,
template <typename T> template <typename T>
class DiffWrapper : public AbiDiffHelper { class DiffWrapper : public AbiDiffHelper {
public: public:
DiffWrapper(const T *oldp, const T *newp, DiffWrapper(const T *oldp, const T *newp,
abi_util::IRDiffDumper *ir_diff_dumper, abi_util::IRDiffDumper *ir_diff_dumper,
@@ -44,7 +45,9 @@ class DiffWrapper : public AbiDiffHelper {
std::set<std::string> *type_cache) std::set<std::string> *type_cache)
: AbiDiffHelper(old_types, new_types, type_cache, ir_diff_dumper), : AbiDiffHelper(old_types, new_types, type_cache, ir_diff_dumper),
oldp_(oldp), newp_(newp) { } oldp_(oldp), newp_(newp) { }
bool DumpDiff(abi_util::IRDiffDumper::DiffKind diff_kind); bool DumpDiff(abi_util::IRDiffDumper::DiffKind diff_kind);
private: private:
const T *oldp_; const T *oldp_;
const T *newp_; const T *newp_;

View File

@@ -102,6 +102,19 @@ class AbiDiffHelper {
std::deque<std::string> *type_queue, std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind); abi_util::IRDiffDumper::DiffKind diff_kind);
void ReplaceRemovedFieldTypeIdsWithTypeNames(
std::vector<abi_util::RecordFieldIR *> *removed_fields);
void ReplaceDiffedFieldTypeIdsWithTypeNames(
abi_util::RecordFieldDiffIR *diffed_field);
std::vector<std::pair<abi_util::RecordFieldIR, abi_util::RecordFieldIR>>
FixupDiffedFieldTypeIds(
const std::vector<abi_util::RecordFieldDiffIR> &field_diffs);
std::vector<abi_util::RecordFieldIR>FixupRemovedFieldTypeIds(
const std::vector<const abi_util::RecordFieldIR *> &fields_removed);
DiffStatusPair<std::unique_ptr<abi_util::RecordFieldDiffIR>> DiffStatusPair<std::unique_ptr<abi_util::RecordFieldDiffIR>>
CompareCommonRecordFields( CompareCommonRecordFields(
const abi_util::RecordFieldIR *old_field, const abi_util::RecordFieldIR *old_field,
@@ -158,5 +171,8 @@ class AbiDiffHelper {
AbiElementMap<MergeStatus> *local_to_global_type_id_map_ = nullptr; AbiElementMap<MergeStatus> *local_to_global_type_id_map_ = nullptr;
}; };
void ReplaceTypeIdsWithTypeNames(
const AbiElementMap<const TypeIR *> &type_graph, LinkableMessageIR *lm);
} // namespace abi_util } // namespace abi_util
#endif #endif

View File

@@ -1104,7 +1104,6 @@ class RecordFieldDiffIR {
return new_field_; return new_field_;
} }
protected:
const RecordFieldIR *old_field_; const RecordFieldIR *old_field_;
const RecordFieldIR *new_field_; const RecordFieldIR *new_field_;
}; };

View File

@@ -19,7 +19,7 @@ std::string Unwind(const std::deque<std::string> *type_queue) {
} }
static void TypeQueueCheckAndPushBack(std::deque<std::string> *type_queue, static void TypeQueueCheckAndPushBack(std::deque<std::string> *type_queue,
const std::string &str) { const std::string &str) {
if (type_queue) { if (type_queue) {
type_queue->push_back(str); type_queue->push_back(str);
} }
@@ -51,6 +51,96 @@ static bool IsAccessDownGraded(abi_util::AccessSpecifierIR old_access,
return access_downgraded; return access_downgraded;
} }
static std::string ConvertTypeIdToString(
const AbiElementMap<const TypeIR *> &type_graph,
const std::string &type_id) {
auto it = type_graph.find(type_id);
if (it != type_graph.end()) {
return it->second->GetName();
}
return "type-unexported";
}
template <typename Container>
static void ReplaceReferencesOtherTypeIdWithName(
const AbiElementMap<const TypeIR *> &type_graph,
Container &to_fix_elements) {
for (auto &element : to_fix_elements) {
element.SetReferencedType(
ConvertTypeIdToString(type_graph, element.GetReferencedType()));
}
}
static void ReplaceEnumTypeIRTypeIdsWithTypeNames(
const AbiElementMap<const TypeIR *> &type_graph,
EnumTypeIR *enum_type_ir) {
// Replace underlying type.
enum_type_ir->SetUnderlyingType(
ConvertTypeIdToString(type_graph, enum_type_ir->GetUnderlyingType()));
}
static void ReplaceRecordTypeIRTypeIdsWithTypeNames(
const AbiElementMap<const TypeIR *> &type_graph,
RecordTypeIR *record_type_ir) {
// Replace Fields
ReplaceReferencesOtherTypeIdWithName(type_graph,
record_type_ir->GetFields());
// Replace template parameters
ReplaceReferencesOtherTypeIdWithName(type_graph,
record_type_ir->GetTemplateElements());
// Replace bases
ReplaceReferencesOtherTypeIdWithName(type_graph,
record_type_ir->GetBases());
}
static void ReplaceGlobalVarTypeIdsWithTypeNames(
const AbiElementMap<const TypeIR *> &type_graph,
GlobalVarIR *global_var_ir) {
// Replace referenced type id.
global_var_ir->SetReferencedType(
ConvertTypeIdToString(type_graph, global_var_ir->GetReferencedType()));
}
static void ReplaceFunctionTypeIdsWithTypeNames(
const AbiElementMap<const TypeIR *> &type_graph, FunctionIR *function_ir) {
// Replace return type
function_ir->SetReturnType(
ConvertTypeIdToString(type_graph, function_ir->GetReturnType()));
// Replace function parameters
ReplaceReferencesOtherTypeIdWithName(type_graph,
function_ir->GetParameters());
// Replace function template parameters
ReplaceReferencesOtherTypeIdWithName(type_graph,
function_ir->GetTemplateElements());
}
void ReplaceTypeIdsWithTypeNames(
const AbiElementMap<const TypeIR *> &type_graph,
LinkableMessageIR *lm) {
switch (lm->GetKind()) {
case FunctionKind:
ReplaceFunctionTypeIdsWithTypeNames(type_graph,
static_cast<FunctionIR *>(lm));
break;
case GlobalVarKind:
ReplaceGlobalVarTypeIdsWithTypeNames(type_graph,
static_cast<GlobalVarIR *>(lm));
break;
case RecordTypeKind:
ReplaceRecordTypeIRTypeIdsWithTypeNames(type_graph,
static_cast<RecordTypeIR *>(lm));
break;
case EnumTypeKind:
ReplaceEnumTypeIRTypeIdsWithTypeNames(type_graph,
static_cast<EnumTypeIR *>(lm));
break;
default:
// This method should not be called on any other LinkableMessage
assert(0);
}
}
void AbiDiffHelper::CompareEnumFields( void AbiDiffHelper::CompareEnumFields(
const std::vector<abi_util::EnumFieldIR> &old_fields, const std::vector<abi_util::EnumFieldIR> &old_fields,
const std::vector<abi_util::EnumFieldIR> &new_fields, const std::vector<abi_util::EnumFieldIR> &new_fields,
@@ -98,8 +188,10 @@ DiffStatus AbiDiffHelper::CompareEnumTypes(
} }
auto enum_type_diff_ir = std::make_unique<abi_util::EnumTypeDiffIR>(); auto enum_type_diff_ir = std::make_unique<abi_util::EnumTypeDiffIR>();
enum_type_diff_ir->SetName(old_type->GetName()); enum_type_diff_ir->SetName(old_type->GetName());
const std::string &old_underlying_type = old_type->GetUnderlyingType(); const std::string &old_underlying_type =
const std::string &new_underlying_type = new_type->GetUnderlyingType(); ConvertTypeIdToString(old_types_, old_type->GetUnderlyingType());
const std::string &new_underlying_type =
ConvertTypeIdToString(new_types_, new_type->GetUnderlyingType());
if (old_underlying_type != new_underlying_type) { if (old_underlying_type != new_underlying_type) {
enum_type_diff_ir->SetUnderlyingTypeDiff( enum_type_diff_ir->SetUnderlyingTypeDiff(
std::make_unique<std::pair<std::string, std::string>>( std::make_unique<std::pair<std::string, std::string>>(
@@ -189,7 +281,7 @@ AbiDiffHelper::CompareRecordFields(
std::deque<std::string> *type_queue, std::deque<std::string> *type_queue,
abi_util::DiffMessageIR::DiffKind diff_kind) { abi_util::DiffMessageIR::DiffKind diff_kind) {
std::pair<std::vector<abi_util::RecordFieldDiffIR>, std::pair<std::vector<abi_util::RecordFieldDiffIR>,
std::vector<const abi_util::RecordFieldIR *>> diffed_and_removed_fields; std::vector<const abi_util::RecordFieldIR *>> diffed_and_removed_fields;
AbiElementMap<const abi_util::RecordFieldIR *> old_fields_map; AbiElementMap<const abi_util::RecordFieldIR *> old_fields_map;
AbiElementMap<const abi_util::RecordFieldIR *> new_fields_map; AbiElementMap<const abi_util::RecordFieldIR *> new_fields_map;
std::map<uint64_t, const abi_util::RecordFieldIR *> old_fields_offset_map; std::map<uint64_t, const abi_util::RecordFieldIR *> old_fields_offset_map;
@@ -235,6 +327,7 @@ AbiDiffHelper::CompareRecordFields(
removed_fields.erase( removed_fields.erase(
std::remove_if(removed_fields.begin(), removed_fields.end(), predicate), std::remove_if(removed_fields.begin(), removed_fields.end(), predicate),
removed_fields.end()); removed_fields.end());
diffed_and_removed_fields.second = std::move(removed_fields); diffed_and_removed_fields.second = std::move(removed_fields);
std::vector<std::pair< std::vector<std::pair<
const abi_util::RecordFieldIR *, const abi_util::RecordFieldIR *>> cf = const abi_util::RecordFieldIR *, const abi_util::RecordFieldIR *>> cf =
@@ -292,7 +385,6 @@ void AbiDiffHelper::CompareTemplateInfo(
std::deque<std::string> *type_queue, std::deque<std::string> *type_queue,
abi_util::DiffMessageIR::DiffKind diff_kind) { abi_util::DiffMessageIR::DiffKind diff_kind) {
uint32_t old_template_size = old_template_elements.size(); uint32_t old_template_size = old_template_elements.size();
assert(old_template_size == new_template_elements.size());
uint32_t i = 0; uint32_t i = 0;
while (i < old_template_size) { while (i < old_template_size) {
const abi_util::TemplateElementIR &old_template_element = const abi_util::TemplateElementIR &old_template_element =
@@ -306,6 +398,57 @@ void AbiDiffHelper::CompareTemplateInfo(
} }
} }
template <typename DiffContainer, typename T>
static std::vector<DiffContainer> ConvertToDiffContainerVector(
std::vector<std::pair<T, T>> &nc_vector) {
std::vector<DiffContainer> cptr_vec;
for (auto &e : nc_vector) {
cptr_vec.emplace_back(&e.first, &e.second);
}
return cptr_vec;
}
template <typename T>
static std::vector<const T*> ConvertToConstPtrVector(
std::vector<T> &nc_vector) {
std::vector<const T*> cptr_vec;
for (auto &e : nc_vector) {
cptr_vec.emplace_back(&e);
}
return cptr_vec;
}
std::vector<abi_util::RecordFieldIR> AbiDiffHelper::FixupRemovedFieldTypeIds(
const std::vector<const abi_util::RecordFieldIR *> &removed_fields) {
std::vector<abi_util::RecordFieldIR> removed_fields_dup;
for (auto &removed_field : removed_fields) {
removed_fields_dup.emplace_back(*removed_field);
RecordFieldIR &it = removed_fields_dup[removed_fields_dup.size() -1];
it.SetReferencedType(
ConvertTypeIdToString(old_types_, it.GetReferencedType()));
}
return removed_fields_dup;
}
std::vector<std::pair<abi_util::RecordFieldIR, abi_util::RecordFieldIR>>
AbiDiffHelper::FixupDiffedFieldTypeIds(
const std::vector<abi_util::RecordFieldDiffIR> &field_diffs) {
std::vector<std::pair<abi_util::RecordFieldIR, abi_util::RecordFieldIR>>
diffed_fields_dup;
for (auto &field_diff : field_diffs) {
diffed_fields_dup.emplace_back(*(field_diff.old_field_),
*(field_diff.new_field_));
auto it = diffed_fields_dup[diffed_fields_dup.size() - 1];
abi_util::RecordFieldIR &old_field = it.first;
abi_util::RecordFieldIR &new_field = it.second;
old_field.SetReferencedType(
ConvertTypeIdToString(old_types_, old_field.GetReferencedType()));
new_field.SetReferencedType(
ConvertTypeIdToString(new_types_, new_field.GetReferencedType()));
}
return diffed_fields_dup;
}
DiffStatus AbiDiffHelper::CompareRecordTypes( DiffStatus AbiDiffHelper::CompareRecordTypes(
const abi_util::RecordTypeIR *old_type, const abi_util::RecordTypeIR *old_type,
const abi_util::RecordTypeIR *new_type, const abi_util::RecordTypeIR *new_type,
@@ -342,32 +485,50 @@ DiffStatus AbiDiffHelper::CompareRecordTypes(
std::make_unique<abi_util::VTableLayoutDiffIR>( std::make_unique<abi_util::VTableLayoutDiffIR>(
old_type->GetVTableLayout(), new_type->GetVTableLayout())); old_type->GetVTableLayout(), new_type->GetVTableLayout()));
} }
auto &old_fields_dup = old_type->GetFields();
auto &new_fields_dup = new_type->GetFields();
auto field_status_and_diffs = auto field_status_and_diffs =
CompareRecordFields(old_type->GetFields(), new_type->GetFields(), CompareRecordFields(old_fields_dup, new_fields_dup,
type_queue, diff_kind); type_queue, diff_kind);
// TODO: combine this with base class diffs as well. // TODO: combine this with base class diffs as well.
final_diff_status = final_diff_status | field_status_and_diffs.first; final_diff_status = final_diff_status | field_status_and_diffs.first;
auto field_diffs = field_status_and_diffs.second; auto field_diffs = field_status_and_diffs.second;
record_type_diff_ir->SetFieldDiffs(std::move(field_diffs.first));
record_type_diff_ir->SetFieldsRemoved(std::move(field_diffs.second));
const std::vector<abi_util::CXXBaseSpecifierIR> &old_bases =
old_type->GetBases();
const std::vector<abi_util::CXXBaseSpecifierIR> &new_bases =
new_type->GetBases();
if (!CompareBaseSpecifiers(old_bases, new_bases, type_queue, diff_kind)) { std::vector<abi_util::CXXBaseSpecifierIR> old_bases = old_type->GetBases();
std::vector<abi_util::CXXBaseSpecifierIR> new_bases = new_type->GetBases();
if (!CompareBaseSpecifiers(old_bases, new_bases, type_queue, diff_kind) &&
ir_diff_dumper_) {
ReplaceReferencesOtherTypeIdWithName(old_types_, old_bases);
ReplaceReferencesOtherTypeIdWithName(new_types_, new_bases);
record_type_diff_ir->SetBaseSpecifierDiffs ( record_type_diff_ir->SetBaseSpecifierDiffs (
std::make_unique<abi_util::CXXBaseSpecifierDiffIR>(old_bases, std::make_unique<abi_util::CXXBaseSpecifierDiffIR>(old_bases,
new_bases)); new_bases));
} }
if (record_type_diff_ir->DiffExists() && if (ir_diff_dumper_) {
ir_diff_dumper_ && // Make copies of the fields removed and diffed, since we have to change
!ir_diff_dumper_->AddDiffMessageIR(record_type_diff_ir.get(), // type ids -> type strings.
Unwind(type_queue), diff_kind)) { std::vector<std::pair<RecordFieldIR, RecordFieldIR>> field_diff_dups =
llvm::errs() << "AddDiffMessage on record type failed\n"; FixupDiffedFieldTypeIds(field_diffs.first);
::exit(1); std::vector<abi_util::RecordFieldDiffIR> field_diffs_fixed =
} // No need to add a dump for an extension since records can't be "extended". ConvertToDiffContainerVector<abi_util::RecordFieldDiffIR,
abi_util::RecordFieldIR>(field_diff_dups);
std::vector<abi_util::RecordFieldIR> field_removed_dups =
FixupRemovedFieldTypeIds(field_diffs.second);
std::vector<const abi_util::RecordFieldIR *> fields_removed_fixed =
ConvertToConstPtrVector(field_removed_dups);
record_type_diff_ir->SetFieldDiffs(std::move(field_diffs_fixed));
record_type_diff_ir->SetFieldsRemoved(std::move(fields_removed_fixed));
if (record_type_diff_ir->DiffExists() &&
!ir_diff_dumper_->AddDiffMessageIR(record_type_diff_ir.get(),
Unwind(type_queue), diff_kind)) {
llvm::errs() << "AddDiffMessage on record type failed\n";
::exit(1);
} // No need to add a dump for an extension since records can't be "extended".
}
CompareTemplateInfo(old_type->GetTemplateElements(), CompareTemplateInfo(old_type->GetTemplateElements(),
new_type->GetTemplateElements(), new_type->GetTemplateElements(),
type_queue, diff_kind); type_queue, diff_kind);
@@ -545,7 +706,8 @@ DiffStatus AbiDiffHelper::CompareAndDumpTypeDiff(
if (!type_cache_->insert(old_type_id + new_type_id).second) { if (!type_cache_->insert(old_type_id + new_type_id).second) {
return DiffStatus::no_diff; return DiffStatus::no_diff;
} else { } else {
TypeQueueCheckAndPushBack(type_queue, old_type_id); TypeQueueCheckAndPushBack(type_queue,
ConvertTypeIdToString(old_types_,old_type_id));
} }
AbiElementMap<const abi_util::TypeIR *>::const_iterator old_it = AbiElementMap<const abi_util::TypeIR *>::const_iterator old_it =
old_types_.find(old_type_id); old_types_.find(old_type_id);