Merge changes from topic "multithreaded-header-linker-ir"
am: 6a233fe18a
Change-Id: I0ac785a3c0e1fa007932a465935979dca4fd6470
This commit is contained in:
@@ -18,9 +18,6 @@
|
||||
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -30,16 +27,16 @@
|
||||
abi_util::CompatibilityStatusIR HeaderAbiDiff::GenerateCompatibilityReport() {
|
||||
using abi_util::TextFormatToIRReader;
|
||||
std::unique_ptr<abi_util::TextFormatToIRReader> old_reader =
|
||||
TextFormatToIRReader::CreateTextFormatToIRReader("protobuf", old_dump_);
|
||||
TextFormatToIRReader::CreateTextFormatToIRReader(text_format_old_);
|
||||
std::unique_ptr<abi_util::TextFormatToIRReader> new_reader =
|
||||
TextFormatToIRReader::CreateTextFormatToIRReader("protobuf", new_dump_);
|
||||
if (!old_reader || !new_reader || !old_reader->ReadDump() ||
|
||||
!new_reader->ReadDump()) {
|
||||
TextFormatToIRReader::CreateTextFormatToIRReader(text_format_new_);
|
||||
if (!old_reader || !new_reader || !old_reader->ReadDump(old_dump_) ||
|
||||
!new_reader->ReadDump(new_dump_)) {
|
||||
llvm::errs() << "Could not create Text Format readers\n";
|
||||
::exit(1);
|
||||
}
|
||||
std::unique_ptr<abi_util::IRDiffDumper> ir_diff_dumper =
|
||||
abi_util::IRDiffDumper::CreateIRDiffDumper("protobuf", cr_);
|
||||
abi_util::IRDiffDumper::CreateIRDiffDumper(text_format_diff_, cr_);
|
||||
abi_util::CompatibilityStatusIR status =
|
||||
CompareTUs(old_reader.get(), new_reader.get(), ir_diff_dumper.get());
|
||||
if (!ir_diff_dumper->Dump()) {
|
||||
@@ -49,17 +46,18 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::GenerateCompatibilityReport() {
|
||||
return status;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static void AddTypesToMap(std::map<std::string, const abi_util::TypeIR *> *dst,
|
||||
const abi_util::TextFormatToIRReader *tu, F func) {
|
||||
AddToMap(dst, tu->GetRecordTypes(), func);
|
||||
AddToMap(dst, tu->GetEnumTypes(), func);
|
||||
AddToMap(dst, tu->GetPointerTypes(), func);
|
||||
AddToMap(dst, tu->GetBuiltinTypes(), func);
|
||||
AddToMap(dst, tu->GetArrayTypes(), func);
|
||||
AddToMap(dst, tu->GetLvalueReferenceTypes(), func);
|
||||
AddToMap(dst, tu->GetRvalueReferenceTypes(), func);
|
||||
AddToMap(dst, tu->GetQualifiedTypes(), func);
|
||||
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(
|
||||
@@ -68,12 +66,14 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
// Collect all old and new types in maps, so that we can refer to them by
|
||||
// type name / linker_set_key later.
|
||||
std::map<std::string, const abi_util::TypeIR *> old_types;
|
||||
std::map<std::string, const abi_util::TypeIR *> new_types;
|
||||
AbiElementMap<const abi_util::TypeIR *> old_types;
|
||||
AbiElementMap<const abi_util::TypeIR *> new_types;
|
||||
AddTypesToMap(&old_types, old_tu,
|
||||
[](const abi_util::TypeIR *e) {return e->GetLinkerSetKey();});
|
||||
[](auto e) {return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
AddTypesToMap(&new_types, new_tu,
|
||||
[](const abi_util::TypeIR *e) {return e->GetLinkerSetKey();});
|
||||
[](auto e) {return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
|
||||
// Collect fills in added, removed ,unsafe and safe function diffs.
|
||||
if (!CollectDynsymExportables(old_tu->GetFunctions(), new_tu->GetFunctions(),
|
||||
@@ -111,8 +111,8 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
|
||||
bool HeaderAbiDiff::CollectUserDefinedTypes(
|
||||
const abi_util::TextFormatToIRReader *old_tu,
|
||||
const abi_util::TextFormatToIRReader *new_tu,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
return CollectUserDefinedTypesInternal(
|
||||
old_tu->GetRecordTypes(), new_tu->GetRecordTypes(), old_types_map,
|
||||
@@ -124,22 +124,23 @@ bool HeaderAbiDiff::CollectUserDefinedTypes(
|
||||
|
||||
template <typename T>
|
||||
bool HeaderAbiDiff::CollectUserDefinedTypesInternal(
|
||||
const std::vector<T> &old_ud_types,
|
||||
const std::vector<T> &new_ud_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
|
||||
const AbiElementMap<T> &old_ud_types,
|
||||
const AbiElementMap<T> &new_ud_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
|
||||
// No elf information for records and enums.
|
||||
std::map<std::string, const T *> old_ud_types_map;
|
||||
std::map<std::string, const T *> new_ud_types_map;
|
||||
AbiElementMap<const T *> old_ud_types_map;
|
||||
AbiElementMap<const T *> new_ud_types_map;
|
||||
|
||||
abi_util::AddToMap(&old_ud_types_map, old_ud_types,
|
||||
[](const T *e)
|
||||
{ return e->GetLinkerSetKey();});
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
|
||||
abi_util::AddToMap(&new_ud_types_map, new_ud_types,
|
||||
[](const T *e)
|
||||
{ return e->GetLinkerSetKey();});
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
|
||||
return Collect(old_ud_types_map, new_ud_types_map, nullptr, nullptr,
|
||||
ir_diff_dumper) &&
|
||||
@@ -150,30 +151,34 @@ bool HeaderAbiDiff::CollectUserDefinedTypesInternal(
|
||||
|
||||
template <typename T, typename ElfSymbolType>
|
||||
bool HeaderAbiDiff::CollectDynsymExportables(
|
||||
const std::vector<T> &old_exportables,
|
||||
const std::vector<T> &new_exportables,
|
||||
const std::vector<ElfSymbolType> &old_elf_symbols,
|
||||
const std::vector<ElfSymbolType> &new_elf_symbols,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
|
||||
const AbiElementMap<T> &old_exportables,
|
||||
const AbiElementMap<T> &new_exportables,
|
||||
const AbiElementMap<ElfSymbolType> &old_elf_symbols,
|
||||
const AbiElementMap<ElfSymbolType> &new_elf_symbols,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
std::map<std::string, const T *> old_exportables_map;
|
||||
std::map<std::string, const T *> new_exportables_map;
|
||||
std::map<std::string, const abi_util::ElfSymbolIR *> old_elf_symbol_map;
|
||||
std::map<std::string, const abi_util::ElfSymbolIR *> new_elf_symbol_map;
|
||||
AbiElementMap<const T *> old_exportables_map;
|
||||
AbiElementMap<const T *> new_exportables_map;
|
||||
AbiElementMap<const abi_util::ElfSymbolIR *> old_elf_symbol_map;
|
||||
AbiElementMap<const abi_util::ElfSymbolIR *> new_elf_symbol_map;
|
||||
|
||||
abi_util::AddToMap(&old_exportables_map, old_exportables,
|
||||
[](const T *e)
|
||||
{ return e->GetLinkerSetKey();});
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
abi_util::AddToMap(&new_exportables_map, new_exportables,
|
||||
[](const T *e)
|
||||
{ return e->GetLinkerSetKey();});
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) { return &(e->second);});
|
||||
|
||||
abi_util::AddToMap(
|
||||
&old_elf_symbol_map, old_elf_symbols,
|
||||
[](const ElfSymbolType *symbol) { return symbol->GetName();});
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
|
||||
abi_util::AddToMap(
|
||||
&new_elf_symbol_map, new_elf_symbols,
|
||||
[](const ElfSymbolType *symbol) { return symbol->GetName();});
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
|
||||
if (!Collect(old_exportables_map,
|
||||
new_exportables_map, &old_elf_symbol_map, &new_elf_symbol_map,
|
||||
@@ -197,10 +202,10 @@ bool HeaderAbiDiff::CollectDynsymExportables(
|
||||
|
||||
template <typename T>
|
||||
bool HeaderAbiDiff::Collect(
|
||||
const std::map<std::string, const T*> &old_elements_map,
|
||||
const std::map<std::string, const T*> &new_elements_map,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *old_elf_map,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *new_elf_map,
|
||||
const AbiElementMap<const T*> &old_elements_map,
|
||||
const AbiElementMap<const T*> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
if (!PopulateRemovedElements(
|
||||
old_elements_map, new_elements_map, new_elf_map, ir_diff_dumper,
|
||||
@@ -215,8 +220,8 @@ bool HeaderAbiDiff::Collect(
|
||||
}
|
||||
|
||||
bool HeaderAbiDiff::CollectElfSymbols(
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> &old_symbols,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> &new_symbols,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> &old_symbols,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> &new_symbols,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
std::vector<const abi_util::ElfSymbolIR *> removed_elements =
|
||||
abi_util::FindRemovedElements(old_symbols, new_symbols);
|
||||
@@ -244,9 +249,9 @@ bool HeaderAbiDiff::PopulateElfElements(
|
||||
|
||||
template <typename T>
|
||||
bool HeaderAbiDiff::PopulateRemovedElements(
|
||||
const std::map<std::string, const T*> &old_elements_map,
|
||||
const std::map<std::string, const T*> &new_elements_map,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
|
||||
const AbiElementMap<const T*> &old_elements_map,
|
||||
const AbiElementMap<const T*> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind) {
|
||||
std::vector<const T *> removed_elements =
|
||||
@@ -258,12 +263,15 @@ bool HeaderAbiDiff::PopulateRemovedElements(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find the common elements (common records, common enums, common functions etc)
|
||||
// Dump the differences (we need type maps for this diff since we'll get
|
||||
// reachable types from here)
|
||||
template <typename T>
|
||||
bool HeaderAbiDiff::PopulateCommonElements(
|
||||
const std::map<std::string, const T *> &old_elements_map,
|
||||
const std::map<std::string, const T *> &new_elements_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types,
|
||||
const AbiElementMap<const T *> &old_elements_map,
|
||||
const AbiElementMap<const T *> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind) {
|
||||
std::vector<std::pair<const T *, const T *>> common_elements =
|
||||
@@ -279,7 +287,7 @@ bool HeaderAbiDiff::PopulateCommonElements(
|
||||
template <typename T>
|
||||
bool HeaderAbiDiff::DumpLoneElements(
|
||||
std::vector<const T *> &elements,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind) {
|
||||
// If the record / enum has source file information, skip it.
|
||||
@@ -310,12 +318,11 @@ bool HeaderAbiDiff::DumpLoneElements(
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
bool HeaderAbiDiff::DumpDiffElements(
|
||||
std::vector<std::pair<const T *,const T *>> &pairs,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind) {
|
||||
for (auto &&pair : pairs) {
|
||||
|
||||
@@ -26,16 +26,22 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using abi_util::AbiElementMap;
|
||||
|
||||
class HeaderAbiDiff {
|
||||
public:
|
||||
HeaderAbiDiff(const std::string &lib_name, const std::string &arch,
|
||||
const std::string &old_dump, const std::string &new_dump,
|
||||
const std::string &compatibility_report,
|
||||
const std::set<std::string> &ignored_symbols,
|
||||
bool check_all_apis)
|
||||
bool check_all_apis, abi_util::TextFormatIR text_format_old,
|
||||
abi_util::TextFormatIR text_format_new,
|
||||
abi_util::TextFormatIR text_format_diff)
|
||||
: lib_name_(lib_name), arch_(arch), old_dump_(old_dump),
|
||||
new_dump_(new_dump), cr_(compatibility_report),
|
||||
ignored_symbols_(ignored_symbols), check_all_apis_(check_all_apis) { }
|
||||
ignored_symbols_(ignored_symbols), check_all_apis_(check_all_apis),
|
||||
text_format_old_(text_format_old), text_format_new_(text_format_new),
|
||||
text_format_diff_(text_format_diff) { }
|
||||
|
||||
abi_util::CompatibilityStatusIR GenerateCompatibilityReport();
|
||||
|
||||
@@ -47,25 +53,25 @@ class HeaderAbiDiff {
|
||||
|
||||
template <typename T, typename ElfSymbolType>
|
||||
bool CollectDynsymExportables(
|
||||
const std::vector<T> &old_exportables,
|
||||
const std::vector<T> &new_exportables,
|
||||
const std::vector<ElfSymbolType> &old_elf_symbols,
|
||||
const std::vector<ElfSymbolType> &new_elf_symbols,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
|
||||
const AbiElementMap<T> &old_exportables,
|
||||
const AbiElementMap<T> &new_exportables,
|
||||
const AbiElementMap<ElfSymbolType> &old_elf_symbols,
|
||||
const AbiElementMap<ElfSymbolType> &new_elf_symbols,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper);
|
||||
|
||||
template <typename T>
|
||||
bool Collect(
|
||||
const std::map<std::string, const T *> &old_elements_map,
|
||||
const std::map<std::string, const T *> &new_elements_map,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *old_elf_map,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *new_elf_map,
|
||||
const AbiElementMap<const T *> &old_elements_map,
|
||||
const AbiElementMap<const T *> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper);
|
||||
|
||||
bool CollectElfSymbols(
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> &old_symbols,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> &new_symbols,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> &old_symbols,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> &new_symbols,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper);
|
||||
|
||||
bool PopulateElfElements(
|
||||
@@ -75,49 +81,49 @@ class HeaderAbiDiff {
|
||||
|
||||
template <typename T>
|
||||
bool PopulateRemovedElements(
|
||||
const std::map<std::string, const T *> &old_elements_map,
|
||||
const std::map<std::string, const T *> &new_elements_map,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
|
||||
const AbiElementMap<const T *> &old_elements_map,
|
||||
const AbiElementMap<const T *> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
template <typename T>
|
||||
bool PopulateCommonElements(
|
||||
const std::map<std::string, const T *> &old_elements_map,
|
||||
const std::map<std::string, const T *> &new_elements_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types,
|
||||
const AbiElementMap<const T *> &old_elements_map,
|
||||
const AbiElementMap<const T *> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
template <typename T>
|
||||
bool DumpDiffElements(
|
||||
std::vector<std::pair<const T *, const T *>> &pairs,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
template <typename T>
|
||||
bool DumpLoneElements(
|
||||
std::vector<const T *> &elements,
|
||||
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
bool CollectUserDefinedTypes(
|
||||
const abi_util::TextFormatToIRReader *old_tu,
|
||||
const abi_util::TextFormatToIRReader *new_tu,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper);
|
||||
|
||||
template <typename T>
|
||||
bool CollectUserDefinedTypesInternal(
|
||||
const std::vector<T> &old_ud_types,
|
||||
const std::vector<T> &new_ud_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
|
||||
const AbiElementMap<T> &old_ud_types,
|
||||
const AbiElementMap<T> &new_ud_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper);
|
||||
|
||||
private:
|
||||
@@ -129,4 +135,7 @@ class HeaderAbiDiff {
|
||||
const std::set<std::string> &ignored_symbols_;
|
||||
bool check_all_apis_;
|
||||
std::set<std::string> type_cache_;
|
||||
abi_util::TextFormatIR text_format_old_;
|
||||
abi_util::TextFormatIR text_format_new_;
|
||||
abi_util::TextFormatIR text_format_diff_;
|
||||
};
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
namespace abi_diff_wrappers {
|
||||
|
||||
using abi_util::AbiElementMap;
|
||||
|
||||
static bool IsAccessDownGraded(abi_util::AccessSpecifierIR old_access,
|
||||
abi_util::AccessSpecifierIR new_access) {
|
||||
bool access_downgraded = false;
|
||||
@@ -57,14 +59,16 @@ void DiffWrapperBase::CompareEnumFields(
|
||||
const std::vector<abi_util::EnumFieldIR> &old_fields,
|
||||
const std::vector<abi_util::EnumFieldIR> &new_fields,
|
||||
abi_util::EnumTypeDiffIR *enum_type_diff_ir) {
|
||||
std::map<std::string, const abi_util::EnumFieldIR *> old_fields_map;
|
||||
std::map<std::string, const abi_util::EnumFieldIR *> new_fields_map;
|
||||
AbiElementMap<const abi_util::EnumFieldIR *> old_fields_map;
|
||||
AbiElementMap<const abi_util::EnumFieldIR *> new_fields_map;
|
||||
abi_util::AddToMap(&old_fields_map, old_fields,
|
||||
[](const abi_util::EnumFieldIR *f)
|
||||
{return f->GetName();});
|
||||
[](const abi_util::EnumFieldIR *f) {return f->GetName();},
|
||||
[](const abi_util::EnumFieldIR *f) {return f;});
|
||||
|
||||
abi_util::AddToMap(&new_fields_map, new_fields,
|
||||
[](const abi_util::EnumFieldIR *f)
|
||||
{return f->GetName();});
|
||||
[](const abi_util::EnumFieldIR *f) {return f->GetName();},
|
||||
[](const abi_util::EnumFieldIR *f) {return f;});
|
||||
|
||||
std::vector<const abi_util::EnumFieldIR *> removed_fields =
|
||||
abi_util::FindRemovedElements(old_fields_map, new_fields_map);
|
||||
|
||||
@@ -184,23 +188,27 @@ DiffWrapperBase::CompareRecordFields(
|
||||
abi_util::DiffMessageIR::DiffKind diff_kind) {
|
||||
std::pair<std::vector<abi_util::RecordFieldDiffIR>,
|
||||
std::vector<const abi_util::RecordFieldIR *>> diffed_and_removed_fields;
|
||||
std::map<std::string, const abi_util::RecordFieldIR *> old_fields_map;
|
||||
std::map<std::string, const abi_util::RecordFieldIR *> new_fields_map;
|
||||
AbiElementMap<const abi_util::RecordFieldIR *> old_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 *> new_fields_offset_map;
|
||||
|
||||
abi_util::AddToMap(&old_fields_map, old_fields,
|
||||
[](const abi_util::RecordFieldIR *f)
|
||||
{return f->GetName();});
|
||||
abi_util::AddToMap(&new_fields_map, new_fields,
|
||||
[](const abi_util::RecordFieldIR *f)
|
||||
{return f->GetName();});
|
||||
abi_util::AddToMap(&old_fields_offset_map, old_fields,
|
||||
[](const abi_util::RecordFieldIR *f)
|
||||
{return f->GetOffset();});
|
||||
abi_util::AddToMap(&new_fields_offset_map, new_fields,
|
||||
[](const abi_util::RecordFieldIR *f)
|
||||
{return f->GetOffset();});
|
||||
abi_util::AddToMap(
|
||||
&old_fields_map, old_fields,
|
||||
[](const abi_util::RecordFieldIR *f) {return f->GetName();},
|
||||
[](const abi_util::RecordFieldIR *f) {return f;});
|
||||
abi_util::AddToMap(
|
||||
&new_fields_map, new_fields,
|
||||
[](const abi_util::RecordFieldIR *f) {return f->GetName();},
|
||||
[](const abi_util::RecordFieldIR *f) {return f;});
|
||||
abi_util::AddToMap(
|
||||
&old_fields_offset_map, old_fields,
|
||||
[](const abi_util::RecordFieldIR *f) {return f->GetOffset();},
|
||||
[](const abi_util::RecordFieldIR *f) {return f;});
|
||||
abi_util::AddToMap(
|
||||
&new_fields_offset_map, new_fields,
|
||||
[](const abi_util::RecordFieldIR *f) {return f->GetOffset();},
|
||||
[](const abi_util::RecordFieldIR *f) {return f;});
|
||||
// If a field is removed from the map field_name -> offset see if another
|
||||
// field is present at the same offset and compare the size and type etc,
|
||||
// remove it from the removed fields if they're compatible.
|
||||
@@ -522,9 +530,9 @@ DiffStatus DiffWrapperBase::CompareAndDumpTypeDiff(
|
||||
}
|
||||
type_queue->push_back(old_type_str);
|
||||
}
|
||||
std::map<std::string, const abi_util::TypeIR *>::const_iterator old_it =
|
||||
AbiElementMap<const abi_util::TypeIR *>::const_iterator old_it =
|
||||
old_types_.find(old_type_str);
|
||||
std::map<std::string, const abi_util::TypeIR *>::const_iterator new_it =
|
||||
AbiElementMap<const abi_util::TypeIR *>::const_iterator new_it =
|
||||
new_types_.find(new_type_str);
|
||||
if (old_it == old_types_.end() || new_it == new_types_.end()) {
|
||||
// Do a simple string comparison.
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
namespace abi_diff_wrappers {
|
||||
|
||||
using abi_util::AbiElementMap;
|
||||
|
||||
template <typename T, typename F>
|
||||
static bool IgnoreSymbol(const T *element,
|
||||
const std::set<std::string> &ignored_symbols,
|
||||
@@ -50,8 +52,8 @@ class DiffWrapperBase {
|
||||
protected:
|
||||
DiffWrapperBase(
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types,
|
||||
std::set<std::string> *type_cache)
|
||||
: ir_diff_dumper_(ir_diff_dumper),
|
||||
old_types_(old_types), new_types_(new_types),
|
||||
@@ -157,8 +159,8 @@ class DiffWrapperBase {
|
||||
std::deque<std::string> *type_queue = nullptr);
|
||||
protected:
|
||||
abi_util::IRDiffDumper *ir_diff_dumper_;
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types_;
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types_;
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_;
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_;
|
||||
std::set<std::string> *type_cache_;
|
||||
};
|
||||
|
||||
@@ -167,8 +169,8 @@ class DiffWrapper : public DiffWrapperBase {
|
||||
public:
|
||||
DiffWrapper(const T *oldp, const T *newp,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &old_types,
|
||||
const std::map<std::string, const abi_util::TypeIR *> &new_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types,
|
||||
std::set<std::string> *type_cache)
|
||||
: DiffWrapperBase(ir_diff_dumper, old_types, new_types, type_cache),
|
||||
oldp_(oldp), newp_(newp) { }
|
||||
|
||||
@@ -85,6 +85,30 @@ static llvm::cl::opt<bool> allow_unreferenced_changes(
|
||||
" APIs."),
|
||||
llvm::cl::Optional, llvm::cl::cat(header_checker_category));
|
||||
|
||||
static llvm::cl::opt<abi_util::TextFormatIR> text_format_old(
|
||||
"text-format-old", llvm::cl::desc("Specify text format of old abi dump"),
|
||||
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
|
||||
"ProtobufTextFormat","ProtobufTextFormat"),
|
||||
clEnumValEnd),
|
||||
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
|
||||
llvm::cl::cat(header_checker_category));
|
||||
|
||||
static llvm::cl::opt<abi_util::TextFormatIR> text_format_new(
|
||||
"text-format-new", llvm::cl::desc("Specify text format of new abi dump"),
|
||||
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
|
||||
"ProtobufTextFormat", "ProtobugTextFormat"),
|
||||
clEnumValEnd),
|
||||
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
|
||||
llvm::cl::cat(header_checker_category));
|
||||
|
||||
static llvm::cl::opt<abi_util::TextFormatIR> text_format_diff(
|
||||
"text-format-diff", llvm::cl::desc("Specify text format of abi-diff"),
|
||||
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
|
||||
"ProtobufTextFormat", "ProtobufTextFormat"),
|
||||
clEnumValEnd),
|
||||
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
|
||||
llvm::cl::cat(header_checker_category));
|
||||
|
||||
static std::set<std::string> LoadIgnoredSymbols(std::string &symbol_list_path) {
|
||||
std::ifstream symbol_ifstream(symbol_list_path);
|
||||
std::set<std::string> ignored_symbols;
|
||||
@@ -100,14 +124,14 @@ static std::set<std::string> LoadIgnoredSymbols(std::string &symbol_list_path) {
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
llvm::cl::ParseCommandLineOptions(argc, argv, "header-checker");
|
||||
std::set<std::string> ignored_symbols;
|
||||
if (llvm::sys::fs::exists(ignore_symbol_list)) {
|
||||
ignored_symbols = LoadIgnoredSymbols(ignore_symbol_list);
|
||||
}
|
||||
HeaderAbiDiff judge(lib_name, arch, old_dump, new_dump, compatibility_report,
|
||||
ignored_symbols, check_all_apis);
|
||||
ignored_symbols, check_all_apis, text_format_old,
|
||||
text_format_new, text_format_diff);
|
||||
|
||||
abi_util::CompatibilityStatusIR status = judge.GenerateCompatibilityReport();
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ HeaderASTVisitor::HeaderASTVisitor(
|
||||
clang::MangleContext *mangle_contextp,
|
||||
clang::ASTContext *ast_contextp,
|
||||
const clang::CompilerInstance *compiler_instance_p,
|
||||
const std::string ¤t_file_name,
|
||||
const std::set<std::string> &exported_headers,
|
||||
const clang::Decl *tu_decl,
|
||||
std::set<std::string> *type_cache,
|
||||
@@ -41,7 +40,6 @@ HeaderASTVisitor::HeaderASTVisitor(
|
||||
: mangle_contextp_(mangle_contextp),
|
||||
ast_contextp_(ast_contextp),
|
||||
cip_(compiler_instance_p),
|
||||
current_file_name_(current_file_name),
|
||||
exported_headers_(exported_headers),
|
||||
tu_decl_(tu_decl),
|
||||
type_cache_(type_cache),
|
||||
@@ -167,14 +165,14 @@ bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) {
|
||||
}
|
||||
|
||||
HeaderASTConsumer::HeaderASTConsumer(
|
||||
const std::string &file_name,
|
||||
clang::CompilerInstance *compiler_instancep,
|
||||
const std::string &out_dump_name,
|
||||
const std::set<std::string> &exported_headers)
|
||||
: file_name_(file_name),
|
||||
cip_(compiler_instancep),
|
||||
const std::set<std::string> &exported_headers,
|
||||
abi_util::TextFormatIR text_format)
|
||||
: cip_(compiler_instancep),
|
||||
out_dump_name_(out_dump_name),
|
||||
exported_headers_(exported_headers) { }
|
||||
exported_headers_(exported_headers),
|
||||
text_format_(text_format){ }
|
||||
|
||||
void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
||||
clang::PrintingPolicy policy(ctx.getPrintingPolicy());
|
||||
@@ -188,10 +186,9 @@ void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
||||
ctx.createMangleContext());
|
||||
std::set<std::string> type_cache;
|
||||
std::unique_ptr<abi_util::IRDumper> ir_dumper =
|
||||
abi_util::IRDumper::CreateIRDumper("protobuf", out_dump_name_);
|
||||
HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, file_name_,
|
||||
exported_headers_, translation_unit, &type_cache,
|
||||
ir_dumper.get());
|
||||
abi_util::IRDumper::CreateIRDumper(text_format_, out_dump_name_);
|
||||
HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, exported_headers_,
|
||||
translation_unit, &type_cache, ir_dumper.get());
|
||||
if (!v.TraverseDecl(translation_unit) || !ir_dumper->Dump()) {
|
||||
llvm::errs() << "Serialization to ostream failed\n";
|
||||
::exit(1);
|
||||
|
||||
@@ -38,7 +38,6 @@ class HeaderASTVisitor
|
||||
HeaderASTVisitor(clang::MangleContext *mangle_contextp,
|
||||
clang::ASTContext *ast_contextp,
|
||||
const clang::CompilerInstance *compiler_instance_p,
|
||||
const std::string ¤t_file_name,
|
||||
const std::set<std::string> &exported_headers,
|
||||
const clang::Decl *tu_decl,
|
||||
std::set<std::string> *type_cache,
|
||||
@@ -63,7 +62,6 @@ class HeaderASTVisitor
|
||||
clang::MangleContext *mangle_contextp_;
|
||||
clang::ASTContext *ast_contextp_;
|
||||
const clang::CompilerInstance *cip_;
|
||||
const std::string current_file_name_;
|
||||
const std::set<std::string> &exported_headers_;
|
||||
// To optimize recursion into only exported abi.
|
||||
const clang::Decl *tu_decl_;
|
||||
@@ -76,18 +74,18 @@ class HeaderASTVisitor
|
||||
|
||||
class HeaderASTConsumer : public clang::ASTConsumer {
|
||||
public:
|
||||
HeaderASTConsumer(const std::string &file_name,
|
||||
clang::CompilerInstance *compiler_instancep,
|
||||
HeaderASTConsumer(clang::CompilerInstance *compiler_instancep,
|
||||
const std::string &out_dump_name,
|
||||
const std::set<std::string> &exported_headers);
|
||||
const std::set<std::string> &exported_headers,
|
||||
abi_util::TextFormatIR text_format);
|
||||
|
||||
void HandleTranslationUnit(clang::ASTContext &ctx) override;
|
||||
|
||||
private:
|
||||
std::string file_name_;
|
||||
clang::CompilerInstance *cip_;
|
||||
std::string out_dump_name_;
|
||||
const std::string &out_dump_name_;
|
||||
const std::set<std::string> &exported_headers_;
|
||||
abi_util::TextFormatIR text_format_;
|
||||
};
|
||||
|
||||
#endif // AST_PROCESSING_H_
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "ast_processing.h"
|
||||
#include "frontend_action.h"
|
||||
#include <header_abi_util.h>
|
||||
#include <ir_representation.h>
|
||||
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
@@ -25,13 +26,15 @@
|
||||
#include <llvm/Support/Path.h>
|
||||
|
||||
HeaderCheckerFrontendAction::HeaderCheckerFrontendAction(
|
||||
const std::string &dump_name, const std::set<std::string> &exported_headers)
|
||||
: dump_name_(dump_name), exported_headers_(exported_headers) { }
|
||||
const std::string &dump_name, const std::set<std::string> &exported_headers,
|
||||
abi_util::TextFormatIR text_format)
|
||||
: dump_name_(dump_name), exported_headers_(exported_headers),
|
||||
text_format_(text_format) { }
|
||||
|
||||
std::unique_ptr<clang::ASTConsumer>
|
||||
HeaderCheckerFrontendAction::CreateASTConsumer(clang::CompilerInstance &ci,
|
||||
llvm::StringRef header_file) {
|
||||
// Create AST consumers.
|
||||
return llvm::make_unique<HeaderASTConsumer>(header_file, &ci, dump_name_,
|
||||
exported_headers_);
|
||||
return llvm::make_unique<HeaderASTConsumer>(&ci, dump_name_,
|
||||
exported_headers_, text_format_);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#ifndef FRONTEND_ACTION_H_
|
||||
#define FRONTEND_ACTION_H_
|
||||
|
||||
#include <ir_representation.h>
|
||||
|
||||
#include <clang/Frontend/FrontendAction.h>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
|
||||
@@ -30,13 +32,15 @@ namespace clang {
|
||||
|
||||
class HeaderCheckerFrontendAction : public clang::ASTFrontendAction {
|
||||
private:
|
||||
std::string dump_name_;
|
||||
const std::string &dump_name_;
|
||||
const std::set<std::string> &exported_headers_;
|
||||
abi_util::TextFormatIR text_format_;
|
||||
|
||||
public:
|
||||
HeaderCheckerFrontendAction(
|
||||
const std::string &dump_name,
|
||||
const std::set<std::string> &exported_headers);
|
||||
const std::set<std::string> &exported_headers,
|
||||
abi_util::TextFormatIR text_format);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
|
||||
HeaderCheckerFrontendActionFactory::HeaderCheckerFrontendActionFactory(
|
||||
const std::string &dump_name,
|
||||
const std::set<std::string> &exported_headers)
|
||||
: dump_name_(dump_name), exported_headers_(exported_headers) { }
|
||||
const std::set<std::string> &exported_headers,
|
||||
abi_util::TextFormatIR text_format)
|
||||
: dump_name_(dump_name), exported_headers_(exported_headers),
|
||||
text_format_(text_format) { }
|
||||
|
||||
clang::FrontendAction *HeaderCheckerFrontendActionFactory::create() {
|
||||
return new HeaderCheckerFrontendAction(dump_name_, exported_headers_);
|
||||
return new HeaderCheckerFrontendAction(dump_name_, exported_headers_,
|
||||
text_format_);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef FRONTEND_ACTION_FACTORY_H_
|
||||
#define FRONTEND_ACTION_FACTORY_H_
|
||||
|
||||
#include <ir_representation.h>
|
||||
#include <clang/Tooling/Tooling.h>
|
||||
|
||||
#include <vector>
|
||||
@@ -22,13 +23,15 @@
|
||||
class HeaderCheckerFrontendActionFactory
|
||||
: public clang::tooling::FrontendActionFactory {
|
||||
private:
|
||||
std::string dump_name_;
|
||||
const std::string &dump_name_;
|
||||
const std::set<std::string> &exported_headers_;
|
||||
abi_util::TextFormatIR text_format_;
|
||||
|
||||
public:
|
||||
HeaderCheckerFrontendActionFactory(
|
||||
const std::string &dump_name,
|
||||
const std::set<std::string> &exported_headers);
|
||||
const std::set<std::string> &exported_headers,
|
||||
abi_util::TextFormatIR text_format);
|
||||
|
||||
clang::FrontendAction *create() override;
|
||||
};
|
||||
|
||||
@@ -49,6 +49,14 @@ static llvm::cl::opt<bool> no_filter(
|
||||
"no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional,
|
||||
llvm::cl::cat(header_checker_category));
|
||||
|
||||
static llvm::cl::opt<abi_util::TextFormatIR> text_format(
|
||||
"text-format", llvm::cl::desc("Specify text format of abi dump"),
|
||||
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
|
||||
"ProtobufTextFormat", "ProtobufTextFormat"),
|
||||
clEnumValEnd),
|
||||
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
|
||||
llvm::cl::cat(header_checker_category));
|
||||
|
||||
// Hide irrelevant command line options defined in LLVM libraries.
|
||||
static void HideIrrelevantCommandLineOptions() {
|
||||
llvm::StringMap<llvm::cl::Option *> &map = llvm::cl::getRegisteredOptions();
|
||||
@@ -108,7 +116,8 @@ int main(int argc, const char **argv) {
|
||||
|
||||
clang::tooling::ClangTool tool(*compilations, header_files);
|
||||
std::unique_ptr<clang::tooling::FrontendActionFactory> factory(
|
||||
new HeaderCheckerFrontendActionFactory(out_dump, exported_headers));
|
||||
new HeaderCheckerFrontendActionFactory(out_dump, exported_headers,
|
||||
text_format));
|
||||
|
||||
return tool.run(factory.get());
|
||||
}
|
||||
|
||||
@@ -12,28 +12,24 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
#pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||
#include "proto/abi_dump.pb.h"
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#include <header_abi_util.h>
|
||||
#include <ir_representation.h>
|
||||
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static constexpr std::size_t kSourcesPerBatchThread = 7;
|
||||
|
||||
static llvm::cl::OptionCategory header_linker_category(
|
||||
"header-abi-linker options");
|
||||
|
||||
@@ -69,6 +65,14 @@ static llvm::cl::opt<std::string> so_file(
|
||||
"so", llvm::cl::desc("<path to so file>"), llvm::cl::Optional,
|
||||
llvm::cl::cat(header_linker_category));
|
||||
|
||||
static llvm::cl::opt<abi_util::TextFormatIR> text_format(
|
||||
"text-format", llvm::cl::desc("Specify text format of abi dumps"),
|
||||
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
|
||||
"ProtobufTextFormat", "ProtobufTextFormat"),
|
||||
clEnumValEnd),
|
||||
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
|
||||
llvm::cl::cat(header_linker_category));
|
||||
|
||||
class HeaderAbiLinker {
|
||||
public:
|
||||
HeaderAbiLinker(
|
||||
@@ -85,36 +89,30 @@ class HeaderAbiLinker {
|
||||
|
||||
bool LinkAndDump();
|
||||
|
||||
template <typename T>
|
||||
static std::string GetLinkageName(T &element) {
|
||||
return element.type_info().linker_set_key();
|
||||
}
|
||||
template <typename T>
|
||||
static std::string GetSourceFile(T &element) {
|
||||
return element.type_info().source_file();
|
||||
}
|
||||
private:
|
||||
bool LinkTypes(const abi_dump::TranslationUnit &dump_tu,
|
||||
abi_dump::TranslationUnit *linked_tu);
|
||||
bool LinkFunctions(const abi_dump::TranslationUnit &dump_tu,
|
||||
abi_dump::TranslationUnit *linked_tu);
|
||||
|
||||
bool LinkGlobalVars(const abi_dump::TranslationUnit &dump_tu,
|
||||
abi_dump::TranslationUnit *linked_tu);
|
||||
|
||||
template <typename T>
|
||||
inline bool LinkDecl(google::protobuf::RepeatedPtrField<T> *dst,
|
||||
inline bool LinkDecl(abi_util::IRDumper *dst,
|
||||
std::set<std::string> *link_set,
|
||||
std::set<std::string> *regex_matched_link_set,
|
||||
const std::regex *vs_regex,
|
||||
const google::protobuf::RepeatedPtrField<T> &src,
|
||||
const std::map<std::string, T> &src,
|
||||
bool use_version_script);
|
||||
|
||||
bool ParseVersionScriptFiles();
|
||||
|
||||
bool ParseSoFile();
|
||||
|
||||
bool AddElfSymbols(abi_dump::TranslationUnit *linked_tu);
|
||||
bool LinkTypes(const abi_util::TextFormatToIRReader *ir_reader,
|
||||
abi_util::IRDumper *ir_dumper);
|
||||
|
||||
bool LinkFunctions(const abi_util::TextFormatToIRReader *ir_reader,
|
||||
abi_util::IRDumper *ir_dumper);
|
||||
|
||||
bool LinkGlobalVars(const abi_util::TextFormatToIRReader *ir_reader,
|
||||
abi_util::IRDumper *ir_dumper);
|
||||
|
||||
bool AddElfSymbols(abi_util::IRDumper *ir_dumper);
|
||||
|
||||
|
||||
private:
|
||||
const std::vector<std::string> &dump_files_;
|
||||
@@ -138,29 +136,56 @@ class HeaderAbiLinker {
|
||||
};
|
||||
|
||||
template <typename T, typename Iterable>
|
||||
static bool AddElfSymbols(google::protobuf::RepeatedPtrField<T> *dst,
|
||||
Iterable symbols) {
|
||||
static bool AddElfSymbols(abi_util::IRDumper *dst, const Iterable &symbols) {
|
||||
for (auto &&symbol : symbols) {
|
||||
auto *added_symbol = dst->Add();
|
||||
if (added_symbol == nullptr) {
|
||||
T elf_symbol(symbol);
|
||||
if (!dst->AddElfSymbolMessageIR(&elf_symbol)) {
|
||||
return false;
|
||||
}
|
||||
added_symbol->set_name(symbol);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// To be called right after parsing the .so file / version script.
|
||||
bool HeaderAbiLinker::AddElfSymbols(abi_dump::TranslationUnit *linked_tu) {
|
||||
bool HeaderAbiLinker::AddElfSymbols(abi_util::IRDumper *ir_dumper) {
|
||||
return ::AddElfSymbols<abi_util::ElfFunctionIR>(ir_dumper,
|
||||
function_decl_set_) &&
|
||||
::AddElfSymbols<abi_util::ElfObjectIR>(ir_dumper,
|
||||
globvar_decl_set_);
|
||||
}
|
||||
|
||||
return ::AddElfSymbols(linked_tu->mutable_elf_functions(), function_decl_set_)
|
||||
&& ::AddElfSymbols(linked_tu->mutable_elf_objects(), globvar_decl_set_);
|
||||
static void DeDuplicateAbiElementsThread(
|
||||
const std::vector<std::string> &dump_files,
|
||||
const std::set<std::string> *exported_headers,
|
||||
abi_util::TextFormatToIRReader *greader, std::mutex *greader_lock,
|
||||
std::atomic<std::size_t> *cnt) {
|
||||
std::unique_ptr<abi_util::TextFormatToIRReader> local_reader =
|
||||
abi_util::TextFormatToIRReader::CreateTextFormatToIRReader(
|
||||
text_format, exported_headers);
|
||||
auto begin_it = dump_files.begin();
|
||||
std::size_t num_sources = dump_files.size();
|
||||
while (1) {
|
||||
std::size_t i = cnt->fetch_add(kSourcesPerBatchThread);
|
||||
if (i >= num_sources) {
|
||||
break;
|
||||
}
|
||||
std::size_t end = std::min(i + kSourcesPerBatchThread, num_sources);
|
||||
std::unique_ptr<abi_util::TextFormatToIRReader> reader =
|
||||
abi_util::TextFormatToIRReader::CreateTextFormatToIRReader(
|
||||
text_format, exported_headers);
|
||||
assert(reader != nullptr);
|
||||
if (!reader->ReadDumps(begin_it + i, begin_it + end)) {
|
||||
llvm::errs() << "ReadDump failed\n";
|
||||
::exit(1);
|
||||
}
|
||||
// This merge is needed since the iterators might not be contigous.
|
||||
local_reader->Merge(std::move(*reader));
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(*greader_lock);
|
||||
greader->Merge(std::move(*local_reader));
|
||||
}
|
||||
|
||||
bool HeaderAbiLinker::LinkAndDump() {
|
||||
abi_dump::TranslationUnit linked_tu;
|
||||
std::ofstream text_output(out_dump_name_);
|
||||
google::protobuf::io::OstreamOutputStream text_os(&text_output);
|
||||
// If the user specifies that a version script should be used, use that.
|
||||
if (!so_file_.empty()) {
|
||||
exported_headers_ =
|
||||
@@ -173,22 +198,40 @@ bool HeaderAbiLinker::LinkAndDump() {
|
||||
llvm::errs() << "Failed to parse stub files for exported symbols\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
AddElfSymbols(&linked_tu);
|
||||
|
||||
for (auto &&i : dump_files_) {
|
||||
abi_dump::TranslationUnit dump_tu;
|
||||
std::ifstream input(i);
|
||||
google::protobuf::io::IstreamInputStream text_is(&input);
|
||||
if (!google::protobuf::TextFormat::Parse(&text_is, &dump_tu) ||
|
||||
!LinkTypes(dump_tu, &linked_tu) ||
|
||||
!LinkFunctions(dump_tu, &linked_tu) ||
|
||||
!LinkGlobalVars(dump_tu, &linked_tu)) {
|
||||
llvm::errs() << "Failed to link elements\n";
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<abi_util::IRDumper> ir_dumper =
|
||||
abi_util::IRDumper::CreateIRDumper(text_format, out_dump_name_);
|
||||
assert(ir_dumper != nullptr);
|
||||
AddElfSymbols(ir_dumper.get());
|
||||
// Create a reader, on which we never actually call ReadDump(), since multiple
|
||||
// dump files are associated with it.
|
||||
std::unique_ptr<abi_util::TextFormatToIRReader> greader =
|
||||
abi_util::TextFormatToIRReader::CreateTextFormatToIRReader(
|
||||
text_format, &exported_headers_);
|
||||
std::size_t max_threads = std::thread::hardware_concurrency();
|
||||
std::size_t num_threads = kSourcesPerBatchThread < dump_files_.size() ?
|
||||
std::min(dump_files_.size() / kSourcesPerBatchThread,
|
||||
max_threads) : 0;
|
||||
std::vector<std::thread> threads;
|
||||
std::atomic<std::size_t> cnt(0);
|
||||
std::mutex greader_lock;
|
||||
for (std::size_t i = 1; i < num_threads; i++) {
|
||||
threads.emplace_back(DeDuplicateAbiElementsThread, dump_files_,
|
||||
&exported_headers_, greader.get(), &greader_lock,
|
||||
&cnt);
|
||||
}
|
||||
if (!google::protobuf::TextFormat::Print(linked_tu, &text_os)) {
|
||||
DeDuplicateAbiElementsThread(dump_files_, &exported_headers_, greader.get(),
|
||||
&greader_lock, &cnt);
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
if (!LinkTypes(greader.get(), ir_dumper.get()) ||
|
||||
!LinkFunctions(greader.get(), ir_dumper.get()) ||
|
||||
!LinkGlobalVars(greader.get(), ir_dumper.get())) {
|
||||
llvm::errs() << "Failed to link elements\n";
|
||||
return false;
|
||||
}
|
||||
if (!ir_dumper->Dump()) {
|
||||
llvm::errs() << "Serialization to ostream failed\n";
|
||||
return false;
|
||||
}
|
||||
@@ -228,25 +271,24 @@ static std::regex CreateRegexMatchExprFromSet(
|
||||
return std::regex(all_regex_match_str);
|
||||
}
|
||||
|
||||
//TODO: make linking decls multi-threaded b/63590537.
|
||||
template <typename T>
|
||||
inline bool HeaderAbiLinker::LinkDecl(
|
||||
google::protobuf::RepeatedPtrField<T> *dst, std::set<std::string> *link_set,
|
||||
abi_util::IRDumper *dst, std::set<std::string> *link_set,
|
||||
std::set<std::string> *regex_matched_link_set, const std::regex *vs_regex,
|
||||
const google::protobuf::RepeatedPtrField<T> &src, bool use_version_script) {
|
||||
const std::map<std::string, T> &src, bool use_version_script) {
|
||||
assert(dst != nullptr);
|
||||
assert(link_set != nullptr);
|
||||
for (auto &&element : src) {
|
||||
// If we are not using a version script and exported headers are available,
|
||||
// filter out unexported abi.
|
||||
std::string source_file = GetSourceFile(element);
|
||||
std::string source_file = element.second.GetSourceFile();
|
||||
// Builtin types will not have source file information.
|
||||
if (!exported_headers_.empty() && !source_file.empty() &&
|
||||
exported_headers_.find(source_file) ==
|
||||
exported_headers_.end()) {
|
||||
continue;
|
||||
}
|
||||
std::string element_str = GetLinkageName(element);
|
||||
const std::string &element_str = element.first;
|
||||
// Check for the existence of the element in linked dump / symbol file.
|
||||
if (!use_version_script) {
|
||||
if (!link_set->insert(element_str).second) {
|
||||
@@ -264,86 +306,67 @@ inline bool HeaderAbiLinker::LinkDecl(
|
||||
link_set->erase(*it); // Avoid multiple instances of the same symbol.
|
||||
}
|
||||
}
|
||||
T *added_element = dst->Add();
|
||||
if (!added_element) {
|
||||
if (!dst->AddLinkableMessageIR(&(element.second))) {
|
||||
llvm::errs() << "Failed to add element to linked dump\n";
|
||||
return false;
|
||||
}
|
||||
*added_element = element;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::string HeaderAbiLinker::GetLinkageName<const abi_dump::FunctionDecl> (
|
||||
const abi_dump::FunctionDecl &element) {
|
||||
return element.linker_set_key();
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string HeaderAbiLinker::GetSourceFile<const abi_dump::FunctionDecl> (
|
||||
const abi_dump::FunctionDecl &element) {
|
||||
return element.source_file();
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string HeaderAbiLinker::GetLinkageName<const abi_dump::GlobalVarDecl> (
|
||||
const abi_dump::GlobalVarDecl &element) {
|
||||
return element.linker_set_key();
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string HeaderAbiLinker::GetSourceFile<const abi_dump::GlobalVarDecl> (
|
||||
const abi_dump::GlobalVarDecl &element) {
|
||||
return element.source_file();
|
||||
}
|
||||
|
||||
bool HeaderAbiLinker::LinkTypes(const abi_dump::TranslationUnit &dump_tu,
|
||||
abi_dump::TranslationUnit *linked_tu) {
|
||||
assert(linked_tu != nullptr);
|
||||
bool HeaderAbiLinker::LinkTypes(const abi_util::TextFormatToIRReader *reader,
|
||||
abi_util::IRDumper *ir_dumper) {
|
||||
assert(reader != nullptr);
|
||||
assert(ir_dumper != nullptr);
|
||||
// Even if version scripts are available we take in types, since the symbols
|
||||
// in the version script might reference a type exposed by the library.
|
||||
return LinkDecl(linked_tu->mutable_record_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.record_types(), false) &&
|
||||
LinkDecl(linked_tu->mutable_enum_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.enum_types(), false) &&
|
||||
LinkDecl(linked_tu->mutable_builtin_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.builtin_types(), false) &&
|
||||
LinkDecl(linked_tu->mutable_pointer_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.pointer_types(), false) &&
|
||||
LinkDecl(linked_tu->mutable_rvalue_reference_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.rvalue_reference_types(), false) &&
|
||||
LinkDecl(linked_tu->mutable_lvalue_reference_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.lvalue_reference_types(), false) &&
|
||||
LinkDecl(linked_tu->mutable_array_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.array_types(), false) &&
|
||||
LinkDecl(linked_tu->mutable_qualified_types(), &types_set_, nullptr,
|
||||
nullptr, dump_tu.qualified_types(), false);
|
||||
return LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetRecordTypes(), false) &&
|
||||
LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetEnumTypes(), false) &&
|
||||
LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetBuiltinTypes(), false) &&
|
||||
LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetPointerTypes(), false) &&
|
||||
LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetRvalueReferenceTypes(), false) &&
|
||||
LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetLvalueReferenceTypes(), false) &&
|
||||
LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetArrayTypes(), false) &&
|
||||
LinkDecl(ir_dumper, &types_set_, nullptr,
|
||||
nullptr, reader->GetQualifiedTypes(), false);
|
||||
}
|
||||
|
||||
bool HeaderAbiLinker::LinkFunctions(const abi_dump::TranslationUnit &dump_tu,
|
||||
abi_dump::TranslationUnit *linked_tu) {
|
||||
assert(linked_tu != nullptr);
|
||||
return LinkDecl(linked_tu->mutable_functions(), &function_decl_set_,
|
||||
bool HeaderAbiLinker::LinkFunctions(
|
||||
const abi_util::TextFormatToIRReader *reader,
|
||||
abi_util::IRDumper *ir_dumper) {
|
||||
|
||||
assert(reader != nullptr);
|
||||
return LinkDecl(ir_dumper, &function_decl_set_,
|
||||
&functions_regex_matched_set, &functions_vs_regex_,
|
||||
dump_tu.functions(),
|
||||
reader->GetFunctions(),
|
||||
(!version_script_.empty() || !so_file_.empty()));
|
||||
}
|
||||
|
||||
bool HeaderAbiLinker::LinkGlobalVars(const abi_dump::TranslationUnit &dump_tu,
|
||||
abi_dump::TranslationUnit *linked_tu) {
|
||||
assert(linked_tu != nullptr);
|
||||
return LinkDecl(linked_tu->mutable_global_vars(), &globvar_decl_set_,
|
||||
bool HeaderAbiLinker::LinkGlobalVars(
|
||||
const abi_util::TextFormatToIRReader *reader,
|
||||
abi_util::IRDumper *ir_dumper) {
|
||||
|
||||
assert(reader != nullptr);
|
||||
return LinkDecl(ir_dumper, &globvar_decl_set_,
|
||||
&globvars_regex_matched_set, &globvars_vs_regex_,
|
||||
dump_tu.global_vars(),
|
||||
reader->GetGlobalVariables(),
|
||||
(!version_script.empty() || !so_file_.empty()));
|
||||
|
||||
}
|
||||
|
||||
bool HeaderAbiLinker::ParseVersionScriptFiles() {
|
||||
abi_util::VersionScriptParser version_script_parser(version_script_, arch_,
|
||||
api_);
|
||||
if (!version_script_parser.Parse()) {
|
||||
llvm::errs() << "Failed to parse version script\n";
|
||||
return false;
|
||||
}
|
||||
function_decl_set_ = version_script_parser.GetFunctions();
|
||||
@@ -384,7 +407,6 @@ bool HeaderAbiLinker::ParseSoFile() {
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
llvm::cl::ParseCommandLineOptions(argc, argv, "header-linker");
|
||||
if (so_file.empty() && version_script.empty()) {
|
||||
llvm::errs() << "One of -so or -v needs to be specified\n";
|
||||
@@ -397,6 +419,7 @@ int main(int argc, const char **argv) {
|
||||
so_file, linked_dump, arch, api);
|
||||
|
||||
if (!Linker.LinkAndDump()) {
|
||||
llvm::errs() << "Failed to link and dump elements\n";
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -146,15 +146,17 @@ std::vector<T> FindRemovedElements(
|
||||
return removed_elements;
|
||||
}
|
||||
|
||||
template <typename T, typename F, typename K, typename Iterable>
|
||||
inline void AddToMap(std::map<K, T> *dst, Iterable &src, F get_key) {
|
||||
template <typename K, typename T, typename Iterable, typename KeyGetter,
|
||||
typename ValueGetter>
|
||||
inline void AddToMap(std::map<K, T> *dst, Iterable &src, KeyGetter get_key,
|
||||
ValueGetter get_value) {
|
||||
for (auto &&element : src) {
|
||||
dst->insert(std::make_pair(get_key(&element), &element));
|
||||
dst->insert(std::make_pair(get_key(&element), get_value(&element)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F, typename K, typename Iterable>
|
||||
inline void AddToSet(std::set<K> *dst, Iterable &src, F get_key) {
|
||||
template <typename K, typename Iterable, typename KeyGetter>
|
||||
inline void AddToSet(std::set<K> *dst, Iterable &src, KeyGetter get_key) {
|
||||
for (auto &&element : src) {
|
||||
dst->insert(get_key(element));
|
||||
}
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
// message format specific dumpers.
|
||||
namespace abi_util {
|
||||
|
||||
template <typename T>
|
||||
using AbiElementMap = std::map<std::string, T>;
|
||||
|
||||
enum TextFormatIR {
|
||||
ProtobufTextFormat = 0,
|
||||
};
|
||||
|
||||
enum CompatibilityStatusIR {
|
||||
Compatible = 0,
|
||||
UnreferencedChanges = 1,
|
||||
@@ -691,11 +698,13 @@ class IRDumper {
|
||||
public:
|
||||
IRDumper(const std::string &dump_path) : dump_path_(dump_path) { }
|
||||
|
||||
static std::unique_ptr<IRDumper> CreateIRDumper(const std::string &type,
|
||||
const std::string &dump_path);
|
||||
static std::unique_ptr<IRDumper> CreateIRDumper(
|
||||
TextFormatIR text_format, const std::string &dump_path);
|
||||
|
||||
virtual bool AddLinkableMessageIR(const LinkableMessageIR *) = 0;
|
||||
|
||||
virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *) = 0;
|
||||
|
||||
virtual bool Dump() = 0;
|
||||
|
||||
virtual ~IRDumper() {}
|
||||
@@ -706,77 +715,116 @@ class IRDumper {
|
||||
|
||||
class TextFormatToIRReader {
|
||||
public:
|
||||
TextFormatToIRReader(const std::string &dump_path) : dump_path_(dump_path) { }
|
||||
|
||||
const std::vector<FunctionIR> &GetFunctions() const {
|
||||
TextFormatToIRReader(const std::set<std::string> *exported_headers)
|
||||
: exported_headers_(exported_headers) { }
|
||||
|
||||
const AbiElementMap<FunctionIR> &GetFunctions() const {
|
||||
return functions_;
|
||||
}
|
||||
|
||||
const std::vector<GlobalVarIR> &GetGlobalVariables() const {
|
||||
const AbiElementMap<GlobalVarIR> &GetGlobalVariables() const {
|
||||
return global_variables_;
|
||||
}
|
||||
|
||||
const std::vector<RecordTypeIR> &GetRecordTypes() const {
|
||||
const AbiElementMap<RecordTypeIR> &GetRecordTypes() const {
|
||||
return record_types_;
|
||||
}
|
||||
|
||||
const std::vector<EnumTypeIR> &GetEnumTypes() const {
|
||||
const AbiElementMap<EnumTypeIR> &GetEnumTypes() const {
|
||||
return enum_types_;
|
||||
}
|
||||
|
||||
const std::vector<LvalueReferenceTypeIR> &GetLvalueReferenceTypes() const {
|
||||
const AbiElementMap<LvalueReferenceTypeIR> &
|
||||
GetLvalueReferenceTypes() const {
|
||||
return lvalue_reference_types_;
|
||||
}
|
||||
|
||||
const std::vector<RvalueReferenceTypeIR> &GetRvalueReferenceTypes() const {
|
||||
const AbiElementMap<RvalueReferenceTypeIR> &
|
||||
GetRvalueReferenceTypes() const {
|
||||
return rvalue_reference_types_;
|
||||
}
|
||||
|
||||
const std::vector<QualifiedTypeIR> &GetQualifiedTypes() const {
|
||||
const AbiElementMap<QualifiedTypeIR> &GetQualifiedTypes() const {
|
||||
return qualified_types_;
|
||||
}
|
||||
|
||||
const std::vector<ArrayTypeIR> &GetArrayTypes() const {
|
||||
const AbiElementMap<ArrayTypeIR> &GetArrayTypes() const {
|
||||
return array_types_;
|
||||
}
|
||||
|
||||
const std::vector<PointerTypeIR> &GetPointerTypes() const {
|
||||
const AbiElementMap<PointerTypeIR> &GetPointerTypes() const {
|
||||
return pointer_types_;
|
||||
}
|
||||
|
||||
const std::vector<BuiltinTypeIR> &GetBuiltinTypes() const {
|
||||
const AbiElementMap<BuiltinTypeIR> &GetBuiltinTypes() const {
|
||||
return builtin_types_;
|
||||
}
|
||||
|
||||
const std::vector<ElfFunctionIR> &GetElfFunctions() const {
|
||||
const AbiElementMap<ElfFunctionIR> &GetElfFunctions() const {
|
||||
return elf_functions_;
|
||||
}
|
||||
|
||||
const std::vector<ElfObjectIR> &GetElfObjects() const {
|
||||
const AbiElementMap<ElfObjectIR> &GetElfObjects() const {
|
||||
return elf_objects_;
|
||||
}
|
||||
|
||||
virtual bool ReadDump() = 0;
|
||||
virtual bool ReadDump(const std::string &dump_file) = 0;
|
||||
|
||||
template <typename Iterator>
|
||||
bool ReadDumps(Iterator begin, Iterator end) {
|
||||
Iterator it = begin;
|
||||
while(it != end) {
|
||||
if (!ReadDump(*it)) {
|
||||
return false;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~TextFormatToIRReader() { }
|
||||
|
||||
void Merge(TextFormatToIRReader &&addend) {
|
||||
MergeElements(&functions_, std::move(addend.functions_));
|
||||
MergeElements(&global_variables_, std::move(addend.global_variables_));
|
||||
MergeElements(&record_types_, std::move(addend.record_types_));
|
||||
MergeElements(&enum_types_, std::move(addend.enum_types_));
|
||||
MergeElements(&pointer_types_, std::move(addend.pointer_types_));
|
||||
MergeElements(&lvalue_reference_types_,
|
||||
std::move(addend.lvalue_reference_types_));
|
||||
MergeElements(&rvalue_reference_types_,
|
||||
std::move(addend.rvalue_reference_types_));
|
||||
MergeElements(&array_types_, std::move(addend.array_types_));
|
||||
MergeElements(&builtin_types_, std::move(addend.builtin_types_));
|
||||
MergeElements(&qualified_types_, std::move(addend.qualified_types_));
|
||||
}
|
||||
|
||||
static std::unique_ptr<TextFormatToIRReader> CreateTextFormatToIRReader(
|
||||
const std::string &text_format, const std::string &dump_path);
|
||||
TextFormatIR text_format,
|
||||
const std::set<std::string> *exported_headers = nullptr);
|
||||
|
||||
protected:
|
||||
const std::string &dump_path_;
|
||||
std::vector<FunctionIR> functions_;
|
||||
std::vector<GlobalVarIR> global_variables_;
|
||||
std::vector<RecordTypeIR> record_types_;
|
||||
std::vector<EnumTypeIR> enum_types_;
|
||||
std::vector<PointerTypeIR> pointer_types_;
|
||||
std::vector<LvalueReferenceTypeIR> lvalue_reference_types_;
|
||||
std::vector<RvalueReferenceTypeIR> rvalue_reference_types_;
|
||||
std::vector<ArrayTypeIR> array_types_;
|
||||
std::vector<BuiltinTypeIR> builtin_types_;
|
||||
std::vector<QualifiedTypeIR> qualified_types_;
|
||||
std::vector<ElfFunctionIR> elf_functions_;
|
||||
std::vector<ElfObjectIR> elf_objects_;
|
||||
|
||||
template <typename Augend, typename Addend>
|
||||
inline void MergeElements(Augend *augend, Addend &&addend) {
|
||||
augend->insert(std::make_move_iterator(addend.begin()),
|
||||
std::make_move_iterator(addend.end()));
|
||||
}
|
||||
|
||||
AbiElementMap<FunctionIR> functions_;
|
||||
AbiElementMap<GlobalVarIR> global_variables_;
|
||||
AbiElementMap<RecordTypeIR> record_types_;
|
||||
AbiElementMap<EnumTypeIR> enum_types_;
|
||||
AbiElementMap<PointerTypeIR> pointer_types_;
|
||||
AbiElementMap<LvalueReferenceTypeIR> lvalue_reference_types_;
|
||||
AbiElementMap<RvalueReferenceTypeIR> rvalue_reference_types_;
|
||||
AbiElementMap<ArrayTypeIR> array_types_;
|
||||
AbiElementMap<BuiltinTypeIR> builtin_types_;
|
||||
AbiElementMap<QualifiedTypeIR> qualified_types_;
|
||||
AbiElementMap<ElfFunctionIR> elf_functions_;
|
||||
AbiElementMap<ElfObjectIR> elf_objects_;
|
||||
const std::set<std::string> *exported_headers_;
|
||||
};
|
||||
|
||||
class DiffMessageIR {
|
||||
@@ -1120,7 +1168,7 @@ class IRDiffDumper {
|
||||
|
||||
virtual ~IRDiffDumper() {}
|
||||
static std::unique_ptr<IRDiffDumper> CreateIRDiffDumper(
|
||||
const std::string &type, const std::string &dump_path);
|
||||
TextFormatIR, const std::string &dump_path);
|
||||
protected:
|
||||
const std::string &dump_path_;
|
||||
};
|
||||
|
||||
@@ -270,11 +270,17 @@ class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter {
|
||||
|
||||
bool AddGlobalVarIR(const GlobalVarIR *);
|
||||
|
||||
bool AddElfFunctionIR(const ElfFunctionIR *);
|
||||
|
||||
bool AddElfObjectIR(const ElfObjectIR *);
|
||||
|
||||
public:
|
||||
ProtobufIRDumper(const std::string &dump_path)
|
||||
: IRDumper(dump_path), tu_ptr_(new abi_dump::TranslationUnit()) { }
|
||||
|
||||
bool AddLinkableMessageIR(const LinkableMessageIR *);
|
||||
bool AddLinkableMessageIR(const LinkableMessageIR *) override;
|
||||
|
||||
bool AddElfSymbolMessageIR(const ElfSymbolIR *) override;
|
||||
|
||||
bool Dump() override;
|
||||
|
||||
@@ -288,44 +294,35 @@ class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter {
|
||||
class ProtobufTextFormatToIRReader : public TextFormatToIRReader {
|
||||
public:
|
||||
|
||||
virtual bool ReadDump() override;
|
||||
ProtobufTextFormatToIRReader(const std::set<std::string> *exported_headers)
|
||||
: TextFormatToIRReader(exported_headers) { }
|
||||
|
||||
ProtobufTextFormatToIRReader(const std::string &dump_path)
|
||||
: TextFormatToIRReader(dump_path) { }
|
||||
bool ReadDump(const std::string &dump_file) override;
|
||||
|
||||
private:
|
||||
std::vector<FunctionIR> ReadFunctions(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadFunctions(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<GlobalVarIR> ReadGlobalVariables(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadGlobalVariables(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<EnumTypeIR> ReadEnumTypes(const abi_dump::TranslationUnit &tu);
|
||||
void ReadEnumTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<RecordTypeIR> ReadRecordTypes(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadRecordTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<PointerTypeIR> ReadPointerTypes(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadPointerTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<BuiltinTypeIR> ReadBuiltinTypes(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadBuiltinTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<QualifiedTypeIR> ReadQualifiedTypes(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadQualifiedTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<ArrayTypeIR> ReadArrayTypes(const abi_dump::TranslationUnit &tu);
|
||||
void ReadArrayTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<LvalueReferenceTypeIR> ReadLvalueReferenceTypes(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadLvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<RvalueReferenceTypeIR> ReadRvalueReferenceTypes(
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadRvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<ElfFunctionIR> ReadElfFunctions (
|
||||
const abi_dump::TranslationUnit &tu);
|
||||
void ReadElfFunctions (const abi_dump::TranslationUnit &tu);
|
||||
|
||||
std::vector<ElfObjectIR> ReadElfObjects (const abi_dump::TranslationUnit &tu);
|
||||
void ReadElfObjects (const abi_dump::TranslationUnit &tu);
|
||||
|
||||
void ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl &type_info,
|
||||
TypeIR *typep);
|
||||
|
||||
@@ -33,34 +33,40 @@
|
||||
namespace abi_util {
|
||||
|
||||
std::unique_ptr<IRDumper> IRDumper::CreateIRDumper(
|
||||
const std::string &type, const std::string &dump_path) {
|
||||
if (type == "protobuf") {
|
||||
return std::make_unique<ProtobufIRDumper>(dump_path);
|
||||
TextFormatIR text_format, const std::string &dump_path) {
|
||||
switch (text_format) {
|
||||
case TextFormatIR::ProtobufTextFormat:
|
||||
return std::make_unique<ProtobufIRDumper>(dump_path);
|
||||
default:
|
||||
// Nothing else is supported yet.
|
||||
llvm::errs() << "Text format not supported yet\n";
|
||||
return nullptr;
|
||||
}
|
||||
// Nothing else is supported yet.
|
||||
llvm::errs() << type << " message format is not supported yet!\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<IRDiffDumper> IRDiffDumper::CreateIRDiffDumper(
|
||||
const std::string &type, const std::string &dump_path) {
|
||||
if (type == "protobuf") {
|
||||
return std::make_unique<ProtobufIRDiffDumper>(dump_path);
|
||||
TextFormatIR text_format, const std::string &dump_path) {
|
||||
switch (text_format) {
|
||||
case TextFormatIR::ProtobufTextFormat:
|
||||
return std::make_unique<ProtobufIRDiffDumper>(dump_path);
|
||||
default:
|
||||
// Nothing else is supported yet.
|
||||
llvm::errs() << "Text format not supported yet\n";
|
||||
return nullptr;
|
||||
}
|
||||
// Nothing else is supported yet.
|
||||
llvm::errs() << type << " message format is not supported yet!\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<TextFormatToIRReader>
|
||||
TextFormatToIRReader::CreateTextFormatToIRReader(
|
||||
const std::string &type, const std::string &dump_path) {
|
||||
if (type == "protobuf") {
|
||||
return std::make_unique<ProtobufTextFormatToIRReader>(dump_path);
|
||||
TextFormatIR text_format, const std::set<std::string> *exported_headers) {
|
||||
switch (text_format) {
|
||||
case TextFormatIR::ProtobufTextFormat:
|
||||
return std::make_unique<ProtobufTextFormatToIRReader>(exported_headers);
|
||||
default:
|
||||
// Nothing else is supported yet.
|
||||
llvm::errs() << "Text format not supported yet\n";
|
||||
return nullptr;
|
||||
}
|
||||
// Nothing else is supported yet.
|
||||
llvm::errs() << type << " message format is not supported yet!\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace abi_util
|
||||
|
||||
@@ -23,6 +23,16 @@
|
||||
|
||||
namespace abi_util {
|
||||
|
||||
static bool IsPresentInExportedHeaders(
|
||||
const LinkableMessageIR &linkable_message,
|
||||
const std::set<std::string> *exported_headers) {
|
||||
if (exported_headers == nullptr || exported_headers->empty()) {
|
||||
return true;
|
||||
}
|
||||
return exported_headers->find(linkable_message.GetSourceFile())
|
||||
!= exported_headers->end();
|
||||
}
|
||||
|
||||
void ProtobufTextFormatToIRReader::ReadTypeInfo(
|
||||
const abi_dump::BasicNamedAndTypedDecl &type_info,
|
||||
TypeIR *typep) {
|
||||
@@ -34,9 +44,9 @@ void ProtobufTextFormatToIRReader::ReadTypeInfo(
|
||||
typep->SetAlignment(type_info.alignment());
|
||||
}
|
||||
|
||||
bool ProtobufTextFormatToIRReader::ReadDump() {
|
||||
bool ProtobufTextFormatToIRReader::ReadDump(const std::string &dump_file) {
|
||||
abi_dump::TranslationUnit tu;
|
||||
std::ifstream input(dump_path_);
|
||||
std::ifstream input(dump_file);
|
||||
google::protobuf::io::IstreamInputStream text_is(&input);
|
||||
|
||||
if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) {
|
||||
@@ -44,21 +54,20 @@ bool ProtobufTextFormatToIRReader::ReadDump() {
|
||||
return false;
|
||||
}
|
||||
|
||||
functions_ = ReadFunctions(tu);
|
||||
global_variables_ = ReadGlobalVariables(tu);
|
||||
ReadFunctions(tu);
|
||||
ReadGlobalVariables(tu);
|
||||
|
||||
enum_types_ = ReadEnumTypes(tu);
|
||||
record_types_ = ReadRecordTypes(tu);
|
||||
array_types_ = ReadArrayTypes(tu);
|
||||
pointer_types_ = ReadPointerTypes(tu);
|
||||
qualified_types_ = ReadQualifiedTypes(tu);
|
||||
builtin_types_ = ReadBuiltinTypes(tu);
|
||||
lvalue_reference_types_ = ReadLvalueReferenceTypes(tu);
|
||||
rvalue_reference_types_ = ReadRvalueReferenceTypes(tu);
|
||||
|
||||
elf_functions_ = ReadElfFunctions(tu);
|
||||
elf_objects_ = ReadElfObjects(tu);
|
||||
ReadEnumTypes(tu);
|
||||
ReadRecordTypes(tu);
|
||||
ReadArrayTypes(tu);
|
||||
ReadPointerTypes(tu);
|
||||
ReadQualifiedTypes(tu);
|
||||
ReadBuiltinTypes(tu);
|
||||
ReadLvalueReferenceTypes(tu);
|
||||
ReadRvalueReferenceTypes(tu);
|
||||
|
||||
ReadElfFunctions(tu);
|
||||
ReadElfObjects(tu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -171,9 +180,8 @@ EnumTypeIR ProtobufTextFormatToIRReader::EnumTypeProtobufToIR(
|
||||
return enum_type_ir;
|
||||
}
|
||||
|
||||
std::vector<GlobalVarIR> ProtobufTextFormatToIRReader::ReadGlobalVariables(
|
||||
void ProtobufTextFormatToIRReader::ReadGlobalVariables(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<GlobalVarIR> global_variables;
|
||||
for (auto &&global_variable_protobuf : tu.global_vars()) {
|
||||
GlobalVarIR global_variable_ir;
|
||||
global_variable_ir.SetName(global_variable_protobuf.name());
|
||||
@@ -182,38 +190,44 @@ std::vector<GlobalVarIR> ProtobufTextFormatToIRReader::ReadGlobalVariables(
|
||||
global_variable_protobuf.referenced_type());
|
||||
global_variable_ir.SetLinkerSetKey(
|
||||
global_variable_protobuf.linker_set_key());
|
||||
global_variables.emplace_back(std::move(global_variable_ir));
|
||||
if (!IsPresentInExportedHeaders(global_variable_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
global_variables_.insert(
|
||||
{global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)});
|
||||
}
|
||||
return global_variables;
|
||||
}
|
||||
|
||||
std::vector<PointerTypeIR> ProtobufTextFormatToIRReader::ReadPointerTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadPointerTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<PointerTypeIR> pointer_types;
|
||||
for (auto &&pointer_type_protobuf : tu.pointer_types()) {
|
||||
PointerTypeIR pointer_type_ir;
|
||||
ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir);
|
||||
pointer_types.emplace_back(std::move(pointer_type_ir));
|
||||
if (!IsPresentInExportedHeaders(pointer_type_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
pointer_types_.insert(
|
||||
{pointer_type_ir.GetLinkerSetKey(), std::move(pointer_type_ir)});
|
||||
}
|
||||
return pointer_types;
|
||||
}
|
||||
|
||||
std::vector<BuiltinTypeIR> ProtobufTextFormatToIRReader::ReadBuiltinTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadBuiltinTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<BuiltinTypeIR> builtin_types;
|
||||
for (auto &&builtin_type_protobuf : tu.builtin_types()) {
|
||||
BuiltinTypeIR builtin_type_ir;
|
||||
ReadTypeInfo(builtin_type_protobuf.type_info(), &builtin_type_ir);
|
||||
builtin_type_ir.SetSignedness(builtin_type_protobuf.is_unsigned());
|
||||
builtin_type_ir.SetIntegralType(builtin_type_protobuf.is_integral());
|
||||
builtin_types.emplace_back(std::move(builtin_type_ir));
|
||||
if (!IsPresentInExportedHeaders(builtin_type_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
builtin_types_.insert(
|
||||
{builtin_type_ir.GetLinkerSetKey(), std::move(builtin_type_ir)});
|
||||
}
|
||||
return builtin_types;
|
||||
}
|
||||
|
||||
std::vector<QualifiedTypeIR> ProtobufTextFormatToIRReader::ReadQualifiedTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadQualifiedTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<QualifiedTypeIR> qualified_types;
|
||||
for (auto &&qualified_type_protobuf : tu.qualified_types()) {
|
||||
QualifiedTypeIR qualified_type_ir;
|
||||
ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir);
|
||||
@@ -221,94 +235,110 @@ std::vector<QualifiedTypeIR> ProtobufTextFormatToIRReader::ReadQualifiedTypes(
|
||||
qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile());
|
||||
qualified_type_ir.SetRestrictedness(
|
||||
qualified_type_protobuf.is_restricted());
|
||||
qualified_types.emplace_back(std::move(qualified_type_ir));
|
||||
if (!IsPresentInExportedHeaders(qualified_type_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
qualified_types_.insert(
|
||||
{qualified_type_ir.GetLinkerSetKey(), std::move(qualified_type_ir)});
|
||||
}
|
||||
return qualified_types;
|
||||
}
|
||||
|
||||
std::vector<ArrayTypeIR> ProtobufTextFormatToIRReader::ReadArrayTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadArrayTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<ArrayTypeIR> array_types;
|
||||
for (auto &&array_type_protobuf : tu.array_types()) {
|
||||
ArrayTypeIR array_type_ir;
|
||||
ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir);
|
||||
array_types.emplace_back(std::move(array_type_ir));
|
||||
if (!IsPresentInExportedHeaders(array_type_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
array_types_.insert(
|
||||
{array_type_ir.GetLinkerSetKey(), std::move(array_type_ir)});
|
||||
}
|
||||
return array_types;
|
||||
}
|
||||
|
||||
std::vector<LvalueReferenceTypeIR>
|
||||
ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<LvalueReferenceTypeIR> lvalue_reference_types;
|
||||
for (auto &&lvalue_reference_type_protobuf : tu.lvalue_reference_types()) {
|
||||
LvalueReferenceTypeIR lvalue_reference_type_ir;
|
||||
ReadTypeInfo(lvalue_reference_type_protobuf.type_info(),
|
||||
&lvalue_reference_type_ir);
|
||||
lvalue_reference_types.emplace_back(std::move(lvalue_reference_type_ir));
|
||||
if (!IsPresentInExportedHeaders(lvalue_reference_type_ir,
|
||||
exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
lvalue_reference_types_.insert(
|
||||
{lvalue_reference_type_ir.GetLinkerSetKey(),
|
||||
std::move(lvalue_reference_type_ir)});
|
||||
}
|
||||
return lvalue_reference_types;
|
||||
}
|
||||
|
||||
std::vector<RvalueReferenceTypeIR>
|
||||
ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<RvalueReferenceTypeIR> rvalue_reference_types;
|
||||
for (auto &&rvalue_reference_type_protobuf : tu.rvalue_reference_types()) {
|
||||
RvalueReferenceTypeIR rvalue_reference_type_ir;
|
||||
ReadTypeInfo(rvalue_reference_type_protobuf.type_info(),
|
||||
&rvalue_reference_type_ir);
|
||||
rvalue_reference_types.emplace_back(std::move(rvalue_reference_type_ir));
|
||||
if (!IsPresentInExportedHeaders(rvalue_reference_type_ir,
|
||||
exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
rvalue_reference_types_.insert(
|
||||
{rvalue_reference_type_ir.GetLinkerSetKey(),
|
||||
std::move(rvalue_reference_type_ir)});
|
||||
}
|
||||
return rvalue_reference_types;
|
||||
}
|
||||
|
||||
std::vector<FunctionIR> ProtobufTextFormatToIRReader::ReadFunctions(
|
||||
void ProtobufTextFormatToIRReader::ReadFunctions(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<FunctionIR> functions;
|
||||
for (auto &&function_protobuf : tu.functions()) {
|
||||
FunctionIR function_ir = FunctionProtobufToIR(function_protobuf);
|
||||
functions.emplace_back(std::move(function_ir));
|
||||
if (!IsPresentInExportedHeaders(function_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
functions_.insert({function_ir.GetLinkerSetKey(), std::move(function_ir)});
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
std::vector<RecordTypeIR> ProtobufTextFormatToIRReader::ReadRecordTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadRecordTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<RecordTypeIR> record_types;
|
||||
for (auto &&record_type_protobuf : tu.record_types()) {
|
||||
RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf);
|
||||
record_types.emplace_back(std::move(record_type_ir));
|
||||
if (!IsPresentInExportedHeaders(record_type_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
record_types_.insert(
|
||||
{record_type_ir.GetLinkerSetKey(), std::move(record_type_ir)});
|
||||
}
|
||||
return record_types;
|
||||
}
|
||||
|
||||
std::vector<EnumTypeIR> ProtobufTextFormatToIRReader::ReadEnumTypes(
|
||||
void ProtobufTextFormatToIRReader::ReadEnumTypes(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<EnumTypeIR> enum_types;
|
||||
for (auto &&enum_type_protobuf : tu.enum_types()) {
|
||||
EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf);
|
||||
enum_types.emplace_back(std::move(enum_type_ir));
|
||||
if (!IsPresentInExportedHeaders(enum_type_ir, exported_headers_)) {
|
||||
continue;
|
||||
}
|
||||
enum_types_.insert(
|
||||
{enum_type_ir.GetLinkerSetKey(), std::move(enum_type_ir)});
|
||||
}
|
||||
return enum_types;
|
||||
}
|
||||
|
||||
std::vector<ElfFunctionIR> ProtobufTextFormatToIRReader::ReadElfFunctions(
|
||||
void ProtobufTextFormatToIRReader::ReadElfFunctions(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<ElfFunctionIR> elf_functions;
|
||||
for (auto &&elf_function : tu.elf_functions()) {
|
||||
elf_functions.emplace_back(ElfFunctionIR(elf_function.name()));
|
||||
ElfFunctionIR elf_function_ir(elf_function.name());
|
||||
elf_functions_.insert(
|
||||
{elf_function_ir.GetName(), std::move(elf_function_ir)});
|
||||
}
|
||||
return elf_functions;
|
||||
}
|
||||
|
||||
std::vector<ElfObjectIR> ProtobufTextFormatToIRReader::ReadElfObjects(
|
||||
void ProtobufTextFormatToIRReader::ReadElfObjects(
|
||||
const abi_dump::TranslationUnit &tu) {
|
||||
std::vector<ElfObjectIR> elf_objects;
|
||||
for (auto &&elf_object : tu.elf_objects()) {
|
||||
elf_objects.emplace_back(ElfObjectIR(elf_object.name()));
|
||||
ElfObjectIR elf_object_ir(elf_object.name());
|
||||
elf_objects_.insert(
|
||||
{elf_object_ir.GetName(), std::move(elf_object_ir)});
|
||||
}
|
||||
return elf_objects;
|
||||
}
|
||||
|
||||
bool IRToProtobufConverter::AddTemplateInformation(
|
||||
@@ -903,6 +933,34 @@ bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtobufIRDumper::AddElfFunctionIR(const ElfFunctionIR *elf_function) {
|
||||
abi_dump::ElfFunction *added_elf_function = tu_ptr_->add_elf_functions();
|
||||
if (!added_elf_function) {
|
||||
return false;
|
||||
}
|
||||
added_elf_function->set_name(elf_function->GetName());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProtobufIRDumper::AddElfObjectIR(const ElfObjectIR *elf_object) {
|
||||
abi_dump::ElfObject *added_elf_object = tu_ptr_->add_elf_objects();
|
||||
if (!added_elf_object) {
|
||||
return false;
|
||||
}
|
||||
added_elf_object->set_name(elf_object->GetName());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) {
|
||||
switch (em->GetKind()) {
|
||||
case ElfSymbolIR::ElfFunctionKind:
|
||||
return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(em));
|
||||
case ElfSymbolIR::ElfObjectKind:
|
||||
return AddElfObjectIR(static_cast<const ElfObjectIR *>(em));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) {
|
||||
abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types();
|
||||
if (!added_record_type) {
|
||||
|
||||
Reference in New Issue
Block a user