From fb0213fe3d98be7fc591bec657b75613075a05c4 Mon Sep 17 00:00:00 2001 From: Logan Chien Date: Thu, 14 Mar 2019 15:48:35 +0800 Subject: header-checker: Split IRDumper and IRReader Test: ./tests/test.py Test: ${ANDROID_HOST_OUT}/nativetest64/\ header-checker-unittests/header-checker-unittests Change-Id: I975ec98924901f2ab059d2b7a96065d419742dfb --- vndk/tools/header-checker/Android.bp | 13 +- .../src/diff_merge/merge_abi_diff.cpp | 8 +- .../header-checker/src/dumper/abi_wrappers.cpp | 2 + .../tools/header-checker/src/dumper/abi_wrappers.h | 1 + .../header-checker/src/dumper/ast_processing.h | 1 + .../src/linker/header_abi_linker.cpp | 2 + .../header-checker/src/repr/abi_diff_helpers.h | 5 +- .../header-checker/src/repr/ir_diff_dumper.cpp | 44 + .../tools/header-checker/src/repr/ir_diff_dumper.h | 68 + .../src/repr/ir_diff_representation.h | 358 +++++ vndk/tools/header-checker/src/repr/ir_dumper.cpp | 45 + vndk/tools/header-checker/src/repr/ir_dumper.h | 51 + vndk/tools/header-checker/src/repr/ir_reader.cpp | 598 ++++++++ vndk/tools/header-checker/src/repr/ir_reader.h | 275 ++++ .../header-checker/src/repr/ir_representation.cpp | 600 -------- .../header-checker/src/repr/ir_representation.h | 671 --------- .../src/repr/ir_representation_internal.h | 86 ++ .../header-checker/src/repr/json/converter.cpp | 67 + .../tools/header-checker/src/repr/json/converter.h | 134 ++ .../header-checker/src/repr/json/ir_dumper.cpp | 431 ++++++ .../tools/header-checker/src/repr/json/ir_dumper.h | 103 ++ .../header-checker/src/repr/json/ir_reader.cpp | 483 +++++++ .../tools/header-checker/src/repr/json/ir_reader.h | 186 +++ .../src/repr/json/ir_representation_json.cpp | 952 ------------- .../src/repr/json/ir_representation_json.h | 295 ---- .../header-checker/src/repr/protobuf/abi_diff.h | 26 + .../header-checker/src/repr/protobuf/abi_dump.h | 26 + .../header-checker/src/repr/protobuf/converter.cpp | 289 ++++ .../header-checker/src/repr/protobuf/converter.h | 371 +++++ .../src/repr/protobuf/ir_diff_dumper.cpp | 371 +++++ .../src/repr/protobuf/ir_diff_dumper.h | 95 ++ .../header-checker/src/repr/protobuf/ir_dumper.cpp | 494 +++++++ .../header-checker/src/repr/protobuf/ir_dumper.h | 81 ++ .../header-checker/src/repr/protobuf/ir_reader.cpp | 386 +++++ .../header-checker/src/repr/protobuf/ir_reader.h | 110 ++ .../repr/protobuf/ir_representation_protobuf.cpp | 1504 -------------------- .../src/repr/protobuf/ir_representation_protobuf.h | 490 ------- 37 files changed, 5200 insertions(+), 4522 deletions(-) create mode 100644 vndk/tools/header-checker/src/repr/ir_diff_dumper.cpp create mode 100644 vndk/tools/header-checker/src/repr/ir_diff_dumper.h create mode 100644 vndk/tools/header-checker/src/repr/ir_diff_representation.h create mode 100644 vndk/tools/header-checker/src/repr/ir_dumper.cpp create mode 100644 vndk/tools/header-checker/src/repr/ir_dumper.h create mode 100644 vndk/tools/header-checker/src/repr/ir_reader.cpp create mode 100644 vndk/tools/header-checker/src/repr/ir_reader.h delete mode 100644 vndk/tools/header-checker/src/repr/ir_representation.cpp create mode 100644 vndk/tools/header-checker/src/repr/ir_representation_internal.h create mode 100644 vndk/tools/header-checker/src/repr/json/converter.cpp create mode 100644 vndk/tools/header-checker/src/repr/json/converter.h create mode 100644 vndk/tools/header-checker/src/repr/json/ir_dumper.cpp create mode 100644 vndk/tools/header-checker/src/repr/json/ir_dumper.h create mode 100644 vndk/tools/header-checker/src/repr/json/ir_reader.cpp create mode 100644 vndk/tools/header-checker/src/repr/json/ir_reader.h delete mode 100644 vndk/tools/header-checker/src/repr/json/ir_representation_json.cpp delete mode 100644 vndk/tools/header-checker/src/repr/json/ir_representation_json.h create mode 100644 vndk/tools/header-checker/src/repr/protobuf/abi_diff.h create mode 100644 vndk/tools/header-checker/src/repr/protobuf/abi_dump.h create mode 100644 vndk/tools/header-checker/src/repr/protobuf/converter.cpp create mode 100644 vndk/tools/header-checker/src/repr/protobuf/converter.h create mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.cpp create mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.h create mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_dumper.cpp create mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_dumper.h create mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_reader.cpp create mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_reader.h delete mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.cpp delete mode 100644 vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.h (limited to 'vndk') diff --git a/vndk/tools/header-checker/Android.bp b/vndk/tools/header-checker/Android.bp index a27385f02..f49e620b7 100644 --- a/vndk/tools/header-checker/Android.bp +++ b/vndk/tools/header-checker/Android.bp @@ -150,9 +150,16 @@ cc_library_host_static { srcs: [ "src/repr/abi_diff_helpers.cpp", - "src/repr/ir_representation.cpp", - "src/repr/json/ir_representation_json.cpp", - "src/repr/protobuf/ir_representation_protobuf.cpp", + "src/repr/ir_diff_dumper.cpp", + "src/repr/ir_dumper.cpp", + "src/repr/ir_reader.cpp", + "src/repr/json/converter.cpp", + "src/repr/json/ir_dumper.cpp", + "src/repr/json/ir_reader.cpp", + "src/repr/protobuf/converter.cpp", + "src/repr/protobuf/ir_diff_dumper.cpp", + "src/repr/protobuf/ir_dumper.cpp", + "src/repr/protobuf/ir_reader.cpp", "src/repr/symbol/exported_symbol_set.cpp", "src/repr/symbol/so_file_parser.cpp", "src/repr/symbol/version_script_parser.cpp", diff --git a/vndk/tools/header-checker/src/diff_merge/merge_abi_diff.cpp b/vndk/tools/header-checker/src/diff_merge/merge_abi_diff.cpp index 52ab971fa..dd582eafe 100644 --- a/vndk/tools/header-checker/src/diff_merge/merge_abi_diff.cpp +++ b/vndk/tools/header-checker/src/diff_merge/merge_abi_diff.cpp @@ -12,12 +12,8 @@ // 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 "abi_dump.pb.h" -#include "abi_diff.pb.h" -#pragma clang diagnostic pop +#include "repr/protobuf/abi_diff.h" +#include "repr/protobuf/abi_dump.h" #include #include diff --git a/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp b/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp index efd835148..eff66fbc1 100644 --- a/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp +++ b/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp @@ -14,6 +14,8 @@ #include "dumper/abi_wrappers.h" +#include "repr/ir_dumper.h" +#include "repr/ir_reader.h" #include "utils/header_abi_util.h" #include diff --git a/vndk/tools/header-checker/src/dumper/abi_wrappers.h b/vndk/tools/header-checker/src/dumper/abi_wrappers.h index 624e0edfe..243c3627b 100644 --- a/vndk/tools/header-checker/src/dumper/abi_wrappers.h +++ b/vndk/tools/header-checker/src/dumper/abi_wrappers.h @@ -16,6 +16,7 @@ #define ABI_WRAPPERS_H_ #include "dumper/ast_util.h" +#include "repr/ir_dumper.h" #include "repr/ir_representation.h" #include diff --git a/vndk/tools/header-checker/src/dumper/ast_processing.h b/vndk/tools/header-checker/src/dumper/ast_processing.h index 1fbad8e39..729cc62b1 100644 --- a/vndk/tools/header-checker/src/dumper/ast_processing.h +++ b/vndk/tools/header-checker/src/dumper/ast_processing.h @@ -17,6 +17,7 @@ #include "dumper/ast_util.h" #include "dumper/header_checker.h" +#include "repr/ir_dumper.h" #include #include diff --git a/vndk/tools/header-checker/src/linker/header_abi_linker.cpp b/vndk/tools/header-checker/src/linker/header_abi_linker.cpp index 4fcbbf50e..094e9e594 100644 --- a/vndk/tools/header-checker/src/linker/header_abi_linker.cpp +++ b/vndk/tools/header-checker/src/linker/header_abi_linker.cpp @@ -13,6 +13,8 @@ // limitations under the License. #include "repr/ir_representation.h" +#include "repr/ir_dumper.h" +#include "repr/ir_reader.h" #include "repr/symbol/so_file_parser.h" #include "repr/symbol/version_script_parser.h" #include "utils/header_abi_util.h" diff --git a/vndk/tools/header-checker/src/repr/abi_diff_helpers.h b/vndk/tools/header-checker/src/repr/abi_diff_helpers.h index 0425709ac..b31d3ae34 100644 --- a/vndk/tools/header-checker/src/repr/abi_diff_helpers.h +++ b/vndk/tools/header-checker/src/repr/abi_diff_helpers.h @@ -15,6 +15,9 @@ #ifndef ABI_DIFF_HELPERS_H_ #define ABI_DIFF_HELPERS_H_ +#include "repr/ir_diff_dumper.h" +#include "repr/ir_diff_representation.h" +#include "repr/ir_reader.h" #include "repr/ir_representation.h" #include @@ -41,7 +44,7 @@ enum DiffStatus { opaque_diff = 3, }; -static inline DiffStatus operator|(DiffStatus f,DiffStatus s) { +static inline DiffStatus operator|(DiffStatus f, DiffStatus s) { return static_cast( static_cast::type>(f) | static_cast::type>(s)); diff --git a/vndk/tools/header-checker/src/repr/ir_diff_dumper.cpp b/vndk/tools/header-checker/src/repr/ir_diff_dumper.cpp new file mode 100644 index 000000000..0a40a312b --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_diff_dumper.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/ir_diff_dumper.h" + +#include "repr/ir_representation.h" +#include "repr/protobuf/ir_diff_dumper.h" + +#include +#include + +#include + + +namespace header_checker { +namespace repr { + + +std::unique_ptr IRDiffDumper::CreateIRDiffDumper( + TextFormatIR text_format, const std::string &dump_path) { + switch (text_format) { + case TextFormatIR::ProtobufTextFormat: + return std::make_unique(dump_path); + default: + // Nothing else is supported yet. + llvm::errs() << "Text format not supported yet\n"; + return nullptr; + } +} + + +} // namespace repr +} // header_checker diff --git a/vndk/tools/header-checker/src/repr/ir_diff_dumper.h b/vndk/tools/header-checker/src/repr/ir_diff_dumper.h new file mode 100644 index 000000000..bb7a2eb2a --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_diff_dumper.h @@ -0,0 +1,68 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_IR_DIFF_DUMPER_H_ +#define HEADER_CHECKER_REPR_IR_DIFF_DUMPER_H_ + +#include "repr/ir_diff_representation.h" + +#include + + +namespace header_checker { +namespace repr { + + +class IRDiffDumper { + public: + typedef DiffMessageIR::DiffKind DiffKind; + + public: + IRDiffDumper(const std::string &dump_path) : dump_path_(dump_path) {} + + virtual ~IRDiffDumper() {} + + virtual bool AddDiffMessageIR(const DiffMessageIR *, + const std::string &type_stack, + DiffKind diff_kind) = 0; + + virtual bool AddLinkableMessageIR(const LinkableMessageIR *, + DiffKind diff_kind) = 0; + + virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *, + DiffKind diff_kind) = 0; + + virtual void AddLibNameIR(const std::string &name) = 0; + + virtual void AddArchIR(const std::string &arch) = 0; + + virtual void AddCompatibilityStatusIR(CompatibilityStatusIR status) = 0; + + virtual bool Dump() = 0; + + virtual CompatibilityStatusIR GetCompatibilityStatusIR() = 0; + + static std::unique_ptr CreateIRDiffDumper( + TextFormatIR, const std::string &dump_path); + + protected: + const std::string &dump_path_; +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_IR_DIFF_DUMPER_H_ diff --git a/vndk/tools/header-checker/src/repr/ir_diff_representation.h b/vndk/tools/header-checker/src/repr/ir_diff_representation.h new file mode 100644 index 000000000..2ec4c0def --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_diff_representation.h @@ -0,0 +1,358 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_IR_DIFF_REPRESENTATION_H_ +#define HEADER_CHECKER_REPR_IR_DIFF_REPRESENTATION_H_ + +#include "repr/ir_representation.h" + +#include +#include +#include +#include +#include + + +namespace header_checker { +namespace repr { + + +class DiffMessageIR { + public: + enum DiffKind { + Extension, // Applicable for enums. + Added, + Removed, + Referenced, + Unreferenced + }; + + public: + virtual ~DiffMessageIR() {} + + virtual LinkableMessageKind Kind() const = 0; + + void SetName(const std::string &name) { + name_ = name; + } + + const std::string &GetName() const { + return name_; + } + + protected: + std::string name_; +}; + +class AccessSpecifierDiffIR { + public: + AccessSpecifierDiffIR(AccessSpecifierIR old_access, + AccessSpecifierIR new_access) + : old_access_(old_access), new_access_(new_access) {} + + protected: + AccessSpecifierIR old_access_; + AccessSpecifierIR new_access_; +}; + +class TypeDiffIR { + public: + TypeDiffIR(std::pair &&sizes, + std::pair &&alignment) + : sizes_(std::move(sizes)), alignments_(std::move(alignment)) {} + + const std::pair &GetSizes() const { + return sizes_; + } + + const std::pair &GetAlignments() const { + return alignments_; + } + + protected: + std::pair sizes_; + std::pair alignments_; +}; + +class VTableLayoutDiffIR { + public: + VTableLayoutDiffIR(const VTableLayoutIR &old_layout, + const VTableLayoutIR &new_layout) + : old_layout_(old_layout), new_layout_(new_layout) {} + + const VTableLayoutIR &GetOldVTable() const { + return old_layout_; + } + + const VTableLayoutIR &GetNewVTable() const { + return new_layout_; + } + + protected: + const VTableLayoutIR &old_layout_; + const VTableLayoutIR &new_layout_; +}; + +class RecordFieldDiffIR { + public: + RecordFieldDiffIR(const RecordFieldIR *old_field, + const RecordFieldIR *new_field) + : old_field_(old_field), new_field_(new_field) {} + + const RecordFieldIR *GetOldField() const { + return old_field_; + } + + const RecordFieldIR *GetNewField() const { + return new_field_; + } + + const RecordFieldIR *old_field_; + const RecordFieldIR *new_field_; +}; + +class CXXBaseSpecifierDiffIR { + public: + CXXBaseSpecifierDiffIR( + const std::vector &old_base_specifiers, + const std::vector &new_base_specifiers) + : old_base_specifiers_(old_base_specifiers), + new_base_specifiers_(new_base_specifiers) {} + + const std::vector &GetOldBases() const { + return old_base_specifiers_; + } + + const std::vector &GetNewBases() const { + return new_base_specifiers_; + } + + protected: + const std::vector &old_base_specifiers_; + const std::vector &new_base_specifiers_; +}; + +class RecordTypeDiffIR : public DiffMessageIR { + public: + LinkableMessageKind Kind() const override { + return LinkableMessageKind::RecordTypeKind; + } + + void SetFieldDiffs(std::vector &&field_diffs) { + field_diffs_ = std::move(field_diffs); + } + + const std::vector &GetFieldDiffs() const { + return field_diffs_; + } + + void SetFieldsRemoved(std::vector &&fields_removed) { + fields_removed_ = std::move(fields_removed); + } + + void SetFieldsAdded(std::vector &&fields_added) { + fields_added_ = std::move(fields_added); + } + + const std::vector &GetFieldsRemoved() const { + return fields_removed_; + } + + const std::vector &GetFieldsAdded() const { + return fields_added_; + } + + void SetVTableLayoutDiff(std::unique_ptr &&vtable_diffs) { + vtable_diffs_ = std::move(vtable_diffs); + } + + void SetTypeDiff(std::unique_ptr &&type_diff) { + type_diff_ = std::move(type_diff); + } + + void SetAccessDiff(std::unique_ptr &&access_diff) { + access_diff_ = std::move(access_diff); + } + + void SetBaseSpecifierDiffs( + std::unique_ptr &&base_diffs) { + base_specifier_diffs_ = std::move(base_diffs); + } + + bool DiffExists() const { + return (type_diff_ != nullptr) || (vtable_diffs_ != nullptr) || + (fields_removed_.size() != 0) || (field_diffs_.size() != 0) || + (access_diff_ != nullptr) || (base_specifier_diffs_ != nullptr); + } + + const TypeDiffIR *GetTypeDiff() const { + return type_diff_.get(); + } + + const VTableLayoutDiffIR *GetVTableLayoutDiff() const { + return vtable_diffs_.get(); + } + + const CXXBaseSpecifierDiffIR *GetBaseSpecifiers() const { + return base_specifier_diffs_.get(); + } + + protected: + // optional implemented with vector / std::unique_ptr. + std::unique_ptr type_diff_; + std::unique_ptr vtable_diffs_; + std::vector field_diffs_; + std::vector fields_removed_; + std::vector fields_added_; + std::unique_ptr access_diff_; + std::unique_ptr base_specifier_diffs_; + // Template Diffs are not needed since they will show up in the linker set + // key. +}; + +class EnumFieldDiffIR { + public: + EnumFieldDiffIR(const EnumFieldIR *old_field, const EnumFieldIR *new_field) + : old_field_(old_field), new_field_(new_field) {} + + const EnumFieldIR *GetOldField() const { + return old_field_; + } + + const EnumFieldIR *GetNewField() const { + return new_field_; + } + + protected: + const EnumFieldIR *old_field_; + const EnumFieldIR *new_field_; +}; + +class EnumTypeDiffIR : public DiffMessageIR { + public: + void SetFieldsRemoved(std::vector &&fields_removed) { + fields_removed_ = std::move(fields_removed); + } + + const std::vector &GetFieldsRemoved() const { + return fields_removed_; + } + + void SetFieldsAdded(std::vector &&fields_added) { + fields_added_ = std::move(fields_added); + } + + const std::vector &GetFieldsAdded() const { + return fields_added_; + } + + void SetFieldsDiff(std::vector &&fields_diff) { + fields_diff_ = std::move(fields_diff); + } + + const std::vector &GetFieldsDiff() const { + return fields_diff_; + } + + void SetUnderlyingTypeDiff( + std::unique_ptr> &&utype_diff) { + underlying_type_diff_ = std::move(utype_diff); + } + + const std::pair *GetUnderlyingTypeDiff() const { + return underlying_type_diff_.get(); + } + + bool IsExtended() const { + if (fields_removed_.size() == 0 && fields_diff_.size() == 0 && + fields_added_.size() != 0) { + return true; + } + return false; + } + + bool IsIncompatible() const { + if (fields_removed_.size() != 0 || fields_diff_.size() != 0) { + return true; + } + return false; + } + + LinkableMessageKind Kind() const override { + return LinkableMessageKind::EnumTypeKind; + } + + protected: + // The underlying type can only be integral, so we just need to check for + // referenced type. + std::unique_ptr> underlying_type_diff_; + std::vector fields_removed_; + std::vector fields_added_; + std::vector fields_diff_; + // Modifiable to allow implicit construction. + std::string name_; +}; + +class GlobalVarDiffIR : public DiffMessageIR { + public: + LinkableMessageKind Kind() const override { + return LinkableMessageKind::GlobalVarKind; + } + + GlobalVarDiffIR(const GlobalVarIR *old_global_var, + const GlobalVarIR *new_global_var) + : old_global_var_(old_global_var), new_global_var_(new_global_var) {} + + const GlobalVarIR *GetOldGlobalVar() const { + return old_global_var_; + } + + const GlobalVarIR *GetNewGlobalVar() const { + return new_global_var_; + } + + protected: + const GlobalVarIR *old_global_var_; + const GlobalVarIR *new_global_var_; +}; + +class FunctionDiffIR : public DiffMessageIR { + public: + FunctionDiffIR(const FunctionIR *old_function, + const FunctionIR *new_function) + : old_function_(old_function), new_function_(new_function) {} + + LinkableMessageKind Kind() const override { + return LinkableMessageKind::FunctionKind; + } + + const FunctionIR *GetOldFunction() const { + return old_function_; + } + + const FunctionIR *GetNewFunction() const { + return new_function_; + } + + protected: + const FunctionIR *old_function_; + const FunctionIR *new_function_; +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_IR_DIFF_REPRESENTATION_H_ diff --git a/vndk/tools/header-checker/src/repr/ir_dumper.cpp b/vndk/tools/header-checker/src/repr/ir_dumper.cpp new file mode 100644 index 000000000..3466a8540 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_dumper.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/ir_dumper.h" + +#include "repr/json/ir_dumper.h" +#include "repr/protobuf/ir_dumper.h" + +#include +#include + +#include + + +namespace header_checker { +namespace repr { + + +std::unique_ptr IRDumper::CreateIRDumper( + TextFormatIR text_format, const std::string &dump_path) { + switch (text_format) { + case TextFormatIR::ProtobufTextFormat: + return std::make_unique(dump_path); + case TextFormatIR::Json: + return std::make_unique(dump_path); + default: + llvm::errs() << "Text format not supported yet\n"; + return nullptr; + } +} + + +} // namespace repr +} // header_checker diff --git a/vndk/tools/header-checker/src/repr/ir_dumper.h b/vndk/tools/header-checker/src/repr/ir_dumper.h new file mode 100644 index 000000000..1e6128d08 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_dumper.h @@ -0,0 +1,51 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_IR_DUMPER_H_ +#define HEADER_CHECKER_REPR_IR_DUMPER_H_ + +#include "repr/ir_representation.h" + +#include + + +namespace header_checker { +namespace repr { + + +class IRDumper { + public: + IRDumper(const std::string &dump_path) : dump_path_(dump_path) {} + + virtual ~IRDumper() {} + + static std::unique_ptr 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; + + protected: + const std::string &dump_path_; +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_IR_DUMPER_H_ diff --git a/vndk/tools/header-checker/src/repr/ir_reader.cpp b/vndk/tools/header-checker/src/repr/ir_reader.cpp new file mode 100644 index 000000000..0b7ad2f3e --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_reader.cpp @@ -0,0 +1,598 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/ir_reader.h" + +#include "repr/abi_diff_helpers.h" +#include "repr/ir_representation.h" +#include "repr/ir_representation_internal.h" +#include "repr/ir_diff_representation.h" +#include "repr/json/ir_reader.h" +#include "repr/protobuf/ir_reader.h" + +#include +#include +#include +#include + +#include + + +namespace header_checker { +namespace repr { + + +using MergeStatus = TextFormatToIRReader::MergeStatus; + + +std::unique_ptr +TextFormatToIRReader::CreateTextFormatToIRReader( + TextFormatIR text_format, const std::set *exported_headers) { + switch (text_format) { + case TextFormatIR::ProtobufTextFormat: + return std::make_unique(exported_headers); + case TextFormatIR::Json: + return std::make_unique(exported_headers); + default: + llvm::errs() << "Text format not supported yet\n"; + return nullptr; + } +} + + +void TextFormatToIRReader::AddToODRListMap(const std::string &key, + const TypeIR *value) { + auto map_it = module_->odr_list_map_.find(key); + if (map_it == module_->odr_list_map_.end()) { + module_->odr_list_map_.emplace(key, std::list({value})); + return; + } + module_->odr_list_map_[key].emplace_back(value); +} + + +MergeStatus TextFormatToIRReader::IsBuiltinTypeNodePresent( + const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + std::string builtin_linker_set_key = builtin_type->GetLinkerSetKey(); + auto builtin_it = module_->builtin_types_.find(builtin_linker_set_key); + if (builtin_it != module_->builtin_types_.end()) { + return MergeStatus(false, builtin_it->second.GetSelfType()); + } + // Add this builtin type to the parent graph's builtin_types_ map. + // Before that, correct the type id of the builtin-type. + const std::string &local_type_id = builtin_type->GetSelfType(); + std::string builtin_global_type_id = AllocateNewTypeId(); + auto it = module_->builtin_types_.emplace( + builtin_linker_set_key, *builtin_type); + it.first->second.SetSelfType(builtin_global_type_id); + it.first->second.SetReferencedType(builtin_global_type_id); + module_->type_graph_.emplace(builtin_global_type_id, &((it.first)->second)); + + MergeStatus merge_status(true, builtin_global_type_id); + local_to_global_type_id_map->emplace(local_type_id, merge_status); + return merge_status; +} + + +MergeStatus TextFormatToIRReader::DoesUDTypeODRViolationExist( + const TypeIR *ud_type, const TextFormatToIRReader &addend, + const std::string ud_type_unique_id_and_source, + AbiElementMap *local_to_global_type_id_map_) { + // Per entry in the map: + // /-----------------------------------------------------------------------\ + // | UDType->UniqueTagId + UdType->source File => list(const UDTypeIR *) | + // \-----------------------------------------------------------------------/ + auto it = module_->odr_list_map_.find(ud_type_unique_id_and_source); + if (it == module_->odr_list_map_.end()) { + // Calling this an ODR violation even though it means no UD with the same + // name + source combination was seen in the parent graph. The type-id + // passed does not matter since was_newly_added_ is true, the type will get + // allocated a new type id. + return MergeStatus(true, ""); + } + std::set type_cache; + DiffPolicyOptions diff_policy_options(false) ; + AbiDiffHelper diff_helper(module_->type_graph_, addend.module_->type_graph_, + diff_policy_options, &type_cache, + nullptr, local_to_global_type_id_map_); + for (auto &contender_ud : it->second) { + if (diff_helper.CompareAndDumpTypeDiff(contender_ud->GetSelfType(), + ud_type->GetSelfType()) == + DiffStatus::no_diff) { + local_to_global_type_id_map_->emplace( + ud_type->GetSelfType(), + MergeStatus(false, contender_ud->GetSelfType())); + return MergeStatus(false, contender_ud->GetSelfType()); + } + } +#ifdef DEBUG + llvm::errs() << "ODR violation detected for: " << ud_type->GetName() << "\n"; +#endif + return MergeStatus(true, (*(it->second.begin()))->GetSelfType()); +} + + +MergeStatus TextFormatToIRReader::IsTypeNodePresent( + const TypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + std::string unique_type_id; + switch (addend_node->GetKind()) { + case RecordTypeKind: + unique_type_id = + GetODRListMapKey(static_cast(addend_node)); + break; + case EnumTypeKind: + unique_type_id = + GetODRListMapKey(static_cast(addend_node)); + break; + case FunctionTypeKind: + unique_type_id = + GetODRListMapKey(static_cast(addend_node)); + break; + default: + // We add the type proactively. + return MergeStatus(true, "type-hidden"); + } + // Every other type is a referencing type / builtin type, so it is proactively + // added by returning MergeStatus with was_newly_added_ = true. + return DoesUDTypeODRViolationExist( + addend_node, addend, unique_type_id, local_to_global_type_id_map); +} + + +// This method merges the type referenced by 'references_type' into the parent +// graph. It also corrects the referenced_type field in the references_type +// object passed and returns the merge status of the *referenced type*. +MergeStatus TextFormatToIRReader::MergeReferencingTypeInternal( + const TextFormatToIRReader &addend, + ReferencesOtherType *references_type, + AbiElementMap *local_to_global_type_id_map) { + // First look in the local_to_global_type_id_map for the referenced type's + // id. + const std::string &referenced_type_id = + references_type->GetReferencedType(); + auto local_to_global_it = local_to_global_type_id_map->find( + referenced_type_id); + if (local_to_global_it != local_to_global_type_id_map->end()) { + // The type was already added to the parent graph. So change the + // referenced type to the global type id. + references_type->SetReferencedType(local_to_global_it->second.type_id_); + return local_to_global_it->second; + } + + // If that did not go through, look at the addend's type_map_ and get the + // TypeIR* and call MergeType on it. + auto local_type_it = addend.module_->type_graph_.find(referenced_type_id); + if (local_type_it != addend.module_->type_graph_.end()) { + // We don't care about merge_status.was_newly_added since we wouldn't have + // gotten this far if we weren't adding this. + MergeStatus merge_status = + MergeType(local_type_it->second, addend, local_to_global_type_id_map); + const std::string &global_type_id = merge_status.type_id_; + references_type->SetReferencedType(global_type_id); + return merge_status; + } + + // The referenced type was hidden, so just set it to type-hidden. + const std::string &hidden_type_id = AllocateNewTypeId(); + references_type->SetReferencedType(hidden_type_id); + return MergeStatus(true, hidden_type_id); +} + + +void TextFormatToIRReader::MergeRecordFields( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map) { + for (auto &field : added_node->GetFields()) { + MergeReferencingTypeInternal(addend, &field, local_to_global_type_id_map); + } +} + + +void TextFormatToIRReader::MergeRecordCXXBases( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map) { + for (auto &base : added_node->GetBases()) { + MergeReferencingTypeInternal(addend, &base, local_to_global_type_id_map); + } +} + + +void TextFormatToIRReader::MergeRecordTemplateElements( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map) { + for (auto &template_element : added_node->GetTemplateElements()) { + MergeReferencingTypeInternal( + addend, &template_element, local_to_global_type_id_map); + } +} + + +void TextFormatToIRReader::MergeRecordDependencies( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map) { + // First call MergeType on all its fields. + MergeRecordFields(addend, added_node, local_to_global_type_id_map); + + // Call MergeType on CXXBases of the record. + MergeRecordCXXBases(addend, added_node, local_to_global_type_id_map); + + MergeRecordTemplateElements(addend, added_node, local_to_global_type_id_map); +} + + +template +std::pair::iterator> +TextFormatToIRReader::UpdateUDTypeAccounting( + const T *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map, + AbiElementMap *specific_type_map) { + std::string added_type_id = AllocateNewTypeId(); + // Add the ud-type with type-id to the type_graph_, since if there are generic + // reference types which refer to the record being added, they'll need to find + // it's id in the map. + // Add ud-type to the parent graph. + T added_type_ir = *addend_node; + added_type_ir.SetSelfType(added_type_id); + added_type_ir.SetReferencedType(added_type_id); + auto it = AddToMapAndTypeGraph(std::move(added_type_ir), specific_type_map, + &module_->type_graph_); + // Add to faciliate ODR checking. + const std::string &key = GetODRListMapKey(&(it->second)); + MergeStatus type_merge_status = MergeStatus(true, added_type_id); + AddToODRListMap(key, &(it->second)); + local_to_global_type_id_map->emplace(addend_node->GetSelfType(), + type_merge_status); + return {type_merge_status, it}; +} + + +// This method is necessarily going to have a was_newly_merged_ = true in its +// MergeStatus return. So it necessarily merges a new RecordType. +MergeStatus TextFormatToIRReader::MergeRecordAndDependencies( + const RecordTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + auto merge_status_and_it = + UpdateUDTypeAccounting(addend_node, addend, local_to_global_type_id_map, + &module_->record_types_); + auto it = merge_status_and_it.second; + MergeRecordDependencies(addend, &(it->second), local_to_global_type_id_map); + return merge_status_and_it.first; +} + + +void TextFormatToIRReader::MergeEnumDependencies( + const TextFormatToIRReader &addend, EnumTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map) { + const std::string underlying_type_id = added_node->GetUnderlyingType(); + // Get the underlying type, it nessarily has to be present in the addend's + // type graph since builtin types can't be hidden. Call MergeType on it and + // change the underlying type to that. + auto it = addend.module_->type_graph_.find(underlying_type_id); + if (it == addend.module_->type_graph_.end()) { + llvm::errs() << "Enum underlying types should not be hidden\n"; + ::exit(1); + } + MergeStatus merge_status = MergeType(it->second, addend, + local_to_global_type_id_map); + added_node->SetUnderlyingType(merge_status.type_id_); +} + + +// This method is necessarily going to have a was_newly_merged_ = true in its +// MergeStatus return. So it necessarily merges a new EnumType. +MergeStatus TextFormatToIRReader::MergeEnumType( + const EnumTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + auto merge_status_and_it = + UpdateUDTypeAccounting(addend_node, addend, local_to_global_type_id_map, + &module_->enum_types_); + auto it = merge_status_and_it.second; + MergeEnumDependencies(addend, &(it->second), local_to_global_type_id_map); + return merge_status_and_it.first; +} + + +MergeStatus TextFormatToIRReader::MergeFunctionType( + const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + auto merge_status_and_it = + UpdateUDTypeAccounting(addend_node, addend, local_to_global_type_id_map, + &module_->function_types_); + auto it = merge_status_and_it.second; + MergeCFunctionLikeDeps(addend, &(it->second), local_to_global_type_id_map); + return merge_status_and_it.first; +} + + +template +MergeStatus TextFormatToIRReader::MergeReferencingTypeInternalAndUpdateParent( + const TextFormatToIRReader &addend, const T *addend_node, + AbiElementMap *local_to_global_type_id_map, + AbiElementMap *parent_map, const std::string &updated_self_type_id) { + MergeStatus merge_status; + uint64_t old_max_type_id = max_type_id_; + // Create copy of addend_node + T added_node = *(addend_node); + added_node.SetSelfType(updated_self_type_id); + // The merge status returned is the merge status of the referenced type. + merge_status = MergeReferencingTypeInternal(addend, &added_node, + local_to_global_type_id_map); + if (merge_status.was_newly_added_) { + // Emplace to map (type-referenced -> Referencing type) + AddToMapAndTypeGraph(std::move(added_node), parent_map, + &module_->type_graph_); + return MergeStatus(true, updated_self_type_id); + } + + // The type that the added_node references was not newly added to the parent + // graph. However, we still might need to add the added_node to the parent + // graph, since for the particular 'Kind' of the added_node, it may not be + // present in the parent graph. This will be determined by looking at the + // appropriate 'type-referenced' -> TypeElement map in the parent for the + // type-id returned by the MergeStatus. If the map doesn't have an entry for + // the type-id returned by the MergeStatus, the added_type is not present in + // the parent graph and needs to be 'newly' added. We also need to modify the + // global type id in the local_to_global_type_id map. The added_node should + // already have it's self_type and referenced_type fields fixed up. + // We maintain a rollback id to have contiguous type ids. + max_type_id_ = old_max_type_id; + + // Try finding the referenced_type is referred to by any referencing type + // of the same kind in the parent graph. It is safe to call this on the + // added_node, since the referenced_type in the added_node would have been + // modified by the MergeReferencingTypeInternal call. + auto it = parent_map->find(GetReferencedTypeMapKey(added_node)); + if (it == parent_map->end()) { + // There was no counterpart found for the added_node's type Kind referencing + // the referenced type, so we added it to the parent and also updated the + // local_to_global_type_id_map's global_id value. + AddToMapAndTypeGraph(std::move(added_node), parent_map, + &module_->type_graph_); + + merge_status = MergeStatus(true, updated_self_type_id); + return merge_status; + } + + // Update local_to_global_type_id map's MergeStatus.was_newly_added value for + // this key with false since this was node was not newly added. + // We never remove anything from the local_to_global_type_id_map, what's + // the point ? Since you store the decision of whether the type was newly + // added or not. It's global type id is the type-id of the element found + // in the parent map which refers to the added_node's modified + // referenced_type. + merge_status = MergeStatus(false, it->second.GetSelfType()); + (*local_to_global_type_id_map)[addend_node->GetSelfType()] = merge_status; + + return merge_status; +} + + +MergeStatus TextFormatToIRReader::MergeReferencingType( + const TextFormatToIRReader &addend, const TypeIR *addend_node, + AbiElementMap *local_to_global_type_id_map, + const std::string &updated_self_type_id) { + switch (addend_node->GetKind()) { + case PointerTypeKind: + return MergeReferencingTypeInternalAndUpdateParent( + addend, static_cast(addend_node), + local_to_global_type_id_map, &module_->pointer_types_, + updated_self_type_id); + case QualifiedTypeKind: + return MergeReferencingTypeInternalAndUpdateParent( + addend, static_cast(addend_node), + local_to_global_type_id_map, &module_->qualified_types_, + updated_self_type_id); + case ArrayTypeKind: + return MergeReferencingTypeInternalAndUpdateParent( + addend, static_cast(addend_node), + local_to_global_type_id_map, &module_->array_types_, + updated_self_type_id); + case LvalueReferenceTypeKind: + return MergeReferencingTypeInternalAndUpdateParent( + addend, static_cast(addend_node), + local_to_global_type_id_map, &module_->lvalue_reference_types_, + updated_self_type_id); + case RvalueReferenceTypeKind: + return MergeReferencingTypeInternalAndUpdateParent( + addend, static_cast(addend_node), + local_to_global_type_id_map, &module_->rvalue_reference_types_, + updated_self_type_id); + default: + // Only referencing types + assert(0); + } +} + + +// This method creates a new node for the addend node in the graph if MergeType +// on the reference returned a MergeStatus with was_newly_added_ = true. +MergeStatus TextFormatToIRReader::MergeGenericReferringType( + const TextFormatToIRReader &addend, const TypeIR *addend_node, + AbiElementMap *local_to_global_type_id_map) { + // First add the type 'pro-actively'. We need to do this since we'll need to + // fill in 'referenced-type' fields in all this type's descendants and + // descendants which are compound types (records), can refer to this type. + std::string added_type_id = AllocateNewTypeId(); + // Add the added record type to the local_to_global_type_id_map + local_to_global_type_id_map->emplace(addend_node->GetSelfType(), + MergeStatus(true, added_type_id)); + return MergeReferencingType(addend, addend_node, local_to_global_type_id_map, + added_type_id); +} + + +MergeStatus TextFormatToIRReader::MergeTypeInternal( + const TypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + switch (addend_node->GetKind()) { + case BuiltinTypeKind: + return IsBuiltinTypeNodePresent( + static_cast(addend_node), addend, + local_to_global_type_id_map); + break; + case RecordTypeKind: + return MergeRecordAndDependencies( + static_cast(addend_node), + addend, local_to_global_type_id_map); + case EnumTypeKind: + return MergeEnumType(static_cast( + addend_node), addend, local_to_global_type_id_map); + case FunctionTypeKind: + return MergeFunctionType(static_cast( + addend_node), addend, local_to_global_type_id_map); + default: + return MergeGenericReferringType(addend, addend_node, + local_to_global_type_id_map); + } + assert(0); +} + + +MergeStatus TextFormatToIRReader::MergeType( + const TypeIR *addend_node, + const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + // Check if the addend type is already in the parent graph. Since we're + // going to traverse all the dependencies add whichever ones are not in the + // parent graph. This does not add the node itself though. + auto type_it = local_to_global_type_id_map->find(addend_node->GetSelfType()); + if (type_it != local_to_global_type_id_map->end()) { + return type_it->second; + } + + MergeStatus merge_status = IsTypeNodePresent( + addend_node, addend, local_to_global_type_id_map); + if (!merge_status.was_newly_added_) { + return merge_status; + } + merge_status = MergeTypeInternal( + addend_node, addend, local_to_global_type_id_map); + return merge_status; +} + + +void TextFormatToIRReader::MergeCFunctionLikeDeps( + const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, + AbiElementMap *local_to_global_type_id_map) { + // Merge the return type first. + auto ret_type_it = + addend.module_->type_graph_.find(cfunction_like_ir->GetReturnType()); + if (ret_type_it == addend.module_->type_graph_.end()) { + // Hidden types aren't officially added to the parent since there is + // nothing actually backing it. We assign a type-id. + cfunction_like_ir->SetReturnType(AllocateNewTypeId()); + } else { + MergeStatus ret_merge_status = MergeType(ret_type_it->second, addend, + local_to_global_type_id_map); + cfunction_like_ir->SetReturnType(ret_merge_status.type_id_); + } + // Merge and fix parameters. + for (auto ¶m : cfunction_like_ir->GetParameters()) { + MergeReferencingTypeInternal(addend, ¶m, local_to_global_type_id_map); + } +} + + +void TextFormatToIRReader::MergeFunctionDeps( + FunctionIR *added_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + MergeCFunctionLikeDeps(addend, added_node, local_to_global_type_id_map); + // Merge and fix template parameters + for (auto &template_element : added_node->GetTemplateElements()) { + MergeReferencingTypeInternal(addend, &template_element, + local_to_global_type_id_map); + } +} + + +template +static bool IsLinkableMessagePresent(const LinkableMessageIR *lm, + const AbiElementMap &message_map) { + return (message_map.find(lm->GetLinkerSetKey()) != message_map.end()); +} + + +void TextFormatToIRReader::MergeFunction( + const FunctionIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + const std::string &function_linkage_name = addend_node->GetLinkerSetKey(); + if (IsLinkableMessagePresent(addend_node, module_->functions_)) { + // The functions and all of its dependencies have already been added. + // No two globally visible functions can have the same symbol name. + return; + } + FunctionIR function_ir = *addend_node; + MergeFunctionDeps(&function_ir, addend, local_to_global_type_id_map); + // Add it to the parent's function map. + module_->functions_.emplace(function_linkage_name, std::move(function_ir)); +} + + +std::string TextFormatToIRReader::AllocateNewTypeId() { + return "type-" + std::to_string(++max_type_id_); +} + + +void TextFormatToIRReader::MergeGlobalVariable( + const GlobalVarIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map) { + const std::string &global_variable_linkage_name = + addend_node->GetLinkerSetKey(); + if (IsLinkableMessagePresent(addend_node, module_->global_variables_)) { + // The global variable and all of its dependencies have already been added. + return; + } + GlobalVarIR global_variable_ir = *addend_node; + MergeReferencingTypeInternal(addend, &global_variable_ir, + local_to_global_type_id_map); + module_->global_variables_.emplace( + global_variable_linkage_name, std::move(global_variable_ir)); +} + + +void TextFormatToIRReader::MergeGraphs(const TextFormatToIRReader &addend) { + // Iterate through nodes of addend reader and merge them. + // Keep a merged types cache since if a type is merged, so will all of its + // dependencies which weren't already merged. + AbiElementMap merged_types_cache; + + for (auto &&type_ir : addend.module_->type_graph_) { + MergeType(type_ir.second, addend, &merged_types_cache); + } + + for (auto &&function_ir : addend.module_->functions_) { + MergeFunction(&function_ir.second, addend, &merged_types_cache); + } + + for (auto &&global_var_ir : addend.module_->global_variables_) { + MergeGlobalVariable(&global_var_ir.second, addend, &merged_types_cache); + } +} + + +bool TextFormatToIRReader::IsLinkableMessageInExportedHeaders( + const LinkableMessageIR *linkable_message) const { + if (module_->exported_headers_ == nullptr || + module_->exported_headers_->empty()) { + return true; + } + return module_->exported_headers_->find(linkable_message->GetSourceFile()) != + module_->exported_headers_->end(); +} + + +} // namespace repr +} // header_checker diff --git a/vndk/tools/header-checker/src/repr/ir_reader.h b/vndk/tools/header-checker/src/repr/ir_reader.h new file mode 100644 index 000000000..ec380a890 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_reader.h @@ -0,0 +1,275 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_IR_READER_H_ +#define HEADER_CHECKER_REPR_IR_READER_H_ + +#include "repr/ir_representation.h" + +#include +#include +#include +#include +#include +#include + + +namespace header_checker { +namespace repr { + + +class TextFormatToIRReader { + public: + struct MergeStatus { + MergeStatus(bool was_newly_added, const std::string &type_id) + : was_newly_added_(was_newly_added), type_id_(type_id) {} + + MergeStatus() {} + + // type_id_ always has the global_type_id corresponding to the type this + // MergeStatus corresponds to. For + // generic reference types (pointers, qual types, l(r)value references etc), + // this will be a proactively added type_id, which will be added to the + // parent type_graph if the we decide to add the referencing type to the + // parent post ODR checking. + bool was_newly_added_ = false; + + std::string type_id_; + }; + + public: + TextFormatToIRReader(const std::set *exported_headers) + : module_(new ModuleIR(exported_headers)) {} + + virtual ~TextFormatToIRReader() {} + + const AbiElementMap &GetFunctions() const { + return module_->functions_; + } + + const AbiElementMap &GetGlobalVariables() const { + return module_->global_variables_; + } + + const AbiElementMap &GetRecordTypes() const { + return module_->record_types_; + } + + const AbiElementMap &GetFunctionTypes() const { + return module_->function_types_; + } + + const AbiElementMap &GetEnumTypes() const { + return module_->enum_types_; + } + + const AbiElementMap &GetLvalueReferenceTypes() const { + return module_->lvalue_reference_types_; + } + + const AbiElementMap &GetRvalueReferenceTypes() const { + return module_->rvalue_reference_types_; + } + + const AbiElementMap &GetQualifiedTypes() const { + return module_->qualified_types_; + } + + const AbiElementMap &GetArrayTypes() const { + return module_->array_types_; + } + + const AbiElementMap &GetPointerTypes() const { + return module_->pointer_types_; + } + + const AbiElementMap &GetBuiltinTypes() const { + return module_->builtin_types_; + } + + const AbiElementMap &GetElfFunctions() const { + return module_->elf_functions_; + } + + const AbiElementMap &GetElfObjects() const { + return module_->elf_objects_; + } + + const AbiElementMap &GetTypeGraph() const { + return module_->type_graph_; + } + + const AbiElementUnorderedMap> & + GetODRListMap() const { + return module_->odr_list_map_; + } + + virtual bool ReadDump(const std::string &dump_file) = 0; + + void Merge(TextFormatToIRReader &&addend) { + MergeElements(&module_->functions_, std::move(addend.module_->functions_)); + MergeElements(&module_->global_variables_, + std::move(addend.module_->global_variables_)); + MergeElements(&module_->record_types_, + std::move(addend.module_->record_types_)); + MergeElements(&module_->enum_types_, + std::move(addend.module_->enum_types_)); + MergeElements(&module_->pointer_types_, + std::move(addend.module_->pointer_types_)); + MergeElements(&module_->lvalue_reference_types_, + std::move(addend.module_->lvalue_reference_types_)); + MergeElements(&module_->rvalue_reference_types_, + std::move(addend.module_->rvalue_reference_types_)); + MergeElements(&module_->array_types_, + std::move(addend.module_->array_types_)); + MergeElements(&module_->builtin_types_, + std::move(addend.module_->builtin_types_)); + MergeElements(&module_->qualified_types_, + std::move(addend.module_->qualified_types_)); + } + + void AddToODRListMap(const std::string &key, const TypeIR *value); + + template + MergeStatus MergeReferencingTypeInternalAndUpdateParent( + const TextFormatToIRReader &addend, const T *addend_node, + AbiElementMap *local_to_global_type_id_map, + AbiElementMap *parent_map, const std::string &updated_self_type_id); + + MergeStatus DoesUDTypeODRViolationExist( + const TypeIR *ud_type, const TextFormatToIRReader &addend, + const std::string ud_type_unique_id, + AbiElementMap *local_to_global_type_id_map_); + + MergeStatus MergeReferencingTypeInternal( + const TextFormatToIRReader &addend, ReferencesOtherType *references_type, + AbiElementMap *local_to_global_type_id_map); + + MergeStatus MergeReferencingType( + const TextFormatToIRReader &addend, const TypeIR *addend_node, + AbiElementMap *local_to_global_type_id_map, + const std::string &updated_self_type_id); + + MergeStatus MergeGenericReferringType( + const TextFormatToIRReader &addend, const TypeIR *addend_node, + AbiElementMap *local_to_global_type_id_map); + + template + std::pair::iterator> + UpdateUDTypeAccounting( + const T *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map, + AbiElementMap *specific_type_map); + + MergeStatus MergeTypeInternal( + const TypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeCFunctionLikeDeps( + const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, + AbiElementMap *local_to_global_type_id_map); + + MergeStatus MergeFunctionType( + const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + MergeStatus MergeEnumType( + const EnumTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeEnumDependencies( + const TextFormatToIRReader &addend, EnumTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map); + + MergeStatus MergeRecordAndDependencies( + const RecordTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeRecordDependencies( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map); + + void MergeRecordFields( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map); + + void MergeRecordCXXBases( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map); + + void MergeRecordTemplateElements( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap *local_to_global_type_id_map); + + MergeStatus IsBuiltinTypeNodePresent( + const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeGlobalVariable( + const GlobalVarIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeGlobalVariables( + const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeFunctionDeps( + FunctionIR *added_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeFunction( + const FunctionIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + void MergeGraphs(const TextFormatToIRReader &addend); + + void UpdateTextFormatToIRReaderTypeGraph( + const TypeIR *addend_node, const std::string &added_type_id, + AbiElementMap *local_to_global_type_id_map); + + MergeStatus IsTypeNodePresent( + const TypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap *local_to_global_type_id_map); + + MergeStatus MergeType( + const TypeIR *addend_type, const TextFormatToIRReader &addend, + AbiElementMap *merged_types_cache); + + std::string AllocateNewTypeId(); + + static std::unique_ptr CreateTextFormatToIRReader( + TextFormatIR text_format, + const std::set *exported_headers = nullptr); + + protected: + template + inline void MergeElements(Augend *augend, Addend &&addend) { + augend->insert(std::make_move_iterator(addend.begin()), + std::make_move_iterator(addend.end())); + } + + bool IsLinkableMessageInExportedHeaders( + const LinkableMessageIR *linkable_message) const; + + std::unique_ptr module_; + + uint64_t max_type_id_ = 0; +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_IR_READER_H_ diff --git a/vndk/tools/header-checker/src/repr/ir_representation.cpp b/vndk/tools/header-checker/src/repr/ir_representation.cpp deleted file mode 100644 index af70a5e67..000000000 --- a/vndk/tools/header-checker/src/repr/ir_representation.cpp +++ /dev/null @@ -1,600 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "repr/ir_representation.h" - -#include "repr/abi_diff_helpers.h" -#include "repr/json/ir_representation_json.h" -#include "repr/protobuf/ir_representation_protobuf.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" -#pragma clang diagnostic ignored "-Wnested-anon-types" -#include "abi_dump.pb.h" -#pragma clang diagnostic pop - -#include -#include - -#include - -#include -#include - - - -namespace header_checker { -namespace repr { - - -using MergeStatus = TextFormatToIRReader::MergeStatus; - -std::unique_ptr IRDumper::CreateIRDumper( - TextFormatIR text_format, const std::string &dump_path) { - switch (text_format) { - case TextFormatIR::ProtobufTextFormat: - return std::make_unique(dump_path); - case TextFormatIR::Json: - return std::make_unique(dump_path); - default: - llvm::errs() << "Text format not supported yet\n"; - return nullptr; - } -} - -std::unique_ptr IRDiffDumper::CreateIRDiffDumper( - TextFormatIR text_format, const std::string &dump_path) { - switch (text_format) { - case TextFormatIR::ProtobufTextFormat: - return std::make_unique(dump_path); - default: - // Nothing else is supported yet. - llvm::errs() << "Text format not supported yet\n"; - return nullptr; - } -} - -std::unique_ptr -TextFormatToIRReader::CreateTextFormatToIRReader( - TextFormatIR text_format, const std::set *exported_headers) { - switch (text_format) { - case TextFormatIR::ProtobufTextFormat: - return std::make_unique(exported_headers); - case TextFormatIR::Json: - return std::make_unique(exported_headers); - default: - llvm::errs() << "Text format not supported yet\n"; - return nullptr; - } -} - -void TextFormatToIRReader::AddToODRListMap(const std::string &key, - const TypeIR *value) { - auto map_it = module_->odr_list_map_.find(key); - if (map_it == module_->odr_list_map_.end()) { - module_->odr_list_map_.emplace(key, std::list({value})); - return; - } - module_->odr_list_map_[key].emplace_back(value); -} - -MergeStatus TextFormatToIRReader::IsBuiltinTypeNodePresent( - const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - - std::string builtin_linker_set_key = builtin_type->GetLinkerSetKey(); - auto builtin_it = module_->builtin_types_.find(builtin_linker_set_key); - if (builtin_it != module_->builtin_types_.end()) { - return MergeStatus(false, builtin_it->second.GetSelfType()); - } - // Add this builtin type to the parent graph's builtin_types_ map. - // Before that, correct the type id of the builtin-type. - const std::string &local_type_id = builtin_type->GetSelfType(); - std::string builtin_global_type_id = AllocateNewTypeId(); - auto it = module_->builtin_types_.emplace( - builtin_linker_set_key, *builtin_type); - it.first->second.SetSelfType(builtin_global_type_id); - it.first->second.SetReferencedType(builtin_global_type_id); - module_->type_graph_.emplace(builtin_global_type_id, &((it.first)->second)); - - MergeStatus merge_status(true, builtin_global_type_id); - local_to_global_type_id_map->emplace(local_type_id, merge_status); - return merge_status; -} - -MergeStatus TextFormatToIRReader::DoesUDTypeODRViolationExist( - const TypeIR *ud_type, const TextFormatToIRReader &addend, - const std::string ud_type_unique_id_and_source, - AbiElementMap *local_to_global_type_id_map_) { - // Per entry in the map: - // /-----------------------------------------------------------------------\ - // | UDType->UniqueTagId + UdType->source File => list(const UDTypeIR *) | - // \-----------------------------------------------------------------------/ - auto it = module_->odr_list_map_.find(ud_type_unique_id_and_source); - if (it == module_->odr_list_map_.end()) { - // Calling this an ODR violation even though it means no UD with the same - // name + source combination was seen in the parent graph. The type-id - // passed does not matter since was_newly_added_ is true, the type will get - // allocated a new type id. - return MergeStatus(true, ""); - } - std::set type_cache; - DiffPolicyOptions diff_policy_options(false) ; - AbiDiffHelper diff_helper(module_->type_graph_, addend.module_->type_graph_, - diff_policy_options, &type_cache, - nullptr, local_to_global_type_id_map_); - for (auto &contender_ud : it->second) { - if (diff_helper.CompareAndDumpTypeDiff(contender_ud->GetSelfType(), - ud_type->GetSelfType()) == - DiffStatus::no_diff) { - local_to_global_type_id_map_->emplace( - ud_type->GetSelfType(), - MergeStatus(false, contender_ud->GetSelfType())); - return MergeStatus(false, contender_ud->GetSelfType()); - } - } -#ifdef DEBUG - llvm::errs() << "ODR violation detected for: " << ud_type->GetName() << "\n"; -#endif - return MergeStatus(true, (*(it->second.begin()))->GetSelfType()); -} - -MergeStatus TextFormatToIRReader::IsTypeNodePresent( - const TypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - std::string unique_type_id; - switch (addend_node->GetKind()) { - case RecordTypeKind: - unique_type_id = - GetODRListMapKey(static_cast(addend_node)); - break; - case EnumTypeKind: - unique_type_id = - GetODRListMapKey(static_cast(addend_node)); - break; - case FunctionTypeKind: - unique_type_id = - GetODRListMapKey(static_cast(addend_node)); - break; - default: - // We add the type proactively. - return MergeStatus(true, "type-hidden"); - } - // Every other type is a referencing type / builtin type, so it is proactively - // added by returning MergeStatus with was_newly_added_ = true. - return DoesUDTypeODRViolationExist( - addend_node, addend, unique_type_id, local_to_global_type_id_map); -} - -// This method merges the type referenced by 'references_type' into the parent -// graph. It also corrects the referenced_type field in the references_type -// object passed and returns the merge status of the *referenced type*. -MergeStatus TextFormatToIRReader::MergeReferencingTypeInternal( - const TextFormatToIRReader &addend, - ReferencesOtherType *references_type, - AbiElementMap *local_to_global_type_id_map) { - // First look in the local_to_global_type_id_map for the referenced type's - // id. - const std::string &referenced_type_id = - references_type->GetReferencedType(); - auto local_to_global_it = local_to_global_type_id_map->find( - referenced_type_id); - if (local_to_global_it != local_to_global_type_id_map->end()) { - // The type was already added to the parent graph. So change the - // referenced type to the global type id. - references_type->SetReferencedType(local_to_global_it->second.type_id_); - return local_to_global_it->second; - } - - // If that did not go through, look at the addend's type_map_ and get the - // TypeIR* and call MergeType on it. - auto local_type_it = addend.module_->type_graph_.find(referenced_type_id); - if (local_type_it != addend.module_->type_graph_.end()) { - // We don't care about merge_status.was_newly_added since we wouldn't have - // gotten this far if we weren't adding this. - MergeStatus merge_status = - MergeType(local_type_it->second, addend, local_to_global_type_id_map); - const std::string &global_type_id = merge_status.type_id_; - references_type->SetReferencedType(global_type_id); - return merge_status; - } - - // The referenced type was hidden, so just set it to type-hidden. - const std::string &hidden_type_id = AllocateNewTypeId(); - references_type->SetReferencedType(hidden_type_id); - return MergeStatus(true, hidden_type_id); -} - -void TextFormatToIRReader::MergeRecordFields( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map) { - for (auto &field : added_node->GetFields()) { - MergeReferencingTypeInternal(addend, &field, local_to_global_type_id_map); - } -} - -void TextFormatToIRReader::MergeRecordCXXBases( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map) { - for (auto &base : added_node->GetBases()) { - MergeReferencingTypeInternal(addend, &base, local_to_global_type_id_map); - } -} - -void TextFormatToIRReader::MergeRecordTemplateElements( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map) { - for (auto &template_element : added_node->GetTemplateElements()) { - MergeReferencingTypeInternal( - addend, &template_element, local_to_global_type_id_map); - } -} - -void TextFormatToIRReader::MergeRecordDependencies( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map) { - // First call MergeType on all its fields. - MergeRecordFields(addend, added_node, local_to_global_type_id_map); - - // Call MergeType on CXXBases of the record. - MergeRecordCXXBases(addend, added_node, local_to_global_type_id_map); - - MergeRecordTemplateElements(addend, added_node, local_to_global_type_id_map); -} - -template -std::pair::iterator> -TextFormatToIRReader::UpdateUDTypeAccounting( - const T *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map, - AbiElementMap *specific_type_map) { - std::string added_type_id = AllocateNewTypeId(); - // Add the ud-type with type-id to the type_graph_, since if there are generic - // reference types which refer to the record being added, they'll need to find - // it's id in the map. - // Add ud-type to the parent graph. - T added_type_ir = *addend_node; - added_type_ir.SetSelfType(added_type_id); - added_type_ir.SetReferencedType(added_type_id); - auto it = AddToMapAndTypeGraph(std::move(added_type_ir), specific_type_map, - &module_->type_graph_); - // Add to faciliate ODR checking. - const std::string &key = GetODRListMapKey(&(it->second)); - MergeStatus type_merge_status = MergeStatus(true, added_type_id); - AddToODRListMap(key, &(it->second)); - local_to_global_type_id_map->emplace(addend_node->GetSelfType(), - type_merge_status); - return {type_merge_status, it}; -} -// This method is necessarily going to have a was_newly_merged_ = true in its -// MergeStatus return. So it necessarily merges a new RecordType. -MergeStatus TextFormatToIRReader::MergeRecordAndDependencies( - const RecordTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - auto merge_status_and_it = - UpdateUDTypeAccounting(addend_node, addend, local_to_global_type_id_map, - &module_->record_types_); - auto it = merge_status_and_it.second; - MergeRecordDependencies(addend, &(it->second), local_to_global_type_id_map); - return merge_status_and_it.first; -} - -void TextFormatToIRReader::MergeEnumDependencies( - const TextFormatToIRReader &addend, EnumTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map) { - const std::string underlying_type_id = added_node->GetUnderlyingType(); - // Get the underlying type, it nessarily has to be present in the addend's - // type graph since builtin types can't be hidden. Call MergeType on it and - // change the underlying type to that. - auto it = addend.module_->type_graph_.find(underlying_type_id); - if (it == addend.module_->type_graph_.end()) { - llvm::errs() << "Enum underlying types should not be hidden\n"; - ::exit(1); - } - MergeStatus merge_status = MergeType(it->second, addend, - local_to_global_type_id_map); - added_node->SetUnderlyingType(merge_status.type_id_); -} - -// This method is necessarily going to have a was_newly_merged_ = true in its -// MergeStatus return. So it necessarily merges a new EnumType. -MergeStatus TextFormatToIRReader::MergeEnumType( - const EnumTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - auto merge_status_and_it = - UpdateUDTypeAccounting(addend_node, addend, local_to_global_type_id_map, - &module_->enum_types_); - auto it = merge_status_and_it.second; - MergeEnumDependencies(addend, &(it->second), local_to_global_type_id_map); - return merge_status_and_it.first; -} - -MergeStatus TextFormatToIRReader::MergeFunctionType( - const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - auto merge_status_and_it = - UpdateUDTypeAccounting(addend_node, addend, local_to_global_type_id_map, - &module_->function_types_); - auto it = merge_status_and_it.second; - MergeCFunctionLikeDeps(addend, &(it->second), local_to_global_type_id_map); - return merge_status_and_it.first; -} - -template -MergeStatus TextFormatToIRReader::MergeReferencingTypeInternalAndUpdateParent( - const TextFormatToIRReader &addend, const T *addend_node, - AbiElementMap *local_to_global_type_id_map, - AbiElementMap *parent_map, const std::string &updated_self_type_id) { - MergeStatus merge_status; - uint64_t old_max_type_id = max_type_id_; - // Create copy of addend_node - T added_node = *(addend_node); - added_node.SetSelfType(updated_self_type_id); - // The merge status returned is the merge status of the referenced type. - merge_status = MergeReferencingTypeInternal(addend, &added_node, - local_to_global_type_id_map); - if (merge_status.was_newly_added_) { - // Emplace to map (type-referenced -> Referencing type) - AddToMapAndTypeGraph(std::move(added_node), parent_map, - &module_->type_graph_); - return MergeStatus(true, updated_self_type_id); - } - - // The type that the added_node references was not newly added to the parent - // graph. However, we still might need to add the added_node to the parent - // graph, since for the particular 'Kind' of the added_node, it may not be - // present in the parent graph. This will be determined by looking at the - // appropriate 'type-referenced' -> TypeElement map in the parent for the - // type-id returned by the MergeStatus. If the map doesn't have an entry for - // the type-id returned by the MergeStatus, the added_type is not present in - // the parent graph and needs to be 'newly' added. We also need to modify the - // global type id in the local_to_global_type_id map. The added_node should - // already have it's self_type and referenced_type fields fixed up. - // We maintain a rollback id to have contiguous type ids. - max_type_id_ = old_max_type_id; - - // Try finding the referenced_type is referred to by any referencing type - // of the same kind in the parent graph. It is safe to call this on the - // added_node, since the referenced_type in the added_node would have been - // modified by the MergeReferencingTypeInternal call. - auto it = parent_map->find(GetReferencedTypeMapKey(added_node)); - if (it == parent_map->end()) { - // There was no counterpart found for the added_node's type Kind referencing - // the referenced type, so we added it to the parent and also updated the - // local_to_global_type_id_map's global_id value. - AddToMapAndTypeGraph(std::move(added_node), parent_map, - &module_->type_graph_); - - merge_status = MergeStatus(true, updated_self_type_id); - return merge_status; - } - - // Update local_to_global_type_id map's MergeStatus.was_newly_added value for - // this key with false since this was node was not newly added. - // We never remove anything from the local_to_global_type_id_map, what's - // the point ? Since you store the decision of whether the type was newly - // added or not. It's global type id is the type-id of the element found - // in the parent map which refers to the added_node's modified - // referenced_type. - merge_status = MergeStatus(false, it->second.GetSelfType()); - (*local_to_global_type_id_map)[addend_node->GetSelfType()] = merge_status; - - return merge_status; -} - -MergeStatus TextFormatToIRReader::MergeReferencingType( - const TextFormatToIRReader &addend, const TypeIR *addend_node, - AbiElementMap *local_to_global_type_id_map, - const std::string &updated_self_type_id) { - switch (addend_node->GetKind()) { - case PointerTypeKind: - return MergeReferencingTypeInternalAndUpdateParent( - addend, static_cast(addend_node), - local_to_global_type_id_map, &module_->pointer_types_, - updated_self_type_id); - case QualifiedTypeKind: - return MergeReferencingTypeInternalAndUpdateParent( - addend, static_cast(addend_node), - local_to_global_type_id_map, &module_->qualified_types_, - updated_self_type_id); - case ArrayTypeKind: - return MergeReferencingTypeInternalAndUpdateParent( - addend, static_cast(addend_node), - local_to_global_type_id_map, &module_->array_types_, - updated_self_type_id); - case LvalueReferenceTypeKind: - return MergeReferencingTypeInternalAndUpdateParent( - addend, static_cast(addend_node), - local_to_global_type_id_map, &module_->lvalue_reference_types_, - updated_self_type_id); - case RvalueReferenceTypeKind: - return MergeReferencingTypeInternalAndUpdateParent( - addend, static_cast(addend_node), - local_to_global_type_id_map, &module_->rvalue_reference_types_, - updated_self_type_id); - default: - // Only referencing types - assert(0); - } -} - -// This method creates a new node for the addend node in the graph if MergeType -// on the reference returned a MergeStatus with was_newly_added_ = true. -MergeStatus TextFormatToIRReader::MergeGenericReferringType( - const TextFormatToIRReader &addend, const TypeIR *addend_node, - AbiElementMap *local_to_global_type_id_map) { - // First add the type 'pro-actively'. We need to do this since we'll need to - // fill in 'referenced-type' fields in all this type's descendants and - // descendants which are compound types (records), can refer to this type. - std::string added_type_id = AllocateNewTypeId(); - // Add the added record type to the local_to_global_type_id_map - local_to_global_type_id_map->emplace(addend_node->GetSelfType(), - MergeStatus(true, added_type_id)); - return MergeReferencingType(addend, addend_node, local_to_global_type_id_map, - added_type_id); -} - -MergeStatus TextFormatToIRReader::MergeTypeInternal( - const TypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - switch (addend_node->GetKind()) { - case BuiltinTypeKind: - return IsBuiltinTypeNodePresent( - static_cast(addend_node), addend, - local_to_global_type_id_map); - break; - case RecordTypeKind: - return MergeRecordAndDependencies( - static_cast(addend_node), - addend, local_to_global_type_id_map); - case EnumTypeKind: - return MergeEnumType(static_cast( - addend_node), addend, local_to_global_type_id_map); - case FunctionTypeKind: - return MergeFunctionType(static_cast( - addend_node), addend, local_to_global_type_id_map); - default: - return MergeGenericReferringType(addend, addend_node, - local_to_global_type_id_map); - } - assert(0); -} - -MergeStatus TextFormatToIRReader::MergeType( - const TypeIR *addend_node, - const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - // Check if the addend type is already in the parent graph. Since we're - // going to traverse all the dependencies add whichever ones are not in the - // parent graph. This does not add the node itself though. - auto type_it = local_to_global_type_id_map->find(addend_node->GetSelfType()); - if (type_it != local_to_global_type_id_map->end()) { - return type_it->second; - } - - MergeStatus merge_status = IsTypeNodePresent( - addend_node, addend, local_to_global_type_id_map); - if (!merge_status.was_newly_added_) { - return merge_status; - } - merge_status = MergeTypeInternal( - addend_node, addend, local_to_global_type_id_map); - return merge_status; -} - -void TextFormatToIRReader::MergeCFunctionLikeDeps( - const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, - AbiElementMap *local_to_global_type_id_map) { - // Merge the return type first. - auto ret_type_it = - addend.module_->type_graph_.find(cfunction_like_ir->GetReturnType()); - if (ret_type_it == addend.module_->type_graph_.end()) { - // Hidden types aren't officially added to the parent since there is - // nothing actually backing it. We assign a type-id. - cfunction_like_ir->SetReturnType(AllocateNewTypeId()); - } else { - MergeStatus ret_merge_status = MergeType(ret_type_it->second, addend, - local_to_global_type_id_map); - cfunction_like_ir->SetReturnType(ret_merge_status.type_id_); - } - // Merge and fix parameters. - for (auto ¶m : cfunction_like_ir->GetParameters()) { - MergeReferencingTypeInternal(addend, ¶m, local_to_global_type_id_map); - } -} - -void TextFormatToIRReader::MergeFunctionDeps( - FunctionIR *added_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - MergeCFunctionLikeDeps(addend, added_node, local_to_global_type_id_map); - // Merge and fix template parameters - for (auto &template_element : added_node->GetTemplateElements()) { - MergeReferencingTypeInternal(addend, &template_element, - local_to_global_type_id_map); - } -} - -template -static bool IsLinkableMessagePresent(const LinkableMessageIR *lm, - const AbiElementMap &message_map) { - return (message_map.find(lm->GetLinkerSetKey()) != message_map.end()); -} - -void TextFormatToIRReader::MergeFunction( - const FunctionIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - const std::string &function_linkage_name = addend_node->GetLinkerSetKey(); - if (IsLinkableMessagePresent(addend_node, module_->functions_)) { - // The functions and all of its dependencies have already been added. - // No two globally visible functions can have the same symbol name. - return; - } - FunctionIR function_ir = *addend_node; - MergeFunctionDeps(&function_ir, addend, local_to_global_type_id_map); - // Add it to the parent's function map. - module_->functions_.emplace(function_linkage_name, std::move(function_ir)); -} - -std::string TextFormatToIRReader::AllocateNewTypeId() { - return "type-" + std::to_string(++max_type_id_); -} - -void TextFormatToIRReader::MergeGlobalVariable( - const GlobalVarIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map) { - const std::string &global_variable_linkage_name = - addend_node->GetLinkerSetKey(); - if (IsLinkableMessagePresent(addend_node, module_->global_variables_)) { - // The global variable and all of its dependencies have already been added. - return; - } - GlobalVarIR global_variable_ir = *addend_node; - MergeReferencingTypeInternal(addend, &global_variable_ir, - local_to_global_type_id_map); - module_->global_variables_.emplace( - global_variable_linkage_name, std::move(global_variable_ir)); -} - -void TextFormatToIRReader::MergeGraphs(const TextFormatToIRReader &addend) { - // Iterate through nodes of addend reader and merge them. - // Keep a merged types cache since if a type is merged, so will all of its - // dependencies which weren't already merged. - AbiElementMap merged_types_cache; - - for (auto &&type_ir : addend.module_->type_graph_) { - MergeType(type_ir.second, addend, &merged_types_cache); - } - - for (auto &&function_ir : addend.module_->functions_) { - MergeFunction(&function_ir.second, addend, &merged_types_cache); - } - - for (auto &&global_var_ir : addend.module_->global_variables_) { - MergeGlobalVariable(&global_var_ir.second, addend, &merged_types_cache); - } -} - -bool TextFormatToIRReader::IsLinkableMessageInExportedHeaders( - const LinkableMessageIR *linkable_message) const { - if (module_->exported_headers_ == nullptr || - module_->exported_headers_->empty()) { - return true; - } - return module_->exported_headers_->find(linkable_message->GetSourceFile()) != - module_->exported_headers_->end(); -} - - -} // namespace repr -} // header_checker diff --git a/vndk/tools/header-checker/src/repr/ir_representation.h b/vndk/tools/header-checker/src/repr/ir_representation.h index f14755c96..32ec8b019 100644 --- a/vndk/tools/header-checker/src/repr/ir_representation.h +++ b/vndk/tools/header-checker/src/repr/ir_representation.h @@ -15,11 +15,9 @@ #ifndef IR_REPRESENTATION_H_ #define IR_REPRESENTATION_H_ -#include #include #include #include -#include #include #include #include @@ -869,675 +867,6 @@ class ModuleIR { const std::set *exported_headers_; }; -class IRDumper { - public: - IRDumper(const std::string &dump_path) : dump_path_(dump_path) {} - - virtual ~IRDumper() {} - - static std::unique_ptr 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; - - protected: - const std::string &dump_path_; -}; - -template -inline std::string GetReferencedTypeMapKey(T &element) { - return element.GetReferencedType(); -} - -template <> -inline std::string GetReferencedTypeMapKey(ArrayTypeIR &element) { - return element.GetReferencedType() + ":" + std::to_string(element.GetSize()); -} - -template <> -inline std::string GetReferencedTypeMapKey( - BuiltinTypeIR &element) { - return element.GetLinkerSetKey(); -} - -inline static std::string BoolToString(bool val) { - return val ? "true" : "false"; -} - -template <> -inline std::string GetReferencedTypeMapKey( - QualifiedTypeIR &element) { - return element.GetReferencedType() + BoolToString(element.IsRestricted()) + - BoolToString(element.IsVolatile()) + BoolToString(element.IsConst()); -} - -inline std::string GetODRListMapKey(const RecordTypeIR *record_type_ir) { - if (record_type_ir->IsAnonymous()) { - return record_type_ir->GetLinkerSetKey() + record_type_ir->GetUniqueId(); - } - return record_type_ir->GetUniqueId() + record_type_ir->GetSourceFile(); -} - -inline std::string GetODRListMapKey(const EnumTypeIR *enum_type_ir) { - return enum_type_ir->GetUniqueId() + enum_type_ir->GetSourceFile(); -} - -inline std::string GetODRListMapKey(const FunctionTypeIR *function_type_ir) { - return function_type_ir->GetLinkerSetKey(); -} - -// The map that is being updated maps special_key -> Type / Function/ GlobVar -// This special key is needed to distinguish what is being referenced. -template -typename AbiElementMap::iterator AddToMapAndTypeGraph( - T &&element, AbiElementMap *map_to_update, - AbiElementMap *type_graph) { - auto it = map_to_update->emplace(GetReferencedTypeMapKey(element), - std::move(element)); - type_graph->emplace(it.first->second.GetSelfType(), &(it.first->second)); - return it.first; -} - -class TextFormatToIRReader { - public: - struct MergeStatus { - MergeStatus(bool was_newly_added, const std::string &type_id) - : was_newly_added_(was_newly_added), type_id_(type_id) {} - - MergeStatus() {} - - // type_id_ always has the global_type_id corresponding to the type this - // MergeStatus corresponds to. For - // generic reference types (pointers, qual types, l(r)value references etc), - // this will be a proactively added type_id, which will be added to the - // parent type_graph if the we decide to add the referencing type to the - // parent post ODR checking. - bool was_newly_added_ = false; - - std::string type_id_; - }; - - public: - TextFormatToIRReader(const std::set *exported_headers) - : module_(new ModuleIR(exported_headers)) {} - - virtual ~TextFormatToIRReader() {} - - const AbiElementMap &GetFunctions() const { - return module_->functions_; - } - - const AbiElementMap &GetGlobalVariables() const { - return module_->global_variables_; - } - - const AbiElementMap &GetRecordTypes() const { - return module_->record_types_; - } - - const AbiElementMap &GetFunctionTypes() const { - return module_->function_types_; - } - - const AbiElementMap &GetEnumTypes() const { - return module_->enum_types_; - } - - const AbiElementMap &GetLvalueReferenceTypes() const { - return module_->lvalue_reference_types_; - } - - const AbiElementMap &GetRvalueReferenceTypes() const { - return module_->rvalue_reference_types_; - } - - const AbiElementMap &GetQualifiedTypes() const { - return module_->qualified_types_; - } - - const AbiElementMap &GetArrayTypes() const { - return module_->array_types_; - } - - const AbiElementMap &GetPointerTypes() const { - return module_->pointer_types_; - } - - const AbiElementMap &GetBuiltinTypes() const { - return module_->builtin_types_; - } - - const AbiElementMap &GetElfFunctions() const { - return module_->elf_functions_; - } - - const AbiElementMap &GetElfObjects() const { - return module_->elf_objects_; - } - - const AbiElementMap &GetTypeGraph() const { - return module_->type_graph_; - } - - const AbiElementUnorderedMap> & - GetODRListMap() const { - return module_->odr_list_map_; - } - - virtual bool ReadDump(const std::string &dump_file) = 0; - - void Merge(TextFormatToIRReader &&addend) { - MergeElements(&module_->functions_, std::move(addend.module_->functions_)); - MergeElements(&module_->global_variables_, - std::move(addend.module_->global_variables_)); - MergeElements(&module_->record_types_, - std::move(addend.module_->record_types_)); - MergeElements(&module_->enum_types_, - std::move(addend.module_->enum_types_)); - MergeElements(&module_->pointer_types_, - std::move(addend.module_->pointer_types_)); - MergeElements(&module_->lvalue_reference_types_, - std::move(addend.module_->lvalue_reference_types_)); - MergeElements(&module_->rvalue_reference_types_, - std::move(addend.module_->rvalue_reference_types_)); - MergeElements(&module_->array_types_, - std::move(addend.module_->array_types_)); - MergeElements(&module_->builtin_types_, - std::move(addend.module_->builtin_types_)); - MergeElements(&module_->qualified_types_, - std::move(addend.module_->qualified_types_)); - } - - void AddToODRListMap(const std::string &key, const TypeIR *value); - - template - MergeStatus MergeReferencingTypeInternalAndUpdateParent( - const TextFormatToIRReader &addend, const T *addend_node, - AbiElementMap *local_to_global_type_id_map, - AbiElementMap *parent_map, const std::string &updated_self_type_id); - - MergeStatus DoesUDTypeODRViolationExist( - const TypeIR *ud_type, const TextFormatToIRReader &addend, - const std::string ud_type_unique_id, - AbiElementMap *local_to_global_type_id_map_); - - MergeStatus MergeReferencingTypeInternal( - const TextFormatToIRReader &addend, ReferencesOtherType *references_type, - AbiElementMap *local_to_global_type_id_map); - - MergeStatus MergeReferencingType( - const TextFormatToIRReader &addend, const TypeIR *addend_node, - AbiElementMap *local_to_global_type_id_map, - const std::string &updated_self_type_id); - - MergeStatus MergeGenericReferringType( - const TextFormatToIRReader &addend, const TypeIR *addend_node, - AbiElementMap *local_to_global_type_id_map); - - template - std::pair::iterator> - UpdateUDTypeAccounting( - const T *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map, - AbiElementMap *specific_type_map); - - MergeStatus MergeTypeInternal( - const TypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeCFunctionLikeDeps( - const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, - AbiElementMap *local_to_global_type_id_map); - - MergeStatus MergeFunctionType( - const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - MergeStatus MergeEnumType( - const EnumTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeEnumDependencies( - const TextFormatToIRReader &addend, EnumTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map); - - MergeStatus MergeRecordAndDependencies( - const RecordTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeRecordDependencies( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map); - - void MergeRecordFields( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map); - - void MergeRecordCXXBases( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map); - - void MergeRecordTemplateElements( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap *local_to_global_type_id_map); - - MergeStatus IsBuiltinTypeNodePresent( - const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeGlobalVariable( - const GlobalVarIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeGlobalVariables( - const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeFunctionDeps( - FunctionIR *added_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeFunction( - const FunctionIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - void MergeGraphs(const TextFormatToIRReader &addend); - - void UpdateTextFormatToIRReaderTypeGraph( - const TypeIR *addend_node, const std::string &added_type_id, - AbiElementMap *local_to_global_type_id_map); - - MergeStatus IsTypeNodePresent( - const TypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap *local_to_global_type_id_map); - - MergeStatus MergeType( - const TypeIR *addend_type, const TextFormatToIRReader &addend, - AbiElementMap *merged_types_cache); - - std::string AllocateNewTypeId(); - - static std::unique_ptr CreateTextFormatToIRReader( - TextFormatIR text_format, - const std::set *exported_headers = nullptr); - - protected: - template - inline void MergeElements(Augend *augend, Addend &&addend) { - augend->insert(std::make_move_iterator(addend.begin()), - std::make_move_iterator(addend.end())); - } - - bool IsLinkableMessageInExportedHeaders( - const LinkableMessageIR *linkable_message) const; - - std::unique_ptr module_; - - uint64_t max_type_id_ = 0; -}; - -class DiffMessageIR { - public: - enum DiffKind { - Extension, // Applicable for enums. - Added, - Removed, - Referenced, - Unreferenced - }; - - public: - virtual ~DiffMessageIR() {} - - virtual LinkableMessageKind Kind() const = 0; - - void SetName(const std::string &name) { - name_ = name; - } - - const std::string &GetName() const { - return name_; - } - - protected: - std::string name_; -}; - -class AccessSpecifierDiffIR { - public: - AccessSpecifierDiffIR(AccessSpecifierIR old_access, - AccessSpecifierIR new_access) - : old_access_(old_access), new_access_(new_access) {} - - protected: - AccessSpecifierIR old_access_; - AccessSpecifierIR new_access_; -}; - -class TypeDiffIR { - public: - TypeDiffIR(std::pair &&sizes, - std::pair &&alignment) - : sizes_(std::move(sizes)), alignments_(std::move(alignment)) {} - - const std::pair &GetSizes() const { - return sizes_; - } - - const std::pair &GetAlignments() const { - return alignments_; - } - - protected: - std::pair sizes_; - std::pair alignments_; -}; - -class VTableLayoutDiffIR { - public: - VTableLayoutDiffIR(const VTableLayoutIR &old_layout, - const VTableLayoutIR &new_layout) - : old_layout_(old_layout), new_layout_(new_layout) {} - - const VTableLayoutIR &GetOldVTable() const { - return old_layout_; - } - - const VTableLayoutIR &GetNewVTable() const { - return new_layout_; - } - - protected: - const VTableLayoutIR &old_layout_; - const VTableLayoutIR &new_layout_; -}; - -class RecordFieldDiffIR { - public: - RecordFieldDiffIR(const RecordFieldIR *old_field, - const RecordFieldIR *new_field) - : old_field_(old_field), new_field_(new_field) {} - - const RecordFieldIR *GetOldField() const { - return old_field_; - } - - const RecordFieldIR *GetNewField() const { - return new_field_; - } - - const RecordFieldIR *old_field_; - const RecordFieldIR *new_field_; -}; - -class CXXBaseSpecifierDiffIR { - public: - CXXBaseSpecifierDiffIR( - const std::vector &old_base_specifiers, - const std::vector &new_base_specifiers) - : old_base_specifiers_(old_base_specifiers), - new_base_specifiers_(new_base_specifiers) {} - - const std::vector &GetOldBases() const { - return old_base_specifiers_; - } - - const std::vector &GetNewBases() const { - return new_base_specifiers_; - } - - protected: - const std::vector &old_base_specifiers_; - const std::vector &new_base_specifiers_; -}; - -class RecordTypeDiffIR : public DiffMessageIR { - public: - LinkableMessageKind Kind() const override { - return LinkableMessageKind::RecordTypeKind; - } - - void SetFieldDiffs(std::vector &&field_diffs) { - field_diffs_ = std::move(field_diffs); - } - - const std::vector &GetFieldDiffs() const { - return field_diffs_; - } - - void SetFieldsRemoved(std::vector &&fields_removed) { - fields_removed_ = std::move(fields_removed); - } - - void SetFieldsAdded(std::vector &&fields_added) { - fields_added_ = std::move(fields_added); - } - - const std::vector &GetFieldsRemoved() const { - return fields_removed_; - } - - const std::vector &GetFieldsAdded() const { - return fields_added_; - } - - void SetVTableLayoutDiff(std::unique_ptr &&vtable_diffs) { - vtable_diffs_ = std::move(vtable_diffs); - } - - void SetTypeDiff(std::unique_ptr &&type_diff) { - type_diff_ = std::move(type_diff); - } - - void SetAccessDiff(std::unique_ptr &&access_diff) { - access_diff_ = std::move(access_diff); - } - - void SetBaseSpecifierDiffs( - std::unique_ptr &&base_diffs) { - base_specifier_diffs_ = std::move(base_diffs); - } - - bool DiffExists() const { - return (type_diff_ != nullptr) || (vtable_diffs_ != nullptr) || - (fields_removed_.size() != 0) || (field_diffs_.size() != 0) || - (access_diff_ != nullptr) || (base_specifier_diffs_ != nullptr); - } - - const TypeDiffIR *GetTypeDiff() const { - return type_diff_.get(); - } - - const VTableLayoutDiffIR *GetVTableLayoutDiff() const { - return vtable_diffs_.get(); - } - - const CXXBaseSpecifierDiffIR *GetBaseSpecifiers() const { - return base_specifier_diffs_.get(); - } - - protected: - // optional implemented with vector / std::unique_ptr. - std::unique_ptr type_diff_; - std::unique_ptr vtable_diffs_; - std::vector field_diffs_; - std::vector fields_removed_; - std::vector fields_added_; - std::unique_ptr access_diff_; - std::unique_ptr base_specifier_diffs_; - // Template Diffs are not needed since they will show up in the linker set - // key. -}; - -class EnumFieldDiffIR { - public: - EnumFieldDiffIR(const EnumFieldIR *old_field, const EnumFieldIR *new_field) - : old_field_(old_field), new_field_(new_field) {} - - const EnumFieldIR *GetOldField() const { - return old_field_; - } - - const EnumFieldIR *GetNewField() const { - return new_field_; - } - - protected: - const EnumFieldIR *old_field_; - const EnumFieldIR *new_field_; -}; - -class EnumTypeDiffIR : public DiffMessageIR { - public: - void SetFieldsRemoved(std::vector &&fields_removed) { - fields_removed_ = std::move(fields_removed); - } - - const std::vector &GetFieldsRemoved() const { - return fields_removed_; - } - - void SetFieldsAdded(std::vector &&fields_added) { - fields_added_ = std::move(fields_added); - } - - const std::vector &GetFieldsAdded() const { - return fields_added_; - } - - void SetFieldsDiff(std::vector &&fields_diff) { - fields_diff_ = std::move(fields_diff); - } - - const std::vector &GetFieldsDiff() const { - return fields_diff_; - } - - void SetUnderlyingTypeDiff( - std::unique_ptr> &&utype_diff) { - underlying_type_diff_ = std::move(utype_diff); - } - - const std::pair *GetUnderlyingTypeDiff() const { - return underlying_type_diff_.get(); - } - - bool IsExtended() const { - if (fields_removed_.size() == 0 && fields_diff_.size() == 0 && - fields_added_.size() != 0) { - return true; - } - return false; - } - - bool IsIncompatible() const { - if (fields_removed_.size() != 0 || fields_diff_.size() != 0) { - return true; - } - return false; - } - - LinkableMessageKind Kind() const override { - return LinkableMessageKind::EnumTypeKind; - } - - protected: - // The underlying type can only be integral, so we just need to check for - // referenced type. - std::unique_ptr> underlying_type_diff_; - std::vector fields_removed_; - std::vector fields_added_; - std::vector fields_diff_; - // Modifiable to allow implicit construction. - std::string name_; -}; - -class GlobalVarDiffIR : public DiffMessageIR { - public: - LinkableMessageKind Kind() const override { - return LinkableMessageKind::GlobalVarKind; - } - - GlobalVarDiffIR(const GlobalVarIR *old_global_var, - const GlobalVarIR *new_global_var) - : old_global_var_(old_global_var), new_global_var_(new_global_var) {} - - const GlobalVarIR *GetOldGlobalVar() const { - return old_global_var_; - } - - const GlobalVarIR *GetNewGlobalVar() const { - return new_global_var_; - } - - protected: - const GlobalVarIR *old_global_var_; - const GlobalVarIR *new_global_var_; -}; - -class FunctionDiffIR : public DiffMessageIR { - public: - FunctionDiffIR(const FunctionIR *old_function, - const FunctionIR *new_function) - : old_function_(old_function), new_function_(new_function) {} - - LinkableMessageKind Kind() const override { - return LinkableMessageKind::FunctionKind; - } - - const FunctionIR *GetOldFunction() const { - return old_function_; - } - - const FunctionIR *GetNewFunction() const { - return new_function_; - } - - protected: - const FunctionIR *old_function_; - const FunctionIR *new_function_; -}; - -class IRDiffDumper { - public: - typedef DiffMessageIR::DiffKind DiffKind; - - public: - IRDiffDumper(const std::string &dump_path) : dump_path_(dump_path) {} - - virtual ~IRDiffDumper() {} - - virtual bool AddDiffMessageIR(const DiffMessageIR *, - const std::string &type_stack, - DiffKind diff_kind) = 0; - - virtual bool AddLinkableMessageIR(const LinkableMessageIR *, - DiffKind diff_kind) = 0; - - virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *, - DiffKind diff_kind) = 0; - - virtual void AddLibNameIR(const std::string &name) = 0; - - virtual void AddArchIR(const std::string &arch) = 0; - - virtual void AddCompatibilityStatusIR(CompatibilityStatusIR status) = 0; - - virtual bool Dump() = 0; - - virtual CompatibilityStatusIR GetCompatibilityStatusIR() = 0; - - static std::unique_ptr CreateIRDiffDumper( - TextFormatIR, const std::string &dump_path); - - protected: - const std::string &dump_path_; -}; - } // namespace repr } // namespace header_checker diff --git a/vndk/tools/header-checker/src/repr/ir_representation_internal.h b/vndk/tools/header-checker/src/repr/ir_representation_internal.h new file mode 100644 index 000000000..c5df1bb86 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/ir_representation_internal.h @@ -0,0 +1,86 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_IR_REPRESENTATION_INTERNAL_H_ +#define HEADER_CHECKER_REPR_IR_REPRESENTATION_INTERNAL_H_ + +#include "repr/ir_representation.h" + +#include + + +namespace header_checker { +namespace repr { + + +template +inline std::string GetReferencedTypeMapKey(T &element) { + return element.GetReferencedType(); +} + +template <> +inline std::string GetReferencedTypeMapKey(ArrayTypeIR &element) { + return element.GetReferencedType() + ":" + std::to_string(element.GetSize()); +} + +template <> +inline std::string GetReferencedTypeMapKey( + BuiltinTypeIR &element) { + return element.GetLinkerSetKey(); +} + +inline static std::string BoolToString(bool val) { + return val ? "true" : "false"; +} + +template <> +inline std::string GetReferencedTypeMapKey( + QualifiedTypeIR &element) { + return element.GetReferencedType() + BoolToString(element.IsRestricted()) + + BoolToString(element.IsVolatile()) + BoolToString(element.IsConst()); +} + +inline std::string GetODRListMapKey(const RecordTypeIR *record_type_ir) { + if (record_type_ir->IsAnonymous()) { + return record_type_ir->GetLinkerSetKey() + record_type_ir->GetUniqueId(); + } + return record_type_ir->GetUniqueId() + record_type_ir->GetSourceFile(); +} + +inline std::string GetODRListMapKey(const EnumTypeIR *enum_type_ir) { + return enum_type_ir->GetUniqueId() + enum_type_ir->GetSourceFile(); +} + +inline std::string GetODRListMapKey(const FunctionTypeIR *function_type_ir) { + return function_type_ir->GetLinkerSetKey(); +} + +// The map that is being updated maps special_key -> Type / Function/ GlobVar +// This special key is needed to distinguish what is being referenced. +template +typename AbiElementMap::iterator AddToMapAndTypeGraph( + T &&element, AbiElementMap *map_to_update, + AbiElementMap *type_graph) { + auto it = map_to_update->emplace(GetReferencedTypeMapKey(element), + std::move(element)); + type_graph->emplace(it.first->second.GetSelfType(), &(it.first->second)); + return it.first; +} + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_IR_REPRESENTATION_INTERNAL_H_ diff --git a/vndk/tools/header-checker/src/repr/json/converter.cpp b/vndk/tools/header-checker/src/repr/json/converter.cpp new file mode 100644 index 000000000..1cdaeddb8 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/json/converter.cpp @@ -0,0 +1,67 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/json/converter.h" + + +namespace header_checker { +namespace repr { + + +const JsonArray json_empty_array; +const JsonObject json_empty_object; +const Json::Value json_0(0); +const Json::Value json_false(false); +const Json::Value json_empty_string(""); + + +const AccessSpecifierIR default_access_ir = AccessSpecifierIR::PublicAccess; + +const RecordTypeIR::RecordKind default_record_kind_ir = + RecordTypeIR::RecordKind::struct_kind; + +const VTableComponentIR::Kind default_vtable_component_kind_ir = + VTableComponentIR::Kind::FunctionPointer; + +const ElfSymbolIR::ElfSymbolBinding default_elf_symbol_binding_ir = + ElfSymbolIR::ElfSymbolBinding::Global; + + +void JsonObject::Set(const std::string &key, bool value) { + SetOmissible(key, value, false); +} + + +void JsonObject::Set(const std::string &key, uint64_t value) { + SetOmissible(key, value, 0); +} + + +void JsonObject::Set(const std::string &key, int64_t value) { + SetOmissible(key, value, 0); +} + + +void JsonObject::Set(const std::string &key, const std::string &value) { + SetOmissible(key, value, ""); +} + + +void JsonObject::Set(const std::string &key, const JsonArray &value) { + SetOmissible(key, value, json_empty_array); +} + + +} // namespace repr +} // header_checker diff --git a/vndk/tools/header-checker/src/repr/json/converter.h b/vndk/tools/header-checker/src/repr/json/converter.h new file mode 100644 index 000000000..a6c82b980 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/json/converter.h @@ -0,0 +1,134 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_JSON_CONVERTER_H_ +#define HEADER_CHECKER_REPR_JSON_CONVERTER_H_ + +#include "repr/ir_representation.h" + +#include + +#include +#include + +#include + + +namespace header_checker { +namespace repr { + + +// These classes wrap constructors of Json::Value. +class JsonArray : public Json::Value { + public: + JsonArray() : Json::Value(Json::ValueType::arrayValue) {} +}; + + +class JsonObject : public Json::Value { + public: + JsonObject() : Json::Value(Json::ValueType::objectValue) {} + + // This method inserts the key-value pair if the value is not equal to the + // omissible value. + // Omit false. + void Set(const std::string &key, bool value); + + // Omit 0. + void Set(const std::string &key, uint64_t value); + + // Omit 0. + void Set(const std::string &key, int64_t value); + + // Omit "". + void Set(const std::string &key, const std::string &value); + + // Omit []. + void Set(const std::string &key, const JsonArray &value); + + private: + template + inline void SetOmissible(const std::string &key, T value, T omissible_value) { + if (value != omissible_value) { + (*this)[key] = value; + } else { + removeMember(key); + } + } +}; + + +extern const JsonArray json_empty_array; +extern const JsonObject json_empty_object; +extern const Json::Value json_0; +extern const Json::Value json_false; +extern const Json::Value json_empty_string; + +extern const AccessSpecifierIR default_access_ir; +extern const RecordTypeIR::RecordKind default_record_kind_ir; +extern const VTableComponentIR::Kind default_vtable_component_kind_ir; +extern const ElfSymbolIR::ElfSymbolBinding default_elf_symbol_binding_ir; + + +// Conversion between IR enums and JSON strings. +static const std::map access_ir_to_json{ + {AccessSpecifierIR::PublicAccess, "public"}, + {AccessSpecifierIR::ProtectedAccess, "protected"}, + {AccessSpecifierIR::PrivateAccess, "private"}, +}; + +static const std::map + record_kind_ir_to_json{ + {RecordTypeIR::RecordKind::struct_kind, "struct"}, + {RecordTypeIR::RecordKind::class_kind, "class"}, + {RecordTypeIR::RecordKind::union_kind, "union"}, +}; + +static const std::map + vtable_component_kind_ir_to_json{ + {VTableComponentIR::Kind::VCallOffset, "vcall_offset"}, + {VTableComponentIR::Kind::VBaseOffset, "vbase_offset"}, + {VTableComponentIR::Kind::OffsetToTop, "offset_to_top"}, + {VTableComponentIR::Kind::RTTI, "rtti"}, + {VTableComponentIR::Kind::FunctionPointer, "function_pointer"}, + {VTableComponentIR::Kind::CompleteDtorPointer, "complete_dtor_pointer"}, + {VTableComponentIR::Kind::DeletingDtorPointer, "deleting_dtor_pointer"}, + {VTableComponentIR::Kind::UnusedFunctionPointer, "unused_function_pointer"}, +}; + +static const std::map + elf_symbol_binding_ir_to_json{ + {ElfSymbolIR::ElfSymbolBinding::Weak, "weak"}, + {ElfSymbolIR::ElfSymbolBinding::Global, "global"}, +}; + +// If m contains k, this function returns the value. +// Otherwise, it prints error_msg and exits. +template +static inline const V &FindInMap(const std::map &m, const K &k, + const std::string &error_msg) { + auto it = m.find(k); + if (it == m.end()) { + llvm::errs() << error_msg << "\n"; + ::exit(1); + } + return it->second; +} + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_JSON_CONVERTER_H_ diff --git a/vndk/tools/header-checker/src/repr/json/ir_dumper.cpp b/vndk/tools/header-checker/src/repr/json/ir_dumper.cpp new file mode 100644 index 000000000..8c4a7fc23 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/json/ir_dumper.cpp @@ -0,0 +1,431 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/json/ir_dumper.h" + +#include "repr/ir_dumper.h" +#include "repr/ir_reader.h" +#include "repr/ir_representation_internal.h" +#include "repr/json/converter.h" + +#include +#include + +#include + +#include +#include +#include +#include + + +namespace header_checker { +namespace repr { + + +static void AddAccess(JsonObject &type_decl, AccessSpecifierIR value) { + if (value != default_access_ir) { + type_decl.Set("access", + FindInMap(access_ir_to_json, value, + "Failed to convert AccessSpecifierIR to JSON")); + } +} + +static void AddRecordKind(JsonObject &record_type, + RecordTypeIR::RecordKind value) { + if (value != default_record_kind_ir) { + record_type.Set("record_kind", + FindInMap(record_kind_ir_to_json, value, + "Failed to convert RecordKind to JSON")); + } +} + +static void AddVtableComponentKind(JsonObject &vtable_component, + VTableComponentIR::Kind value) { + if (value != default_vtable_component_kind_ir) { + vtable_component.Set( + "kind", FindInMap(vtable_component_kind_ir_to_json, value, + "Failed to convert VTableComponentIR::Kind to JSON")); + } +} + +static void AddElfSymbolBinding(JsonObject &elf_symbol, + ElfSymbolIR::ElfSymbolBinding value) { + if (value != default_elf_symbol_binding_ir) { + elf_symbol.Set("binding", + FindInMap(elf_symbol_binding_ir_to_json, value, + "Failed to convert ElfSymbolBinding to JSON")); + } +} + +void IRToJsonConverter::AddTemplateInfo( + JsonObject &type_decl, const TemplatedArtifactIR *template_ir) { + JsonArray args; + for (auto &&template_element_ir : template_ir->GetTemplateElements()) { + args.append(template_element_ir.GetReferencedType()); + } + type_decl.Set("template_args", args); +} + +void IRToJsonConverter::AddTypeInfo(JsonObject &type_decl, + const TypeIR *type_ir) { + type_decl.Set("linker_set_key", type_ir->GetLinkerSetKey()); + type_decl.Set("source_file", type_ir->GetSourceFile()); + type_decl.Set("name", type_ir->GetName()); + type_decl.Set("size", (uint64_t)type_ir->GetSize()); + type_decl.Set("alignment", (uint64_t)type_ir->GetAlignment()); + type_decl.Set("referenced_type", type_ir->GetReferencedType()); + type_decl.Set("self_type", type_ir->GetSelfType()); +} + +static JsonObject ConvertRecordFieldIR(const RecordFieldIR *record_field_ir) { + JsonObject record_field; + record_field.Set("field_name", record_field_ir->GetName()); + record_field.Set("referenced_type", record_field_ir->GetReferencedType()); + AddAccess(record_field, record_field_ir->GetAccess()); + record_field.Set("field_offset", (uint64_t)record_field_ir->GetOffset()); + return record_field; +} + +void IRToJsonConverter::AddRecordFields(JsonObject &record_type, + const RecordTypeIR *record_ir) { + JsonArray fields; + for (auto &&field_ir : record_ir->GetFields()) { + fields.append(ConvertRecordFieldIR(&field_ir)); + } + record_type.Set("fields", fields); +} + +static JsonObject +ConvertBaseSpecifierIR(const CXXBaseSpecifierIR &base_specifier_ir) { + JsonObject base_specifier; + base_specifier.Set("referenced_type", base_specifier_ir.GetReferencedType()); + base_specifier.Set("is_virtual", base_specifier_ir.IsVirtual()); + AddAccess(base_specifier, base_specifier_ir.GetAccess()); + return base_specifier; +} + +void IRToJsonConverter::AddBaseSpecifiers(JsonObject &record_type, + const RecordTypeIR *record_ir) { + JsonArray base_specifiers; + for (auto &&base_ir : record_ir->GetBases()) { + base_specifiers.append(ConvertBaseSpecifierIR(base_ir)); + } + record_type.Set("base_specifiers", base_specifiers); +} + +static JsonObject +ConvertVTableComponentIR(const VTableComponentIR &vtable_component_ir) { + JsonObject vtable_component; + AddVtableComponentKind(vtable_component, vtable_component_ir.GetKind()); + vtable_component.Set("component_value", + (int64_t)vtable_component_ir.GetValue()); + vtable_component.Set("mangled_component_name", vtable_component_ir.GetName()); + vtable_component.Set("is_pure", vtable_component_ir.GetIsPure()); + return vtable_component; +} + +void IRToJsonConverter::AddVTableLayout(JsonObject &record_type, + const RecordTypeIR *record_ir) { + JsonArray vtable_components; + for (auto &&vtable_component_ir : + record_ir->GetVTableLayout().GetVTableComponents()) { + vtable_components.append(ConvertVTableComponentIR(vtable_component_ir)); + } + record_type.Set("vtable_components", vtable_components); +} + +void IRToJsonConverter::AddTagTypeInfo(JsonObject &type_decl, + const TagTypeIR *tag_type_ir) { + type_decl.Set("unique_id", tag_type_ir->GetUniqueId()); +} + +JsonObject IRToJsonConverter::ConvertRecordTypeIR(const RecordTypeIR *recordp) { + JsonObject record_type; + + AddAccess(record_type, recordp->GetAccess()); + AddRecordKind(record_type, recordp->GetRecordKind()); + record_type.Set("is_anonymous", recordp->IsAnonymous()); + AddTypeInfo(record_type, recordp); + AddRecordFields(record_type, recordp); + AddBaseSpecifiers(record_type, recordp); + AddVTableLayout(record_type, recordp); + AddTagTypeInfo(record_type, recordp); + AddTemplateInfo(record_type, recordp); + return record_type; +} + +void IRToJsonConverter::AddFunctionParametersAndSetReturnType( + JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) { + function.Set("return_type", cfunction_like_ir->GetReturnType()); + AddFunctionParameters(function, cfunction_like_ir); +} + +void IRToJsonConverter::AddFunctionParameters( + JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) { + JsonArray parameters; + for (auto &¶meter_ir : cfunction_like_ir->GetParameters()) { + JsonObject parameter; + parameter.Set("referenced_type", parameter_ir.GetReferencedType()); + parameter.Set("default_arg", parameter_ir.GetIsDefault()); + parameter.Set("is_this_ptr", parameter_ir.GetIsThisPtr()); + parameters.append(parameter); + } + function.Set("parameters", parameters); +} + +JsonObject +IRToJsonConverter::ConvertFunctionTypeIR(const FunctionTypeIR *function_typep) { + JsonObject function_type; + AddTypeInfo(function_type, function_typep); + AddFunctionParametersAndSetReturnType(function_type, function_typep); + return function_type; +} + +JsonObject IRToJsonConverter::ConvertFunctionIR(const FunctionIR *functionp) { + JsonObject function; + AddAccess(function, functionp->GetAccess()); + function.Set("linker_set_key", functionp->GetLinkerSetKey()); + function.Set("source_file", functionp->GetSourceFile()); + function.Set("function_name", functionp->GetName()); + AddFunctionParametersAndSetReturnType(function, functionp); + AddTemplateInfo(function, functionp); + return function; +} + +static JsonObject ConvertEnumFieldIR(const EnumFieldIR *enum_field_ir) { + JsonObject enum_field; + enum_field.Set("name", enum_field_ir->GetName()); + // Never omit enum values. + enum_field["enum_field_value"] = Json::Int64(enum_field_ir->GetValue()); + return enum_field; +} + +void IRToJsonConverter::AddEnumFields(JsonObject &enum_type, + const EnumTypeIR *enum_ir) { + JsonArray enum_fields; + for (auto &&field : enum_ir->GetFields()) { + enum_fields.append(ConvertEnumFieldIR(&field)); + } + enum_type.Set("enum_fields", enum_fields); +} + +JsonObject IRToJsonConverter::ConvertEnumTypeIR(const EnumTypeIR *enump) { + JsonObject enum_type; + AddAccess(enum_type, enump->GetAccess()); + enum_type.Set("underlying_type", enump->GetUnderlyingType()); + AddTypeInfo(enum_type, enump); + AddEnumFields(enum_type, enump); + AddTagTypeInfo(enum_type, enump); + return enum_type; +} + +JsonObject +IRToJsonConverter::ConvertGlobalVarIR(const GlobalVarIR *global_varp) { + JsonObject global_var; + global_var.Set("referenced_type", global_varp->GetReferencedType()); + global_var.Set("source_file", global_varp->GetSourceFile()); + global_var.Set("name", global_varp->GetName()); + global_var.Set("linker_set_key", global_varp->GetLinkerSetKey()); + AddAccess(global_var, global_varp->GetAccess()); + return global_var; +} + +JsonObject +IRToJsonConverter::ConvertPointerTypeIR(const PointerTypeIR *pointerp) { + JsonObject pointer_type; + AddTypeInfo(pointer_type, pointerp); + return pointer_type; +} + +JsonObject +IRToJsonConverter::ConvertQualifiedTypeIR(const QualifiedTypeIR *qualtypep) { + JsonObject qualified_type; + AddTypeInfo(qualified_type, qualtypep); + qualified_type.Set("is_const", qualtypep->IsConst()); + qualified_type.Set("is_volatile", qualtypep->IsVolatile()); + qualified_type.Set("is_restricted", qualtypep->IsRestricted()); + return qualified_type; +} + +JsonObject +IRToJsonConverter::ConvertBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) { + JsonObject builtin_type; + builtin_type.Set("is_unsigned", builtin_typep->IsUnsigned()); + builtin_type.Set("is_integral", builtin_typep->IsIntegralType()); + AddTypeInfo(builtin_type, builtin_typep); + return builtin_type; +} + +JsonObject +IRToJsonConverter::ConvertArrayTypeIR(const ArrayTypeIR *array_typep) { + JsonObject array_type; + AddTypeInfo(array_type, array_typep); + return array_type; +} + +JsonObject IRToJsonConverter::ConvertLvalueReferenceTypeIR( + const LvalueReferenceTypeIR *lvalue_reference_typep) { + JsonObject lvalue_reference_type; + AddTypeInfo(lvalue_reference_type, lvalue_reference_typep); + return lvalue_reference_type; +} + +JsonObject IRToJsonConverter::ConvertRvalueReferenceTypeIR( + const RvalueReferenceTypeIR *rvalue_reference_typep) { + JsonObject rvalue_reference_type; + AddTypeInfo(rvalue_reference_type, rvalue_reference_typep); + return rvalue_reference_type; +} + +bool JsonIRDumper::AddLinkableMessageIR(const LinkableMessageIR *lm) { + std::string key; + JsonObject converted; + // No RTTI + switch (lm->GetKind()) { + case RecordTypeKind: + key = "record_types"; + converted = ConvertRecordTypeIR(static_cast(lm)); + break; + case EnumTypeKind: + key = "enum_types"; + converted = ConvertEnumTypeIR(static_cast(lm)); + break; + case PointerTypeKind: + key = "pointer_types"; + converted = ConvertPointerTypeIR(static_cast(lm)); + break; + case QualifiedTypeKind: + key = "qualified_types"; + converted = + ConvertQualifiedTypeIR(static_cast(lm)); + break; + case ArrayTypeKind: + key = "array_types"; + converted = ConvertArrayTypeIR(static_cast(lm)); + break; + case LvalueReferenceTypeKind: + key = "lvalue_reference_types"; + converted = ConvertLvalueReferenceTypeIR( + static_cast(lm)); + break; + case RvalueReferenceTypeKind: + key = "rvalue_reference_types"; + converted = ConvertRvalueReferenceTypeIR( + static_cast(lm)); + break; + case BuiltinTypeKind: + key = "builtin_types"; + converted = ConvertBuiltinTypeIR(static_cast(lm)); + break; + case FunctionTypeKind: + key = "function_types"; + converted = ConvertFunctionTypeIR(static_cast(lm)); + break; + case GlobalVarKind: + key = "global_vars"; + converted = ConvertGlobalVarIR(static_cast(lm)); + break; + case FunctionKind: + key = "functions"; + converted = ConvertFunctionIR(static_cast(lm)); + break; + default: + return false; + } + translation_unit_[key].append(converted); + return true; +} + +bool JsonIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *elf_symbol_ir) { + std::string key; + switch (elf_symbol_ir->GetKind()) { + case ElfSymbolIR::ElfFunctionKind: + key = "elf_functions"; + break; + case ElfSymbolIR::ElfObjectKind: + key = "elf_objects"; + break; + default: + return false; + } + JsonObject elf_symbol; + elf_symbol.Set("name", elf_symbol_ir->GetName()); + AddElfSymbolBinding(elf_symbol, elf_symbol_ir->GetBinding()); + translation_unit_[key].append(elf_symbol); + return true; +} + +static std::string DumpJson(const JsonObject &obj) { + std::ostringstream output_stream; + Json::StyledStreamWriter writer(/* indentation */ " "); + writer.write(output_stream, obj); + return output_stream.str(); +} + +static void WriteTailTrimmedLinesToFile(const std::string &path, + const std::string &output_string) { + std::ofstream output_file(path); + size_t line_start = 0; + while (line_start < output_string.size()) { + size_t trailing_space_start = line_start; + size_t index; + for (index = line_start; + index < output_string.size() && output_string[index] != '\n'; + index++) { + if (output_string[index] != ' ') { + trailing_space_start = index + 1; + } + } + // Only write this line if this line contains non-whitespace characters. + if (trailing_space_start != line_start) { + output_file.write(output_string.data() + line_start, + trailing_space_start - line_start); + output_file.write("\n", 1); + } + line_start = index + 1; + } +} + +bool JsonIRDumper::Dump() { + std::string output_string = DumpJson(translation_unit_); + WriteTailTrimmedLinesToFile(dump_path_, output_string); + return true; +} + +JsonIRDumper::JsonIRDumper(const std::string &dump_path) + : IRDumper(dump_path), translation_unit_() { + const std::string keys[] = { + "record_types", + "enum_types", + "pointer_types", + "lvalue_reference_types", + "rvalue_reference_types", + "builtin_types", + "qualified_types", + "array_types", + "function_types", + "functions", + "global_vars", + "elf_functions", + "elf_objects", + }; + for (auto key : keys) { + translation_unit_[key] = JsonArray(); + } +} + + +} // namespace repr +} // header_checker diff --git a/vndk/tools/header-checker/src/repr/json/ir_dumper.h b/vndk/tools/header-checker/src/repr/json/ir_dumper.h new file mode 100644 index 000000000..d7fc65c29 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/json/ir_dumper.h @@ -0,0 +1,103 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_JSON_IR_DUMPER_H_ +#define HEADER_CHECKER_REPR_JSON_IR_DUMPER_H_ + +#include "repr/ir_dumper.h" +#include "repr/ir_reader.h" +#include "repr/ir_representation.h" +#include "repr/json/converter.h" + + +namespace header_checker { +namespace repr { + + +class IRToJsonConverter { + private: + static void AddTemplateInfo(JsonObject &type_decl, + const TemplatedArtifactIR *template_ir); + + // BasicNamedAndTypedDecl + static void AddTypeInfo(JsonObject &type_decl, const TypeIR *type_ir); + + static void AddRecordFields(JsonObject &record_type, + const RecordTypeIR *record_ir); + + static void AddBaseSpecifiers(JsonObject &record_type, + const RecordTypeIR *record_ir); + + static void AddVTableLayout(JsonObject &record_type, + const RecordTypeIR *record_ir); + + static void AddTagTypeInfo(JsonObject &type_decl, + const TagTypeIR *tag_type_ir); + + static void AddEnumFields(JsonObject &enum_type, const EnumTypeIR *enum_ir); + + public: + static JsonObject ConvertEnumTypeIR(const EnumTypeIR *enump); + + static JsonObject ConvertRecordTypeIR(const RecordTypeIR *recordp); + + static JsonObject ConvertFunctionTypeIR(const FunctionTypeIR *function_typep); + + static void AddFunctionParametersAndSetReturnType( + JsonObject &function, const CFunctionLikeIR *cfunction_like_ir); + + static void AddFunctionParameters(JsonObject &function, + const CFunctionLikeIR *cfunction_like_ir); + + static JsonObject ConvertFunctionIR(const FunctionIR *functionp); + + static JsonObject ConvertGlobalVarIR(const GlobalVarIR *global_varp); + + static JsonObject ConvertPointerTypeIR(const PointerTypeIR *pointerp); + + static JsonObject ConvertQualifiedTypeIR(const QualifiedTypeIR *qualtypep); + + static JsonObject ConvertBuiltinTypeIR(const BuiltinTypeIR *builtin_typep); + + static JsonObject ConvertArrayTypeIR(const ArrayTypeIR *array_typep); + + static JsonObject ConvertLvalueReferenceTypeIR( + const LvalueReferenceTypeIR *lvalue_reference_typep); + + static JsonObject ConvertRvalueReferenceTypeIR( + const RvalueReferenceTypeIR *rvalue_reference_typep); +}; + +class JsonIRDumper : public IRDumper, public IRToJsonConverter { + public: + JsonIRDumper(const std::string &dump_path); + + ~JsonIRDumper() override {} + + bool AddLinkableMessageIR(const LinkableMessageIR *) override; + + bool AddElfSymbolMessageIR(const ElfSymbolIR *) override; + + bool Dump() override; + + private: + JsonObject translation_unit_; +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_JSON_IR_DUMPER_H_ diff --git a/vndk/tools/header-checker/src/repr/json/ir_reader.cpp b/vndk/tools/header-checker/src/repr/json/ir_reader.cpp new file mode 100644 index 000000000..72875901c --- /dev/null +++ b/vndk/tools/header-checker/src/repr/json/ir_reader.cpp @@ -0,0 +1,483 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/json/ir_reader.h" + +#include "repr/ir_dumper.h" +#include "repr/ir_reader.h" +#include "repr/ir_representation_internal.h" +#include "repr/json/converter.h" + +#include +#include + +#include + +#include +#include +#include +#include + + +namespace header_checker { +namespace repr { + + +static const std::map + access_json_to_ir(CreateInverseMap(access_ir_to_json)); + +static const std::map + record_kind_json_to_ir(CreateInverseMap(record_kind_ir_to_json)); + +static const std::map + vtable_component_kind_json_to_ir( + CreateInverseMap(vtable_component_kind_ir_to_json)); + +static const std::map + elf_symbol_binding_json_to_ir( + CreateInverseMap(elf_symbol_binding_ir_to_json)); + + +JsonObjectRef::JsonObjectRef(const Json::Value &json_value, bool &ok) + : object_(json_value.isObject() ? json_value : json_empty_object), ok_(ok) { + if (!json_value.isObject()) { + ok_ = false; + } +} + +const Json::Value & +JsonObjectRef::Get(const std::string &key, const Json::Value &default_value, + IsExpectedJsonType is_expected_type) const { + if (!object_.isMember(key)) { + return default_value; + } + const Json::Value &value = object_[key]; + if (!(value.*is_expected_type)()) { + ok_ = false; + return default_value; + } + return value; +} + +bool JsonObjectRef::GetBool(const std::string &key) const { + return Get(key, json_false, &Json::Value::isBool).asBool(); +} + +int64_t JsonObjectRef::GetInt(const std::string &key) const { + return Get(key, json_0, &Json::Value::isIntegral).asInt64(); +} + +uint64_t JsonObjectRef::GetUint(const std::string &key) const { + return Get(key, json_0, &Json::Value::isIntegral).asUInt64(); +} + +std::string JsonObjectRef::GetString(const std::string &key) const { + return Get(key, json_empty_string, &Json::Value::isString).asString(); +} + +JsonObjectRef JsonObjectRef::GetObject(const std::string &key) const { + return JsonObjectRef(Get(key, json_empty_object, &Json::Value::isObject), + ok_); +} + +JsonArrayRef +JsonObjectRef::GetObjects(const std::string &key) const { + return JsonArrayRef( + Get(key, json_empty_array, &Json::Value::isArray), ok_); +} + +JsonArrayRef +JsonObjectRef::GetStrings(const std::string &key) const { + return JsonArrayRef( + Get(key, json_empty_array, &Json::Value::isArray), ok_); +} + +template <> +JsonObjectRef JsonArrayRef::Iterator::operator*() const { + return JsonObjectRef(array_[index_], ok_); +} + +template <> std::string JsonArrayRef::Iterator::operator*() const { + return array_[index_].asString(); +} + +static AccessSpecifierIR GetAccess(const JsonObjectRef &type_decl) { + std::string access(type_decl.GetString("access")); + if (access.empty()) { + return default_access_ir; + } + return FindInMap(access_json_to_ir, access, + "Failed to convert JSON to AccessSpecifierIR"); +} + +static RecordTypeIR::RecordKind +GetRecordKind(const JsonObjectRef &record_type) { + std::string kind(record_type.GetString("record_kind")); + if (kind.empty()) { + return default_record_kind_ir; + } + return FindInMap(record_kind_json_to_ir, kind, + "Failed to convert JSON to RecordKind"); +} + +static VTableComponentIR::Kind +GetVTableComponentKind(const JsonObjectRef &vtable_component) { + std::string kind(vtable_component.GetString("kind")); + if (kind.empty()) { + return default_vtable_component_kind_ir; + } + return FindInMap(vtable_component_kind_json_to_ir, kind, + "Failed to convert JSON to VTableComponentIR::Kind"); +} + +static ElfSymbolIR::ElfSymbolBinding +GetElfSymbolBinding(const JsonObjectRef &elf_symbol) { + std::string binding(elf_symbol.GetString("binding")); + if (binding.empty()) { + return default_elf_symbol_binding_ir; + } + return FindInMap(elf_symbol_binding_json_to_ir, binding, + "Failed to convert JSON to ElfSymbolBinding"); +} + +bool JsonToIRReader::ReadDump(const std::string &dump_file) { + Json::Value tu_json; + Json::Reader reader; + std::ifstream input(dump_file); + + if (!reader.parse(input, tu_json, /* collectComments */ false)) { + llvm::errs() << "Failed to parse JSON: " + << reader.getFormattedErrorMessages() << "\n"; + return false; + } + bool ok = true; + JsonObjectRef tu(tu_json, ok); + if (!ok) { + llvm::errs() << "Translation unit is not an object\n"; + return false; + } + + ReadFunctions(tu); + ReadGlobalVariables(tu); + ReadEnumTypes(tu); + ReadRecordTypes(tu); + ReadFunctionTypes(tu); + ReadArrayTypes(tu); + ReadPointerTypes(tu); + ReadQualifiedTypes(tu); + ReadBuiltinTypes(tu); + ReadLvalueReferenceTypes(tu); + ReadRvalueReferenceTypes(tu); + ReadElfFunctions(tu); + ReadElfObjects(tu); + if (!ok) { + llvm::errs() << "Failed to convert JSON to IR\n"; + return false; + } + return true; +} + +void JsonToIRReader::ReadTagTypeInfo(const JsonObjectRef &type_decl, + TagTypeIR *tag_type_ir) { + tag_type_ir->SetUniqueId(type_decl.GetString("unique_id")); +} + +void JsonToIRReader::ReadTemplateInfo(const JsonObjectRef &type_decl, + TemplatedArtifactIR *template_ir) { + TemplateInfoIR template_info_ir; + for (auto &&referenced_type : type_decl.GetStrings("template_args")) { + TemplateElementIR template_element_ir(referenced_type); + template_info_ir.AddTemplateElement(std::move(template_element_ir)); + } + template_ir->SetTemplateInfo(std::move(template_info_ir)); +} + +void JsonToIRReader::ReadTypeInfo(const JsonObjectRef &type_decl, + TypeIR *type_ir) { + type_ir->SetLinkerSetKey(type_decl.GetString("linker_set_key")); + type_ir->SetSourceFile(type_decl.GetString("source_file")); + type_ir->SetName(type_decl.GetString("name")); + type_ir->SetReferencedType(type_decl.GetString("referenced_type")); + type_ir->SetSelfType(type_decl.GetString("self_type")); + type_ir->SetSize(type_decl.GetUint("size")); + type_ir->SetAlignment(type_decl.GetUint("alignment")); +} + +void JsonToIRReader::ReadRecordFields(const JsonObjectRef &record_type, + RecordTypeIR *record_ir) { + for (auto &&field : record_type.GetObjects("fields")) { + RecordFieldIR record_field_ir( + field.GetString("field_name"), field.GetString("referenced_type"), + field.GetUint("field_offset"), GetAccess(field)); + record_ir->AddRecordField(std::move(record_field_ir)); + } +} + +void JsonToIRReader::ReadBaseSpecifiers(const JsonObjectRef &record_type, + RecordTypeIR *record_ir) { + for (auto &&base_specifier : record_type.GetObjects("base_specifiers")) { + CXXBaseSpecifierIR record_base_ir( + base_specifier.GetString("referenced_type"), + base_specifier.GetBool("is_virtual"), GetAccess(base_specifier)); + record_ir->AddCXXBaseSpecifier(std::move(record_base_ir)); + } +} + +void JsonToIRReader::ReadVTableLayout(const JsonObjectRef &record_type, + RecordTypeIR *record_ir) { + VTableLayoutIR vtable_layout_ir; + for (auto &&vtable_component : record_type.GetObjects("vtable_components")) { + VTableComponentIR vtable_component_ir( + vtable_component.GetString("mangled_component_name"), + GetVTableComponentKind(vtable_component), + vtable_component.GetInt("component_value"), + vtable_component.GetBool("is_pure")); + vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir)); + } + record_ir->SetVTableLayout(std::move(vtable_layout_ir)); +} + +void JsonToIRReader::ReadEnumFields(const JsonObjectRef &enum_type, + EnumTypeIR *enum_ir) { + for (auto &&field : enum_type.GetObjects("enum_fields")) { + EnumFieldIR enum_field_ir(field.GetString("name"), + field.GetInt("enum_field_value")); + enum_ir->AddEnumField(std::move(enum_field_ir)); + } +} + +void JsonToIRReader::ReadFunctionParametersAndReturnType( + const JsonObjectRef &function, CFunctionLikeIR *function_ir) { + function_ir->SetReturnType(function.GetString("return_type")); + for (auto &¶meter : function.GetObjects("parameters")) { + ParamIR param_ir(parameter.GetString("referenced_type"), + parameter.GetBool("default_arg"), + parameter.GetBool("is_this_ptr")); + function_ir->AddParameter(std::move(param_ir)); + } +} + +FunctionIR JsonToIRReader::FunctionJsonToIR(const JsonObjectRef &function) { + FunctionIR function_ir; + function_ir.SetLinkerSetKey(function.GetString("linker_set_key")); + function_ir.SetName(function.GetString("function_name")); + function_ir.SetAccess(GetAccess(function)); + function_ir.SetSourceFile(function.GetString("source_file")); + ReadFunctionParametersAndReturnType(function, &function_ir); + ReadTemplateInfo(function, &function_ir); + return function_ir; +} + +FunctionTypeIR +JsonToIRReader::FunctionTypeJsonToIR(const JsonObjectRef &function_type) { + FunctionTypeIR function_type_ir; + ReadTypeInfo(function_type, &function_type_ir); + ReadFunctionParametersAndReturnType(function_type, &function_type_ir); + return function_type_ir; +} + +RecordTypeIR +JsonToIRReader::RecordTypeJsonToIR(const JsonObjectRef &record_type) { + RecordTypeIR record_type_ir; + ReadTypeInfo(record_type, &record_type_ir); + ReadTemplateInfo(record_type, &record_type_ir); + record_type_ir.SetAccess(GetAccess(record_type)); + ReadVTableLayout(record_type, &record_type_ir); + ReadRecordFields(record_type, &record_type_ir); + ReadBaseSpecifiers(record_type, &record_type_ir); + record_type_ir.SetRecordKind(GetRecordKind(record_type)); + record_type_ir.SetAnonymity(record_type.GetBool("is_anonymous")); + ReadTagTypeInfo(record_type, &record_type_ir); + return record_type_ir; +} + +EnumTypeIR JsonToIRReader::EnumTypeJsonToIR(const JsonObjectRef &enum_type) { + EnumTypeIR enum_type_ir; + ReadTypeInfo(enum_type, &enum_type_ir); + enum_type_ir.SetUnderlyingType(enum_type.GetString("underlying_type")); + enum_type_ir.SetAccess(GetAccess(enum_type)); + ReadEnumFields(enum_type, &enum_type_ir); + ReadTagTypeInfo(enum_type, &enum_type_ir); + return enum_type_ir; +} + +void JsonToIRReader::ReadGlobalVariables(const JsonObjectRef &tu) { + for (auto &&global_variable : tu.GetObjects("global_vars")) { + GlobalVarIR global_variable_ir; + global_variable_ir.SetName(global_variable.GetString("name")); + global_variable_ir.SetAccess(GetAccess(global_variable)); + global_variable_ir.SetSourceFile(global_variable.GetString("source_file")); + global_variable_ir.SetReferencedType( + global_variable.GetString("referenced_type")); + global_variable_ir.SetLinkerSetKey( + global_variable.GetString("linker_set_key")); + if (!IsLinkableMessageInExportedHeaders(&global_variable_ir)) { + continue; + } + module_->global_variables_.insert( + {global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)}); + } +} + +void JsonToIRReader::ReadPointerTypes(const JsonObjectRef &tu) { + for (auto &&pointer_type : tu.GetObjects("pointer_types")) { + PointerTypeIR pointer_type_ir; + ReadTypeInfo(pointer_type, &pointer_type_ir); + if (!IsLinkableMessageInExportedHeaders(&pointer_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(pointer_type_ir), &module_->pointer_types_, + &module_->type_graph_); + } +} + +void JsonToIRReader::ReadBuiltinTypes(const JsonObjectRef &tu) { + for (auto &&builtin_type : tu.GetObjects("builtin_types")) { + BuiltinTypeIR builtin_type_ir; + ReadTypeInfo(builtin_type, &builtin_type_ir); + builtin_type_ir.SetSignedness(builtin_type.GetBool("is_unsigned")); + builtin_type_ir.SetIntegralType(builtin_type.GetBool("is_integral")); + AddToMapAndTypeGraph(std::move(builtin_type_ir), &module_->builtin_types_, + &module_->type_graph_); + } +} + +void JsonToIRReader::ReadQualifiedTypes(const JsonObjectRef &tu) { + for (auto &&qualified_type : tu.GetObjects("qualified_types")) { + QualifiedTypeIR qualified_type_ir; + ReadTypeInfo(qualified_type, &qualified_type_ir); + qualified_type_ir.SetConstness(qualified_type.GetBool("is_const")); + qualified_type_ir.SetVolatility(qualified_type.GetBool("is_volatile")); + qualified_type_ir.SetRestrictedness( + qualified_type.GetBool("is_restricted")); + if (!IsLinkableMessageInExportedHeaders(&qualified_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(qualified_type_ir), + &module_->qualified_types_, &module_->type_graph_); + } +} + +void JsonToIRReader::ReadArrayTypes(const JsonObjectRef &tu) { + for (auto &&array_type : tu.GetObjects("array_types")) { + ArrayTypeIR array_type_ir; + ReadTypeInfo(array_type, &array_type_ir); + if (!IsLinkableMessageInExportedHeaders(&array_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(array_type_ir), &module_->array_types_, + &module_->type_graph_); + } +} + +void JsonToIRReader::ReadLvalueReferenceTypes(const JsonObjectRef &tu) { + for (auto &&lvalue_reference_type : tu.GetObjects("lvalue_reference_types")) { + LvalueReferenceTypeIR lvalue_reference_type_ir; + ReadTypeInfo(lvalue_reference_type, &lvalue_reference_type_ir); + if (!IsLinkableMessageInExportedHeaders(&lvalue_reference_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(lvalue_reference_type_ir), + &module_->lvalue_reference_types_, + &module_->type_graph_); + } +} + +void JsonToIRReader::ReadRvalueReferenceTypes(const JsonObjectRef &tu) { + for (auto &&rvalue_reference_type : tu.GetObjects("rvalue_reference_types")) { + RvalueReferenceTypeIR rvalue_reference_type_ir; + ReadTypeInfo(rvalue_reference_type, &rvalue_reference_type_ir); + if (!IsLinkableMessageInExportedHeaders(&rvalue_reference_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(rvalue_reference_type_ir), + &module_->rvalue_reference_types_, + &module_->type_graph_); + } +} + +void JsonToIRReader::ReadFunctions(const JsonObjectRef &tu) { + for (auto &&function : tu.GetObjects("functions")) { + FunctionIR function_ir = FunctionJsonToIR(function); + if (!IsLinkableMessageInExportedHeaders(&function_ir)) { + continue; + } + module_->functions_.insert( + {function_ir.GetLinkerSetKey(), std::move(function_ir)}); + } +} + +void JsonToIRReader::ReadRecordTypes(const JsonObjectRef &tu) { + for (auto &&record_type : tu.GetObjects("record_types")) { + RecordTypeIR record_type_ir = RecordTypeJsonToIR(record_type); + if (!IsLinkableMessageInExportedHeaders(&record_type_ir)) { + continue; + } + auto it = AddToMapAndTypeGraph(std::move(record_type_ir), + &module_->record_types_, + &module_->type_graph_); + const std::string &key = GetODRListMapKey(&(it->second)); + AddToODRListMap(key, &(it->second)); + } +} + +void JsonToIRReader::ReadFunctionTypes(const JsonObjectRef &tu) { + for (auto &&function_type : tu.GetObjects("function_types")) { + FunctionTypeIR function_type_ir = FunctionTypeJsonToIR(function_type); + if (!IsLinkableMessageInExportedHeaders(&function_type_ir)) { + continue; + } + auto it = AddToMapAndTypeGraph(std::move(function_type_ir), + &module_->function_types_, + &module_->type_graph_); + const std::string &key = GetODRListMapKey(&(it->second)); + AddToODRListMap(key, &(it->second)); + } +} + +void JsonToIRReader::ReadEnumTypes(const JsonObjectRef &tu) { + for (auto &&enum_type : tu.GetObjects("enum_types")) { + EnumTypeIR enum_type_ir = EnumTypeJsonToIR(enum_type); + if (!IsLinkableMessageInExportedHeaders(&enum_type_ir)) { + continue; + } + auto it = AddToMapAndTypeGraph(std::move(enum_type_ir), + &module_->enum_types_, + &module_->type_graph_); + AddToODRListMap(it->second.GetUniqueId() + it->second.GetSourceFile(), + (&it->second)); + } +} + +void JsonToIRReader::ReadElfFunctions(const JsonObjectRef &tu) { + for (auto &&elf_function : tu.GetObjects("elf_functions")) { + ElfFunctionIR elf_function_ir(elf_function.GetString("name"), + GetElfSymbolBinding(elf_function)); + module_->elf_functions_.insert( + {elf_function_ir.GetName(), std::move(elf_function_ir)}); + } +} + +void JsonToIRReader::ReadElfObjects(const JsonObjectRef &tu) { + for (auto &&elf_object : tu.GetObjects("elf_objects")) { + ElfObjectIR elf_object_ir(elf_object.GetString("name"), + GetElfSymbolBinding(elf_object)); + module_->elf_objects_.insert( + {elf_object_ir.GetName(), std::move(elf_object_ir)}); + } +} + + +} // namespace repr +} // header_checker diff --git a/vndk/tools/header-checker/src/repr/json/ir_reader.h b/vndk/tools/header-checker/src/repr/json/ir_reader.h new file mode 100644 index 000000000..797e65e9b --- /dev/null +++ b/vndk/tools/header-checker/src/repr/json/ir_reader.h @@ -0,0 +1,186 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_JSON_IR_READER_H_ +#define HEADER_CHECKER_REPR_JSON_IR_READER_H_ + +#include "repr/ir_dumper.h" +#include "repr/ir_reader.h" +#include "repr/ir_representation.h" + +#include + + +namespace header_checker { +namespace repr { + + +template class JsonArrayRef; + +// This class loads values from a read-only JSON object. +class JsonObjectRef { + public: + // The constructor sets ok to false if json_value is not an object. + JsonObjectRef(const Json::Value &json_value, bool &ok); + + // This method gets a value from the object and checks the type. + // If the type mismatches, it sets ok_ to false and returns default value. + // If the key doesn't exist, it doesn't change ok_ and returns default value. + // Default to false. + bool GetBool(const std::string &key) const; + + // Default to 0. + int64_t GetInt(const std::string &key) const; + + // Default to 0. + uint64_t GetUint(const std::string &key) const; + + // Default to "". + std::string GetString(const std::string &key) const; + + // Default to {}. + JsonObjectRef GetObject(const std::string &key) const; + + // Default to []. + JsonArrayRef GetObjects(const std::string &key) const; + + JsonArrayRef GetStrings(const std::string &key) const; + + private: + typedef bool (Json::Value::*IsExpectedJsonType)() const; + + const Json::Value &Get(const std::string &key, + const Json::Value &default_value, + IsExpectedJsonType is_expected_type) const; + + const Json::Value &object_; + bool &ok_; +}; + +// This class loads elements as type T from a read-only JSON array. +template class JsonArrayRef { + public: + class Iterator { + public: + Iterator(const Json::Value &json_value, bool &ok, int index) + : array_(json_value), ok_(ok), index_(index) {} + + Iterator &operator++() { + ++index_; + return *this; + } + + bool operator!=(const Iterator &other) const { + return index_ != other.index_; + } + + T operator*() const; + + private: + const Json::Value &array_; + bool &ok_; + int index_; + }; + + // The caller ensures json_value.isArray() == true. + JsonArrayRef(const Json::Value &json_value, bool &ok) + : array_(json_value), ok_(ok) {} + + Iterator begin() const { return Iterator(array_, ok_, 0); } + + Iterator end() const { return Iterator(array_, ok_, array_.size()); } + + private: + const Json::Value &array_; + bool &ok_; +}; + +template <> +JsonObjectRef JsonArrayRef::Iterator::operator*() const; + +template <> std::string JsonArrayRef::Iterator::operator*() const; + +class JsonToIRReader : public TextFormatToIRReader { + public: + JsonToIRReader(const std::set *exported_headers) + : TextFormatToIRReader(exported_headers) {} + + bool ReadDump(const std::string &dump_file) override; + + private: + void ReadFunctions(const JsonObjectRef &tu); + + void ReadGlobalVariables(const JsonObjectRef &tu); + + void ReadEnumTypes(const JsonObjectRef &tu); + + void ReadRecordTypes(const JsonObjectRef &tu); + + void ReadFunctionTypes(const JsonObjectRef &tu); + + void ReadPointerTypes(const JsonObjectRef &tu); + + void ReadBuiltinTypes(const JsonObjectRef &tu); + + void ReadQualifiedTypes(const JsonObjectRef &tu); + + void ReadArrayTypes(const JsonObjectRef &tu); + + void ReadLvalueReferenceTypes(const JsonObjectRef &tu); + + void ReadRvalueReferenceTypes(const JsonObjectRef &tu); + + void ReadElfFunctions(const JsonObjectRef &tu); + + void ReadElfObjects(const JsonObjectRef &tu); + + static void ReadTemplateInfo(const JsonObjectRef &type_decl, + TemplatedArtifactIR *template_ir); + + static void ReadTypeInfo(const JsonObjectRef &type_decl, TypeIR *type_ir); + + static void ReadRecordFields(const JsonObjectRef &record_type, + RecordTypeIR *record_ir); + + static void ReadBaseSpecifiers(const JsonObjectRef &record_type, + RecordTypeIR *record_ir); + + static void ReadVTableLayout(const JsonObjectRef &record_type, + RecordTypeIR *record_ir); + + static void ReadTagTypeInfo(const JsonObjectRef &type_decl, + TagTypeIR *tag_type_ir); + + static void ReadEnumFields(const JsonObjectRef &enum_type, + EnumTypeIR *enum_ir); + + static void ReadFunctionParametersAndReturnType(const JsonObjectRef &function, + CFunctionLikeIR *function_ir); + + static FunctionIR FunctionJsonToIR(const JsonObjectRef &function); + + static FunctionTypeIR + FunctionTypeJsonToIR(const JsonObjectRef &function_type); + + static RecordTypeIR RecordTypeJsonToIR(const JsonObjectRef &record_type); + + static EnumTypeIR EnumTypeJsonToIR(const JsonObjectRef &enum_type); +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_JSON_IR_READER_H_ diff --git a/vndk/tools/header-checker/src/repr/json/ir_representation_json.cpp b/vndk/tools/header-checker/src/repr/json/ir_representation_json.cpp deleted file mode 100644 index 32e25127c..000000000 --- a/vndk/tools/header-checker/src/repr/json/ir_representation_json.cpp +++ /dev/null @@ -1,952 +0,0 @@ -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "repr/json/ir_representation_json.h" - -#include -#include - -#include - -#include -#include -#include -#include - - -namespace header_checker { -namespace repr { - - -// Conversion between IR enums and JSON strings. -static const std::map access_ir_to_json{ - {AccessSpecifierIR::PublicAccess, "public"}, - {AccessSpecifierIR::ProtectedAccess, "protected"}, - {AccessSpecifierIR::PrivateAccess, "private"}, -}; - -static const std::map - access_json_to_ir(CreateInverseMap(access_ir_to_json)); - -static const AccessSpecifierIR default_access_ir = - AccessSpecifierIR::PublicAccess; - -static const std::map - record_kind_ir_to_json{ - {RecordTypeIR::RecordKind::struct_kind, "struct"}, - {RecordTypeIR::RecordKind::class_kind, "class"}, - {RecordTypeIR::RecordKind::union_kind, "union"}, -}; - -static const std::map - record_kind_json_to_ir(CreateInverseMap(record_kind_ir_to_json)); - -static const RecordTypeIR::RecordKind default_record_kind_ir = - RecordTypeIR::RecordKind::struct_kind; - -static const std::map - vtable_component_kind_ir_to_json{ - {VTableComponentIR::Kind::VCallOffset, "vcall_offset"}, - {VTableComponentIR::Kind::VBaseOffset, "vbase_offset"}, - {VTableComponentIR::Kind::OffsetToTop, "offset_to_top"}, - {VTableComponentIR::Kind::RTTI, "rtti"}, - {VTableComponentIR::Kind::FunctionPointer, "function_pointer"}, - {VTableComponentIR::Kind::CompleteDtorPointer, "complete_dtor_pointer"}, - {VTableComponentIR::Kind::DeletingDtorPointer, "deleting_dtor_pointer"}, - {VTableComponentIR::Kind::UnusedFunctionPointer, "unused_function_pointer"}, -}; - -static const std::map - vtable_component_kind_json_to_ir( - CreateInverseMap(vtable_component_kind_ir_to_json)); - -static const VTableComponentIR::Kind default_vtable_component_kind_ir = - VTableComponentIR::Kind::FunctionPointer; - -static const std::map - elf_symbol_binding_ir_to_json{ - {ElfSymbolIR::ElfSymbolBinding::Weak, "weak"}, - {ElfSymbolIR::ElfSymbolBinding::Global, "global"}, -}; - -static const std::map - elf_symbol_binding_json_to_ir( - CreateInverseMap(elf_symbol_binding_ir_to_json)); - -static const ElfSymbolIR::ElfSymbolBinding default_elf_symbol_binding_ir = - ElfSymbolIR::ElfSymbolBinding::Global; - -// If m contains k, this function returns the value. -// Otherwise, it prints error_msg and exits. -template -static inline const V &FindInMap(const std::map &m, const K &k, - const std::string &error_msg) { - auto it = m.find(k); - if (it == m.end()) { - llvm::errs() << error_msg << "\n"; - ::exit(1); - } - return it->second; -} - -static const JsonObject json_empty_object; -static const JsonArray json_empty_array; -static const Json::Value json_0(0); -static const Json::Value json_false(false); -static const Json::Value json_empty_string(""); - -void JsonObject::Set(const std::string &key, bool value) { - SetOmissible(key, value, false); -} - -void JsonObject::Set(const std::string &key, uint64_t value) { - SetOmissible(key, value, 0); -} - -void JsonObject::Set(const std::string &key, int64_t value) { - SetOmissible(key, value, 0); -} - -void JsonObject::Set(const std::string &key, const std::string &value) { - SetOmissible(key, value, ""); -} - -void JsonObject::Set(const std::string &key, const JsonArray &value) { - SetOmissible(key, value, json_empty_array); -} - -static void AddAccess(JsonObject &type_decl, AccessSpecifierIR value) { - if (value != default_access_ir) { - type_decl.Set("access", - FindInMap(access_ir_to_json, value, - "Failed to convert AccessSpecifierIR to JSON")); - } -} - -static void AddRecordKind(JsonObject &record_type, - RecordTypeIR::RecordKind value) { - if (value != default_record_kind_ir) { - record_type.Set("record_kind", - FindInMap(record_kind_ir_to_json, value, - "Failed to convert RecordKind to JSON")); - } -} - -static void AddVtableComponentKind(JsonObject &vtable_component, - VTableComponentIR::Kind value) { - if (value != default_vtable_component_kind_ir) { - vtable_component.Set( - "kind", FindInMap(vtable_component_kind_ir_to_json, value, - "Failed to convert VTableComponentIR::Kind to JSON")); - } -} - -static void AddElfSymbolBinding(JsonObject &elf_symbol, - ElfSymbolIR::ElfSymbolBinding value) { - if (value != default_elf_symbol_binding_ir) { - elf_symbol.Set("binding", - FindInMap(elf_symbol_binding_ir_to_json, value, - "Failed to convert ElfSymbolBinding to JSON")); - } -} - -void IRToJsonConverter::AddTemplateInfo( - JsonObject &type_decl, const TemplatedArtifactIR *template_ir) { - JsonArray args; - for (auto &&template_element_ir : template_ir->GetTemplateElements()) { - args.append(template_element_ir.GetReferencedType()); - } - type_decl.Set("template_args", args); -} - -void IRToJsonConverter::AddTypeInfo(JsonObject &type_decl, - const TypeIR *type_ir) { - type_decl.Set("linker_set_key", type_ir->GetLinkerSetKey()); - type_decl.Set("source_file", type_ir->GetSourceFile()); - type_decl.Set("name", type_ir->GetName()); - type_decl.Set("size", (uint64_t)type_ir->GetSize()); - type_decl.Set("alignment", (uint64_t)type_ir->GetAlignment()); - type_decl.Set("referenced_type", type_ir->GetReferencedType()); - type_decl.Set("self_type", type_ir->GetSelfType()); -} - -static JsonObject ConvertRecordFieldIR(const RecordFieldIR *record_field_ir) { - JsonObject record_field; - record_field.Set("field_name", record_field_ir->GetName()); - record_field.Set("referenced_type", record_field_ir->GetReferencedType()); - AddAccess(record_field, record_field_ir->GetAccess()); - record_field.Set("field_offset", (uint64_t)record_field_ir->GetOffset()); - return record_field; -} - -void IRToJsonConverter::AddRecordFields(JsonObject &record_type, - const RecordTypeIR *record_ir) { - JsonArray fields; - for (auto &&field_ir : record_ir->GetFields()) { - fields.append(ConvertRecordFieldIR(&field_ir)); - } - record_type.Set("fields", fields); -} - -static JsonObject -ConvertBaseSpecifierIR(const CXXBaseSpecifierIR &base_specifier_ir) { - JsonObject base_specifier; - base_specifier.Set("referenced_type", base_specifier_ir.GetReferencedType()); - base_specifier.Set("is_virtual", base_specifier_ir.IsVirtual()); - AddAccess(base_specifier, base_specifier_ir.GetAccess()); - return base_specifier; -} - -void IRToJsonConverter::AddBaseSpecifiers(JsonObject &record_type, - const RecordTypeIR *record_ir) { - JsonArray base_specifiers; - for (auto &&base_ir : record_ir->GetBases()) { - base_specifiers.append(ConvertBaseSpecifierIR(base_ir)); - } - record_type.Set("base_specifiers", base_specifiers); -} - -static JsonObject -ConvertVTableComponentIR(const VTableComponentIR &vtable_component_ir) { - JsonObject vtable_component; - AddVtableComponentKind(vtable_component, vtable_component_ir.GetKind()); - vtable_component.Set("component_value", - (int64_t)vtable_component_ir.GetValue()); - vtable_component.Set("mangled_component_name", vtable_component_ir.GetName()); - vtable_component.Set("is_pure", vtable_component_ir.GetIsPure()); - return vtable_component; -} - -void IRToJsonConverter::AddVTableLayout(JsonObject &record_type, - const RecordTypeIR *record_ir) { - JsonArray vtable_components; - for (auto &&vtable_component_ir : - record_ir->GetVTableLayout().GetVTableComponents()) { - vtable_components.append(ConvertVTableComponentIR(vtable_component_ir)); - } - record_type.Set("vtable_components", vtable_components); -} - -void IRToJsonConverter::AddTagTypeInfo(JsonObject &type_decl, - const TagTypeIR *tag_type_ir) { - type_decl.Set("unique_id", tag_type_ir->GetUniqueId()); -} - -JsonObject IRToJsonConverter::ConvertRecordTypeIR(const RecordTypeIR *recordp) { - JsonObject record_type; - - AddAccess(record_type, recordp->GetAccess()); - AddRecordKind(record_type, recordp->GetRecordKind()); - record_type.Set("is_anonymous", recordp->IsAnonymous()); - AddTypeInfo(record_type, recordp); - AddRecordFields(record_type, recordp); - AddBaseSpecifiers(record_type, recordp); - AddVTableLayout(record_type, recordp); - AddTagTypeInfo(record_type, recordp); - AddTemplateInfo(record_type, recordp); - return record_type; -} - -void IRToJsonConverter::AddFunctionParametersAndSetReturnType( - JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) { - function.Set("return_type", cfunction_like_ir->GetReturnType()); - AddFunctionParameters(function, cfunction_like_ir); -} - -void IRToJsonConverter::AddFunctionParameters( - JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) { - JsonArray parameters; - for (auto &¶meter_ir : cfunction_like_ir->GetParameters()) { - JsonObject parameter; - parameter.Set("referenced_type", parameter_ir.GetReferencedType()); - parameter.Set("default_arg", parameter_ir.GetIsDefault()); - parameter.Set("is_this_ptr", parameter_ir.GetIsThisPtr()); - parameters.append(parameter); - } - function.Set("parameters", parameters); -} - -JsonObject -IRToJsonConverter::ConvertFunctionTypeIR(const FunctionTypeIR *function_typep) { - JsonObject function_type; - AddTypeInfo(function_type, function_typep); - AddFunctionParametersAndSetReturnType(function_type, function_typep); - return function_type; -} - -JsonObject IRToJsonConverter::ConvertFunctionIR(const FunctionIR *functionp) { - JsonObject function; - AddAccess(function, functionp->GetAccess()); - function.Set("linker_set_key", functionp->GetLinkerSetKey()); - function.Set("source_file", functionp->GetSourceFile()); - function.Set("function_name", functionp->GetName()); - AddFunctionParametersAndSetReturnType(function, functionp); - AddTemplateInfo(function, functionp); - return function; -} - -static JsonObject ConvertEnumFieldIR(const EnumFieldIR *enum_field_ir) { - JsonObject enum_field; - enum_field.Set("name", enum_field_ir->GetName()); - // Never omit enum values. - enum_field["enum_field_value"] = Json::Int64(enum_field_ir->GetValue()); - return enum_field; -} - -void IRToJsonConverter::AddEnumFields(JsonObject &enum_type, - const EnumTypeIR *enum_ir) { - JsonArray enum_fields; - for (auto &&field : enum_ir->GetFields()) { - enum_fields.append(ConvertEnumFieldIR(&field)); - } - enum_type.Set("enum_fields", enum_fields); -} - -JsonObject IRToJsonConverter::ConvertEnumTypeIR(const EnumTypeIR *enump) { - JsonObject enum_type; - AddAccess(enum_type, enump->GetAccess()); - enum_type.Set("underlying_type", enump->GetUnderlyingType()); - AddTypeInfo(enum_type, enump); - AddEnumFields(enum_type, enump); - AddTagTypeInfo(enum_type, enump); - return enum_type; -} - -JsonObject -IRToJsonConverter::ConvertGlobalVarIR(const GlobalVarIR *global_varp) { - JsonObject global_var; - global_var.Set("referenced_type", global_varp->GetReferencedType()); - global_var.Set("source_file", global_varp->GetSourceFile()); - global_var.Set("name", global_varp->GetName()); - global_var.Set("linker_set_key", global_varp->GetLinkerSetKey()); - AddAccess(global_var, global_varp->GetAccess()); - return global_var; -} - -JsonObject -IRToJsonConverter::ConvertPointerTypeIR(const PointerTypeIR *pointerp) { - JsonObject pointer_type; - AddTypeInfo(pointer_type, pointerp); - return pointer_type; -} - -JsonObject -IRToJsonConverter::ConvertQualifiedTypeIR(const QualifiedTypeIR *qualtypep) { - JsonObject qualified_type; - AddTypeInfo(qualified_type, qualtypep); - qualified_type.Set("is_const", qualtypep->IsConst()); - qualified_type.Set("is_volatile", qualtypep->IsVolatile()); - qualified_type.Set("is_restricted", qualtypep->IsRestricted()); - return qualified_type; -} - -JsonObject -IRToJsonConverter::ConvertBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) { - JsonObject builtin_type; - builtin_type.Set("is_unsigned", builtin_typep->IsUnsigned()); - builtin_type.Set("is_integral", builtin_typep->IsIntegralType()); - AddTypeInfo(builtin_type, builtin_typep); - return builtin_type; -} - -JsonObject -IRToJsonConverter::ConvertArrayTypeIR(const ArrayTypeIR *array_typep) { - JsonObject array_type; - AddTypeInfo(array_type, array_typep); - return array_type; -} - -JsonObject IRToJsonConverter::ConvertLvalueReferenceTypeIR( - const LvalueReferenceTypeIR *lvalue_reference_typep) { - JsonObject lvalue_reference_type; - AddTypeInfo(lvalue_reference_type, lvalue_reference_typep); - return lvalue_reference_type; -} - -JsonObject IRToJsonConverter::ConvertRvalueReferenceTypeIR( - const RvalueReferenceTypeIR *rvalue_reference_typep) { - JsonObject rvalue_reference_type; - AddTypeInfo(rvalue_reference_type, rvalue_reference_typep); - return rvalue_reference_type; -} - -bool JsonIRDumper::AddLinkableMessageIR(const LinkableMessageIR *lm) { - std::string key; - JsonObject converted; - // No RTTI - switch (lm->GetKind()) { - case RecordTypeKind: - key = "record_types"; - converted = ConvertRecordTypeIR(static_cast(lm)); - break; - case EnumTypeKind: - key = "enum_types"; - converted = ConvertEnumTypeIR(static_cast(lm)); - break; - case PointerTypeKind: - key = "pointer_types"; - converted = ConvertPointerTypeIR(static_cast(lm)); - break; - case QualifiedTypeKind: - key = "qualified_types"; - converted = - ConvertQualifiedTypeIR(static_cast(lm)); - break; - case ArrayTypeKind: - key = "array_types"; - converted = ConvertArrayTypeIR(static_cast(lm)); - break; - case LvalueReferenceTypeKind: - key = "lvalue_reference_types"; - converted = ConvertLvalueReferenceTypeIR( - static_cast(lm)); - break; - case RvalueReferenceTypeKind: - key = "rvalue_reference_types"; - converted = ConvertRvalueReferenceTypeIR( - static_cast(lm)); - break; - case BuiltinTypeKind: - key = "builtin_types"; - converted = ConvertBuiltinTypeIR(static_cast(lm)); - break; - case FunctionTypeKind: - key = "function_types"; - converted = ConvertFunctionTypeIR(static_cast(lm)); - break; - case GlobalVarKind: - key = "global_vars"; - converted = ConvertGlobalVarIR(static_cast(lm)); - break; - case FunctionKind: - key = "functions"; - converted = ConvertFunctionIR(static_cast(lm)); - break; - default: - return false; - } - translation_unit_[key].append(converted); - return true; -} - -bool JsonIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *elf_symbol_ir) { - std::string key; - switch (elf_symbol_ir->GetKind()) { - case ElfSymbolIR::ElfFunctionKind: - key = "elf_functions"; - break; - case ElfSymbolIR::ElfObjectKind: - key = "elf_objects"; - break; - default: - return false; - } - JsonObject elf_symbol; - elf_symbol.Set("name", elf_symbol_ir->GetName()); - AddElfSymbolBinding(elf_symbol, elf_symbol_ir->GetBinding()); - translation_unit_[key].append(elf_symbol); - return true; -} - -static std::string DumpJson(const JsonObject &obj) { - std::ostringstream output_stream; - Json::StyledStreamWriter writer(/* indentation */ " "); - writer.write(output_stream, obj); - return output_stream.str(); -} - -static void WriteTailTrimmedLinesToFile(const std::string &path, - const std::string &output_string) { - std::ofstream output_file(path); - size_t line_start = 0; - while (line_start < output_string.size()) { - size_t trailing_space_start = line_start; - size_t index; - for (index = line_start; - index < output_string.size() && output_string[index] != '\n'; - index++) { - if (output_string[index] != ' ') { - trailing_space_start = index + 1; - } - } - // Only write this line if this line contains non-whitespace characters. - if (trailing_space_start != line_start) { - output_file.write(output_string.data() + line_start, - trailing_space_start - line_start); - output_file.write("\n", 1); - } - line_start = index + 1; - } -} - -bool JsonIRDumper::Dump() { - std::string output_string = DumpJson(translation_unit_); - WriteTailTrimmedLinesToFile(dump_path_, output_string); - return true; -} - -JsonIRDumper::JsonIRDumper(const std::string &dump_path) - : IRDumper(dump_path), translation_unit_() { - const std::string keys[] = { - "record_types", - "enum_types", - "pointer_types", - "lvalue_reference_types", - "rvalue_reference_types", - "builtin_types", - "qualified_types", - "array_types", - "function_types", - "functions", - "global_vars", - "elf_functions", - "elf_objects", - }; - for (auto key : keys) { - translation_unit_[key] = JsonArray(); - } -} - -JsonObjectRef::JsonObjectRef(const Json::Value &json_value, bool &ok) - : object_(json_value.isObject() ? json_value : json_empty_object), ok_(ok) { - if (!json_value.isObject()) { - ok_ = false; - } -} - -const Json::Value & -JsonObjectRef::Get(const std::string &key, const Json::Value &default_value, - IsExpectedJsonType is_expected_type) const { - if (!object_.isMember(key)) { - return default_value; - } - const Json::Value &value = object_[key]; - if (!(value.*is_expected_type)()) { - ok_ = false; - return default_value; - } - return value; -} - -bool JsonObjectRef::GetBool(const std::string &key) const { - return Get(key, json_false, &Json::Value::isBool).asBool(); -} - -int64_t JsonObjectRef::GetInt(const std::string &key) const { - return Get(key, json_0, &Json::Value::isIntegral).asInt64(); -} - -uint64_t JsonObjectRef::GetUint(const std::string &key) const { - return Get(key, json_0, &Json::Value::isIntegral).asUInt64(); -} - -std::string JsonObjectRef::GetString(const std::string &key) const { - return Get(key, json_empty_string, &Json::Value::isString).asString(); -} - -JsonObjectRef JsonObjectRef::GetObject(const std::string &key) const { - return JsonObjectRef(Get(key, json_empty_object, &Json::Value::isObject), - ok_); -} - -JsonArrayRef -JsonObjectRef::GetObjects(const std::string &key) const { - return JsonArrayRef( - Get(key, json_empty_array, &Json::Value::isArray), ok_); -} - -JsonArrayRef -JsonObjectRef::GetStrings(const std::string &key) const { - return JsonArrayRef( - Get(key, json_empty_array, &Json::Value::isArray), ok_); -} - -template <> -JsonObjectRef JsonArrayRef::Iterator::operator*() const { - return JsonObjectRef(array_[index_], ok_); -} - -template <> std::string JsonArrayRef::Iterator::operator*() const { - return array_[index_].asString(); -} - -static AccessSpecifierIR GetAccess(const JsonObjectRef &type_decl) { - std::string access(type_decl.GetString("access")); - if (access.empty()) { - return default_access_ir; - } - return FindInMap(access_json_to_ir, access, - "Failed to convert JSON to AccessSpecifierIR"); -} - -static RecordTypeIR::RecordKind -GetRecordKind(const JsonObjectRef &record_type) { - std::string kind(record_type.GetString("record_kind")); - if (kind.empty()) { - return default_record_kind_ir; - } - return FindInMap(record_kind_json_to_ir, kind, - "Failed to convert JSON to RecordKind"); -} - -static VTableComponentIR::Kind -GetVTableComponentKind(const JsonObjectRef &vtable_component) { - std::string kind(vtable_component.GetString("kind")); - if (kind.empty()) { - return default_vtable_component_kind_ir; - } - return FindInMap(vtable_component_kind_json_to_ir, kind, - "Failed to convert JSON to VTableComponentIR::Kind"); -} - -static ElfSymbolIR::ElfSymbolBinding -GetElfSymbolBinding(const JsonObjectRef &elf_symbol) { - std::string binding(elf_symbol.GetString("binding")); - if (binding.empty()) { - return default_elf_symbol_binding_ir; - } - return FindInMap(elf_symbol_binding_json_to_ir, binding, - "Failed to convert JSON to ElfSymbolBinding"); -} - -bool JsonToIRReader::ReadDump(const std::string &dump_file) { - Json::Value tu_json; - Json::Reader reader; - std::ifstream input(dump_file); - - if (!reader.parse(input, tu_json, /* collectComments */ false)) { - llvm::errs() << "Failed to parse JSON: " - << reader.getFormattedErrorMessages() << "\n"; - return false; - } - bool ok = true; - JsonObjectRef tu(tu_json, ok); - if (!ok) { - llvm::errs() << "Translation unit is not an object\n"; - return false; - } - - ReadFunctions(tu); - ReadGlobalVariables(tu); - ReadEnumTypes(tu); - ReadRecordTypes(tu); - ReadFunctionTypes(tu); - ReadArrayTypes(tu); - ReadPointerTypes(tu); - ReadQualifiedTypes(tu); - ReadBuiltinTypes(tu); - ReadLvalueReferenceTypes(tu); - ReadRvalueReferenceTypes(tu); - ReadElfFunctions(tu); - ReadElfObjects(tu); - if (!ok) { - llvm::errs() << "Failed to convert JSON to IR\n"; - return false; - } - return true; -} - -void JsonToIRReader::ReadTagTypeInfo(const JsonObjectRef &type_decl, - TagTypeIR *tag_type_ir) { - tag_type_ir->SetUniqueId(type_decl.GetString("unique_id")); -} - -void JsonToIRReader::ReadTemplateInfo(const JsonObjectRef &type_decl, - TemplatedArtifactIR *template_ir) { - TemplateInfoIR template_info_ir; - for (auto &&referenced_type : type_decl.GetStrings("template_args")) { - TemplateElementIR template_element_ir(referenced_type); - template_info_ir.AddTemplateElement(std::move(template_element_ir)); - } - template_ir->SetTemplateInfo(std::move(template_info_ir)); -} - -void JsonToIRReader::ReadTypeInfo(const JsonObjectRef &type_decl, - TypeIR *type_ir) { - type_ir->SetLinkerSetKey(type_decl.GetString("linker_set_key")); - type_ir->SetSourceFile(type_decl.GetString("source_file")); - type_ir->SetName(type_decl.GetString("name")); - type_ir->SetReferencedType(type_decl.GetString("referenced_type")); - type_ir->SetSelfType(type_decl.GetString("self_type")); - type_ir->SetSize(type_decl.GetUint("size")); - type_ir->SetAlignment(type_decl.GetUint("alignment")); -} - -void JsonToIRReader::ReadRecordFields(const JsonObjectRef &record_type, - RecordTypeIR *record_ir) { - for (auto &&field : record_type.GetObjects("fields")) { - RecordFieldIR record_field_ir( - field.GetString("field_name"), field.GetString("referenced_type"), - field.GetUint("field_offset"), GetAccess(field)); - record_ir->AddRecordField(std::move(record_field_ir)); - } -} - -void JsonToIRReader::ReadBaseSpecifiers(const JsonObjectRef &record_type, - RecordTypeIR *record_ir) { - for (auto &&base_specifier : record_type.GetObjects("base_specifiers")) { - CXXBaseSpecifierIR record_base_ir( - base_specifier.GetString("referenced_type"), - base_specifier.GetBool("is_virtual"), GetAccess(base_specifier)); - record_ir->AddCXXBaseSpecifier(std::move(record_base_ir)); - } -} - -void JsonToIRReader::ReadVTableLayout(const JsonObjectRef &record_type, - RecordTypeIR *record_ir) { - VTableLayoutIR vtable_layout_ir; - for (auto &&vtable_component : record_type.GetObjects("vtable_components")) { - VTableComponentIR vtable_component_ir( - vtable_component.GetString("mangled_component_name"), - GetVTableComponentKind(vtable_component), - vtable_component.GetInt("component_value"), - vtable_component.GetBool("is_pure")); - vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir)); - } - record_ir->SetVTableLayout(std::move(vtable_layout_ir)); -} - -void JsonToIRReader::ReadEnumFields(const JsonObjectRef &enum_type, - EnumTypeIR *enum_ir) { - for (auto &&field : enum_type.GetObjects("enum_fields")) { - EnumFieldIR enum_field_ir(field.GetString("name"), - field.GetInt("enum_field_value")); - enum_ir->AddEnumField(std::move(enum_field_ir)); - } -} - -void JsonToIRReader::ReadFunctionParametersAndReturnType( - const JsonObjectRef &function, CFunctionLikeIR *function_ir) { - function_ir->SetReturnType(function.GetString("return_type")); - for (auto &¶meter : function.GetObjects("parameters")) { - ParamIR param_ir(parameter.GetString("referenced_type"), - parameter.GetBool("default_arg"), - parameter.GetBool("is_this_ptr")); - function_ir->AddParameter(std::move(param_ir)); - } -} - -FunctionIR JsonToIRReader::FunctionJsonToIR(const JsonObjectRef &function) { - FunctionIR function_ir; - function_ir.SetLinkerSetKey(function.GetString("linker_set_key")); - function_ir.SetName(function.GetString("function_name")); - function_ir.SetAccess(GetAccess(function)); - function_ir.SetSourceFile(function.GetString("source_file")); - ReadFunctionParametersAndReturnType(function, &function_ir); - ReadTemplateInfo(function, &function_ir); - return function_ir; -} - -FunctionTypeIR -JsonToIRReader::FunctionTypeJsonToIR(const JsonObjectRef &function_type) { - FunctionTypeIR function_type_ir; - ReadTypeInfo(function_type, &function_type_ir); - ReadFunctionParametersAndReturnType(function_type, &function_type_ir); - return function_type_ir; -} - -RecordTypeIR -JsonToIRReader::RecordTypeJsonToIR(const JsonObjectRef &record_type) { - RecordTypeIR record_type_ir; - ReadTypeInfo(record_type, &record_type_ir); - ReadTemplateInfo(record_type, &record_type_ir); - record_type_ir.SetAccess(GetAccess(record_type)); - ReadVTableLayout(record_type, &record_type_ir); - ReadRecordFields(record_type, &record_type_ir); - ReadBaseSpecifiers(record_type, &record_type_ir); - record_type_ir.SetRecordKind(GetRecordKind(record_type)); - record_type_ir.SetAnonymity(record_type.GetBool("is_anonymous")); - ReadTagTypeInfo(record_type, &record_type_ir); - return record_type_ir; -} - -EnumTypeIR JsonToIRReader::EnumTypeJsonToIR(const JsonObjectRef &enum_type) { - EnumTypeIR enum_type_ir; - ReadTypeInfo(enum_type, &enum_type_ir); - enum_type_ir.SetUnderlyingType(enum_type.GetString("underlying_type")); - enum_type_ir.SetAccess(GetAccess(enum_type)); - ReadEnumFields(enum_type, &enum_type_ir); - ReadTagTypeInfo(enum_type, &enum_type_ir); - return enum_type_ir; -} - -void JsonToIRReader::ReadGlobalVariables(const JsonObjectRef &tu) { - for (auto &&global_variable : tu.GetObjects("global_vars")) { - GlobalVarIR global_variable_ir; - global_variable_ir.SetName(global_variable.GetString("name")); - global_variable_ir.SetAccess(GetAccess(global_variable)); - global_variable_ir.SetSourceFile(global_variable.GetString("source_file")); - global_variable_ir.SetReferencedType( - global_variable.GetString("referenced_type")); - global_variable_ir.SetLinkerSetKey( - global_variable.GetString("linker_set_key")); - if (!IsLinkableMessageInExportedHeaders(&global_variable_ir)) { - continue; - } - module_->global_variables_.insert( - {global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)}); - } -} - -void JsonToIRReader::ReadPointerTypes(const JsonObjectRef &tu) { - for (auto &&pointer_type : tu.GetObjects("pointer_types")) { - PointerTypeIR pointer_type_ir; - ReadTypeInfo(pointer_type, &pointer_type_ir); - if (!IsLinkableMessageInExportedHeaders(&pointer_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(pointer_type_ir), &module_->pointer_types_, - &module_->type_graph_); - } -} - -void JsonToIRReader::ReadBuiltinTypes(const JsonObjectRef &tu) { - for (auto &&builtin_type : tu.GetObjects("builtin_types")) { - BuiltinTypeIR builtin_type_ir; - ReadTypeInfo(builtin_type, &builtin_type_ir); - builtin_type_ir.SetSignedness(builtin_type.GetBool("is_unsigned")); - builtin_type_ir.SetIntegralType(builtin_type.GetBool("is_integral")); - AddToMapAndTypeGraph(std::move(builtin_type_ir), &module_->builtin_types_, - &module_->type_graph_); - } -} - -void JsonToIRReader::ReadQualifiedTypes(const JsonObjectRef &tu) { - for (auto &&qualified_type : tu.GetObjects("qualified_types")) { - QualifiedTypeIR qualified_type_ir; - ReadTypeInfo(qualified_type, &qualified_type_ir); - qualified_type_ir.SetConstness(qualified_type.GetBool("is_const")); - qualified_type_ir.SetVolatility(qualified_type.GetBool("is_volatile")); - qualified_type_ir.SetRestrictedness( - qualified_type.GetBool("is_restricted")); - if (!IsLinkableMessageInExportedHeaders(&qualified_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(qualified_type_ir), - &module_->qualified_types_, &module_->type_graph_); - } -} - -void JsonToIRReader::ReadArrayTypes(const JsonObjectRef &tu) { - for (auto &&array_type : tu.GetObjects("array_types")) { - ArrayTypeIR array_type_ir; - ReadTypeInfo(array_type, &array_type_ir); - if (!IsLinkableMessageInExportedHeaders(&array_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(array_type_ir), &module_->array_types_, - &module_->type_graph_); - } -} - -void JsonToIRReader::ReadLvalueReferenceTypes(const JsonObjectRef &tu) { - for (auto &&lvalue_reference_type : tu.GetObjects("lvalue_reference_types")) { - LvalueReferenceTypeIR lvalue_reference_type_ir; - ReadTypeInfo(lvalue_reference_type, &lvalue_reference_type_ir); - if (!IsLinkableMessageInExportedHeaders(&lvalue_reference_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(lvalue_reference_type_ir), - &module_->lvalue_reference_types_, - &module_->type_graph_); - } -} - -void JsonToIRReader::ReadRvalueReferenceTypes(const JsonObjectRef &tu) { - for (auto &&rvalue_reference_type : tu.GetObjects("rvalue_reference_types")) { - RvalueReferenceTypeIR rvalue_reference_type_ir; - ReadTypeInfo(rvalue_reference_type, &rvalue_reference_type_ir); - if (!IsLinkableMessageInExportedHeaders(&rvalue_reference_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(rvalue_reference_type_ir), - &module_->rvalue_reference_types_, - &module_->type_graph_); - } -} - -void JsonToIRReader::ReadFunctions(const JsonObjectRef &tu) { - for (auto &&function : tu.GetObjects("functions")) { - FunctionIR function_ir = FunctionJsonToIR(function); - if (!IsLinkableMessageInExportedHeaders(&function_ir)) { - continue; - } - module_->functions_.insert( - {function_ir.GetLinkerSetKey(), std::move(function_ir)}); - } -} - -void JsonToIRReader::ReadRecordTypes(const JsonObjectRef &tu) { - for (auto &&record_type : tu.GetObjects("record_types")) { - RecordTypeIR record_type_ir = RecordTypeJsonToIR(record_type); - if (!IsLinkableMessageInExportedHeaders(&record_type_ir)) { - continue; - } - auto it = AddToMapAndTypeGraph(std::move(record_type_ir), - &module_->record_types_, - &module_->type_graph_); - const std::string &key = GetODRListMapKey(&(it->second)); - AddToODRListMap(key, &(it->second)); - } -} - -void JsonToIRReader::ReadFunctionTypes(const JsonObjectRef &tu) { - for (auto &&function_type : tu.GetObjects("function_types")) { - FunctionTypeIR function_type_ir = FunctionTypeJsonToIR(function_type); - if (!IsLinkableMessageInExportedHeaders(&function_type_ir)) { - continue; - } - auto it = AddToMapAndTypeGraph(std::move(function_type_ir), - &module_->function_types_, - &module_->type_graph_); - const std::string &key = GetODRListMapKey(&(it->second)); - AddToODRListMap(key, &(it->second)); - } -} - -void JsonToIRReader::ReadEnumTypes(const JsonObjectRef &tu) { - for (auto &&enum_type : tu.GetObjects("enum_types")) { - EnumTypeIR enum_type_ir = EnumTypeJsonToIR(enum_type); - if (!IsLinkableMessageInExportedHeaders(&enum_type_ir)) { - continue; - } - auto it = AddToMapAndTypeGraph(std::move(enum_type_ir), - &module_->enum_types_, - &module_->type_graph_); - AddToODRListMap(it->second.GetUniqueId() + it->second.GetSourceFile(), - (&it->second)); - } -} - -void JsonToIRReader::ReadElfFunctions(const JsonObjectRef &tu) { - for (auto &&elf_function : tu.GetObjects("elf_functions")) { - ElfFunctionIR elf_function_ir(elf_function.GetString("name"), - GetElfSymbolBinding(elf_function)); - module_->elf_functions_.insert( - {elf_function_ir.GetName(), std::move(elf_function_ir)}); - } -} - -void JsonToIRReader::ReadElfObjects(const JsonObjectRef &tu) { - for (auto &&elf_object : tu.GetObjects("elf_objects")) { - ElfObjectIR elf_object_ir(elf_object.GetString("name"), - GetElfSymbolBinding(elf_object)); - module_->elf_objects_.insert( - {elf_object_ir.GetName(), std::move(elf_object_ir)}); - } -} - - -} // namespace repr -} // header_checker diff --git a/vndk/tools/header-checker/src/repr/json/ir_representation_json.h b/vndk/tools/header-checker/src/repr/json/ir_representation_json.h deleted file mode 100644 index 7099cabe6..000000000 --- a/vndk/tools/header-checker/src/repr/json/ir_representation_json.h +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef IR_REPRESENTATION_JSON_H_ -#define IR_REPRESENTATION_JSON_H_ - -#include "repr/ir_representation.h" - -#include - - -namespace header_checker { -namespace repr { - - -// Classes which act as middle-men between clang AST parsing routines and -// message format specific dumpers. - -// These classes wrap constructors of Json::Value. -class JsonArray : public Json::Value { - public: - JsonArray() : Json::Value(Json::ValueType::arrayValue) {} -}; - -class JsonObject : public Json::Value { - public: - JsonObject() : Json::Value(Json::ValueType::objectValue) {} - - // This method inserts the key-value pair if the value is not equal to the - // omissible value. - // Omit false. - void Set(const std::string &key, bool value); - - // Omit 0. - void Set(const std::string &key, uint64_t value); - - // Omit 0. - void Set(const std::string &key, int64_t value); - - // Omit "". - void Set(const std::string &key, const std::string &value); - - // Omit []. - void Set(const std::string &key, const JsonArray &value); - - private: - template - inline void SetOmissible(const std::string &key, T value, T omissible_value) { - if (value != omissible_value) { - (*this)[key] = value; - } else { - removeMember(key); - } - } -}; - -class IRToJsonConverter { - private: - static void AddTemplateInfo(JsonObject &type_decl, - const TemplatedArtifactIR *template_ir); - - // BasicNamedAndTypedDecl - static void AddTypeInfo(JsonObject &type_decl, const TypeIR *type_ir); - - static void AddRecordFields(JsonObject &record_type, - const RecordTypeIR *record_ir); - - static void AddBaseSpecifiers(JsonObject &record_type, - const RecordTypeIR *record_ir); - - static void AddVTableLayout(JsonObject &record_type, - const RecordTypeIR *record_ir); - - static void AddTagTypeInfo(JsonObject &type_decl, - const TagTypeIR *tag_type_ir); - - static void AddEnumFields(JsonObject &enum_type, const EnumTypeIR *enum_ir); - - public: - static JsonObject ConvertEnumTypeIR(const EnumTypeIR *enump); - - static JsonObject ConvertRecordTypeIR(const RecordTypeIR *recordp); - - static JsonObject ConvertFunctionTypeIR(const FunctionTypeIR *function_typep); - - static void AddFunctionParametersAndSetReturnType( - JsonObject &function, const CFunctionLikeIR *cfunction_like_ir); - - static void AddFunctionParameters(JsonObject &function, - const CFunctionLikeIR *cfunction_like_ir); - - static JsonObject ConvertFunctionIR(const FunctionIR *functionp); - - static JsonObject ConvertGlobalVarIR(const GlobalVarIR *global_varp); - - static JsonObject ConvertPointerTypeIR(const PointerTypeIR *pointerp); - - static JsonObject ConvertQualifiedTypeIR(const QualifiedTypeIR *qualtypep); - - static JsonObject ConvertBuiltinTypeIR(const BuiltinTypeIR *builtin_typep); - - static JsonObject ConvertArrayTypeIR(const ArrayTypeIR *array_typep); - - static JsonObject ConvertLvalueReferenceTypeIR( - const LvalueReferenceTypeIR *lvalue_reference_typep); - - static JsonObject ConvertRvalueReferenceTypeIR( - const RvalueReferenceTypeIR *rvalue_reference_typep); -}; - -class JsonIRDumper : public IRDumper, public IRToJsonConverter { - public: - JsonIRDumper(const std::string &dump_path); - - ~JsonIRDumper() override {} - - bool AddLinkableMessageIR(const LinkableMessageIR *) override; - - bool AddElfSymbolMessageIR(const ElfSymbolIR *) override; - - bool Dump() override; - - private: - JsonObject translation_unit_; -}; - -template class JsonArrayRef; - -// This class loads values from a read-only JSON object. -class JsonObjectRef { - public: - // The constructor sets ok to false if json_value is not an object. - JsonObjectRef(const Json::Value &json_value, bool &ok); - - // This method gets a value from the object and checks the type. - // If the type mismatches, it sets ok_ to false and returns default value. - // If the key doesn't exist, it doesn't change ok_ and returns default value. - // Default to false. - bool GetBool(const std::string &key) const; - - // Default to 0. - int64_t GetInt(const std::string &key) const; - - // Default to 0. - uint64_t GetUint(const std::string &key) const; - - // Default to "". - std::string GetString(const std::string &key) const; - - // Default to {}. - JsonObjectRef GetObject(const std::string &key) const; - - // Default to []. - JsonArrayRef GetObjects(const std::string &key) const; - - JsonArrayRef GetStrings(const std::string &key) const; - - private: - typedef bool (Json::Value::*IsExpectedJsonType)() const; - - const Json::Value &Get(const std::string &key, - const Json::Value &default_value, - IsExpectedJsonType is_expected_type) const; - - const Json::Value &object_; - bool &ok_; -}; - -// This class loads elements as type T from a read-only JSON array. -template class JsonArrayRef { - public: - class Iterator { - public: - Iterator(const Json::Value &json_value, bool &ok, int index) - : array_(json_value), ok_(ok), index_(index) {} - - Iterator &operator++() { - ++index_; - return *this; - } - - bool operator!=(const Iterator &other) const { - return index_ != other.index_; - } - - T operator*() const; - - private: - const Json::Value &array_; - bool &ok_; - int index_; - }; - - // The caller ensures json_value.isArray() == true. - JsonArrayRef(const Json::Value &json_value, bool &ok) - : array_(json_value), ok_(ok) {} - - Iterator begin() const { return Iterator(array_, ok_, 0); } - - Iterator end() const { return Iterator(array_, ok_, array_.size()); } - - private: - const Json::Value &array_; - bool &ok_; -}; - -template <> -JsonObjectRef JsonArrayRef::Iterator::operator*() const; - -template <> std::string JsonArrayRef::Iterator::operator*() const; - -class JsonToIRReader : public TextFormatToIRReader { - public: - JsonToIRReader(const std::set *exported_headers) - : TextFormatToIRReader(exported_headers) {} - - bool ReadDump(const std::string &dump_file) override; - - private: - void ReadFunctions(const JsonObjectRef &tu); - - void ReadGlobalVariables(const JsonObjectRef &tu); - - void ReadEnumTypes(const JsonObjectRef &tu); - - void ReadRecordTypes(const JsonObjectRef &tu); - - void ReadFunctionTypes(const JsonObjectRef &tu); - - void ReadPointerTypes(const JsonObjectRef &tu); - - void ReadBuiltinTypes(const JsonObjectRef &tu); - - void ReadQualifiedTypes(const JsonObjectRef &tu); - - void ReadArrayTypes(const JsonObjectRef &tu); - - void ReadLvalueReferenceTypes(const JsonObjectRef &tu); - - void ReadRvalueReferenceTypes(const JsonObjectRef &tu); - - void ReadElfFunctions(const JsonObjectRef &tu); - - void ReadElfObjects(const JsonObjectRef &tu); - - static void ReadTemplateInfo(const JsonObjectRef &type_decl, - TemplatedArtifactIR *template_ir); - - static void ReadTypeInfo(const JsonObjectRef &type_decl, TypeIR *type_ir); - - static void ReadRecordFields(const JsonObjectRef &record_type, - RecordTypeIR *record_ir); - - static void ReadBaseSpecifiers(const JsonObjectRef &record_type, - RecordTypeIR *record_ir); - - static void ReadVTableLayout(const JsonObjectRef &record_type, - RecordTypeIR *record_ir); - - static void ReadTagTypeInfo(const JsonObjectRef &type_decl, - TagTypeIR *tag_type_ir); - - static void ReadEnumFields(const JsonObjectRef &enum_type, - EnumTypeIR *enum_ir); - - static void ReadFunctionParametersAndReturnType(const JsonObjectRef &function, - CFunctionLikeIR *function_ir); - - static FunctionIR FunctionJsonToIR(const JsonObjectRef &function); - - static FunctionTypeIR - FunctionTypeJsonToIR(const JsonObjectRef &function_type); - - static RecordTypeIR RecordTypeJsonToIR(const JsonObjectRef &record_type); - - static EnumTypeIR EnumTypeJsonToIR(const JsonObjectRef &enum_type); -}; - - -} // namespace repr -} // namespace header_checker - - -#endif // IR_REPRESENTATION_JSON_H_ diff --git a/vndk/tools/header-checker/src/repr/protobuf/abi_diff.h b/vndk/tools/header-checker/src/repr/protobuf/abi_diff.h new file mode 100644 index 000000000..d697e7557 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/abi_diff.h @@ -0,0 +1,26 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_PROTOBUF_ABI_DIFF_H_ +#define HEADER_CHECKER_REPR_PROTOBUF_ABI_DIFF_H_ + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#pragma clang diagnostic ignored "-Wnested-anon-types" +#include "abi_diff.pb.h" +#pragma clang diagnostic pop + + +#endif // HEADER_CHECKER_REPR_PROTOBUF_ABI_DIFF_H_ diff --git a/vndk/tools/header-checker/src/repr/protobuf/abi_dump.h b/vndk/tools/header-checker/src/repr/protobuf/abi_dump.h new file mode 100644 index 000000000..52d0904c2 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/abi_dump.h @@ -0,0 +1,26 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_PROTOBUF_ABI_DUMP_H_ +#define HEADER_CHECKER_REPR_PROTOBUF_ABI_DUMP_H_ + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#pragma clang diagnostic ignored "-Wnested-anon-types" +#include "abi_dump.pb.h" +#pragma clang diagnostic pop + + +#endif // HEADER_CHECKER_REPR_PROTOBUF_ABI_DUMP_H_ diff --git a/vndk/tools/header-checker/src/repr/protobuf/converter.cpp b/vndk/tools/header-checker/src/repr/protobuf/converter.cpp new file mode 100644 index 000000000..0ec9ab729 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/converter.cpp @@ -0,0 +1,289 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/protobuf/converter.h" + +#include + +#include +#include +#include +#include + + +namespace header_checker { +namespace repr { + + +bool IRDiffToProtobufConverter::AddTypeInfoDiff( + abi_diff::TypeInfoDiff *type_info_diff_protobuf, + const TypeDiffIR *type_diff_ir) { + abi_diff::TypeInfo *old_type_info_protobuf = + type_info_diff_protobuf->mutable_old_type_info(); + abi_diff::TypeInfo *new_type_info_protobuf = + type_info_diff_protobuf->mutable_new_type_info(); + if (old_type_info_protobuf == nullptr || new_type_info_protobuf == nullptr) { + return false; + } + const std::pair &sizes = type_diff_ir->GetSizes(); + const std::pair &alignments = + type_diff_ir->GetAlignments(); + old_type_info_protobuf->set_size(sizes.first); + new_type_info_protobuf->set_size(sizes.second); + + old_type_info_protobuf->set_alignment(alignments.first); + new_type_info_protobuf->set_alignment(alignments.second); + return true; +} + +bool IRDiffToProtobufConverter::AddVTableLayoutDiff( + abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf, + const VTableLayoutDiffIR *vtable_layout_diff_ir) { + abi_dump:: VTableLayout *old_vtable = + vtable_layout_diff_protobuf->mutable_old_vtable(); + abi_dump:: VTableLayout *new_vtable = + vtable_layout_diff_protobuf->mutable_new_vtable(); + if (old_vtable == nullptr || new_vtable == nullptr || + !SetIRToProtobufVTableLayout(old_vtable, + vtable_layout_diff_ir->GetOldVTable()) || + !SetIRToProtobufVTableLayout(new_vtable, + vtable_layout_diff_ir->GetNewVTable())) { + return false; + } + return true; +} + +template +static bool CopyBaseSpecifiersDiffIRToProtobuf( + google::protobuf::RepeatedPtrField *dst, + const std::vector &bases_ir) { + for (auto &&base_ir : bases_ir) { + T *added_base = dst->Add(); + if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) { + return false; + } + } + return true; +} + +bool IRDiffToProtobufConverter::AddBaseSpecifierDiffs( + abi_diff::CXXBaseSpecifierDiff *base_specifiers_diff_protobuf, + const CXXBaseSpecifierDiffIR *base_specifiers_diff_ir) { + if (!CopyBaseSpecifiersDiffIRToProtobuf( + base_specifiers_diff_protobuf->mutable_old_bases(), + base_specifiers_diff_ir->GetOldBases()) || + !CopyBaseSpecifiersDiffIRToProtobuf( + base_specifiers_diff_protobuf->mutable_new_bases(), + base_specifiers_diff_ir->GetNewBases())) { + return false; + } + return true; +} + +bool IRDiffToProtobufConverter::AddRecordFields( + abi_diff::RecordTypeDiff *record_diff_protobuf, + const std::vector &record_fields_ir, + bool field_removed) { + for (auto &&record_field_ir : record_fields_ir) { + abi_dump::RecordFieldDecl *field = nullptr; + if (field_removed) { + field = record_diff_protobuf->add_fields_removed(); + } else { + field = record_diff_protobuf->add_fields_added(); + } + if (field == nullptr) { + return false; + } + SetIRToProtobufRecordField(field, record_field_ir); + } + return true; +} + +bool IRDiffToProtobufConverter::AddRecordFieldDiffs( + abi_diff::RecordTypeDiff *record_diff_protobuf, + const std::vector &record_field_diffs_ir) { + for (auto &&record_field_diff_ir : record_field_diffs_ir) { + abi_diff::RecordFieldDeclDiff *record_field_diff = + record_diff_protobuf->add_fields_diff(); + if (record_field_diff == nullptr) { + return false; + } + abi_dump::RecordFieldDecl *old_field = + record_field_diff->mutable_old_field(); + abi_dump::RecordFieldDecl *new_field = + record_field_diff->mutable_new_field(); + if (old_field == nullptr || new_field == nullptr) { + return false; + } + SetIRToProtobufRecordField(old_field, + record_field_diff_ir.GetOldField()); + SetIRToProtobufRecordField(new_field, + record_field_diff_ir.GetNewField()); + } + return true; +} + +abi_diff::RecordTypeDiff IRDiffToProtobufConverter::ConvertRecordTypeDiffIR( + const RecordTypeDiffIR *record_type_diff_ir) { + abi_diff::RecordTypeDiff record_type_diff_protobuf; + record_type_diff_protobuf.set_name(record_type_diff_ir->GetName()); + const TypeDiffIR *type_diff_ir = record_type_diff_ir->GetTypeDiff(); + // If a type_info diff exists + if (type_diff_ir != nullptr) { + abi_diff::TypeInfoDiff *type_info_diff = + record_type_diff_protobuf.mutable_type_info_diff(); + if (!AddTypeInfoDiff(type_info_diff, type_diff_ir)) { + llvm::errs() << "RecordType could not be converted\n"; + ::exit(1); + } + } + // If vtables differ. + const VTableLayoutDiffIR *vtable_layout_diff_ir = + record_type_diff_ir->GetVTableLayoutDiff(); + if (vtable_layout_diff_ir != nullptr) { + abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf = + record_type_diff_protobuf.mutable_vtable_layout_diff(); + if (!AddVTableLayoutDiff(vtable_layout_diff_protobuf, + vtable_layout_diff_ir)) { + llvm::errs() << "VTable layout diff could not be added\n"; + ::exit(1); + } + } + // If base specifiers differ. + const CXXBaseSpecifierDiffIR *base_specifier_diff_ir = + record_type_diff_ir->GetBaseSpecifiers(); + if (base_specifier_diff_ir != nullptr) { + abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf = + record_type_diff_protobuf.mutable_bases_diff(); + if (!AddBaseSpecifierDiffs(base_specifier_diff_protobuf, + base_specifier_diff_ir)) { + llvm::errs() << "Base Specifier diff could not be added\n"; + ::exit(1); + } + } + // Field diffs + if (!AddRecordFields(&record_type_diff_protobuf, + record_type_diff_ir->GetFieldsRemoved(), true) || + !AddRecordFields(&record_type_diff_protobuf, + record_type_diff_ir->GetFieldsAdded(), false) || + !AddRecordFieldDiffs(&record_type_diff_protobuf, + record_type_diff_ir->GetFieldDiffs())) { + llvm::errs() << "Record Field diff could not be added\n"; + ::exit(1); + } + return record_type_diff_protobuf; +} + +bool IRDiffToProtobufConverter::AddEnumUnderlyingTypeDiff( + abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf, + const std::pair *underlying_type_diff_ir) { + if (underlying_type_diff_protobuf == nullptr) { + return false; + } + underlying_type_diff_protobuf->set_old_type(underlying_type_diff_ir->first); + underlying_type_diff_protobuf->set_new_type(underlying_type_diff_ir->second); + return true; +} + +static bool AddEnumFields( + google::protobuf::RepeatedPtrField *dst, + const std::vector &enum_fields) { + for (auto &&enum_field : enum_fields) { + abi_dump::EnumFieldDecl *added_enum_field = dst->Add(); + if (!SetIRToProtobufEnumField(added_enum_field, enum_field)) { + return false; + } + } + return true; +} + +static bool AddEnumFieldDiffs( + google::protobuf::RepeatedPtrField *dst, + const std::vector &fields_diff_ir) { + for (auto &&field_diff_ir : fields_diff_ir) { + abi_diff::EnumFieldDeclDiff *field_diff_protobuf = dst->Add(); + if (field_diff_protobuf == nullptr) { + return false; + } + if (!SetIRToProtobufEnumField(field_diff_protobuf->mutable_old_field(), + field_diff_ir.GetOldField()) || + !SetIRToProtobufEnumField(field_diff_protobuf->mutable_new_field(), + field_diff_ir.GetNewField())) { + return false; + } + } + return true; +} + +abi_diff::EnumTypeDiff IRDiffToProtobufConverter::ConvertEnumTypeDiffIR( + const EnumTypeDiffIR *enum_type_diff_ir) { + abi_diff::EnumTypeDiff enum_type_diff_protobuf; + enum_type_diff_protobuf.set_name(enum_type_diff_ir->GetName()); + const std::pair *underlying_type_diff = + enum_type_diff_ir->GetUnderlyingTypeDiff(); + if ((underlying_type_diff != nullptr && + !AddEnumUnderlyingTypeDiff( + enum_type_diff_protobuf.mutable_underlying_type_diff(), + underlying_type_diff)) || + !AddEnumFields(enum_type_diff_protobuf.mutable_fields_removed(), + enum_type_diff_ir->GetFieldsRemoved()) || + !AddEnumFields(enum_type_diff_protobuf.mutable_fields_added(), + enum_type_diff_ir->GetFieldsAdded()) || + !AddEnumFieldDiffs(enum_type_diff_protobuf.mutable_fields_diff(), + enum_type_diff_ir->GetFieldsDiff())) { + llvm::errs() << "Enum field diff could not be added\n"; + ::exit(1); + } + return enum_type_diff_protobuf; +} + +abi_diff::GlobalVarDeclDiff IRDiffToProtobufConverter::ConvertGlobalVarDiffIR( + const GlobalVarDiffIR *global_var_diff_ir) { + abi_diff::GlobalVarDeclDiff global_var_diff; + global_var_diff.set_name(global_var_diff_ir->GetName()); + abi_dump::GlobalVarDecl *old_global_var = global_var_diff.mutable_old(); + abi_dump::GlobalVarDecl *new_global_var = global_var_diff.mutable_new_(); + if (old_global_var == nullptr || new_global_var == nullptr) { + llvm::errs() << "Globar Var diff could not be added\n"; + ::exit(1); + } + *old_global_var = + IRToProtobufConverter::ConvertGlobalVarIR( + global_var_diff_ir->GetOldGlobalVar()); + *new_global_var = + IRToProtobufConverter::ConvertGlobalVarIR( + global_var_diff_ir->GetNewGlobalVar()); + return global_var_diff; +} + +abi_diff::FunctionDeclDiff IRDiffToProtobufConverter::ConvertFunctionDiffIR( + const FunctionDiffIR *function_diff_ir) { + abi_diff::FunctionDeclDiff function_diff; + function_diff.set_name(function_diff_ir->GetName()); + abi_dump::FunctionDecl *old_function = function_diff.mutable_old(); + abi_dump::FunctionDecl *new_function = function_diff.mutable_new_(); + if (old_function == nullptr || new_function == nullptr) { + llvm::errs() << "Function diff could not be added\n"; + ::exit(1); + } + *old_function = IRToProtobufConverter::ConvertFunctionIR( + function_diff_ir->GetOldFunction()); + *new_function = IRToProtobufConverter::ConvertFunctionIR( + function_diff_ir->GetNewFunction()); + return function_diff; +} + + +} // namespace repr +} // namespace header_checker diff --git a/vndk/tools/header-checker/src/repr/protobuf/converter.h b/vndk/tools/header-checker/src/repr/protobuf/converter.h new file mode 100644 index 000000000..8f4829a76 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/converter.h @@ -0,0 +1,371 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_PROTOBUF_CONVERTER_H_ +#define HEADER_CHECKER_PROTOBUF_CONVERTER_H_ + +#include "repr/ir_diff_representation.h" +#include "repr/ir_representation.h" +#include "repr/protobuf/abi_diff.h" +#include "repr/protobuf/abi_dump.h" + +#include + + +namespace header_checker { +namespace repr { + + +inline abi_diff::CompatibilityStatus CompatibilityStatusIRToProtobuf( + CompatibilityStatusIR status) { + switch (status) { + case CompatibilityStatusIR::Incompatible: + return abi_diff::CompatibilityStatus::INCOMPATIBLE; + case CompatibilityStatusIR::Extension: + return abi_diff::CompatibilityStatus::EXTENSION; + default: + break; + } + return abi_diff::CompatibilityStatus::COMPATIBLE; +} + +inline abi_dump::ElfSymbolBinding ElfSymbolBindingIRToProtobuf( + ElfSymbolIR::ElfSymbolBinding binding) { + switch (binding) { + case ElfSymbolIR::ElfSymbolBinding::Global: + return abi_dump::ElfSymbolBinding::Global; + case ElfSymbolIR::ElfSymbolBinding::Weak: + return abi_dump::ElfSymbolBinding::Weak; + } + // We skip symbols of all other Bindings + // TODO: Add all bindings, don't leave out info + assert(0); +} + +inline ElfSymbolIR::ElfSymbolBinding ElfSymbolBindingProtobufToIR( + abi_dump::ElfSymbolBinding binding) { + switch (binding) { + case abi_dump::ElfSymbolBinding::Global: + return ElfSymbolIR::ElfSymbolBinding::Global; + case abi_dump::ElfSymbolBinding::Weak: + return ElfSymbolIR::ElfSymbolBinding::Weak; + } + // We skip symbols of all other Bindings + assert(0); +} + +inline abi_dump::AccessSpecifier AccessIRToProtobuf(AccessSpecifierIR access) { + switch (access) { + case AccessSpecifierIR::ProtectedAccess: + return abi_dump::AccessSpecifier::protected_access; + case AccessSpecifierIR::PrivateAccess: + return abi_dump::AccessSpecifier::private_access; + default: + return abi_dump::AccessSpecifier::public_access; + } + return abi_dump::AccessSpecifier::public_access; +} + +inline AccessSpecifierIR AccessProtobufToIR( + abi_dump::AccessSpecifier access) { + switch (access) { + case abi_dump::AccessSpecifier::protected_access: + return AccessSpecifierIR::ProtectedAccess; + case abi_dump::AccessSpecifier::private_access: + return AccessSpecifierIR::PrivateAccess; + default: + return AccessSpecifierIR::PublicAccess; + } + return AccessSpecifierIR::PublicAccess; +} + +inline abi_dump::RecordKind RecordKindIRToProtobuf( + RecordTypeIR::RecordKind kind) { + switch (kind) { + case RecordTypeIR::RecordKind::struct_kind: + return abi_dump::RecordKind::struct_kind; + + case RecordTypeIR::RecordKind::class_kind: + return abi_dump::RecordKind::class_kind; + + case RecordTypeIR::RecordKind::union_kind: + return abi_dump::RecordKind::union_kind; + + default: + return abi_dump::RecordKind::struct_kind; + } + // Should not be reached + assert(false); +} + +inline RecordTypeIR::RecordKind RecordKindProtobufToIR( + abi_dump::RecordKind kind) { + switch (kind) { + case abi_dump::RecordKind::struct_kind: + return RecordTypeIR::struct_kind; + + case abi_dump::RecordKind::class_kind: + return RecordTypeIR::class_kind; + + case abi_dump::RecordKind::union_kind: + return RecordTypeIR::union_kind; + + default: + return RecordTypeIR::struct_kind; + } + // Should not be reached + assert(false); +} + +inline abi_dump::VTableComponent::Kind VTableComponentKindIRToProtobuf( + VTableComponentIR::Kind kind) { + switch (kind) { + case VTableComponentIR::Kind::VCallOffset: + return abi_dump::VTableComponent_Kind_VCallOffset; + + case VTableComponentIR::Kind::VBaseOffset: + return abi_dump::VTableComponent_Kind_VBaseOffset; + + case VTableComponentIR::Kind::OffsetToTop: + return abi_dump::VTableComponent_Kind_OffsetToTop; + + case VTableComponentIR::Kind::RTTI: + return abi_dump::VTableComponent_Kind_RTTI; + + case VTableComponentIR::Kind::FunctionPointer: + return abi_dump::VTableComponent_Kind_FunctionPointer; + + case VTableComponentIR::Kind::CompleteDtorPointer: + return abi_dump::VTableComponent_Kind_CompleteDtorPointer; + + case VTableComponentIR::Kind::DeletingDtorPointer: + return abi_dump::VTableComponent_Kind_DeletingDtorPointer; + + default: + return abi_dump::VTableComponent_Kind_UnusedFunctionPointer; + } + // Should not be reached + assert(false); +} + +inline VTableComponentIR::Kind VTableComponentKindProtobufToIR( + abi_dump::VTableComponent_Kind kind) { + switch (kind) { + case abi_dump::VTableComponent_Kind_VCallOffset: + return VTableComponentIR::Kind::VCallOffset; + + case abi_dump::VTableComponent_Kind_VBaseOffset: + return VTableComponentIR::Kind::VBaseOffset; + + case abi_dump::VTableComponent_Kind_OffsetToTop: + return VTableComponentIR::Kind::OffsetToTop; + + case abi_dump::VTableComponent_Kind_RTTI: + return VTableComponentIR::Kind::RTTI; + + case abi_dump::VTableComponent_Kind_FunctionPointer: + return VTableComponentIR::Kind::FunctionPointer; + + case abi_dump::VTableComponent_Kind_CompleteDtorPointer: + return VTableComponentIR::Kind::CompleteDtorPointer; + + case abi_dump::VTableComponent_Kind_DeletingDtorPointer: + return VTableComponentIR::Kind::DeletingDtorPointer; + + default: + return VTableComponentIR::Kind::UnusedFunctionPointer; + } + // Should not be reached + assert(false); +} + +class IRToProtobufConverter { + private: + static bool AddTemplateInformation( + abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta); + + static bool AddTypeInfo( + abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep); + + static bool AddRecordFields( + abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir); + + static bool AddBaseSpecifiers( + abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir); + + static bool AddVTableLayout( + abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir); + + static bool AddTagTypeInfo(abi_dump::TagType *tag_type_protobuf, + const TagTypeIR *tag_type_ir); + + static bool AddEnumFields(abi_dump::EnumType *enum_protobuf, + const EnumTypeIR *enum_ir); + + public: + static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump); + + static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp); + + static abi_dump::FunctionType ConvertFunctionTypeIR ( + const FunctionTypeIR *function_typep); + + template + static bool AddFunctionParametersAndSetReturnType( + CFunctionLikeMessage *function_like_protobuf, + const CFunctionLikeIR *cfunction_like_ir); + + template + static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf, + const CFunctionLikeIR *cfunction_like_ir); + + static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp); + + static abi_dump::GlobalVarDecl ConvertGlobalVarIR( + const GlobalVarIR *global_varp); + + static abi_dump::PointerType ConvertPointerTypeIR( + const PointerTypeIR *pointerp); + + static abi_dump::QualifiedType ConvertQualifiedTypeIR( + const QualifiedTypeIR *qualtypep); + + static abi_dump::BuiltinType ConvertBuiltinTypeIR( + const BuiltinTypeIR *builtin_typep); + + static abi_dump::ArrayType ConvertArrayTypeIR( + const ArrayTypeIR *array_typep); + + static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR( + const LvalueReferenceTypeIR *lvalue_reference_typep); + + static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR( + const RvalueReferenceTypeIR *rvalue_reference_typep); + + static abi_dump::ElfFunction ConvertElfFunctionIR( + const ElfFunctionIR *elf_function_ir); + + static abi_dump::ElfObject ConvertElfObjectIR( + const ElfObjectIR *elf_object_ir); +}; + +class IRDiffToProtobufConverter { + private: + static bool AddTypeInfoDiff( + abi_diff::TypeInfoDiff *type_info_diff_protobuf, + const TypeDiffIR *type_diff_ir); + + static bool AddVTableLayoutDiff( + abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf, + const VTableLayoutDiffIR *vtable_layout_diff_ir); + + static bool AddBaseSpecifierDiffs( + abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf, + const CXXBaseSpecifierDiffIR *base_specifier_diff_ir); + + static bool AddRecordFields( + abi_diff::RecordTypeDiff *record_diff_protobuf, + const std::vector &record_fields_removed_ir, + bool removed); + + static bool AddRecordFieldDiffs( + abi_diff::RecordTypeDiff *record_diff_protobuf, + const std::vector &record_field_diff_ir); + + static bool AddEnumUnderlyingTypeDiff( + abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf, + const std::pair *underlying_type_diff_ir); + + public: + static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR( + const RecordTypeDiffIR *record_type_diffp); + + static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR( + const EnumTypeDiffIR *enum_type_diffp); + + static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR( + const FunctionDiffIR *function_diffp); + + static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR( + const GlobalVarDiffIR *global_var_diffp); +}; + +inline void SetIRToProtobufRecordField( + abi_dump::RecordFieldDecl *record_field_protobuf, + const RecordFieldIR *record_field_ir) { + record_field_protobuf->set_field_name(record_field_ir->GetName()); + record_field_protobuf->set_referenced_type( + record_field_ir->GetReferencedType()); + record_field_protobuf->set_access( + AccessIRToProtobuf(record_field_ir->GetAccess())); + record_field_protobuf->set_field_offset(record_field_ir->GetOffset()); +} + +inline bool SetIRToProtobufBaseSpecifier( + abi_dump::CXXBaseSpecifier *base_specifier_protobuf, + const CXXBaseSpecifierIR &base_specifier_ir) { + if (!base_specifier_protobuf) { + llvm::errs() << "Protobuf base specifier not valid\n"; + return false; + } + base_specifier_protobuf->set_referenced_type( + base_specifier_ir.GetReferencedType()); + base_specifier_protobuf->set_is_virtual( + base_specifier_ir.IsVirtual()); + base_specifier_protobuf->set_access( + AccessIRToProtobuf(base_specifier_ir.GetAccess())); + return true; +} + +inline bool SetIRToProtobufVTableLayout( + abi_dump::VTableLayout *vtable_layout_protobuf, + const VTableLayoutIR &vtable_layout_ir) { + if (vtable_layout_protobuf == nullptr) { + llvm::errs() << "vtable layout protobuf not valid\n"; + return false; + } + for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) { + abi_dump::VTableComponent *added_vtable_component = + vtable_layout_protobuf->add_vtable_components(); + if (!added_vtable_component) { + llvm::errs() << "Couldn't add vtable component\n"; + return false; + } + added_vtable_component->set_kind( + VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind())); + added_vtable_component->set_component_value(vtable_component_ir.GetValue()); + added_vtable_component->set_mangled_component_name( + vtable_component_ir.GetName()); + added_vtable_component->set_is_pure(vtable_component_ir.GetIsPure()); + } + return true; +} + +inline bool SetIRToProtobufEnumField( + abi_dump::EnumFieldDecl *enum_field_protobuf, + const EnumFieldIR *enum_field_ir) { + if (enum_field_protobuf == nullptr) { + return true; + } + enum_field_protobuf->set_name(enum_field_ir->GetName()); + enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue()); + return true; +} + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_PROTOBUF_CONVERTER_H_ diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.cpp b/vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.cpp new file mode 100644 index 000000000..4c4106ae5 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.cpp @@ -0,0 +1,371 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/protobuf/ir_diff_dumper.h" + +#include "repr/ir_diff_representation.h" +#include "repr/protobuf/converter.h" + +#include +#include + +#include + +#include +#include + + +namespace header_checker { +namespace repr { + + +void ProtobufIRDiffDumper::AddLibNameIR(const std::string &name) { + diff_tu_->set_lib_name(name); +} + +void ProtobufIRDiffDumper::AddArchIR(const std::string &arch) { + diff_tu_->set_arch(arch); +} + +CompatibilityStatusIR ProtobufIRDiffDumper::GetCompatibilityStatusIR() { + if (diff_tu_->functions_removed().size() != 0 || + diff_tu_->global_vars_removed().size() != 0 || + diff_tu_->function_diffs().size() != 0 || + diff_tu_->global_var_diffs().size() != 0 || + diff_tu_->enum_type_diffs().size() != 0 || + diff_tu_->record_type_diffs().size() != 0) { + return CompatibilityStatusIR::Incompatible; + } + + CompatibilityStatusIR combined_status = CompatibilityStatusIR::Compatible; + + if (diff_tu_->enum_type_extension_diffs().size() != 0 || + diff_tu_->functions_added().size() != 0 || + diff_tu_->global_vars_added().size() != 0) { + combined_status = combined_status | CompatibilityStatusIR::Extension; + } + + if (diff_tu_->unreferenced_enum_type_diffs().size() != 0 || + diff_tu_->unreferenced_enum_types_removed().size() != 0 || + diff_tu_->unreferenced_record_types_removed().size() != 0 || + diff_tu_->unreferenced_record_type_diffs().size() != 0 || + diff_tu_->unreferenced_enum_type_extension_diffs().size() != 0 || + diff_tu_->unreferenced_record_types_added().size() != 0 || + diff_tu_->unreferenced_enum_types_added().size()) { + combined_status = + combined_status | CompatibilityStatusIR::UnreferencedChanges; + } + + if (diff_tu_->removed_elf_functions().size() != 0 || + diff_tu_->removed_elf_objects().size() != 0) { + combined_status = combined_status | CompatibilityStatusIR::ElfIncompatible; + } + + return combined_status; +} + +void ProtobufIRDiffDumper::AddCompatibilityStatusIR( + CompatibilityStatusIR status) { + diff_tu_->set_compatibility_status(CompatibilityStatusIRToProtobuf(status)); +} + +bool ProtobufIRDiffDumper::AddDiffMessageIR(const DiffMessageIR *message, + const std::string &type_stack, + DiffKind diff_kind) { + switch (message->Kind()) { + case RecordTypeKind: + return AddRecordTypeDiffIR( + static_cast(message), type_stack, + diff_kind); + case EnumTypeKind: + return AddEnumTypeDiffIR( + static_cast(message), type_stack, diff_kind); + case GlobalVarKind: + return AddGlobalVarDiffIR( + static_cast(message), type_stack, diff_kind); + case FunctionKind: + return AddFunctionDiffIR( + static_cast(message), type_stack, diff_kind); + default: + break; + } + llvm::errs() << "Dump Diff attempted on something not a user defined type / " + << "function / global variable\n"; + return false; +} + +bool ProtobufIRDiffDumper::AddLinkableMessageIR( + const LinkableMessageIR *message, DiffKind diff_kind) { + switch (message->GetKind()) { + case RecordTypeKind: + return AddLoneRecordTypeDiffIR( + static_cast(message), diff_kind); + case EnumTypeKind: + return AddLoneEnumTypeDiffIR( + static_cast(message), diff_kind); + case GlobalVarKind: + return AddLoneGlobalVarDiffIR( + static_cast(message), diff_kind); + case FunctionKind: + return AddLoneFunctionDiffIR( + static_cast(message), diff_kind); + default: + break; + } + llvm::errs() << "Dump Diff attempted on something not a user defined type / " + << "function / global variable\n"; + return false; +} + +bool ProtobufIRDiffDumper::AddElfSymbolMessageIR(const ElfSymbolIR *elf_symbol, + DiffKind diff_kind) { + switch (elf_symbol->GetKind()) { + case ElfSymbolIR::ElfFunctionKind: + return AddElfFunctionIR(static_cast(elf_symbol), + diff_kind); + break; + case ElfSymbolIR::ElfObjectKind: + return AddElfObjectIR(static_cast(elf_symbol), + diff_kind); + break; + } + // Any other kind is invalid + return false; +} + +bool ProtobufIRDiffDumper::AddElfFunctionIR( + const ElfFunctionIR *elf_function_ir, DiffKind diff_kind) { + abi_dump::ElfFunction *added_elf_function = nullptr; + switch (diff_kind) { + case DiffKind::Removed: + added_elf_function = diff_tu_->add_removed_elf_functions(); + break; + case DiffKind::Added: + added_elf_function = diff_tu_->add_added_elf_functions(); + break; + default: + llvm::errs() << "Invalid call to AddElfFunctionIR\n"; + return false; + } + if (added_elf_function == nullptr) { + return false; + } + *added_elf_function = + IRToProtobufConverter::ConvertElfFunctionIR(elf_function_ir); + return true; +} + +bool ProtobufIRDiffDumper::AddElfObjectIR( + const ElfObjectIR *elf_object_ir, DiffKind diff_kind) { + abi_dump::ElfObject *added_elf_object = nullptr; + switch (diff_kind) { + case DiffKind::Removed: + added_elf_object = diff_tu_->add_removed_elf_objects(); + break; + case DiffKind::Added: + added_elf_object = diff_tu_->add_added_elf_objects(); + break; + default: + llvm::errs() << "Invalid call to AddElfObjectIR\n"; + return false; + } + if (added_elf_object == nullptr) { + return false; + } + *added_elf_object = + IRToProtobufConverter::ConvertElfObjectIR(elf_object_ir); + return true; +} + +bool ProtobufIRDiffDumper::AddLoneRecordTypeDiffIR( + const RecordTypeIR *record_type_ir, DiffKind diff_kind) { + abi_dump::RecordType *added_record_type = nullptr; + switch (diff_kind) { + case DiffKind::Removed: + // Referenced record types do not get reported as added / removed, + // the diff shows up in the parent type / function/ global variable + // referencing the record. + added_record_type = diff_tu_->add_unreferenced_record_types_removed(); + break; + case DiffKind::Added: + added_record_type = diff_tu_->add_unreferenced_record_types_added(); + break; + default: + llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n"; + return false; + } + if (added_record_type == nullptr) { + return false; + } + *added_record_type = + IRToProtobufConverter::ConvertRecordTypeIR(record_type_ir); + return true; +} + +bool ProtobufIRDiffDumper::AddLoneFunctionDiffIR( + const FunctionIR *function_ir, DiffKind diff_kind) { + abi_dump::FunctionDecl *added_function = nullptr; + switch (diff_kind) { + case DiffKind::Removed: + added_function = diff_tu_->add_functions_removed(); + break; + case DiffKind::Added: + added_function = diff_tu_->add_functions_added(); + break; + default: + llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n"; + return false; + } + *added_function = IRToProtobufConverter::ConvertFunctionIR(function_ir); + return true; +} + +bool ProtobufIRDiffDumper::AddLoneEnumTypeDiffIR( + const EnumTypeIR *enum_type_ir, DiffKind diff_kind) { + abi_dump::EnumType *added_enum_type = nullptr; + switch (diff_kind) { + case DiffKind::Removed: + // Referenced enum types do not get reported as added / removed, + // the diff shows up in the parent type / function/ global variable + // referencing the enum. + added_enum_type = diff_tu_->add_unreferenced_enum_types_removed(); + break; + case DiffKind::Added: + added_enum_type = diff_tu_->add_unreferenced_enum_types_added(); + break; + default: + llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n"; + return false; + } + if (added_enum_type == nullptr) { + return false; + } + *added_enum_type = IRToProtobufConverter::ConvertEnumTypeIR(enum_type_ir); + return true; +} + +bool ProtobufIRDiffDumper::AddLoneGlobalVarDiffIR( + const GlobalVarIR *global_var_ir, DiffKind diff_kind) { + abi_dump::GlobalVarDecl *added_global_var = nullptr; + switch (diff_kind) { + case DiffKind::Removed: + added_global_var = diff_tu_->add_global_vars_removed(); + break; + case DiffKind::Added: + added_global_var = diff_tu_->add_global_vars_added(); + break; + default: + llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n"; + return false; + } + *added_global_var = IRToProtobufConverter::ConvertGlobalVarIR(global_var_ir); + return true; +} + +bool ProtobufIRDiffDumper::AddRecordTypeDiffIR( + const RecordTypeDiffIR *record_diff_ir, const std::string &type_stack, + DiffKind diff_kind) { + abi_diff::RecordTypeDiff *added_record_type_diff = nullptr; + switch (diff_kind) { + case DiffKind::Unreferenced: + added_record_type_diff = diff_tu_->add_unreferenced_record_type_diffs(); + break; + case DiffKind::Referenced: + added_record_type_diff = diff_tu_->add_record_type_diffs(); + break; + default: + break; + } + if (!added_record_type_diff) { + return false; + } + + *added_record_type_diff = + IRDiffToProtobufConverter::ConvertRecordTypeDiffIR(record_diff_ir); + added_record_type_diff->set_type_stack(type_stack); + return true; +} + +bool ProtobufIRDiffDumper::AddFunctionDiffIR( + const FunctionDiffIR *function_diff_ir, const std::string &type_stack, + DiffKind diff_kind) { + abi_diff::FunctionDeclDiff *added_function_diff = + diff_tu_->add_function_diffs(); + if (!added_function_diff) { + return false; + } + *added_function_diff = + IRDiffToProtobufConverter::ConvertFunctionDiffIR(function_diff_ir); + return true; +} + +bool ProtobufIRDiffDumper::AddEnumTypeDiffIR(const EnumTypeDiffIR *enum_diff_ir, + const std::string &type_stack, + DiffKind diff_kind) { + abi_diff::EnumTypeDiff *added_enum_type_diff = nullptr; + switch (diff_kind) { + case DiffKind::Unreferenced: + if (enum_diff_ir->IsExtended()) { + added_enum_type_diff = + diff_tu_->add_unreferenced_enum_type_extension_diffs(); + } else { + added_enum_type_diff = + diff_tu_->add_unreferenced_enum_type_diffs(); + } + break; + case DiffKind::Referenced: + if (enum_diff_ir->IsExtended()) { + added_enum_type_diff = + diff_tu_->add_enum_type_extension_diffs(); + } else { + added_enum_type_diff = + diff_tu_->add_enum_type_diffs(); + } + break; + default: + break; + } + if (!added_enum_type_diff) { + return false; + } + *added_enum_type_diff = + IRDiffToProtobufConverter::ConvertEnumTypeDiffIR(enum_diff_ir); + added_enum_type_diff->set_type_stack(type_stack); + return true; +} + +bool ProtobufIRDiffDumper::AddGlobalVarDiffIR( + const GlobalVarDiffIR *global_var_diff_ir, const std::string &type_stack, + DiffKind diff_kind) { + abi_diff::GlobalVarDeclDiff *added_global_var_diff = + diff_tu_->add_global_var_diffs(); + if (!added_global_var_diff) { + return false; + } + *added_global_var_diff = + IRDiffToProtobufConverter::ConvertGlobalVarDiffIR(global_var_diff_ir); + return true; +} + +bool ProtobufIRDiffDumper::Dump() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + assert(diff_tu_.get() != nullptr); + std::ofstream text_output(dump_path_); + google::protobuf::io::OstreamOutputStream text_os(&text_output); + return google::protobuf::TextFormat::Print(*diff_tu_.get(), &text_os); +} + + +} // namespace repr +} // namespace header_checker diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.h b/vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.h new file mode 100644 index 000000000..c36bcab65 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.h @@ -0,0 +1,95 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_PROTOBUF_IR_DIFF_DUMPER_H_ +#define HEADER_CHECKER_REPR_PROTOBUF_IR_DIFF_DUMPER_H_ + +#include "repr/ir_diff_dumper.h" +#include "repr/ir_diff_representation.h" +#include "repr/ir_representation.h" +#include "repr/protobuf/abi_diff.h" + +#include + + +namespace header_checker { +namespace repr { + + +class ProtobufIRDiffDumper : public IRDiffDumper { + public: + ProtobufIRDiffDumper(const std::string &dump_path) + : IRDiffDumper(dump_path), + diff_tu_(new abi_diff::TranslationUnitDiff()) {} + + ~ProtobufIRDiffDumper() override {} + + bool AddDiffMessageIR(const DiffMessageIR *, const std::string &type_stack, + DiffKind diff_kind) override; + + bool AddLinkableMessageIR(const LinkableMessageIR *, + DiffKind diff_kind) override; + + bool AddElfSymbolMessageIR(const ElfSymbolIR *, DiffKind diff_kind) override; + + void AddLibNameIR(const std::string &name) override; + + void AddArchIR(const std::string &arch) override; + + void AddCompatibilityStatusIR(CompatibilityStatusIR status) override; + + bool Dump() override; + + CompatibilityStatusIR GetCompatibilityStatusIR() override; + + + private: + bool AddRecordTypeDiffIR(const RecordTypeDiffIR *, + const std::string &type_stack, DiffKind diff_kind); + + bool AddEnumTypeDiffIR(const EnumTypeDiffIR *, + const std::string &type_stack, DiffKind diff_kind); + + bool AddFunctionDiffIR(const FunctionDiffIR *, + const std::string &type_stack, DiffKind diff_kind); + + bool AddGlobalVarDiffIR(const GlobalVarDiffIR *, + const std::string &type_stack, DiffKind diff_kind); + + + bool AddLoneRecordTypeDiffIR(const RecordTypeIR *, DiffKind diff_kind); + + bool AddLoneEnumTypeDiffIR(const EnumTypeIR *, DiffKind diff_kind); + + bool AddLoneFunctionDiffIR(const FunctionIR *, DiffKind diff_kind); + + bool AddLoneGlobalVarDiffIR(const GlobalVarIR *, DiffKind diff_kind); + + + bool AddElfObjectIR(const ElfObjectIR *elf_object_ir, DiffKind diff_kind); + + bool AddElfFunctionIR(const ElfFunctionIR *elf_function_ir, + DiffKind diff_kind); + + + protected: + std::unique_ptr diff_tu_; +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_PROTOBUF_PROTOBUF_IR_DIFF_DUMPER_H_ diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_dumper.cpp b/vndk/tools/header-checker/src/repr/protobuf/ir_dumper.cpp new file mode 100644 index 000000000..5c7931f93 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/ir_dumper.cpp @@ -0,0 +1,494 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/protobuf/ir_dumper.h" + +#include "repr/protobuf/abi_dump.h" + +#include + +#include + +#include +#include + + +namespace header_checker { +namespace repr { + + +bool IRToProtobufConverter::AddTemplateInformation( + abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta) { + for (auto &&template_element : ta->GetTemplateElements()) { + abi_dump::TemplateElement *added_element = ti->add_elements(); + if (!added_element) { + llvm::errs() << "Failed to add template element\n"; + return false; + } + added_element->set_referenced_type(template_element.GetReferencedType()); + } + return true; +} + +bool IRToProtobufConverter::AddTypeInfo( + abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep) { + if (!type_info || !typep) { + llvm::errs() << "Typeinfo not valid\n"; + return false; + } + type_info->set_linker_set_key(typep->GetLinkerSetKey()); + type_info->set_source_file(typep->GetSourceFile()); + type_info->set_name(typep->GetName()); + type_info->set_size(typep->GetSize()); + type_info->set_alignment(typep->GetAlignment()); + type_info->set_referenced_type(typep->GetReferencedType()); + type_info->set_self_type(typep->GetSelfType()); + return true; +} + +bool IRToProtobufConverter::AddRecordFields( + abi_dump::RecordType *record_protobuf, + const RecordTypeIR *record_ir) { + // Iterate through the fields and create corresponding ones for the protobuf + // record + for (auto &&field_ir : record_ir->GetFields()) { + abi_dump::RecordFieldDecl *added_field = record_protobuf->add_fields(); + if (!added_field) { + llvm::errs() << "Couldn't add record field\n"; + } + SetIRToProtobufRecordField(added_field, &field_ir); + } + return true; +} + +bool IRToProtobufConverter::AddBaseSpecifiers( + abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir) { + for (auto &&base_ir : record_ir->GetBases()) { + abi_dump::CXXBaseSpecifier *added_base = + record_protobuf->add_base_specifiers(); + if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) { + return false; + } + } + return true; +} + +bool IRToProtobufConverter::AddVTableLayout( + abi_dump::RecordType *record_protobuf, + const RecordTypeIR *record_ir) { + // If there are no entries in the vtable, just return. + if (record_ir->GetVTableNumEntries() == 0) { + return true; + } + const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout(); + abi_dump::VTableLayout *vtable_layout_protobuf = + record_protobuf->mutable_vtable_layout(); + if (!SetIRToProtobufVTableLayout(vtable_layout_protobuf, vtable_layout_ir)) { + return false; + } + return true; +} + +bool IRToProtobufConverter::AddTagTypeInfo( + abi_dump::TagType *tag_type_protobuf, + const TagTypeIR *tag_type_ir) { + if (!tag_type_protobuf || !tag_type_ir) { + return false; + } + tag_type_protobuf->set_unique_id(tag_type_ir->GetUniqueId()); + return true; +} + +abi_dump::RecordType IRToProtobufConverter::ConvertRecordTypeIR( + const RecordTypeIR *recordp) { + abi_dump::RecordType added_record_type; + added_record_type.set_access(AccessIRToProtobuf(recordp->GetAccess())); + added_record_type.set_record_kind( + RecordKindIRToProtobuf(recordp->GetRecordKind())); + if (recordp->IsAnonymous()) { + added_record_type.set_is_anonymous(true); + } + if (!AddTypeInfo(added_record_type.mutable_type_info(), recordp) || + !AddRecordFields(&added_record_type, recordp) || + !AddBaseSpecifiers(&added_record_type, recordp) || + !AddVTableLayout(&added_record_type, recordp) || + !AddTagTypeInfo(added_record_type.mutable_tag_info(), recordp) || + !(recordp->GetTemplateElements().size() ? + AddTemplateInformation(added_record_type.mutable_template_info(), + recordp) : true)) { + llvm::errs() << "Template information could not be added\n"; + ::exit(1); + } + return added_record_type; +} + + +abi_dump::ElfObject IRToProtobufConverter::ConvertElfObjectIR( + const ElfObjectIR *elf_object_ir) { + abi_dump::ElfObject elf_object_protobuf; + elf_object_protobuf.set_name(elf_object_ir->GetName()); + return elf_object_protobuf; +} + +abi_dump::ElfFunction IRToProtobufConverter::ConvertElfFunctionIR( + const ElfFunctionIR *elf_function_ir) { + abi_dump::ElfFunction elf_function_protobuf; + elf_function_protobuf.set_name(elf_function_ir->GetName()); + return elf_function_protobuf; +} + +template +bool IRToProtobufConverter::AddFunctionParametersAndSetReturnType( + CFunctionLikeMessage *function_like_protobuf, + const CFunctionLikeIR *cfunction_like_ir) { + function_like_protobuf->set_return_type(cfunction_like_ir->GetReturnType()); + return AddFunctionParameters(function_like_protobuf, cfunction_like_ir); +} + +template +bool IRToProtobufConverter::AddFunctionParameters( + CFunctionLikeMessage *function_like_protobuf, + const CFunctionLikeIR *cfunction_like_ir) { + for (auto &¶meter : cfunction_like_ir->GetParameters()) { + abi_dump::ParamDecl *added_parameter = + function_like_protobuf->add_parameters(); + if (!added_parameter) { + return false; + } + added_parameter->set_referenced_type( + parameter.GetReferencedType()); + added_parameter->set_default_arg(parameter.GetIsDefault()); + added_parameter->set_is_this_ptr(parameter.GetIsThisPtr()); + } + return true; +} + +abi_dump::FunctionType IRToProtobufConverter::ConvertFunctionTypeIR ( + const FunctionTypeIR *function_typep) { + abi_dump::FunctionType added_function_type; + if (!AddTypeInfo(added_function_type.mutable_type_info(), function_typep) || + !AddFunctionParametersAndSetReturnType(&added_function_type, + function_typep)) { + llvm::errs() << "Could not convert FunctionTypeIR to protobuf\n"; + ::exit(1); + } + return added_function_type; +} + +abi_dump::FunctionDecl IRToProtobufConverter::ConvertFunctionIR( + const FunctionIR *functionp) { + abi_dump::FunctionDecl added_function; + added_function.set_access(AccessIRToProtobuf(functionp->GetAccess())); + added_function.set_linker_set_key(functionp->GetLinkerSetKey()); + added_function.set_source_file(functionp->GetSourceFile()); + added_function.set_function_name(functionp->GetName()); + if (!AddFunctionParametersAndSetReturnType(&added_function, functionp) || + !(functionp->GetTemplateElements().size() ? + AddTemplateInformation(added_function.mutable_template_info(), functionp) + : true)) { + llvm::errs() << "Template information could not be added\n"; + ::exit(1); + } + return added_function; +} + +bool IRToProtobufConverter::AddEnumFields(abi_dump::EnumType *enum_protobuf, + const EnumTypeIR *enum_ir) { + for (auto &&field : enum_ir->GetFields()) { + abi_dump::EnumFieldDecl *enum_fieldp = enum_protobuf->add_enum_fields(); + if (!SetIRToProtobufEnumField(enum_fieldp, &field)) { + return false; + } + } + return true; +} + + +abi_dump::EnumType IRToProtobufConverter::ConvertEnumTypeIR( + const EnumTypeIR *enump) { + abi_dump::EnumType added_enum_type; + added_enum_type.set_access(AccessIRToProtobuf(enump->GetAccess())); + added_enum_type.set_underlying_type(enump->GetUnderlyingType()); + if (!AddTypeInfo(added_enum_type.mutable_type_info(), enump) || + !AddEnumFields(&added_enum_type, enump) || + !AddTagTypeInfo(added_enum_type.mutable_tag_info(), enump)) { + llvm::errs() << "EnumTypeIR could not be converted\n"; + ::exit(1); + } + return added_enum_type; +} + +abi_dump::GlobalVarDecl IRToProtobufConverter::ConvertGlobalVarIR( + const GlobalVarIR *global_varp) { + abi_dump::GlobalVarDecl added_global_var; + added_global_var.set_referenced_type(global_varp->GetReferencedType()); + added_global_var.set_source_file(global_varp->GetSourceFile()); + added_global_var.set_name(global_varp->GetName()); + added_global_var.set_linker_set_key(global_varp->GetLinkerSetKey()); + added_global_var.set_access( + AccessIRToProtobuf(global_varp->GetAccess())); + return added_global_var; +} + +abi_dump::PointerType IRToProtobufConverter::ConvertPointerTypeIR( + const PointerTypeIR *pointerp) { + abi_dump::PointerType added_pointer_type; + if (!AddTypeInfo(added_pointer_type.mutable_type_info(), pointerp)) { + llvm::errs() << "PointerTypeIR could not be converted\n"; + ::exit(1); + } + return added_pointer_type; +} + +abi_dump::QualifiedType IRToProtobufConverter::ConvertQualifiedTypeIR( + const QualifiedTypeIR *qualtypep) { + abi_dump::QualifiedType added_qualified_type; + if (!AddTypeInfo(added_qualified_type.mutable_type_info(), qualtypep)) { + llvm::errs() << "QualifiedTypeIR could not be converted\n"; + ::exit(1); + } + added_qualified_type.set_is_const(qualtypep->IsConst()); + added_qualified_type.set_is_volatile(qualtypep->IsVolatile()); + added_qualified_type.set_is_restricted(qualtypep->IsRestricted()); + return added_qualified_type; +} + +abi_dump::BuiltinType IRToProtobufConverter::ConvertBuiltinTypeIR( + const BuiltinTypeIR *builtin_typep) { + abi_dump::BuiltinType added_builtin_type; + added_builtin_type.set_is_unsigned(builtin_typep->IsUnsigned()); + added_builtin_type.set_is_integral(builtin_typep->IsIntegralType()); + if (!AddTypeInfo(added_builtin_type.mutable_type_info(), builtin_typep)) { + llvm::errs() << "BuiltinTypeIR could not be converted\n"; + ::exit(1); + } + return added_builtin_type; +} + +abi_dump::ArrayType IRToProtobufConverter::ConvertArrayTypeIR( + const ArrayTypeIR *array_typep) { + abi_dump::ArrayType added_array_type; + if (!AddTypeInfo(added_array_type.mutable_type_info(), array_typep)) { + llvm::errs() << "ArrayTypeIR could not be converted\n"; + ::exit(1); + } + return added_array_type; +} + +abi_dump::LvalueReferenceType +IRToProtobufConverter::ConvertLvalueReferenceTypeIR( + const LvalueReferenceTypeIR *lvalue_reference_typep) { + abi_dump::LvalueReferenceType added_lvalue_reference_type; + if (!AddTypeInfo(added_lvalue_reference_type.mutable_type_info(), + lvalue_reference_typep)) { + llvm::errs() << "LvalueReferenceTypeIR could not be converted\n"; + ::exit(1); + } + return added_lvalue_reference_type; +} + +abi_dump::RvalueReferenceType +IRToProtobufConverter::ConvertRvalueReferenceTypeIR( + const RvalueReferenceTypeIR *rvalue_reference_typep) { + abi_dump::RvalueReferenceType added_rvalue_reference_type; + if (!AddTypeInfo(added_rvalue_reference_type.mutable_type_info(), + rvalue_reference_typep)) { + llvm::errs() << "RvalueReferenceTypeIR could not be converted\n"; + ::exit(1); + } + return added_rvalue_reference_type; +} + +bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) { + // No RTTI + switch (lm->GetKind()) { + case RecordTypeKind: + return AddRecordTypeIR(static_cast(lm)); + case EnumTypeKind: + return AddEnumTypeIR(static_cast(lm)); + case PointerTypeKind: + return AddPointerTypeIR(static_cast(lm)); + case QualifiedTypeKind: + return AddQualifiedTypeIR(static_cast(lm)); + case ArrayTypeKind: + return AddArrayTypeIR(static_cast(lm)); + case LvalueReferenceTypeKind: + return AddLvalueReferenceTypeIR( + static_cast(lm)); + case RvalueReferenceTypeKind: + return AddRvalueReferenceTypeIR( + static_cast(lm)); + case BuiltinTypeKind: + return AddBuiltinTypeIR(static_cast(lm)); + case FunctionTypeKind: + return AddFunctionTypeIR(static_cast(lm)); + case GlobalVarKind: + return AddGlobalVarIR(static_cast(lm)); + case FunctionKind: + return AddFunctionIR(static_cast(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()); + added_elf_function->set_binding( + ElfSymbolBindingIRToProtobuf(elf_function->GetBinding())); + 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()); + added_elf_object->set_binding( + ElfSymbolBindingIRToProtobuf(elf_object->GetBinding())); + return true; +} + +bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) { + switch (em->GetKind()) { + case ElfSymbolIR::ElfFunctionKind: + return AddElfFunctionIR(static_cast(em)); + case ElfSymbolIR::ElfObjectKind: + return AddElfObjectIR(static_cast(em)); + } + return false; +} + +bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) { + abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types(); + if (!added_record_type) { + return false; + } + *added_record_type = ConvertRecordTypeIR(recordp); + return true; +} + +bool ProtobufIRDumper::AddFunctionTypeIR(const FunctionTypeIR *function_typep) { + abi_dump::FunctionType *added_function_type = tu_ptr_->add_function_types(); + if (!added_function_type) { + return false; + } + *added_function_type = ConvertFunctionTypeIR(function_typep); + return true; +} + +bool ProtobufIRDumper::AddFunctionIR(const FunctionIR *functionp) { + abi_dump::FunctionDecl *added_function = tu_ptr_->add_functions(); + if (!added_function) { + return false; + } + *added_function = ConvertFunctionIR(functionp); + return true; +} + +bool ProtobufIRDumper::AddEnumTypeIR(const EnumTypeIR *enump) { + abi_dump::EnumType *added_enum_type = tu_ptr_->add_enum_types(); + if (!added_enum_type) { + return false; + } + *added_enum_type = ConvertEnumTypeIR(enump); + return true; +} + +bool ProtobufIRDumper::AddGlobalVarIR(const GlobalVarIR *global_varp) { + abi_dump::GlobalVarDecl *added_global_var = tu_ptr_->add_global_vars(); + if (!added_global_var) { + return false; + } + *added_global_var = ConvertGlobalVarIR(global_varp); + return true; +} + +bool ProtobufIRDumper::AddPointerTypeIR(const PointerTypeIR *pointerp) { + abi_dump::PointerType *added_pointer_type = tu_ptr_->add_pointer_types(); + if (!added_pointer_type) { + return false; + } + *added_pointer_type = ConvertPointerTypeIR(pointerp); + return true; +} + +bool ProtobufIRDumper::AddQualifiedTypeIR(const QualifiedTypeIR *qualtypep) { + abi_dump::QualifiedType *added_qualified_type = + tu_ptr_->add_qualified_types(); + if (!added_qualified_type) { + return false; + } + *added_qualified_type = ConvertQualifiedTypeIR(qualtypep); + return true; +} + +bool ProtobufIRDumper::AddBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) { + abi_dump::BuiltinType *added_builtin_type = + tu_ptr_->add_builtin_types(); + if (!added_builtin_type) { + return false; + } + *added_builtin_type = ConvertBuiltinTypeIR(builtin_typep); + return true; +} + +bool ProtobufIRDumper::AddArrayTypeIR(const ArrayTypeIR *array_typep) { + abi_dump::ArrayType *added_array_type = + tu_ptr_->add_array_types(); + if (!added_array_type) { + return false; + } + *added_array_type = ConvertArrayTypeIR(array_typep); + return true; +} + +bool ProtobufIRDumper::AddLvalueReferenceTypeIR( + const LvalueReferenceTypeIR *lvalue_reference_typep) { + abi_dump::LvalueReferenceType *added_lvalue_reference_type = + tu_ptr_->add_lvalue_reference_types(); + if (!added_lvalue_reference_type) { + return false; + } + *added_lvalue_reference_type = + ConvertLvalueReferenceTypeIR(lvalue_reference_typep); + return true; +} + +bool ProtobufIRDumper::AddRvalueReferenceTypeIR( + const RvalueReferenceTypeIR *rvalue_reference_typep) { + abi_dump::RvalueReferenceType *added_rvalue_reference_type = + tu_ptr_->add_rvalue_reference_types(); + if (!added_rvalue_reference_type) { + return false; + } + *added_rvalue_reference_type = + ConvertRvalueReferenceTypeIR(rvalue_reference_typep); + return true; +} + +bool ProtobufIRDumper::Dump() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + assert( tu_ptr_.get() != nullptr); + std::ofstream text_output(dump_path_); + google::protobuf::io::OstreamOutputStream text_os(&text_output); + return google::protobuf::TextFormat::Print(*tu_ptr_.get(), &text_os); +} + + +} // namespace repr +} // namespace header_checker diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_dumper.h b/vndk/tools/header-checker/src/repr/protobuf/ir_dumper.h new file mode 100644 index 000000000..72bac7e30 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/ir_dumper.h @@ -0,0 +1,81 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_PROTOBUF_IR_DUMPER_H_ +#define HEADER_CHECKER_REPR_PROTOBUF_IR_DUMPER_H_ + +#include "repr/ir_dumper.h" +#include "repr/protobuf/abi_dump.h" +#include "repr/protobuf/converter.h" +#include "repr/protobuf/ir_dumper.h" + + +namespace header_checker { +namespace repr { + + +class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter { + private: + // Types + bool AddRecordTypeIR(const RecordTypeIR *); + + bool AddEnumTypeIR(const EnumTypeIR *); + + bool AddPointerTypeIR(const PointerTypeIR *); + + bool AddQualifiedTypeIR(const QualifiedTypeIR *); + + bool AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR *); + + bool AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR *); + + bool AddArrayTypeIR(const ArrayTypeIR *); + + bool AddBuiltinTypeIR(const BuiltinTypeIR *); + + bool AddFunctionTypeIR(const FunctionTypeIR *function_typep); + + // Functions and global variables. + bool AddFunctionIR(const FunctionIR *); + + 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()) {} + + ~ProtobufIRDumper() override {} + + bool AddLinkableMessageIR(const LinkableMessageIR *) override; + + bool AddElfSymbolMessageIR(const ElfSymbolIR *) override; + + bool Dump() override; + + + private: + std::unique_ptr tu_ptr_; +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_PROTOBUF_IR_DUMPER_H_ diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_reader.cpp b/vndk/tools/header-checker/src/repr/protobuf/ir_reader.cpp new file mode 100644 index 000000000..2cf0da96c --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/ir_reader.cpp @@ -0,0 +1,386 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "repr/protobuf/ir_reader.h" + +#include "repr/ir_representation_internal.h" +#include "repr/protobuf/converter.h" + +#include + +#include + + +namespace header_checker { +namespace repr { + + +void ProtobufTextFormatToIRReader::ReadTypeInfo( + const abi_dump::BasicNamedAndTypedDecl &type_info, TypeIR *typep) { + typep->SetLinkerSetKey(type_info.linker_set_key()); + typep->SetName(type_info.name()); + typep->SetSourceFile(type_info.source_file()); + typep->SetReferencedType(type_info.referenced_type()); + typep->SetSelfType(type_info.self_type()); + typep->SetSize(type_info.size()); + typep->SetAlignment(type_info.alignment()); +} + +bool ProtobufTextFormatToIRReader::ReadDump(const std::string &dump_file) { + abi_dump::TranslationUnit tu; + std::ifstream input(dump_file); + google::protobuf::io::IstreamInputStream text_is(&input); + + if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) { + llvm::errs() << "Failed to parse protobuf TextFormat file\n"; + return false; + } + ReadFunctions(tu); + ReadGlobalVariables(tu); + + ReadEnumTypes(tu); + ReadRecordTypes(tu); + ReadFunctionTypes(tu); + ReadArrayTypes(tu); + ReadPointerTypes(tu); + ReadQualifiedTypes(tu); + ReadBuiltinTypes(tu); + ReadLvalueReferenceTypes(tu); + ReadRvalueReferenceTypes(tu); + + ReadElfFunctions(tu); + ReadElfObjects(tu); + return true; +} + +TemplateInfoIR ProtobufTextFormatToIRReader::TemplateInfoProtobufToIR( + const abi_dump::TemplateInfo &template_info_protobuf) { + TemplateInfoIR template_info_ir; + for (auto &&template_element : template_info_protobuf.elements()) { + TemplateElementIR template_element_ir(template_element.referenced_type()); + template_info_ir.AddTemplateElement(std::move(template_element_ir)); + } + return template_info_ir; +} + +template +static void SetupCFunctionLikeIR(const T &cfunction_like_protobuf, + CFunctionLikeIR *cfunction_like_ir) { + cfunction_like_ir->SetReturnType(cfunction_like_protobuf.return_type()); + for (auto &¶meter: cfunction_like_protobuf.parameters()) { + ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(), + false); + cfunction_like_ir->AddParameter(std::move(param_ir)); + } +} + +FunctionIR ProtobufTextFormatToIRReader::FunctionProtobufToIR( + const abi_dump::FunctionDecl &function_protobuf) { + FunctionIR function_ir; + function_ir.SetReturnType(function_protobuf.return_type()); + function_ir.SetLinkerSetKey(function_protobuf.linker_set_key()); + function_ir.SetName(function_protobuf.function_name()); + function_ir.SetAccess(AccessProtobufToIR(function_protobuf.access())); + function_ir.SetSourceFile(function_protobuf.source_file()); + // Set parameters + for (auto &¶meter: function_protobuf.parameters()) { + ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(), + parameter.is_this_ptr()); + function_ir.AddParameter(std::move(param_ir)); + } + // Set Template info + function_ir.SetTemplateInfo( + TemplateInfoProtobufToIR(function_protobuf.template_info())); + return function_ir; +} + +FunctionTypeIR ProtobufTextFormatToIRReader::FunctionTypeProtobufToIR( + const abi_dump::FunctionType &function_type_protobuf) { + FunctionTypeIR function_type_ir; + ReadTypeInfo(function_type_protobuf.type_info(), &function_type_ir); + SetupCFunctionLikeIR(function_type_protobuf, &function_type_ir); + return function_type_ir; +} + +VTableLayoutIR ProtobufTextFormatToIRReader::VTableLayoutProtobufToIR( + const abi_dump::VTableLayout &vtable_layout_protobuf) { + VTableLayoutIR vtable_layout_ir; + for (auto &&vtable_component : vtable_layout_protobuf.vtable_components()) { + VTableComponentIR vtable_component_ir( + vtable_component.mangled_component_name(), + VTableComponentKindProtobufToIR(vtable_component.kind()), + vtable_component.component_value(), + vtable_component.is_pure()); + vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir)); + } + return vtable_layout_ir; +} + +std::vector +ProtobufTextFormatToIRReader::RecordFieldsProtobufToIR( + const google::protobuf::RepeatedPtrField &rfp) { + std::vector record_type_fields_ir; + for (auto &&field : rfp) { + RecordFieldIR record_field_ir(field.field_name(), field.referenced_type(), + field.field_offset(), + AccessProtobufToIR(field.access())); + record_type_fields_ir.emplace_back(std::move(record_field_ir)); + } + return record_type_fields_ir; +} + +std::vector +ProtobufTextFormatToIRReader::RecordCXXBaseSpecifiersProtobufToIR( + const google::protobuf::RepeatedPtrField &rbs) { + std::vector record_type_bases_ir; + for (auto &&base : rbs) { + CXXBaseSpecifierIR record_base_ir( + base.referenced_type(), base.is_virtual(), + AccessProtobufToIR(base.access())); + record_type_bases_ir.emplace_back(std::move(record_base_ir)); + } + return record_type_bases_ir; +} + +RecordTypeIR ProtobufTextFormatToIRReader::RecordTypeProtobufToIR( + const abi_dump::RecordType &record_type_protobuf) { + RecordTypeIR record_type_ir; + ReadTypeInfo(record_type_protobuf.type_info(), &record_type_ir); + record_type_ir.SetTemplateInfo( + TemplateInfoProtobufToIR(record_type_protobuf.template_info())); + record_type_ir.SetAccess(AccessProtobufToIR(record_type_protobuf.access())); + record_type_ir.SetVTableLayout( + VTableLayoutProtobufToIR(record_type_protobuf.vtable_layout())); + // Get fields + record_type_ir.SetRecordFields(RecordFieldsProtobufToIR( + record_type_protobuf.fields())); + // Base Specifiers + record_type_ir.SetCXXBaseSpecifiers(RecordCXXBaseSpecifiersProtobufToIR( + record_type_protobuf.base_specifiers())); + record_type_ir.SetRecordKind( + RecordKindProtobufToIR(record_type_protobuf.record_kind())); + record_type_ir.SetAnonymity(record_type_protobuf.is_anonymous()); + record_type_ir.SetUniqueId(record_type_protobuf.tag_info().unique_id()); + return record_type_ir; +} + +std::vector +ProtobufTextFormatToIRReader::EnumFieldsProtobufToIR( + const google::protobuf::RepeatedPtrField &efp) { + std::vector enum_type_fields_ir; + for (auto &&field : efp) { + EnumFieldIR enum_field_ir(field.name(), field.enum_field_value()); + enum_type_fields_ir.emplace_back(std::move(enum_field_ir)); + } + return enum_type_fields_ir; +} + +EnumTypeIR ProtobufTextFormatToIRReader::EnumTypeProtobufToIR( + const abi_dump::EnumType &enum_type_protobuf) { + EnumTypeIR enum_type_ir; + ReadTypeInfo(enum_type_protobuf.type_info(), &enum_type_ir); + enum_type_ir.SetUnderlyingType(enum_type_protobuf.underlying_type()); + enum_type_ir.SetAccess(AccessProtobufToIR(enum_type_protobuf.access())); + enum_type_ir.SetFields( + EnumFieldsProtobufToIR(enum_type_protobuf.enum_fields())); + enum_type_ir.SetUniqueId(enum_type_protobuf.tag_info().unique_id()); + return enum_type_ir; +} + +void ProtobufTextFormatToIRReader::ReadGlobalVariables( + const abi_dump::TranslationUnit &tu) { + for (auto &&global_variable_protobuf : tu.global_vars()) { + GlobalVarIR global_variable_ir; + global_variable_ir.SetName(global_variable_protobuf.name()); + global_variable_ir.SetAccess(AccessProtobufToIR(global_variable_protobuf.access())); + global_variable_ir.SetSourceFile(global_variable_protobuf.source_file()); + global_variable_ir.SetReferencedType( + global_variable_protobuf.referenced_type()); + global_variable_ir.SetLinkerSetKey( + global_variable_protobuf.linker_set_key()); + if (!IsLinkableMessageInExportedHeaders(&global_variable_ir)) { + continue; + } + module_->global_variables_.insert( + {global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)}); + } +} + +void ProtobufTextFormatToIRReader::ReadPointerTypes( + const abi_dump::TranslationUnit &tu) { + for (auto &&pointer_type_protobuf : tu.pointer_types()) { + PointerTypeIR pointer_type_ir; + ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir); + if (!IsLinkableMessageInExportedHeaders(&pointer_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(pointer_type_ir), &module_->pointer_types_, + &module_->type_graph_); + } +} + +void ProtobufTextFormatToIRReader::ReadBuiltinTypes( + const abi_dump::TranslationUnit &tu) { + 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()); + AddToMapAndTypeGraph(std::move(builtin_type_ir), &module_->builtin_types_, + &module_->type_graph_); + } +} + +void ProtobufTextFormatToIRReader::ReadQualifiedTypes( + const abi_dump::TranslationUnit &tu) { + for (auto &&qualified_type_protobuf : tu.qualified_types()) { + QualifiedTypeIR qualified_type_ir; + ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir); + qualified_type_ir.SetConstness(qualified_type_protobuf.is_const()); + qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile()); + qualified_type_ir.SetRestrictedness( + qualified_type_protobuf.is_restricted()); + if (!IsLinkableMessageInExportedHeaders(&qualified_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(qualified_type_ir), + &module_->qualified_types_, &module_->type_graph_); + } +} + +void ProtobufTextFormatToIRReader::ReadArrayTypes( + const abi_dump::TranslationUnit &tu) { + for (auto &&array_type_protobuf : tu.array_types()) { + ArrayTypeIR array_type_ir; + ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir); + if (!IsLinkableMessageInExportedHeaders(&array_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(array_type_ir), &module_->array_types_, + &module_->type_graph_); + } +} + +void ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes( + const abi_dump::TranslationUnit &tu) { + 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); + if (!IsLinkableMessageInExportedHeaders(&lvalue_reference_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(lvalue_reference_type_ir), + &module_->lvalue_reference_types_, + &module_->type_graph_); + } +} + +void ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes( + const abi_dump::TranslationUnit &tu) { + 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); + if (!IsLinkableMessageInExportedHeaders(&rvalue_reference_type_ir)) { + continue; + } + AddToMapAndTypeGraph(std::move(rvalue_reference_type_ir), + &module_->rvalue_reference_types_, + &module_->type_graph_); + } +} + +void ProtobufTextFormatToIRReader::ReadFunctions( + const abi_dump::TranslationUnit &tu) { + for (auto &&function_protobuf : tu.functions()) { + FunctionIR function_ir = FunctionProtobufToIR(function_protobuf); + if (!IsLinkableMessageInExportedHeaders(&function_ir)) { + continue; + } + module_->functions_.insert( + {function_ir.GetLinkerSetKey(), std::move(function_ir)}); + } +} + +void ProtobufTextFormatToIRReader::ReadRecordTypes( + const abi_dump::TranslationUnit &tu) { + for (auto &&record_type_protobuf : tu.record_types()) { + RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf); + if (!IsLinkableMessageInExportedHeaders(&record_type_ir)) { + continue; + } + auto it = AddToMapAndTypeGraph(std::move(record_type_ir), + &module_->record_types_, + &module_->type_graph_); + const std::string &key = GetODRListMapKey(&(it->second)); + AddToODRListMap(key, &(it->second)); + } +} + +void ProtobufTextFormatToIRReader::ReadFunctionTypes( + const abi_dump::TranslationUnit &tu) { + for (auto &&function_type_protobuf : tu.function_types()) { + FunctionTypeIR function_type_ir = + FunctionTypeProtobufToIR(function_type_protobuf); + if (!IsLinkableMessageInExportedHeaders(&function_type_ir)) { + continue; + } + auto it = AddToMapAndTypeGraph(std::move(function_type_ir), + &module_->function_types_, + &module_->type_graph_); + const std::string &key = GetODRListMapKey(&(it->second)); + AddToODRListMap(key, &(it->second)); + } +} + +void ProtobufTextFormatToIRReader::ReadEnumTypes( + const abi_dump::TranslationUnit &tu) { + for (auto &&enum_type_protobuf : tu.enum_types()) { + EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf); + if (!IsLinkableMessageInExportedHeaders(&enum_type_ir)) { + continue; + } + auto it = AddToMapAndTypeGraph(std::move(enum_type_ir), + &module_->enum_types_, + &module_->type_graph_); + AddToODRListMap(it->second.GetUniqueId() + it->second.GetSourceFile(), + (&it->second)); + } +} + +void ProtobufTextFormatToIRReader::ReadElfFunctions( + const abi_dump::TranslationUnit &tu) { + for (auto &&elf_function : tu.elf_functions()) { + ElfFunctionIR elf_function_ir( + elf_function.name(), + ElfSymbolBindingProtobufToIR(elf_function.binding())); + module_->elf_functions_.insert( + {elf_function_ir.GetName(), std::move(elf_function_ir)}); + } +} + +void ProtobufTextFormatToIRReader::ReadElfObjects( + const abi_dump::TranslationUnit &tu) { + for (auto &&elf_object : tu.elf_objects()) { + ElfObjectIR elf_object_ir( + elf_object.name(), ElfSymbolBindingProtobufToIR(elf_object.binding())); + module_->elf_objects_.insert( + {elf_object_ir.GetName(), std::move(elf_object_ir)}); + } +} + + +} // namespace repr +} // namespace header_checker diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_reader.h b/vndk/tools/header-checker/src/repr/protobuf/ir_reader.h new file mode 100644 index 000000000..15ade4cc5 --- /dev/null +++ b/vndk/tools/header-checker/src/repr/protobuf/ir_reader.h @@ -0,0 +1,110 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef HEADER_CHECKER_REPR_PROTOBUF_IR_READER_H_ +#define HEADER_CHECKER_REPR_PROTOBUF_IR_READER_H_ + +#include "repr/ir_reader.h" +#include "repr/protobuf/abi_diff.h" +#include "repr/protobuf/abi_dump.h" + +#include +#include +#include + +#include +#include + + +namespace header_checker { +namespace repr { + + +class ProtobufTextFormatToIRReader : public TextFormatToIRReader { + private: + template + using RepeatedPtrField = google::protobuf::RepeatedPtrField; + + + public: + ProtobufTextFormatToIRReader(const std::set *exported_headers) + : TextFormatToIRReader(exported_headers) {} + + + bool ReadDump(const std::string &dump_file) override; + + + private: + void ReadFunctions(const abi_dump::TranslationUnit &tu); + + void ReadGlobalVariables(const abi_dump::TranslationUnit &tu); + + void ReadEnumTypes(const abi_dump::TranslationUnit &tu); + + void ReadRecordTypes(const abi_dump::TranslationUnit &tu); + + void ReadFunctionTypes(const abi_dump::TranslationUnit &tu); + + void ReadPointerTypes(const abi_dump::TranslationUnit &tu); + + void ReadBuiltinTypes(const abi_dump::TranslationUnit &tu); + + void ReadQualifiedTypes(const abi_dump::TranslationUnit &tu); + + void ReadArrayTypes(const abi_dump::TranslationUnit &tu); + + void ReadLvalueReferenceTypes(const abi_dump::TranslationUnit &tu); + + void ReadRvalueReferenceTypes(const abi_dump::TranslationUnit &tu); + + void ReadElfFunctions(const abi_dump::TranslationUnit &tu); + + void ReadElfObjects(const abi_dump::TranslationUnit &tu); + + void ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl &type_info, + TypeIR *typep); + + FunctionIR FunctionProtobufToIR(const abi_dump::FunctionDecl &); + + FunctionTypeIR FunctionTypeProtobufToIR( + const abi_dump::FunctionType &function_type_protobuf); + + RecordTypeIR RecordTypeProtobufToIR( + const abi_dump::RecordType &record_type_protobuf); + + std::vector RecordFieldsProtobufToIR( + const RepeatedPtrField &rfp); + + std::vector RecordCXXBaseSpecifiersProtobufToIR( + const RepeatedPtrField &rbs); + + std::vector EnumFieldsProtobufToIR( + const RepeatedPtrField &efp); + + EnumTypeIR EnumTypeProtobufToIR( + const abi_dump::EnumType &enum_type_protobuf); + + VTableLayoutIR VTableLayoutProtobufToIR( + const abi_dump::VTableLayout &vtable_layout_protobuf); + + TemplateInfoIR TemplateInfoProtobufToIR( + const abi_dump::TemplateInfo &template_info_protobuf); +}; + + +} // namespace repr +} // namespace header_checker + + +#endif // HEADER_CHECKER_REPR_PROTOBUF_IR_READER_H_ diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.cpp b/vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.cpp deleted file mode 100644 index ede10fcca..000000000 --- a/vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.cpp +++ /dev/null @@ -1,1504 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "repr/protobuf/ir_representation_protobuf.h" - -#include - -#include -#include -#include -#include - - -namespace header_checker { -namespace repr { - - -void ProtobufTextFormatToIRReader::ReadTypeInfo( - const abi_dump::BasicNamedAndTypedDecl &type_info, TypeIR *typep) { - typep->SetLinkerSetKey(type_info.linker_set_key()); - typep->SetName(type_info.name()); - typep->SetSourceFile(type_info.source_file()); - typep->SetReferencedType(type_info.referenced_type()); - typep->SetSelfType(type_info.self_type()); - typep->SetSize(type_info.size()); - typep->SetAlignment(type_info.alignment()); -} - -bool ProtobufTextFormatToIRReader::ReadDump(const std::string &dump_file) { - abi_dump::TranslationUnit tu; - std::ifstream input(dump_file); - google::protobuf::io::IstreamInputStream text_is(&input); - - if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) { - llvm::errs() << "Failed to parse protobuf TextFormat file\n"; - return false; - } - ReadFunctions(tu); - ReadGlobalVariables(tu); - - ReadEnumTypes(tu); - ReadRecordTypes(tu); - ReadFunctionTypes(tu); - ReadArrayTypes(tu); - ReadPointerTypes(tu); - ReadQualifiedTypes(tu); - ReadBuiltinTypes(tu); - ReadLvalueReferenceTypes(tu); - ReadRvalueReferenceTypes(tu); - - ReadElfFunctions(tu); - ReadElfObjects(tu); - return true; -} - -TemplateInfoIR ProtobufTextFormatToIRReader::TemplateInfoProtobufToIR( - const abi_dump::TemplateInfo &template_info_protobuf) { - TemplateInfoIR template_info_ir; - for (auto &&template_element : template_info_protobuf.elements()) { - TemplateElementIR template_element_ir(template_element.referenced_type()); - template_info_ir.AddTemplateElement(std::move(template_element_ir)); - } - return template_info_ir; -} - -template -static void SetupCFunctionLikeIR(const T &cfunction_like_protobuf, - CFunctionLikeIR *cfunction_like_ir) { - cfunction_like_ir->SetReturnType(cfunction_like_protobuf.return_type()); - for (auto &¶meter: cfunction_like_protobuf.parameters()) { - ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(), - false); - cfunction_like_ir->AddParameter(std::move(param_ir)); - } -} - -FunctionIR ProtobufTextFormatToIRReader::FunctionProtobufToIR( - const abi_dump::FunctionDecl &function_protobuf) { - FunctionIR function_ir; - function_ir.SetReturnType(function_protobuf.return_type()); - function_ir.SetLinkerSetKey(function_protobuf.linker_set_key()); - function_ir.SetName(function_protobuf.function_name()); - function_ir.SetAccess(AccessProtobufToIR(function_protobuf.access())); - function_ir.SetSourceFile(function_protobuf.source_file()); - // Set parameters - for (auto &¶meter: function_protobuf.parameters()) { - ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(), - parameter.is_this_ptr()); - function_ir.AddParameter(std::move(param_ir)); - } - // Set Template info - function_ir.SetTemplateInfo( - TemplateInfoProtobufToIR(function_protobuf.template_info())); - return function_ir; -} - -FunctionTypeIR ProtobufTextFormatToIRReader::FunctionTypeProtobufToIR( - const abi_dump::FunctionType &function_type_protobuf) { - FunctionTypeIR function_type_ir; - ReadTypeInfo(function_type_protobuf.type_info(), &function_type_ir); - SetupCFunctionLikeIR(function_type_protobuf, &function_type_ir); - return function_type_ir; -} - -VTableLayoutIR ProtobufTextFormatToIRReader::VTableLayoutProtobufToIR( - const abi_dump::VTableLayout &vtable_layout_protobuf) { - VTableLayoutIR vtable_layout_ir; - for (auto &&vtable_component : vtable_layout_protobuf.vtable_components()) { - VTableComponentIR vtable_component_ir( - vtable_component.mangled_component_name(), - VTableComponentKindProtobufToIR(vtable_component.kind()), - vtable_component.component_value(), - vtable_component.is_pure()); - vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir)); - } - return vtable_layout_ir; -} - -std::vector -ProtobufTextFormatToIRReader::RecordFieldsProtobufToIR( - const google::protobuf::RepeatedPtrField &rfp) { - std::vector record_type_fields_ir; - for (auto &&field : rfp) { - RecordFieldIR record_field_ir(field.field_name(), field.referenced_type(), - field.field_offset(), - AccessProtobufToIR(field.access())); - record_type_fields_ir.emplace_back(std::move(record_field_ir)); - } - return record_type_fields_ir; -} - -std::vector -ProtobufTextFormatToIRReader::RecordCXXBaseSpecifiersProtobufToIR( - const google::protobuf::RepeatedPtrField &rbs) { - std::vector record_type_bases_ir; - for (auto &&base : rbs) { - CXXBaseSpecifierIR record_base_ir( - base.referenced_type(), base.is_virtual(), - AccessProtobufToIR(base.access())); - record_type_bases_ir.emplace_back(std::move(record_base_ir)); - } - return record_type_bases_ir; -} - -RecordTypeIR ProtobufTextFormatToIRReader::RecordTypeProtobufToIR( - const abi_dump::RecordType &record_type_protobuf) { - RecordTypeIR record_type_ir; - ReadTypeInfo(record_type_protobuf.type_info(), &record_type_ir); - record_type_ir.SetTemplateInfo( - TemplateInfoProtobufToIR(record_type_protobuf.template_info())); - record_type_ir.SetAccess(AccessProtobufToIR(record_type_protobuf.access())); - record_type_ir.SetVTableLayout( - VTableLayoutProtobufToIR(record_type_protobuf.vtable_layout())); - // Get fields - record_type_ir.SetRecordFields(RecordFieldsProtobufToIR( - record_type_protobuf.fields())); - // Base Specifiers - record_type_ir.SetCXXBaseSpecifiers(RecordCXXBaseSpecifiersProtobufToIR( - record_type_protobuf.base_specifiers())); - record_type_ir.SetRecordKind( - RecordKindProtobufToIR(record_type_protobuf.record_kind())); - record_type_ir.SetAnonymity(record_type_protobuf.is_anonymous()); - record_type_ir.SetUniqueId(record_type_protobuf.tag_info().unique_id()); - return record_type_ir; -} - -std::vector -ProtobufTextFormatToIRReader::EnumFieldsProtobufToIR( - const google::protobuf::RepeatedPtrField &efp) { - std::vector enum_type_fields_ir; - for (auto &&field : efp) { - EnumFieldIR enum_field_ir(field.name(), field.enum_field_value()); - enum_type_fields_ir.emplace_back(std::move(enum_field_ir)); - } - return enum_type_fields_ir; -} - -EnumTypeIR ProtobufTextFormatToIRReader::EnumTypeProtobufToIR( - const abi_dump::EnumType &enum_type_protobuf) { - EnumTypeIR enum_type_ir; - ReadTypeInfo(enum_type_protobuf.type_info(), &enum_type_ir); - enum_type_ir.SetUnderlyingType(enum_type_protobuf.underlying_type()); - enum_type_ir.SetAccess(AccessProtobufToIR(enum_type_protobuf.access())); - enum_type_ir.SetFields( - EnumFieldsProtobufToIR(enum_type_protobuf.enum_fields())); - enum_type_ir.SetUniqueId(enum_type_protobuf.tag_info().unique_id()); - return enum_type_ir; -} - -void ProtobufTextFormatToIRReader::ReadGlobalVariables( - const abi_dump::TranslationUnit &tu) { - for (auto &&global_variable_protobuf : tu.global_vars()) { - GlobalVarIR global_variable_ir; - global_variable_ir.SetName(global_variable_protobuf.name()); - global_variable_ir.SetAccess(AccessProtobufToIR(global_variable_protobuf.access())); - global_variable_ir.SetSourceFile(global_variable_protobuf.source_file()); - global_variable_ir.SetReferencedType( - global_variable_protobuf.referenced_type()); - global_variable_ir.SetLinkerSetKey( - global_variable_protobuf.linker_set_key()); - if (!IsLinkableMessageInExportedHeaders(&global_variable_ir)) { - continue; - } - module_->global_variables_.insert( - {global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)}); - } -} - -void ProtobufTextFormatToIRReader::ReadPointerTypes( - const abi_dump::TranslationUnit &tu) { - for (auto &&pointer_type_protobuf : tu.pointer_types()) { - PointerTypeIR pointer_type_ir; - ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir); - if (!IsLinkableMessageInExportedHeaders(&pointer_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(pointer_type_ir), &module_->pointer_types_, - &module_->type_graph_); - } -} - -void ProtobufTextFormatToIRReader::ReadBuiltinTypes( - const abi_dump::TranslationUnit &tu) { - 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()); - AddToMapAndTypeGraph(std::move(builtin_type_ir), &module_->builtin_types_, - &module_->type_graph_); - } -} - -void ProtobufTextFormatToIRReader::ReadQualifiedTypes( - const abi_dump::TranslationUnit &tu) { - for (auto &&qualified_type_protobuf : tu.qualified_types()) { - QualifiedTypeIR qualified_type_ir; - ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir); - qualified_type_ir.SetConstness(qualified_type_protobuf.is_const()); - qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile()); - qualified_type_ir.SetRestrictedness( - qualified_type_protobuf.is_restricted()); - if (!IsLinkableMessageInExportedHeaders(&qualified_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(qualified_type_ir), - &module_->qualified_types_, &module_->type_graph_); - } -} - -void ProtobufTextFormatToIRReader::ReadArrayTypes( - const abi_dump::TranslationUnit &tu) { - for (auto &&array_type_protobuf : tu.array_types()) { - ArrayTypeIR array_type_ir; - ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir); - if (!IsLinkableMessageInExportedHeaders(&array_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(array_type_ir), &module_->array_types_, - &module_->type_graph_); - } -} - -void ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes( - const abi_dump::TranslationUnit &tu) { - 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); - if (!IsLinkableMessageInExportedHeaders(&lvalue_reference_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(lvalue_reference_type_ir), - &module_->lvalue_reference_types_, - &module_->type_graph_); - } -} - -void ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes( - const abi_dump::TranslationUnit &tu) { - 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); - if (!IsLinkableMessageInExportedHeaders(&rvalue_reference_type_ir)) { - continue; - } - AddToMapAndTypeGraph(std::move(rvalue_reference_type_ir), - &module_->rvalue_reference_types_, - &module_->type_graph_); - } -} - -void ProtobufTextFormatToIRReader::ReadFunctions( - const abi_dump::TranslationUnit &tu) { - for (auto &&function_protobuf : tu.functions()) { - FunctionIR function_ir = FunctionProtobufToIR(function_protobuf); - if (!IsLinkableMessageInExportedHeaders(&function_ir)) { - continue; - } - module_->functions_.insert( - {function_ir.GetLinkerSetKey(), std::move(function_ir)}); - } -} - -void ProtobufTextFormatToIRReader::ReadRecordTypes( - const abi_dump::TranslationUnit &tu) { - for (auto &&record_type_protobuf : tu.record_types()) { - RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf); - if (!IsLinkableMessageInExportedHeaders(&record_type_ir)) { - continue; - } - auto it = AddToMapAndTypeGraph(std::move(record_type_ir), - &module_->record_types_, - &module_->type_graph_); - const std::string &key = GetODRListMapKey(&(it->second)); - AddToODRListMap(key, &(it->second)); - } -} - -void ProtobufTextFormatToIRReader::ReadFunctionTypes( - const abi_dump::TranslationUnit &tu) { - for (auto &&function_type_protobuf : tu.function_types()) { - FunctionTypeIR function_type_ir = - FunctionTypeProtobufToIR(function_type_protobuf); - if (!IsLinkableMessageInExportedHeaders(&function_type_ir)) { - continue; - } - auto it = AddToMapAndTypeGraph(std::move(function_type_ir), - &module_->function_types_, - &module_->type_graph_); - const std::string &key = GetODRListMapKey(&(it->second)); - AddToODRListMap(key, &(it->second)); - } -} - -void ProtobufTextFormatToIRReader::ReadEnumTypes( - const abi_dump::TranslationUnit &tu) { - for (auto &&enum_type_protobuf : tu.enum_types()) { - EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf); - if (!IsLinkableMessageInExportedHeaders(&enum_type_ir)) { - continue; - } - auto it = AddToMapAndTypeGraph(std::move(enum_type_ir), - &module_->enum_types_, - &module_->type_graph_); - AddToODRListMap(it->second.GetUniqueId() + it->second.GetSourceFile(), - (&it->second)); - } -} - -void ProtobufTextFormatToIRReader::ReadElfFunctions( - const abi_dump::TranslationUnit &tu) { - for (auto &&elf_function : tu.elf_functions()) { - ElfFunctionIR elf_function_ir( - elf_function.name(), - ElfSymbolBindingProtobufToIR(elf_function.binding())); - module_->elf_functions_.insert( - {elf_function_ir.GetName(), std::move(elf_function_ir)}); - } -} - -void ProtobufTextFormatToIRReader::ReadElfObjects( - const abi_dump::TranslationUnit &tu) { - for (auto &&elf_object : tu.elf_objects()) { - ElfObjectIR elf_object_ir( - elf_object.name(), ElfSymbolBindingProtobufToIR(elf_object.binding())); - module_->elf_objects_.insert( - {elf_object_ir.GetName(), std::move(elf_object_ir)}); - } -} - -bool IRToProtobufConverter::AddTemplateInformation( - abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta) { - for (auto &&template_element : ta->GetTemplateElements()) { - abi_dump::TemplateElement *added_element = ti->add_elements(); - if (!added_element) { - llvm::errs() << "Failed to add template element\n"; - return false; - } - added_element->set_referenced_type(template_element.GetReferencedType()); - } - return true; -} - -bool IRToProtobufConverter::AddTypeInfo( - abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep) { - if (!type_info || !typep) { - llvm::errs() << "Typeinfo not valid\n"; - return false; - } - type_info->set_linker_set_key(typep->GetLinkerSetKey()); - type_info->set_source_file(typep->GetSourceFile()); - type_info->set_name(typep->GetName()); - type_info->set_size(typep->GetSize()); - type_info->set_alignment(typep->GetAlignment()); - type_info->set_referenced_type(typep->GetReferencedType()); - type_info->set_self_type(typep->GetSelfType()); - return true; -} - -static void SetIRToProtobufRecordField( - abi_dump::RecordFieldDecl *record_field_protobuf, - const RecordFieldIR *record_field_ir) { - record_field_protobuf->set_field_name(record_field_ir->GetName()); - record_field_protobuf->set_referenced_type( - record_field_ir->GetReferencedType()); - record_field_protobuf->set_access( - AccessIRToProtobuf(record_field_ir->GetAccess())); - record_field_protobuf->set_field_offset(record_field_ir->GetOffset()); -} - -bool IRToProtobufConverter::AddRecordFields( - abi_dump::RecordType *record_protobuf, - const RecordTypeIR *record_ir) { - // Iterate through the fields and create corresponding ones for the protobuf - // record - for (auto &&field_ir : record_ir->GetFields()) { - abi_dump::RecordFieldDecl *added_field = record_protobuf->add_fields(); - if (!added_field) { - llvm::errs() << "Couldn't add record field\n"; - } - SetIRToProtobufRecordField(added_field, &field_ir); - } - return true; -} - -static bool SetIRToProtobufBaseSpecifier( - abi_dump::CXXBaseSpecifier *base_specifier_protobuf, - const CXXBaseSpecifierIR &base_specifier_ir) { - if (!base_specifier_protobuf) { - llvm::errs() << "Protobuf base specifier not valid\n"; - return false; - } - base_specifier_protobuf->set_referenced_type( - base_specifier_ir.GetReferencedType()); - base_specifier_protobuf->set_is_virtual( - base_specifier_ir.IsVirtual()); - base_specifier_protobuf->set_access( - AccessIRToProtobuf(base_specifier_ir.GetAccess())); - return true; -} - -bool IRToProtobufConverter::AddBaseSpecifiers( - abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir) { - for (auto &&base_ir : record_ir->GetBases()) { - abi_dump::CXXBaseSpecifier *added_base = - record_protobuf->add_base_specifiers(); - if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) { - return false; - } - } - return true; -} - -static bool SetIRToProtobufVTableLayout( - abi_dump::VTableLayout *vtable_layout_protobuf, - const VTableLayoutIR &vtable_layout_ir) { - if (vtable_layout_protobuf == nullptr) { - llvm::errs() << "vtable layout protobuf not valid\n"; - return false; - } - for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) { - abi_dump::VTableComponent *added_vtable_component = - vtable_layout_protobuf->add_vtable_components(); - if (!added_vtable_component) { - llvm::errs() << "Couldn't add vtable component\n"; - return false; - } - added_vtable_component->set_kind( - VTableComponentKindIRToProtobuf(vtable_component_ir.GetKind())); - added_vtable_component->set_component_value(vtable_component_ir.GetValue()); - added_vtable_component->set_mangled_component_name( - vtable_component_ir.GetName()); - added_vtable_component->set_is_pure(vtable_component_ir.GetIsPure()); - } - return true; -} - -bool IRToProtobufConverter::AddVTableLayout( - abi_dump::RecordType *record_protobuf, - const RecordTypeIR *record_ir) { - // If there are no entries in the vtable, just return. - if (record_ir->GetVTableNumEntries() == 0) { - return true; - } - const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout(); - abi_dump::VTableLayout *vtable_layout_protobuf = - record_protobuf->mutable_vtable_layout(); - if (!SetIRToProtobufVTableLayout(vtable_layout_protobuf, vtable_layout_ir)) { - return false; - } - return true; -} - -bool IRToProtobufConverter::AddTagTypeInfo( - abi_dump::TagType *tag_type_protobuf, - const TagTypeIR *tag_type_ir) { - if (!tag_type_protobuf || !tag_type_ir) { - return false; - } - tag_type_protobuf->set_unique_id(tag_type_ir->GetUniqueId()); - return true; -} - -abi_dump::RecordType IRToProtobufConverter::ConvertRecordTypeIR( - const RecordTypeIR *recordp) { - abi_dump::RecordType added_record_type; - added_record_type.set_access(AccessIRToProtobuf(recordp->GetAccess())); - added_record_type.set_record_kind( - RecordKindIRToProtobuf(recordp->GetRecordKind())); - if (recordp->IsAnonymous()) { - added_record_type.set_is_anonymous(true); - } - if (!AddTypeInfo(added_record_type.mutable_type_info(), recordp) || - !AddRecordFields(&added_record_type, recordp) || - !AddBaseSpecifiers(&added_record_type, recordp) || - !AddVTableLayout(&added_record_type, recordp) || - !AddTagTypeInfo(added_record_type.mutable_tag_info(), recordp) || - !(recordp->GetTemplateElements().size() ? - AddTemplateInformation(added_record_type.mutable_template_info(), - recordp) : true)) { - llvm::errs() << "Template information could not be added\n"; - ::exit(1); - } - return added_record_type; -} - - -abi_dump::ElfObject IRToProtobufConverter::ConvertElfObjectIR( - const ElfObjectIR *elf_object_ir) { - abi_dump::ElfObject elf_object_protobuf; - elf_object_protobuf.set_name(elf_object_ir->GetName()); - return elf_object_protobuf; -} - -abi_dump::ElfFunction IRToProtobufConverter::ConvertElfFunctionIR( - const ElfFunctionIR *elf_function_ir) { - abi_dump::ElfFunction elf_function_protobuf; - elf_function_protobuf.set_name(elf_function_ir->GetName()); - return elf_function_protobuf; -} - -template -bool IRToProtobufConverter::AddFunctionParametersAndSetReturnType( - CFunctionLikeMessage *function_like_protobuf, - const CFunctionLikeIR *cfunction_like_ir) { - function_like_protobuf->set_return_type(cfunction_like_ir->GetReturnType()); - return AddFunctionParameters(function_like_protobuf, cfunction_like_ir); -} - -template -bool IRToProtobufConverter::AddFunctionParameters( - CFunctionLikeMessage *function_like_protobuf, - const CFunctionLikeIR *cfunction_like_ir) { - for (auto &¶meter : cfunction_like_ir->GetParameters()) { - abi_dump::ParamDecl *added_parameter = - function_like_protobuf->add_parameters(); - if (!added_parameter) { - return false; - } - added_parameter->set_referenced_type( - parameter.GetReferencedType()); - added_parameter->set_default_arg(parameter.GetIsDefault()); - added_parameter->set_is_this_ptr(parameter.GetIsThisPtr()); - } - return true; -} - -abi_dump::FunctionType IRToProtobufConverter::ConvertFunctionTypeIR ( - const FunctionTypeIR *function_typep) { - abi_dump::FunctionType added_function_type; - if (!AddTypeInfo(added_function_type.mutable_type_info(), function_typep) || - !AddFunctionParametersAndSetReturnType(&added_function_type, - function_typep)) { - llvm::errs() << "Could not convert FunctionTypeIR to protobuf\n"; - ::exit(1); - } - return added_function_type; -} - -abi_dump::FunctionDecl IRToProtobufConverter::ConvertFunctionIR( - const FunctionIR *functionp) { - abi_dump::FunctionDecl added_function; - added_function.set_access(AccessIRToProtobuf(functionp->GetAccess())); - added_function.set_linker_set_key(functionp->GetLinkerSetKey()); - added_function.set_source_file(functionp->GetSourceFile()); - added_function.set_function_name(functionp->GetName()); - if (!AddFunctionParametersAndSetReturnType(&added_function, functionp) || - !(functionp->GetTemplateElements().size() ? - AddTemplateInformation(added_function.mutable_template_info(), functionp) - : true)) { - llvm::errs() << "Template information could not be added\n"; - ::exit(1); - } - return added_function; -} - -static bool SetIRToProtobufEnumField( - abi_dump::EnumFieldDecl *enum_field_protobuf, - const EnumFieldIR *enum_field_ir) { - if (enum_field_protobuf == nullptr) { - return true; - } - enum_field_protobuf->set_name(enum_field_ir->GetName()); - enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue()); - return true; -} - -bool IRToProtobufConverter::AddEnumFields(abi_dump::EnumType *enum_protobuf, - const EnumTypeIR *enum_ir) { - for (auto &&field : enum_ir->GetFields()) { - abi_dump::EnumFieldDecl *enum_fieldp = enum_protobuf->add_enum_fields(); - if (!SetIRToProtobufEnumField(enum_fieldp, &field)) { - return false; - } - } - return true; -} - - -abi_dump::EnumType IRToProtobufConverter::ConvertEnumTypeIR( - const EnumTypeIR *enump) { - abi_dump::EnumType added_enum_type; - added_enum_type.set_access(AccessIRToProtobuf(enump->GetAccess())); - added_enum_type.set_underlying_type(enump->GetUnderlyingType()); - if (!AddTypeInfo(added_enum_type.mutable_type_info(), enump) || - !AddEnumFields(&added_enum_type, enump) || - !AddTagTypeInfo(added_enum_type.mutable_tag_info(), enump)) { - llvm::errs() << "EnumTypeIR could not be converted\n"; - ::exit(1); - } - return added_enum_type; -} - -abi_dump::GlobalVarDecl IRToProtobufConverter::ConvertGlobalVarIR( - const GlobalVarIR *global_varp) { - abi_dump::GlobalVarDecl added_global_var; - added_global_var.set_referenced_type(global_varp->GetReferencedType()); - added_global_var.set_source_file(global_varp->GetSourceFile()); - added_global_var.set_name(global_varp->GetName()); - added_global_var.set_linker_set_key(global_varp->GetLinkerSetKey()); - added_global_var.set_access( - AccessIRToProtobuf(global_varp->GetAccess())); - return added_global_var; -} - -abi_dump::PointerType IRToProtobufConverter::ConvertPointerTypeIR( - const PointerTypeIR *pointerp) { - abi_dump::PointerType added_pointer_type; - if (!AddTypeInfo(added_pointer_type.mutable_type_info(), pointerp)) { - llvm::errs() << "PointerTypeIR could not be converted\n"; - ::exit(1); - } - return added_pointer_type; -} - -abi_dump::QualifiedType IRToProtobufConverter::ConvertQualifiedTypeIR( - const QualifiedTypeIR *qualtypep) { - abi_dump::QualifiedType added_qualified_type; - if (!AddTypeInfo(added_qualified_type.mutable_type_info(), qualtypep)) { - llvm::errs() << "QualifiedTypeIR could not be converted\n"; - ::exit(1); - } - added_qualified_type.set_is_const(qualtypep->IsConst()); - added_qualified_type.set_is_volatile(qualtypep->IsVolatile()); - added_qualified_type.set_is_restricted(qualtypep->IsRestricted()); - return added_qualified_type; -} - -abi_dump::BuiltinType IRToProtobufConverter::ConvertBuiltinTypeIR( - const BuiltinTypeIR *builtin_typep) { - abi_dump::BuiltinType added_builtin_type; - added_builtin_type.set_is_unsigned(builtin_typep->IsUnsigned()); - added_builtin_type.set_is_integral(builtin_typep->IsIntegralType()); - if (!AddTypeInfo(added_builtin_type.mutable_type_info(), builtin_typep)) { - llvm::errs() << "BuiltinTypeIR could not be converted\n"; - ::exit(1); - } - return added_builtin_type; -} - -abi_dump::ArrayType IRToProtobufConverter::ConvertArrayTypeIR( - const ArrayTypeIR *array_typep) { - abi_dump::ArrayType added_array_type; - if (!AddTypeInfo(added_array_type.mutable_type_info(), array_typep)) { - llvm::errs() << "ArrayTypeIR could not be converted\n"; - ::exit(1); - } - return added_array_type; -} - -abi_dump::LvalueReferenceType -IRToProtobufConverter::ConvertLvalueReferenceTypeIR( - const LvalueReferenceTypeIR *lvalue_reference_typep) { - abi_dump::LvalueReferenceType added_lvalue_reference_type; - if (!AddTypeInfo(added_lvalue_reference_type.mutable_type_info(), - lvalue_reference_typep)) { - llvm::errs() << "LvalueReferenceTypeIR could not be converted\n"; - ::exit(1); - } - return added_lvalue_reference_type; -} - -abi_dump::RvalueReferenceType -IRToProtobufConverter::ConvertRvalueReferenceTypeIR( - const RvalueReferenceTypeIR *rvalue_reference_typep) { - abi_dump::RvalueReferenceType added_rvalue_reference_type; - if (!AddTypeInfo(added_rvalue_reference_type.mutable_type_info(), - rvalue_reference_typep)) { - llvm::errs() << "RvalueReferenceTypeIR could not be converted\n"; - ::exit(1); - } - return added_rvalue_reference_type; -} - - -bool IRDiffToProtobufConverter::AddTypeInfoDiff( - abi_diff::TypeInfoDiff *type_info_diff_protobuf, - const TypeDiffIR *type_diff_ir) { - abi_diff::TypeInfo *old_type_info_protobuf = - type_info_diff_protobuf->mutable_old_type_info(); - abi_diff::TypeInfo *new_type_info_protobuf = - type_info_diff_protobuf->mutable_new_type_info(); - if (old_type_info_protobuf == nullptr || new_type_info_protobuf == nullptr) { - return false; - } - const std::pair &sizes = type_diff_ir->GetSizes(); - const std::pair &alignments = - type_diff_ir->GetAlignments(); - old_type_info_protobuf->set_size(sizes.first); - new_type_info_protobuf->set_size(sizes.second); - - old_type_info_protobuf->set_alignment(alignments.first); - new_type_info_protobuf->set_alignment(alignments.second); - return true; -} - -bool IRDiffToProtobufConverter::AddVTableLayoutDiff( - abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf, - const VTableLayoutDiffIR *vtable_layout_diff_ir) { - abi_dump:: VTableLayout *old_vtable = - vtable_layout_diff_protobuf->mutable_old_vtable(); - abi_dump:: VTableLayout *new_vtable = - vtable_layout_diff_protobuf->mutable_new_vtable(); - if (old_vtable == nullptr || new_vtable == nullptr || - !SetIRToProtobufVTableLayout(old_vtable, - vtable_layout_diff_ir->GetOldVTable()) || - !SetIRToProtobufVTableLayout(new_vtable, - vtable_layout_diff_ir->GetNewVTable())) { - return false; - } - return true; -} - -template -static bool CopyBaseSpecifiersDiffIRToProtobuf( - google::protobuf::RepeatedPtrField *dst, - const std::vector &bases_ir) { - for (auto &&base_ir : bases_ir) { - T *added_base = dst->Add(); - if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) { - return false; - } - } - return true; -} - -bool IRDiffToProtobufConverter::AddBaseSpecifierDiffs( - abi_diff::CXXBaseSpecifierDiff *base_specifiers_diff_protobuf, - const CXXBaseSpecifierDiffIR *base_specifiers_diff_ir) { - if (!CopyBaseSpecifiersDiffIRToProtobuf( - base_specifiers_diff_protobuf->mutable_old_bases(), - base_specifiers_diff_ir->GetOldBases()) || - !CopyBaseSpecifiersDiffIRToProtobuf( - base_specifiers_diff_protobuf->mutable_new_bases(), - base_specifiers_diff_ir->GetNewBases())) { - return false; - } - return true; -} - -bool IRDiffToProtobufConverter::AddRecordFields( - abi_diff::RecordTypeDiff *record_diff_protobuf, - const std::vector &record_fields_ir, - bool field_removed) { - for (auto &&record_field_ir : record_fields_ir) { - abi_dump::RecordFieldDecl *field = nullptr; - if (field_removed) { - field = record_diff_protobuf->add_fields_removed(); - } else { - field = record_diff_protobuf->add_fields_added(); - } - if (field == nullptr) { - return false; - } - SetIRToProtobufRecordField(field, record_field_ir); - } - return true; -} - -bool IRDiffToProtobufConverter::AddRecordFieldDiffs( - abi_diff::RecordTypeDiff *record_diff_protobuf, - const std::vector &record_field_diffs_ir) { - for (auto &&record_field_diff_ir : record_field_diffs_ir) { - abi_diff::RecordFieldDeclDiff *record_field_diff = - record_diff_protobuf->add_fields_diff(); - if (record_field_diff == nullptr) { - return false; - } - abi_dump::RecordFieldDecl *old_field = - record_field_diff->mutable_old_field(); - abi_dump::RecordFieldDecl *new_field = - record_field_diff->mutable_new_field(); - if (old_field == nullptr || new_field == nullptr) { - return false; - } - SetIRToProtobufRecordField(old_field, - record_field_diff_ir.GetOldField()); - SetIRToProtobufRecordField(new_field, - record_field_diff_ir.GetNewField()); - } - return true; -} - -abi_diff::RecordTypeDiff IRDiffToProtobufConverter::ConvertRecordTypeDiffIR( - const RecordTypeDiffIR *record_type_diff_ir) { - abi_diff::RecordTypeDiff record_type_diff_protobuf; - record_type_diff_protobuf.set_name(record_type_diff_ir->GetName()); - const TypeDiffIR *type_diff_ir = record_type_diff_ir->GetTypeDiff(); - // If a type_info diff exists - if (type_diff_ir != nullptr) { - abi_diff::TypeInfoDiff *type_info_diff = - record_type_diff_protobuf.mutable_type_info_diff(); - if (!AddTypeInfoDiff(type_info_diff, type_diff_ir)) { - llvm::errs() << "RecordType could not be converted\n"; - ::exit(1); - } - } - // If vtables differ. - const VTableLayoutDiffIR *vtable_layout_diff_ir = - record_type_diff_ir->GetVTableLayoutDiff(); - if (vtable_layout_diff_ir != nullptr) { - abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf = - record_type_diff_protobuf.mutable_vtable_layout_diff(); - if (!AddVTableLayoutDiff(vtable_layout_diff_protobuf, - vtable_layout_diff_ir)) { - llvm::errs() << "VTable layout diff could not be added\n"; - ::exit(1); - } - } - // If base specifiers differ. - const CXXBaseSpecifierDiffIR *base_specifier_diff_ir = - record_type_diff_ir->GetBaseSpecifiers(); - if (base_specifier_diff_ir != nullptr) { - abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf = - record_type_diff_protobuf.mutable_bases_diff(); - if (!AddBaseSpecifierDiffs(base_specifier_diff_protobuf, - base_specifier_diff_ir)) { - llvm::errs() << "Base Specifier diff could not be added\n"; - ::exit(1); - } - } - // Field diffs - if (!AddRecordFields(&record_type_diff_protobuf, - record_type_diff_ir->GetFieldsRemoved(), true) || - !AddRecordFields(&record_type_diff_protobuf, - record_type_diff_ir->GetFieldsAdded(), false) || - !AddRecordFieldDiffs(&record_type_diff_protobuf, - record_type_diff_ir->GetFieldDiffs())) { - llvm::errs() << "Record Field diff could not be added\n"; - ::exit(1); - } - return record_type_diff_protobuf; -} - -bool IRDiffToProtobufConverter::AddEnumUnderlyingTypeDiff( - abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf, - const std::pair *underlying_type_diff_ir) { - if (underlying_type_diff_protobuf == nullptr) { - return false; - } - underlying_type_diff_protobuf->set_old_type(underlying_type_diff_ir->first); - underlying_type_diff_protobuf->set_new_type(underlying_type_diff_ir->second); - return true; -} - -static bool AddEnumFields( - google::protobuf::RepeatedPtrField *dst, - const std::vector &enum_fields) { - for (auto &&enum_field : enum_fields) { - abi_dump::EnumFieldDecl *added_enum_field = dst->Add(); - if (!SetIRToProtobufEnumField(added_enum_field, enum_field)) { - return false; - } - } - return true; -} - -static bool AddEnumFieldDiffs( - google::protobuf::RepeatedPtrField *dst, - const std::vector &fields_diff_ir) { - for (auto &&field_diff_ir : fields_diff_ir) { - abi_diff::EnumFieldDeclDiff *field_diff_protobuf = dst->Add(); - if (field_diff_protobuf == nullptr) { - return false; - } - if (!SetIRToProtobufEnumField(field_diff_protobuf->mutable_old_field(), - field_diff_ir.GetOldField()) || - !SetIRToProtobufEnumField(field_diff_protobuf->mutable_new_field(), - field_diff_ir.GetNewField())) { - return false; - } - } - return true; -} - -abi_diff::EnumTypeDiff IRDiffToProtobufConverter::ConvertEnumTypeDiffIR( - const EnumTypeDiffIR *enum_type_diff_ir) { - abi_diff::EnumTypeDiff enum_type_diff_protobuf; - enum_type_diff_protobuf.set_name(enum_type_diff_ir->GetName()); - const std::pair *underlying_type_diff = - enum_type_diff_ir->GetUnderlyingTypeDiff(); - if ((underlying_type_diff != nullptr && - !AddEnumUnderlyingTypeDiff( - enum_type_diff_protobuf.mutable_underlying_type_diff(), - underlying_type_diff)) || - !AddEnumFields(enum_type_diff_protobuf.mutable_fields_removed(), - enum_type_diff_ir->GetFieldsRemoved()) || - !AddEnumFields(enum_type_diff_protobuf.mutable_fields_added(), - enum_type_diff_ir->GetFieldsAdded()) || - !AddEnumFieldDiffs(enum_type_diff_protobuf.mutable_fields_diff(), - enum_type_diff_ir->GetFieldsDiff())) { - llvm::errs() << "Enum field diff could not be added\n"; - ::exit(1); - } - return enum_type_diff_protobuf; -} - -abi_diff::GlobalVarDeclDiff IRDiffToProtobufConverter::ConvertGlobalVarDiffIR( - const GlobalVarDiffIR *global_var_diff_ir) { - abi_diff::GlobalVarDeclDiff global_var_diff; - global_var_diff.set_name(global_var_diff_ir->GetName()); - abi_dump::GlobalVarDecl *old_global_var = global_var_diff.mutable_old(); - abi_dump::GlobalVarDecl *new_global_var = global_var_diff.mutable_new_(); - if (old_global_var == nullptr || new_global_var == nullptr) { - llvm::errs() << "Globar Var diff could not be added\n"; - ::exit(1); - } - *old_global_var = - IRToProtobufConverter::ConvertGlobalVarIR( - global_var_diff_ir->GetOldGlobalVar()); - *new_global_var = - IRToProtobufConverter::ConvertGlobalVarIR( - global_var_diff_ir->GetNewGlobalVar()); - return global_var_diff; -} - -abi_diff::FunctionDeclDiff IRDiffToProtobufConverter::ConvertFunctionDiffIR( - const FunctionDiffIR *function_diff_ir) { - abi_diff::FunctionDeclDiff function_diff; - function_diff.set_name(function_diff_ir->GetName()); - abi_dump::FunctionDecl *old_function = function_diff.mutable_old(); - abi_dump::FunctionDecl *new_function = function_diff.mutable_new_(); - if (old_function == nullptr || new_function == nullptr) { - llvm::errs() << "Function diff could not be added\n"; - ::exit(1); - } - *old_function = IRToProtobufConverter::ConvertFunctionIR( - function_diff_ir->GetOldFunction()); - *new_function = IRToProtobufConverter::ConvertFunctionIR( - function_diff_ir->GetNewFunction()); - return function_diff; -} - -bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) { - // No RTTI - switch (lm->GetKind()) { - case RecordTypeKind: - return AddRecordTypeIR(static_cast(lm)); - case EnumTypeKind: - return AddEnumTypeIR(static_cast(lm)); - case PointerTypeKind: - return AddPointerTypeIR(static_cast(lm)); - case QualifiedTypeKind: - return AddQualifiedTypeIR(static_cast(lm)); - case ArrayTypeKind: - return AddArrayTypeIR(static_cast(lm)); - case LvalueReferenceTypeKind: - return AddLvalueReferenceTypeIR( - static_cast(lm)); - case RvalueReferenceTypeKind: - return AddRvalueReferenceTypeIR( - static_cast(lm)); - case BuiltinTypeKind: - return AddBuiltinTypeIR(static_cast(lm)); - case FunctionTypeKind: - return AddFunctionTypeIR(static_cast(lm)); - case GlobalVarKind: - return AddGlobalVarIR(static_cast(lm)); - case FunctionKind: - return AddFunctionIR(static_cast(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()); - added_elf_function->set_binding( - ElfSymbolBindingIRToProtobuf(elf_function->GetBinding())); - 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()); - added_elf_object->set_binding( - ElfSymbolBindingIRToProtobuf(elf_object->GetBinding())); - return true; -} - -bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) { - switch (em->GetKind()) { - case ElfSymbolIR::ElfFunctionKind: - return AddElfFunctionIR(static_cast(em)); - case ElfSymbolIR::ElfObjectKind: - return AddElfObjectIR(static_cast(em)); - } - return false; -} - -bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) { - abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types(); - if (!added_record_type) { - return false; - } - *added_record_type = ConvertRecordTypeIR(recordp); - return true; -} - -bool ProtobufIRDumper::AddFunctionTypeIR(const FunctionTypeIR *function_typep) { - abi_dump::FunctionType *added_function_type = tu_ptr_->add_function_types(); - if (!added_function_type) { - return false; - } - *added_function_type = ConvertFunctionTypeIR(function_typep); - return true; -} - -bool ProtobufIRDumper::AddFunctionIR(const FunctionIR *functionp) { - abi_dump::FunctionDecl *added_function = tu_ptr_->add_functions(); - if (!added_function) { - return false; - } - *added_function = ConvertFunctionIR(functionp); - return true; -} - -bool ProtobufIRDumper::AddEnumTypeIR(const EnumTypeIR *enump) { - abi_dump::EnumType *added_enum_type = tu_ptr_->add_enum_types(); - if (!added_enum_type) { - return false; - } - *added_enum_type = ConvertEnumTypeIR(enump); - return true; -} - -bool ProtobufIRDumper::AddGlobalVarIR(const GlobalVarIR *global_varp) { - abi_dump::GlobalVarDecl *added_global_var = tu_ptr_->add_global_vars(); - if (!added_global_var) { - return false; - } - *added_global_var = ConvertGlobalVarIR(global_varp); - return true; -} - -bool ProtobufIRDumper::AddPointerTypeIR(const PointerTypeIR *pointerp) { - abi_dump::PointerType *added_pointer_type = tu_ptr_->add_pointer_types(); - if (!added_pointer_type) { - return false; - } - *added_pointer_type = ConvertPointerTypeIR(pointerp); - return true; -} - -bool ProtobufIRDumper::AddQualifiedTypeIR(const QualifiedTypeIR *qualtypep) { - abi_dump::QualifiedType *added_qualified_type = - tu_ptr_->add_qualified_types(); - if (!added_qualified_type) { - return false; - } - *added_qualified_type = ConvertQualifiedTypeIR(qualtypep); - return true; -} - -bool ProtobufIRDumper::AddBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) { - abi_dump::BuiltinType *added_builtin_type = - tu_ptr_->add_builtin_types(); - if (!added_builtin_type) { - return false; - } - *added_builtin_type = ConvertBuiltinTypeIR(builtin_typep); - return true; -} - -bool ProtobufIRDumper::AddArrayTypeIR(const ArrayTypeIR *array_typep) { - abi_dump::ArrayType *added_array_type = - tu_ptr_->add_array_types(); - if (!added_array_type) { - return false; - } - *added_array_type = ConvertArrayTypeIR(array_typep); - return true; -} - -bool ProtobufIRDumper::AddLvalueReferenceTypeIR( - const LvalueReferenceTypeIR *lvalue_reference_typep) { - abi_dump::LvalueReferenceType *added_lvalue_reference_type = - tu_ptr_->add_lvalue_reference_types(); - if (!added_lvalue_reference_type) { - return false; - } - *added_lvalue_reference_type = - ConvertLvalueReferenceTypeIR(lvalue_reference_typep); - return true; -} - -bool ProtobufIRDumper::AddRvalueReferenceTypeIR( - const RvalueReferenceTypeIR *rvalue_reference_typep) { - abi_dump::RvalueReferenceType *added_rvalue_reference_type = - tu_ptr_->add_rvalue_reference_types(); - if (!added_rvalue_reference_type) { - return false; - } - *added_rvalue_reference_type = - ConvertRvalueReferenceTypeIR(rvalue_reference_typep); - return true; -} - -bool ProtobufIRDumper::Dump() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - assert( tu_ptr_.get() != nullptr); - std::ofstream text_output(dump_path_); - google::protobuf::io::OstreamOutputStream text_os(&text_output); - return google::protobuf::TextFormat::Print(*tu_ptr_.get(), &text_os); -} - -void ProtobufIRDiffDumper::AddLibNameIR(const std::string &name) { - diff_tu_->set_lib_name(name); -} - -void ProtobufIRDiffDumper::AddArchIR(const std::string &arch) { - diff_tu_->set_arch(arch); -} - -CompatibilityStatusIR ProtobufIRDiffDumper::GetCompatibilityStatusIR() { - if (diff_tu_->functions_removed().size() != 0 || - diff_tu_->global_vars_removed().size() != 0 || - diff_tu_->function_diffs().size() != 0 || - diff_tu_->global_var_diffs().size() != 0 || - diff_tu_->enum_type_diffs().size() != 0 || - diff_tu_->record_type_diffs().size() != 0) { - return CompatibilityStatusIR::Incompatible; - } - - CompatibilityStatusIR combined_status = CompatibilityStatusIR::Compatible; - - if (diff_tu_->enum_type_extension_diffs().size() != 0 || - diff_tu_->functions_added().size() != 0 || - diff_tu_->global_vars_added().size() != 0) { - combined_status = combined_status | CompatibilityStatusIR::Extension; - } - - if (diff_tu_->unreferenced_enum_type_diffs().size() != 0 || - diff_tu_->unreferenced_enum_types_removed().size() != 0 || - diff_tu_->unreferenced_record_types_removed().size() != 0 || - diff_tu_->unreferenced_record_type_diffs().size() != 0 || - diff_tu_->unreferenced_enum_type_extension_diffs().size() != 0 || - diff_tu_->unreferenced_record_types_added().size() != 0 || - diff_tu_->unreferenced_enum_types_added().size()) { - combined_status = - combined_status | CompatibilityStatusIR::UnreferencedChanges; - } - - if (diff_tu_->removed_elf_functions().size() != 0 || - diff_tu_->removed_elf_objects().size() != 0) { - combined_status = combined_status | CompatibilityStatusIR::ElfIncompatible; - } - - return combined_status; -} - -void ProtobufIRDiffDumper::AddCompatibilityStatusIR( - CompatibilityStatusIR status) { - diff_tu_->set_compatibility_status(CompatibilityStatusIRToProtobuf(status)); -} - -bool ProtobufIRDiffDumper::AddDiffMessageIR(const DiffMessageIR *message, - const std::string &type_stack, - DiffKind diff_kind) { - switch (message->Kind()) { - case RecordTypeKind: - return AddRecordTypeDiffIR( - static_cast(message), type_stack, - diff_kind); - case EnumTypeKind: - return AddEnumTypeDiffIR( - static_cast(message), type_stack, diff_kind); - case GlobalVarKind: - return AddGlobalVarDiffIR( - static_cast(message), type_stack, diff_kind); - case FunctionKind: - return AddFunctionDiffIR( - static_cast(message), type_stack, diff_kind); - default: - break; - } - llvm::errs() << "Dump Diff attempted on something not a user defined type / " - << "function / global variable\n"; - return false; -} - -bool ProtobufIRDiffDumper::AddLinkableMessageIR( - const LinkableMessageIR *message, DiffKind diff_kind) { - switch (message->GetKind()) { - case RecordTypeKind: - return AddLoneRecordTypeDiffIR( - static_cast(message), diff_kind); - case EnumTypeKind: - return AddLoneEnumTypeDiffIR( - static_cast(message), diff_kind); - case GlobalVarKind: - return AddLoneGlobalVarDiffIR( - static_cast(message), diff_kind); - case FunctionKind: - return AddLoneFunctionDiffIR( - static_cast(message), diff_kind); - default: - break; - } - llvm::errs() << "Dump Diff attempted on something not a user defined type / " - << "function / global variable\n"; - return false; -} - -bool ProtobufIRDiffDumper::AddElfSymbolMessageIR(const ElfSymbolIR *elf_symbol, - DiffKind diff_kind) { - switch (elf_symbol->GetKind()) { - case ElfSymbolIR::ElfFunctionKind: - return AddElfFunctionIR(static_cast(elf_symbol), - diff_kind); - break; - case ElfSymbolIR::ElfObjectKind: - return AddElfObjectIR(static_cast(elf_symbol), - diff_kind); - break; - } - // Any other kind is invalid - return false; -} - -bool ProtobufIRDiffDumper::AddElfFunctionIR( - const ElfFunctionIR *elf_function_ir, DiffKind diff_kind) { - abi_dump::ElfFunction *added_elf_function = nullptr; - switch (diff_kind) { - case DiffKind::Removed: - added_elf_function = diff_tu_->add_removed_elf_functions(); - break; - case DiffKind::Added: - added_elf_function = diff_tu_->add_added_elf_functions(); - break; - default: - llvm::errs() << "Invalid call to AddElfFunctionIR\n"; - return false; - } - if (added_elf_function == nullptr) { - return false; - } - *added_elf_function = - IRToProtobufConverter::ConvertElfFunctionIR(elf_function_ir); - return true; -} - -bool ProtobufIRDiffDumper::AddElfObjectIR( - const ElfObjectIR *elf_object_ir, DiffKind diff_kind) { - abi_dump::ElfObject *added_elf_object = nullptr; - switch (diff_kind) { - case DiffKind::Removed: - added_elf_object = diff_tu_->add_removed_elf_objects(); - break; - case DiffKind::Added: - added_elf_object = diff_tu_->add_added_elf_objects(); - break; - default: - llvm::errs() << "Invalid call to AddElfObjectIR\n"; - return false; - } - if (added_elf_object == nullptr) { - return false; - } - *added_elf_object = - IRToProtobufConverter::ConvertElfObjectIR(elf_object_ir); - return true; -} - -bool ProtobufIRDiffDumper::AddLoneRecordTypeDiffIR( - const RecordTypeIR *record_type_ir, DiffKind diff_kind) { - abi_dump::RecordType *added_record_type = nullptr; - switch (diff_kind) { - case DiffKind::Removed: - // Referenced record types do not get reported as added / removed, - // the diff shows up in the parent type / function/ global variable - // referencing the record. - added_record_type = diff_tu_->add_unreferenced_record_types_removed(); - break; - case DiffKind::Added: - added_record_type = diff_tu_->add_unreferenced_record_types_added(); - break; - default: - llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n"; - return false; - } - if (added_record_type == nullptr) { - return false; - } - *added_record_type = - IRToProtobufConverter::ConvertRecordTypeIR(record_type_ir); - return true; -} - -bool ProtobufIRDiffDumper::AddLoneFunctionDiffIR( - const FunctionIR *function_ir, DiffKind diff_kind) { - abi_dump::FunctionDecl *added_function = nullptr; - switch (diff_kind) { - case DiffKind::Removed: - added_function = diff_tu_->add_functions_removed(); - break; - case DiffKind::Added: - added_function = diff_tu_->add_functions_added(); - break; - default: - llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n"; - return false; - } - *added_function = IRToProtobufConverter::ConvertFunctionIR(function_ir); - return true; -} - -bool ProtobufIRDiffDumper::AddLoneEnumTypeDiffIR( - const EnumTypeIR *enum_type_ir, DiffKind diff_kind) { - abi_dump::EnumType *added_enum_type = nullptr; - switch (diff_kind) { - case DiffKind::Removed: - // Referenced enum types do not get reported as added / removed, - // the diff shows up in the parent type / function/ global variable - // referencing the enum. - added_enum_type = diff_tu_->add_unreferenced_enum_types_removed(); - break; - case DiffKind::Added: - added_enum_type = diff_tu_->add_unreferenced_enum_types_added(); - break; - default: - llvm::errs() << "Invalid call to AddLoneRecordTypeDiffIR\n"; - return false; - } - if (added_enum_type == nullptr) { - return false; - } - *added_enum_type = IRToProtobufConverter::ConvertEnumTypeIR(enum_type_ir); - return true; -} - -bool ProtobufIRDiffDumper::AddLoneGlobalVarDiffIR( - const GlobalVarIR *global_var_ir, DiffKind diff_kind) { - abi_dump::GlobalVarDecl *added_global_var = nullptr; - switch (diff_kind) { - case DiffKind::Removed: - added_global_var = diff_tu_->add_global_vars_removed(); - break; - case DiffKind::Added: - added_global_var = diff_tu_->add_global_vars_added(); - break; - default: - llvm::errs() << "Invalid call to AddLoneFunctionDiffIR\n"; - return false; - } - *added_global_var = IRToProtobufConverter::ConvertGlobalVarIR(global_var_ir); - return true; -} - -bool ProtobufIRDiffDumper::AddRecordTypeDiffIR( - const RecordTypeDiffIR *record_diff_ir, const std::string &type_stack, - DiffKind diff_kind) { - abi_diff::RecordTypeDiff *added_record_type_diff = nullptr; - switch (diff_kind) { - case DiffKind::Unreferenced: - added_record_type_diff = diff_tu_->add_unreferenced_record_type_diffs(); - break; - case DiffKind::Referenced: - added_record_type_diff = diff_tu_->add_record_type_diffs(); - break; - default: - break; - } - if (!added_record_type_diff) { - return false; - } - - *added_record_type_diff = - IRDiffToProtobufConverter::ConvertRecordTypeDiffIR(record_diff_ir); - added_record_type_diff->set_type_stack(type_stack); - return true; -} - -bool ProtobufIRDiffDumper::AddFunctionDiffIR( - const FunctionDiffIR *function_diff_ir, const std::string &type_stack, - DiffKind diff_kind) { - abi_diff::FunctionDeclDiff *added_function_diff = - diff_tu_->add_function_diffs(); - if (!added_function_diff) { - return false; - } - *added_function_diff = - IRDiffToProtobufConverter::ConvertFunctionDiffIR(function_diff_ir); - return true; -} - -bool ProtobufIRDiffDumper::AddEnumTypeDiffIR(const EnumTypeDiffIR *enum_diff_ir, - const std::string &type_stack, - DiffKind diff_kind) { - abi_diff::EnumTypeDiff *added_enum_type_diff = nullptr; - switch (diff_kind) { - case DiffKind::Unreferenced: - if (enum_diff_ir->IsExtended()) { - added_enum_type_diff = - diff_tu_->add_unreferenced_enum_type_extension_diffs(); - } else { - added_enum_type_diff = - diff_tu_->add_unreferenced_enum_type_diffs(); - } - break; - case DiffKind::Referenced: - if (enum_diff_ir->IsExtended()) { - added_enum_type_diff = - diff_tu_->add_enum_type_extension_diffs(); - } else { - added_enum_type_diff = - diff_tu_->add_enum_type_diffs(); - } - break; - default: - break; - } - if (!added_enum_type_diff) { - return false; - } - *added_enum_type_diff = - IRDiffToProtobufConverter::ConvertEnumTypeDiffIR(enum_diff_ir); - added_enum_type_diff->set_type_stack(type_stack); - return true; -} - -bool ProtobufIRDiffDumper::AddGlobalVarDiffIR( - const GlobalVarDiffIR *global_var_diff_ir, const std::string &type_stack, - DiffKind diff_kind) { - abi_diff::GlobalVarDeclDiff *added_global_var_diff = - diff_tu_->add_global_var_diffs(); - if (!added_global_var_diff) { - return false; - } - *added_global_var_diff = - IRDiffToProtobufConverter::ConvertGlobalVarDiffIR(global_var_diff_ir); - return true; -} - -bool ProtobufIRDiffDumper::Dump() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - assert(diff_tu_.get() != nullptr); - std::ofstream text_output(dump_path_); - google::protobuf::io::OstreamOutputStream text_os(&text_output); - return google::protobuf::TextFormat::Print(*diff_tu_.get(), &text_os); -} - - -} // namespace repr -} // namespace header_checker diff --git a/vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.h b/vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.h deleted file mode 100644 index 8f55eb822..000000000 --- a/vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.h +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef IR_REPRESENTATION_PROTOBUF_H_ -#define IR_REPRESENTATION_PROTOBUF_H_ - -#include "repr/ir_representation.h" - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-parameter" -#pragma clang diagnostic ignored "-Wnested-anon-types" -#include "abi_dump.pb.h" -#include "abi_diff.pb.h" -#pragma clang diagnostic pop - -#include -#include - - -namespace header_checker { -namespace repr { - - -// Classes which act as middle-men between clang AST parsing routines and -// message format specific dumpers. - -inline abi_diff::CompatibilityStatus CompatibilityStatusIRToProtobuf( - CompatibilityStatusIR status) { - switch (status) { - case CompatibilityStatusIR::Incompatible: - return abi_diff::CompatibilityStatus::INCOMPATIBLE; - case CompatibilityStatusIR::Extension: - return abi_diff::CompatibilityStatus::EXTENSION; - default: - break; - } - return abi_diff::CompatibilityStatus::COMPATIBLE; -} - -inline abi_dump::ElfSymbolBinding ElfSymbolBindingIRToProtobuf( - ElfSymbolIR::ElfSymbolBinding binding) { - switch (binding) { - case ElfSymbolIR::ElfSymbolBinding::Global: - return abi_dump::ElfSymbolBinding::Global; - case ElfSymbolIR::ElfSymbolBinding::Weak: - return abi_dump::ElfSymbolBinding::Weak; - } - // We skip symbols of all other Bindings - // TODO: Add all bindings, don't leave out info - assert(0); -} - -inline ElfSymbolIR::ElfSymbolBinding ElfSymbolBindingProtobufToIR( - abi_dump::ElfSymbolBinding binding) { - switch (binding) { - case abi_dump::ElfSymbolBinding::Global: - return ElfSymbolIR::ElfSymbolBinding::Global; - case abi_dump::ElfSymbolBinding::Weak: - return ElfSymbolIR::ElfSymbolBinding::Weak; - } - // We skip symbols of all other Bindings - assert(0); -} - -inline abi_dump::AccessSpecifier AccessIRToProtobuf(AccessSpecifierIR access) { - switch (access) { - case AccessSpecifierIR::ProtectedAccess: - return abi_dump::AccessSpecifier::protected_access; - case AccessSpecifierIR::PrivateAccess: - return abi_dump::AccessSpecifier::private_access; - default: - return abi_dump::AccessSpecifier::public_access; - } - return abi_dump::AccessSpecifier::public_access; -} - -inline AccessSpecifierIR AccessProtobufToIR( - abi_dump::AccessSpecifier access) { - switch (access) { - case abi_dump::AccessSpecifier::protected_access: - return AccessSpecifierIR::ProtectedAccess; - case abi_dump::AccessSpecifier::private_access: - return AccessSpecifierIR::PrivateAccess; - default: - return AccessSpecifierIR::PublicAccess; - } - return AccessSpecifierIR::PublicAccess; -} - -inline abi_dump::RecordKind RecordKindIRToProtobuf( - RecordTypeIR::RecordKind kind) { - switch (kind) { - case RecordTypeIR::RecordKind::struct_kind: - return abi_dump::RecordKind::struct_kind; - - case RecordTypeIR::RecordKind::class_kind: - return abi_dump::RecordKind::class_kind; - - case RecordTypeIR::RecordKind::union_kind: - return abi_dump::RecordKind::union_kind; - - default: - return abi_dump::RecordKind::struct_kind; - } - // Should not be reached - assert(false); -} - -inline RecordTypeIR::RecordKind RecordKindProtobufToIR( - abi_dump::RecordKind kind) { - switch (kind) { - case abi_dump::RecordKind::struct_kind: - return RecordTypeIR::struct_kind; - - case abi_dump::RecordKind::class_kind: - return RecordTypeIR::class_kind; - - case abi_dump::RecordKind::union_kind: - return RecordTypeIR::union_kind; - - default: - return RecordTypeIR::struct_kind; - } - // Should not be reached - assert(false); -} - -inline abi_dump::VTableComponent::Kind VTableComponentKindIRToProtobuf( - VTableComponentIR::Kind kind) { - switch (kind) { - case VTableComponentIR::Kind::VCallOffset: - return abi_dump::VTableComponent_Kind_VCallOffset; - - case VTableComponentIR::Kind::VBaseOffset: - return abi_dump::VTableComponent_Kind_VBaseOffset; - - case VTableComponentIR::Kind::OffsetToTop: - return abi_dump::VTableComponent_Kind_OffsetToTop; - - case VTableComponentIR::Kind::RTTI: - return abi_dump::VTableComponent_Kind_RTTI; - - case VTableComponentIR::Kind::FunctionPointer: - return abi_dump::VTableComponent_Kind_FunctionPointer; - - case VTableComponentIR::Kind::CompleteDtorPointer: - return abi_dump::VTableComponent_Kind_CompleteDtorPointer; - - case VTableComponentIR::Kind::DeletingDtorPointer: - return abi_dump::VTableComponent_Kind_DeletingDtorPointer; - - default: - return abi_dump::VTableComponent_Kind_UnusedFunctionPointer; - } - // Should not be reached - assert(false); -} - -inline VTableComponentIR::Kind VTableComponentKindProtobufToIR( - abi_dump::VTableComponent_Kind kind) { - switch (kind) { - case abi_dump::VTableComponent_Kind_VCallOffset: - return VTableComponentIR::Kind::VCallOffset; - - case abi_dump::VTableComponent_Kind_VBaseOffset: - return VTableComponentIR::Kind::VBaseOffset; - - case abi_dump::VTableComponent_Kind_OffsetToTop: - return VTableComponentIR::Kind::OffsetToTop; - - case abi_dump::VTableComponent_Kind_RTTI: - return VTableComponentIR::Kind::RTTI; - - case abi_dump::VTableComponent_Kind_FunctionPointer: - return VTableComponentIR::Kind::FunctionPointer; - - case abi_dump::VTableComponent_Kind_CompleteDtorPointer: - return VTableComponentIR::Kind::CompleteDtorPointer; - - case abi_dump::VTableComponent_Kind_DeletingDtorPointer: - return VTableComponentIR::Kind::DeletingDtorPointer; - - default: - return VTableComponentIR::Kind::UnusedFunctionPointer; - } - // Should not be reached - assert(false); -} - -class IRToProtobufConverter { - private: - static bool AddTemplateInformation( - abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta); - - static bool AddTypeInfo( - abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep); - - static bool AddRecordFields( - abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir); - - static bool AddBaseSpecifiers( - abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir); - - static bool AddVTableLayout( - abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir); - - static bool AddTagTypeInfo(abi_dump::TagType *tag_type_protobuf, - const TagTypeIR *tag_type_ir); - - static bool AddEnumFields(abi_dump::EnumType *enum_protobuf, - const EnumTypeIR *enum_ir); - - public: - static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump); - - static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp); - - static abi_dump::FunctionType ConvertFunctionTypeIR ( - const FunctionTypeIR *function_typep); - - template - static bool AddFunctionParametersAndSetReturnType( - CFunctionLikeMessage *function_like_protobuf, - const CFunctionLikeIR *cfunction_like_ir); - - template - static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf, - const CFunctionLikeIR *cfunction_like_ir); - - static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp); - - static abi_dump::GlobalVarDecl ConvertGlobalVarIR( - const GlobalVarIR *global_varp); - - static abi_dump::PointerType ConvertPointerTypeIR( - const PointerTypeIR *pointerp); - - static abi_dump::QualifiedType ConvertQualifiedTypeIR( - const QualifiedTypeIR *qualtypep); - - static abi_dump::BuiltinType ConvertBuiltinTypeIR( - const BuiltinTypeIR *builtin_typep); - - static abi_dump::ArrayType ConvertArrayTypeIR( - const ArrayTypeIR *array_typep); - - static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR( - const LvalueReferenceTypeIR *lvalue_reference_typep); - - static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR( - const RvalueReferenceTypeIR *rvalue_reference_typep); - - static abi_dump::ElfFunction ConvertElfFunctionIR( - const ElfFunctionIR *elf_function_ir); - - static abi_dump::ElfObject ConvertElfObjectIR( - const ElfObjectIR *elf_object_ir); -}; - -class IRDiffToProtobufConverter { - private: - static bool AddTypeInfoDiff( - abi_diff::TypeInfoDiff *type_info_diff_protobuf, - const TypeDiffIR *type_diff_ir); - - static bool AddVTableLayoutDiff( - abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf, - const VTableLayoutDiffIR *vtable_layout_diff_ir); - - static bool AddBaseSpecifierDiffs( - abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf, - const CXXBaseSpecifierDiffIR *base_specifier_diff_ir); - - static bool AddRecordFields( - abi_diff::RecordTypeDiff *record_diff_protobuf, - const std::vector &record_fields_removed_ir, - bool removed); - - static bool AddRecordFieldDiffs( - abi_diff::RecordTypeDiff *record_diff_protobuf, - const std::vector &record_field_diff_ir); - - static bool AddEnumUnderlyingTypeDiff( - abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf, - const std::pair *underlying_type_diff_ir); - - public: - static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR( - const RecordTypeDiffIR *record_type_diffp); - - static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR( - const EnumTypeDiffIR *enum_type_diffp); - - static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR( - const FunctionDiffIR *function_diffp); - - static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR( - const GlobalVarDiffIR *global_var_diffp); -}; - -class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter { - private: - // Types - bool AddRecordTypeIR(const RecordTypeIR *); - - bool AddEnumTypeIR(const EnumTypeIR *); - - bool AddPointerTypeIR(const PointerTypeIR *); - - bool AddQualifiedTypeIR(const QualifiedTypeIR *); - - bool AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR *); - - bool AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR *); - - bool AddArrayTypeIR(const ArrayTypeIR *); - - bool AddBuiltinTypeIR(const BuiltinTypeIR *); - - bool AddFunctionTypeIR(const FunctionTypeIR *function_typep); - - // Functions and global variables. - bool AddFunctionIR(const FunctionIR *); - - 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()) {} - - ~ProtobufIRDumper() override {} - - bool AddLinkableMessageIR(const LinkableMessageIR *) override; - - bool AddElfSymbolMessageIR(const ElfSymbolIR *) override; - - bool Dump() override; - - private: - std::unique_ptr tu_ptr_; -}; - - -class ProtobufTextFormatToIRReader : public TextFormatToIRReader { - private: - template - using RepeatedPtrField = google::protobuf::RepeatedPtrField; - - public: - ProtobufTextFormatToIRReader(const std::set *exported_headers) - : TextFormatToIRReader(exported_headers) {} - - bool ReadDump(const std::string &dump_file) override; - - private: - void ReadFunctions(const abi_dump::TranslationUnit &tu); - - void ReadGlobalVariables(const abi_dump::TranslationUnit &tu); - - void ReadEnumTypes(const abi_dump::TranslationUnit &tu); - - void ReadRecordTypes(const abi_dump::TranslationUnit &tu); - - void ReadFunctionTypes(const abi_dump::TranslationUnit &tu); - - void ReadPointerTypes(const abi_dump::TranslationUnit &tu); - - void ReadBuiltinTypes(const abi_dump::TranslationUnit &tu); - - void ReadQualifiedTypes(const abi_dump::TranslationUnit &tu); - - void ReadArrayTypes(const abi_dump::TranslationUnit &tu); - - void ReadLvalueReferenceTypes(const abi_dump::TranslationUnit &tu); - - void ReadRvalueReferenceTypes(const abi_dump::TranslationUnit &tu); - - void ReadElfFunctions(const abi_dump::TranslationUnit &tu); - - void ReadElfObjects(const abi_dump::TranslationUnit &tu); - - void ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl &type_info, - TypeIR *typep); - - FunctionIR FunctionProtobufToIR(const abi_dump::FunctionDecl &); - - FunctionTypeIR FunctionTypeProtobufToIR( - const abi_dump::FunctionType &function_type_protobuf); - - RecordTypeIR RecordTypeProtobufToIR( - const abi_dump::RecordType &record_type_protobuf); - - std::vector RecordFieldsProtobufToIR( - const RepeatedPtrField &rfp); - - std::vector RecordCXXBaseSpecifiersProtobufToIR( - const RepeatedPtrField &rbs); - - std::vector EnumFieldsProtobufToIR( - const RepeatedPtrField &efp); - - EnumTypeIR EnumTypeProtobufToIR( - const abi_dump::EnumType &enum_type_protobuf); - - VTableLayoutIR VTableLayoutProtobufToIR( - const abi_dump::VTableLayout &vtable_layout_protobuf); - - TemplateInfoIR TemplateInfoProtobufToIR( - const abi_dump::TemplateInfo &template_info_protobuf); -}; - -class ProtobufIRDiffDumper : public IRDiffDumper { - public: - ProtobufIRDiffDumper(const std::string &dump_path) - : IRDiffDumper(dump_path), - diff_tu_(new abi_diff::TranslationUnitDiff()) {} - - ~ProtobufIRDiffDumper() override {} - - bool AddDiffMessageIR(const DiffMessageIR *, const std::string &type_stack, - DiffKind diff_kind) override; - - bool AddLinkableMessageIR(const LinkableMessageIR *, - DiffKind diff_kind) override; - - bool AddElfSymbolMessageIR(const ElfSymbolIR *, DiffKind diff_kind) override; - - void AddLibNameIR(const std::string &name) override; - - void AddArchIR(const std::string &arch) override; - - void AddCompatibilityStatusIR(CompatibilityStatusIR status) override; - - bool Dump() override; - - CompatibilityStatusIR GetCompatibilityStatusIR() override; - - private: - // User defined types. - bool AddRecordTypeDiffIR(const RecordTypeDiffIR *, - const std::string &type_stack, DiffKind diff_kind); - - bool AddEnumTypeDiffIR(const EnumTypeDiffIR *, - const std::string &type_stack, DiffKind diff_kind); - - // Functions and global variables. - bool AddFunctionDiffIR(const FunctionDiffIR *, - const std::string &type_stack, DiffKind diff_kind); - - bool AddGlobalVarDiffIR(const GlobalVarDiffIR *, - const std::string &type_stack, DiffKind diff_kind); - - bool AddLoneRecordTypeDiffIR(const RecordTypeIR *, DiffKind diff_kind); - - bool AddLoneEnumTypeDiffIR(const EnumTypeIR *, DiffKind diff_kind); - - // Functions and global variables. - bool AddLoneFunctionDiffIR(const FunctionIR *, DiffKind diff_kind); - - bool AddLoneGlobalVarDiffIR(const GlobalVarIR *, DiffKind diff_kind); - - bool AddElfObjectIR(const ElfObjectIR *elf_object_ir, DiffKind diff_kind); - - bool AddElfFunctionIR(const ElfFunctionIR *elf_function_ir, - DiffKind diff_kind); - - protected: - std::unique_ptr diff_tu_; -}; - - -} // namespace repr -} // namespace header_checker - -#endif // IR_REPRESENTATION_PROTOBUF_H_ -- cgit v1.2.3