diff options
| author | Logan Chien <loganchien@google.com> | 2019-03-14 15:48:35 +0800 |
|---|---|---|
| committer | Logan Chien <loganchien@google.com> | 2019-03-20 17:06:13 +0800 |
| commit | fb0213fe3d98be7fc591bec657b75613075a05c4 (patch) | |
| tree | 99c74103a768003e86ea7feab98dffde7a1505f3 /vndk | |
| parent | a58b9d9f6a09d413967c29358fdad54dd04a9574 (diff) | |
| download | android_development-fb0213fe3d98be7fc591bec657b75613075a05c4.tar.gz android_development-fb0213fe3d98be7fc591bec657b75613075a05c4.tar.bz2 android_development-fb0213fe3d98be7fc591bec657b75613075a05c4.zip | |
header-checker: Split IRDumper and IRReader
Test: ./tests/test.py
Test: ${ANDROID_HOST_OUT}/nativetest64/\
header-checker-unittests/header-checker-unittests
Change-Id: I975ec98924901f2ab059d2b7a96065d419742dfb
Diffstat (limited to 'vndk')
33 files changed, 3681 insertions, 3003 deletions
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 <google/protobuf/text_format.h> #include <google/protobuf/io/zero_copy_stream_impl.h> 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 <clang/AST/QualTypeNames.h> 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 <clang/AST/AST.h> 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 <clang/AST/AST.h> #include <clang/AST/ASTConsumer.h> 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 <deque> @@ -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<DiffStatus>( static_cast<std::underlying_type<DiffStatus>::type>(f) | static_cast<std::underlying_type<DiffStatus>::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 <memory> +#include <string> + +#include <llvm/Support/raw_ostream.h> + + +namespace header_checker { +namespace repr { + + +std::unique_ptr<IRDiffDumper> IRDiffDumper::CreateIRDiffDumper( + TextFormatIR text_format, const std::string &dump_path) { + switch (text_format) { + case TextFormatIR::ProtobufTextFormat: + return std::make_unique<ProtobufIRDiffDumper>(dump_path); + default: + // Nothing else is supported yet. + llvm::errs() << "Text format not supported yet\n"; + return nullptr; + } +} + + +} // 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 <string> + + +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<IRDiffDumper> 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 <cstdint> +#include <memory> +#include <string> +#include <utility> +#include <vector> + + +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<uint64_t, uint64_t> &&sizes, + std::pair<uint32_t, uint32_t> &&alignment) + : sizes_(std::move(sizes)), alignments_(std::move(alignment)) {} + + const std::pair<uint64_t, uint64_t> &GetSizes() const { + return sizes_; + } + + const std::pair<uint32_t, uint32_t> &GetAlignments() const { + return alignments_; + } + + protected: + std::pair<uint64_t, uint64_t> sizes_; + std::pair<uint32_t, uint32_t> 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<CXXBaseSpecifierIR> &old_base_specifiers, + const std::vector<CXXBaseSpecifierIR> &new_base_specifiers) + : old_base_specifiers_(old_base_specifiers), + new_base_specifiers_(new_base_specifiers) {} + + const std::vector<CXXBaseSpecifierIR> &GetOldBases() const { + return old_base_specifiers_; + } + + const std::vector<CXXBaseSpecifierIR> &GetNewBases() const { + return new_base_specifiers_; + } + + protected: + const std::vector<CXXBaseSpecifierIR> &old_base_specifiers_; + const std::vector<CXXBaseSpecifierIR> &new_base_specifiers_; +}; + +class RecordTypeDiffIR : public DiffMessageIR { + public: + LinkableMessageKind Kind() const override { + return LinkableMessageKind::RecordTypeKind; + } + + void SetFieldDiffs(std::vector<RecordFieldDiffIR> &&field_diffs) { + field_diffs_ = std::move(field_diffs); + } + + const std::vector<RecordFieldDiffIR> &GetFieldDiffs() const { + return field_diffs_; + } + + void SetFieldsRemoved(std::vector<const RecordFieldIR *> &&fields_removed) { + fields_removed_ = std::move(fields_removed); + } + + void SetFieldsAdded(std::vector<const RecordFieldIR *> &&fields_added) { + fields_added_ = std::move(fields_added); + } + + const std::vector<const RecordFieldIR *> &GetFieldsRemoved() const { + return fields_removed_; + } + + const std::vector<const RecordFieldIR *> &GetFieldsAdded() const { + return fields_added_; + } + + void SetVTableLayoutDiff(std::unique_ptr<VTableLayoutDiffIR> &&vtable_diffs) { + vtable_diffs_ = std::move(vtable_diffs); + } + + void SetTypeDiff(std::unique_ptr<TypeDiffIR> &&type_diff) { + type_diff_ = std::move(type_diff); + } + + void SetAccessDiff(std::unique_ptr<AccessSpecifierDiffIR> &&access_diff) { + access_diff_ = std::move(access_diff); + } + + void SetBaseSpecifierDiffs( + std::unique_ptr<CXXBaseSpecifierDiffIR> &&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<TypeDiffIR> type_diff_; + std::unique_ptr<VTableLayoutDiffIR> vtable_diffs_; + std::vector<RecordFieldDiffIR> field_diffs_; + std::vector<const RecordFieldIR *> fields_removed_; + std::vector<const RecordFieldIR *> fields_added_; + std::unique_ptr<AccessSpecifierDiffIR> access_diff_; + std::unique_ptr<CXXBaseSpecifierDiffIR> 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<const EnumFieldIR *> &&fields_removed) { + fields_removed_ = std::move(fields_removed); + } + + const std::vector<const EnumFieldIR *> &GetFieldsRemoved() const { + return fields_removed_; + } + + void SetFieldsAdded(std::vector<const EnumFieldIR *> &&fields_added) { + fields_added_ = std::move(fields_added); + } + + const std::vector<const EnumFieldIR *> &GetFieldsAdded() const { + return fields_added_; + } + + void SetFieldsDiff(std::vector<EnumFieldDiffIR> &&fields_diff) { + fields_diff_ = std::move(fields_diff); + } + + const std::vector<EnumFieldDiffIR> &GetFieldsDiff() const { + return fields_diff_; + } + + void SetUnderlyingTypeDiff( + std::unique_ptr<std::pair<std::string, std::string>> &&utype_diff) { + underlying_type_diff_ = std::move(utype_diff); + } + + const std::pair<std::string, std::string> *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<std::pair<std::string, std::string>> underlying_type_diff_; + std::vector<const EnumFieldIR *> fields_removed_; + std::vector<const EnumFieldIR *> fields_added_; + std::vector<EnumFieldDiffIR> 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 <memory> +#include <string> + +#include <llvm/Support/raw_ostream.h> + + +namespace header_checker { +namespace repr { + + +std::unique_ptr<IRDumper> IRDumper::CreateIRDumper( + TextFormatIR text_format, const std::string &dump_path) { + switch (text_format) { + case TextFormatIR::ProtobufTextFormat: + return std::make_unique<ProtobufIRDumper>(dump_path); + case TextFormatIR::Json: + return std::make_unique<JsonIRDumper>(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 <string> + + +namespace header_checker { +namespace repr { + + +class IRDumper { + public: + IRDumper(const std::string &dump_path) : dump_path_(dump_path) {} + + virtual ~IRDumper() {} + + static std::unique_ptr<IRDumper> CreateIRDumper( + TextFormatIR text_format, const std::string &dump_path); + + virtual bool AddLinkableMessageIR(const LinkableMessageIR *) = 0; + + virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *) = 0; + + virtual bool Dump() = 0; + + 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_representation.cpp b/vndk/tools/header-checker/src/repr/ir_reader.cpp index af70a5e67..0b7ad2f3e 100644 --- a/vndk/tools/header-checker/src/repr/ir_representation.cpp +++ b/vndk/tools/header-checker/src/repr/ir_reader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Android Open Source Project +// 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. @@ -12,26 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "repr/ir_representation.h" +#include "repr/ir_reader.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 <google/protobuf/text_format.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> - -#include <llvm/Support/raw_ostream.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 <string> +#include <list> #include <memory> +#include <set> +#include <string> +#include <llvm/Support/raw_ostream.h> namespace header_checker { @@ -40,30 +35,6 @@ namespace repr { using MergeStatus = TextFormatToIRReader::MergeStatus; -std::unique_ptr<IRDumper> IRDumper::CreateIRDumper( - TextFormatIR text_format, const std::string &dump_path) { - switch (text_format) { - case TextFormatIR::ProtobufTextFormat: - return std::make_unique<ProtobufIRDumper>(dump_path); - case TextFormatIR::Json: - return std::make_unique<JsonIRDumper>(dump_path); - default: - llvm::errs() << "Text format not supported yet\n"; - return nullptr; - } -} - -std::unique_ptr<IRDiffDumper> IRDiffDumper::CreateIRDiffDumper( - TextFormatIR text_format, const std::string &dump_path) { - switch (text_format) { - case TextFormatIR::ProtobufTextFormat: - return std::make_unique<ProtobufIRDiffDumper>(dump_path); - default: - // Nothing else is supported yet. - llvm::errs() << "Text format not supported yet\n"; - return nullptr; - } -} std::unique_ptr<TextFormatToIRReader> TextFormatToIRReader::CreateTextFormatToIRReader( @@ -79,6 +50,7 @@ TextFormatToIRReader::CreateTextFormatToIRReader( } } + void TextFormatToIRReader::AddToODRListMap(const std::string &key, const TypeIR *value) { auto map_it = module_->odr_list_map_.find(key); @@ -89,10 +61,10 @@ void TextFormatToIRReader::AddToODRListMap(const std::string &key, module_->odr_list_map_[key].emplace_back(value); } + MergeStatus TextFormatToIRReader::IsBuiltinTypeNodePresent( const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, AbiElementMap<MergeStatus> *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()) { @@ -113,6 +85,7 @@ MergeStatus TextFormatToIRReader::IsBuiltinTypeNodePresent( return merge_status; } + MergeStatus TextFormatToIRReader::DoesUDTypeODRViolationExist( const TypeIR *ud_type, const TextFormatToIRReader &addend, const std::string ud_type_unique_id_and_source, @@ -150,6 +123,7 @@ MergeStatus TextFormatToIRReader::DoesUDTypeODRViolationExist( return MergeStatus(true, (*(it->second.begin()))->GetSelfType()); } + MergeStatus TextFormatToIRReader::IsTypeNodePresent( const TypeIR *addend_node, const TextFormatToIRReader &addend, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -177,6 +151,7 @@ MergeStatus TextFormatToIRReader::IsTypeNodePresent( 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*. @@ -216,6 +191,7 @@ MergeStatus TextFormatToIRReader::MergeReferencingTypeInternal( return MergeStatus(true, hidden_type_id); } + void TextFormatToIRReader::MergeRecordFields( const TextFormatToIRReader &addend, RecordTypeIR *added_node, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -224,6 +200,7 @@ void TextFormatToIRReader::MergeRecordFields( } } + void TextFormatToIRReader::MergeRecordCXXBases( const TextFormatToIRReader &addend, RecordTypeIR *added_node, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -232,6 +209,7 @@ void TextFormatToIRReader::MergeRecordCXXBases( } } + void TextFormatToIRReader::MergeRecordTemplateElements( const TextFormatToIRReader &addend, RecordTypeIR *added_node, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -241,6 +219,7 @@ void TextFormatToIRReader::MergeRecordTemplateElements( } } + void TextFormatToIRReader::MergeRecordDependencies( const TextFormatToIRReader &addend, RecordTypeIR *added_node, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -253,6 +232,7 @@ void TextFormatToIRReader::MergeRecordDependencies( MergeRecordTemplateElements(addend, added_node, local_to_global_type_id_map); } + template <typename T> std::pair<MergeStatus, typename AbiElementMap<T>::iterator> TextFormatToIRReader::UpdateUDTypeAccounting( @@ -277,6 +257,8 @@ TextFormatToIRReader::UpdateUDTypeAccounting( 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( @@ -290,6 +272,7 @@ MergeStatus TextFormatToIRReader::MergeRecordAndDependencies( return merge_status_and_it.first; } + void TextFormatToIRReader::MergeEnumDependencies( const TextFormatToIRReader &addend, EnumTypeIR *added_node, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -307,6 +290,7 @@ void TextFormatToIRReader::MergeEnumDependencies( 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( @@ -320,6 +304,7 @@ MergeStatus TextFormatToIRReader::MergeEnumType( return merge_status_and_it.first; } + MergeStatus TextFormatToIRReader::MergeFunctionType( const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -331,6 +316,7 @@ MergeStatus TextFormatToIRReader::MergeFunctionType( return merge_status_and_it.first; } + template <typename T> MergeStatus TextFormatToIRReader::MergeReferencingTypeInternalAndUpdateParent( const TextFormatToIRReader &addend, const T *addend_node, @@ -393,6 +379,7 @@ MergeStatus TextFormatToIRReader::MergeReferencingTypeInternalAndUpdateParent( return merge_status; } + MergeStatus TextFormatToIRReader::MergeReferencingType( const TextFormatToIRReader &addend, const TypeIR *addend_node, AbiElementMap<MergeStatus> *local_to_global_type_id_map, @@ -429,6 +416,7 @@ MergeStatus TextFormatToIRReader::MergeReferencingType( } } + // 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( @@ -445,6 +433,7 @@ MergeStatus TextFormatToIRReader::MergeGenericReferringType( added_type_id); } + MergeStatus TextFormatToIRReader::MergeTypeInternal( const TypeIR *addend_node, const TextFormatToIRReader &addend, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -471,6 +460,7 @@ MergeStatus TextFormatToIRReader::MergeTypeInternal( assert(0); } + MergeStatus TextFormatToIRReader::MergeType( const TypeIR *addend_node, const TextFormatToIRReader &addend, @@ -493,6 +483,7 @@ MergeStatus TextFormatToIRReader::MergeType( return merge_status; } + void TextFormatToIRReader::MergeCFunctionLikeDeps( const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -514,6 +505,7 @@ void TextFormatToIRReader::MergeCFunctionLikeDeps( } } + void TextFormatToIRReader::MergeFunctionDeps( FunctionIR *added_node, const TextFormatToIRReader &addend, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -525,12 +517,14 @@ void TextFormatToIRReader::MergeFunctionDeps( } } + template <typename T> static bool IsLinkableMessagePresent(const LinkableMessageIR *lm, const AbiElementMap<T> &message_map) { return (message_map.find(lm->GetLinkerSetKey()) != message_map.end()); } + void TextFormatToIRReader::MergeFunction( const FunctionIR *addend_node, const TextFormatToIRReader &addend, AbiElementMap<MergeStatus> *local_to_global_type_id_map) { @@ -546,10 +540,12 @@ void TextFormatToIRReader::MergeFunction( 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<MergeStatus> *local_to_global_type_id_map) { @@ -566,6 +562,7 @@ void TextFormatToIRReader::MergeGlobalVariable( 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 @@ -585,6 +582,7 @@ void TextFormatToIRReader::MergeGraphs(const TextFormatToIRReader &addend) { } } + bool TextFormatToIRReader::IsLinkableMessageInExportedHeaders( const LinkableMessageIR *linkable_message) const { if (module_->exported_headers_ == nullptr || 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 <cstdint> +#include <list> +#include <memory> +#include <set> +#include <string> +#include <utility> + + +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<std::string> *exported_headers) + : module_(new ModuleIR(exported_headers)) {} + + virtual ~TextFormatToIRReader() {} + + const AbiElementMap<FunctionIR> &GetFunctions() const { + return module_->functions_; + } + + const AbiElementMap<GlobalVarIR> &GetGlobalVariables() const { + return module_->global_variables_; + } + + const AbiElementMap<RecordTypeIR> &GetRecordTypes() const { + return module_->record_types_; + } + + const AbiElementMap<FunctionTypeIR> &GetFunctionTypes() const { + return module_->function_types_; + } + + const AbiElementMap<EnumTypeIR> &GetEnumTypes() const { + return module_->enum_types_; + } + + const AbiElementMap<LvalueReferenceTypeIR> &GetLvalueReferenceTypes() const { + return module_->lvalue_reference_types_; + } + + const AbiElementMap<RvalueReferenceTypeIR> &GetRvalueReferenceTypes() const { + return module_->rvalue_reference_types_; + } + + const AbiElementMap<QualifiedTypeIR> &GetQualifiedTypes() const { + return module_->qualified_types_; + } + + const AbiElementMap<ArrayTypeIR> &GetArrayTypes() const { + return module_->array_types_; + } + + const AbiElementMap<PointerTypeIR> &GetPointerTypes() const { + return module_->pointer_types_; + } + + const AbiElementMap<BuiltinTypeIR> &GetBuiltinTypes() const { + return module_->builtin_types_; + } + + const AbiElementMap<ElfFunctionIR> &GetElfFunctions() const { + return module_->elf_functions_; + } + + const AbiElementMap<ElfObjectIR> &GetElfObjects() const { + return module_->elf_objects_; + } + + const AbiElementMap<const TypeIR *> &GetTypeGraph() const { + return module_->type_graph_; + } + + const AbiElementUnorderedMap<std::list<const TypeIR *>> & + 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 <typename T> + MergeStatus MergeReferencingTypeInternalAndUpdateParent( + const TextFormatToIRReader &addend, const T *addend_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map, + AbiElementMap<T> *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<MergeStatus> *local_to_global_type_id_map_); + + MergeStatus MergeReferencingTypeInternal( + const TextFormatToIRReader &addend, ReferencesOtherType *references_type, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + MergeStatus MergeReferencingType( + const TextFormatToIRReader &addend, const TypeIR *addend_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map, + const std::string &updated_self_type_id); + + MergeStatus MergeGenericReferringType( + const TextFormatToIRReader &addend, const TypeIR *addend_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + template <typename T> + std::pair<MergeStatus, typename AbiElementMap<T>::iterator> + UpdateUDTypeAccounting( + const T *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map, + AbiElementMap<T> *specific_type_map); + + MergeStatus MergeTypeInternal( + const TypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeCFunctionLikeDeps( + const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + MergeStatus MergeFunctionType( + const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + MergeStatus MergeEnumType( + const EnumTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeEnumDependencies( + const TextFormatToIRReader &addend, EnumTypeIR *added_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + MergeStatus MergeRecordAndDependencies( + const RecordTypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeRecordDependencies( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeRecordFields( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeRecordCXXBases( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeRecordTemplateElements( + const TextFormatToIRReader &addend, RecordTypeIR *added_node, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + MergeStatus IsBuiltinTypeNodePresent( + const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeGlobalVariable( + const GlobalVarIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeGlobalVariables( + const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeFunctionDeps( + FunctionIR *added_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeFunction( + const FunctionIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + void MergeGraphs(const TextFormatToIRReader &addend); + + void UpdateTextFormatToIRReaderTypeGraph( + const TypeIR *addend_node, const std::string &added_type_id, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + MergeStatus IsTypeNodePresent( + const TypeIR *addend_node, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *local_to_global_type_id_map); + + MergeStatus MergeType( + const TypeIR *addend_type, const TextFormatToIRReader &addend, + AbiElementMap<MergeStatus> *merged_types_cache); + + std::string AllocateNewTypeId(); + + static std::unique_ptr<TextFormatToIRReader> CreateTextFormatToIRReader( + TextFormatIR text_format, + const std::set<std::string> *exported_headers = nullptr); + + protected: + template <typename Augend, typename Addend> + inline void MergeElements(Augend *augend, Addend &&addend) { + augend->insert(std::make_move_iterator(addend.begin()), + std::make_move_iterator(addend.end())); + } + + bool IsLinkableMessageInExportedHeaders( + const LinkableMessageIR *linkable_message) const; + + std::unique_ptr<ModuleIR> 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.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 <cassert> #include <list> #include <map> #include <memory> -#include <regex> #include <set> #include <string> #include <unordered_map> @@ -869,675 +867,6 @@ class ModuleIR { const std::set<std::string> *exported_headers_; }; -class IRDumper { - public: - IRDumper(const std::string &dump_path) : dump_path_(dump_path) {} - - virtual ~IRDumper() {} - - static std::unique_ptr<IRDumper> CreateIRDumper( - TextFormatIR text_format, const std::string &dump_path); - - virtual bool AddLinkableMessageIR(const LinkableMessageIR *) = 0; - - virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *) = 0; - - virtual bool Dump() = 0; - - protected: - const std::string &dump_path_; -}; - -template <typename T> -inline std::string GetReferencedTypeMapKey(T &element) { - return element.GetReferencedType(); -} - -template <> -inline std::string GetReferencedTypeMapKey<ArrayTypeIR>(ArrayTypeIR &element) { - return element.GetReferencedType() + ":" + std::to_string(element.GetSize()); -} - -template <> -inline std::string GetReferencedTypeMapKey<BuiltinTypeIR>( - BuiltinTypeIR &element) { - return element.GetLinkerSetKey(); -} - -inline static std::string BoolToString(bool val) { - return val ? "true" : "false"; -} - -template <> -inline std::string GetReferencedTypeMapKey<QualifiedTypeIR>( - 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 T> -typename AbiElementMap<T>::iterator AddToMapAndTypeGraph( - T &&element, AbiElementMap<T> *map_to_update, - AbiElementMap<const TypeIR *> *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<std::string> *exported_headers) - : module_(new ModuleIR(exported_headers)) {} - - virtual ~TextFormatToIRReader() {} - - const AbiElementMap<FunctionIR> &GetFunctions() const { - return module_->functions_; - } - - const AbiElementMap<GlobalVarIR> &GetGlobalVariables() const { - return module_->global_variables_; - } - - const AbiElementMap<RecordTypeIR> &GetRecordTypes() const { - return module_->record_types_; - } - - const AbiElementMap<FunctionTypeIR> &GetFunctionTypes() const { - return module_->function_types_; - } - - const AbiElementMap<EnumTypeIR> &GetEnumTypes() const { - return module_->enum_types_; - } - - const AbiElementMap<LvalueReferenceTypeIR> &GetLvalueReferenceTypes() const { - return module_->lvalue_reference_types_; - } - - const AbiElementMap<RvalueReferenceTypeIR> &GetRvalueReferenceTypes() const { - return module_->rvalue_reference_types_; - } - - const AbiElementMap<QualifiedTypeIR> &GetQualifiedTypes() const { - return module_->qualified_types_; - } - - const AbiElementMap<ArrayTypeIR> &GetArrayTypes() const { - return module_->array_types_; - } - - const AbiElementMap<PointerTypeIR> &GetPointerTypes() const { - return module_->pointer_types_; - } - - const AbiElementMap<BuiltinTypeIR> &GetBuiltinTypes() const { - return module_->builtin_types_; - } - - const AbiElementMap<ElfFunctionIR> &GetElfFunctions() const { - return module_->elf_functions_; - } - - const AbiElementMap<ElfObjectIR> &GetElfObjects() const { - return module_->elf_objects_; - } - - const AbiElementMap<const TypeIR *> &GetTypeGraph() const { - return module_->type_graph_; - } - - const AbiElementUnorderedMap<std::list<const TypeIR *>> & - 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 <typename T> - MergeStatus MergeReferencingTypeInternalAndUpdateParent( - const TextFormatToIRReader &addend, const T *addend_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map, - AbiElementMap<T> *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<MergeStatus> *local_to_global_type_id_map_); - - MergeStatus MergeReferencingTypeInternal( - const TextFormatToIRReader &addend, ReferencesOtherType *references_type, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - MergeStatus MergeReferencingType( - const TextFormatToIRReader &addend, const TypeIR *addend_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map, - const std::string &updated_self_type_id); - - MergeStatus MergeGenericReferringType( - const TextFormatToIRReader &addend, const TypeIR *addend_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - template <typename T> - std::pair<MergeStatus, typename AbiElementMap<T>::iterator> - UpdateUDTypeAccounting( - const T *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map, - AbiElementMap<T> *specific_type_map); - - MergeStatus MergeTypeInternal( - const TypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeCFunctionLikeDeps( - const TextFormatToIRReader &addend, CFunctionLikeIR *cfunction_like_ir, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - MergeStatus MergeFunctionType( - const FunctionTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - MergeStatus MergeEnumType( - const EnumTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeEnumDependencies( - const TextFormatToIRReader &addend, EnumTypeIR *added_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - MergeStatus MergeRecordAndDependencies( - const RecordTypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeRecordDependencies( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeRecordFields( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeRecordCXXBases( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeRecordTemplateElements( - const TextFormatToIRReader &addend, RecordTypeIR *added_node, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - MergeStatus IsBuiltinTypeNodePresent( - const BuiltinTypeIR *builtin_type, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeGlobalVariable( - const GlobalVarIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeGlobalVariables( - const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeFunctionDeps( - FunctionIR *added_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeFunction( - const FunctionIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - void MergeGraphs(const TextFormatToIRReader &addend); - - void UpdateTextFormatToIRReaderTypeGraph( - const TypeIR *addend_node, const std::string &added_type_id, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - MergeStatus IsTypeNodePresent( - const TypeIR *addend_node, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *local_to_global_type_id_map); - - MergeStatus MergeType( - const TypeIR *addend_type, const TextFormatToIRReader &addend, - AbiElementMap<MergeStatus> *merged_types_cache); - - std::string AllocateNewTypeId(); - - static std::unique_ptr<TextFormatToIRReader> CreateTextFormatToIRReader( - TextFormatIR text_format, - const std::set<std::string> *exported_headers = nullptr); - - protected: - template <typename Augend, typename Addend> - inline void MergeElements(Augend *augend, Addend &&addend) { - augend->insert(std::make_move_iterator(addend.begin()), - std::make_move_iterator(addend.end())); - } - - bool IsLinkableMessageInExportedHeaders( - const LinkableMessageIR *linkable_message) const; - - std::unique_ptr<ModuleIR> 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<uint64_t, uint64_t> &&sizes, - std::pair<uint32_t, uint32_t> &&alignment) - : sizes_(std::move(sizes)), alignments_(std::move(alignment)) {} - - const std::pair<uint64_t, uint64_t> &GetSizes() const { - return sizes_; - } - - const std::pair<uint32_t, uint32_t> &GetAlignments() const { - return alignments_; - } - - protected: - std::pair<uint64_t, uint64_t> sizes_; - std::pair<uint32_t, uint32_t> 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<CXXBaseSpecifierIR> &old_base_specifiers, - const std::vector<CXXBaseSpecifierIR> &new_base_specifiers) - : old_base_specifiers_(old_base_specifiers), - new_base_specifiers_(new_base_specifiers) {} - - const std::vector<CXXBaseSpecifierIR> &GetOldBases() const { - return old_base_specifiers_; - } - - const std::vector<CXXBaseSpecifierIR> &GetNewBases() const { - return new_base_specifiers_; - } - - protected: - const std::vector<CXXBaseSpecifierIR> &old_base_specifiers_; - const std::vector<CXXBaseSpecifierIR> &new_base_specifiers_; -}; - -class RecordTypeDiffIR : public DiffMessageIR { - public: - LinkableMessageKind Kind() const override { - return LinkableMessageKind::RecordTypeKind; - } - - void SetFieldDiffs(std::vector<RecordFieldDiffIR> &&field_diffs) { - field_diffs_ = std::move(field_diffs); - } - - const std::vector<RecordFieldDiffIR> &GetFieldDiffs() const { - return field_diffs_; - } - - void SetFieldsRemoved(std::vector<const RecordFieldIR *> &&fields_removed) { - fields_removed_ = std::move(fields_removed); - } - - void SetFieldsAdded(std::vector<const RecordFieldIR *> &&fields_added) { - fields_added_ = std::move(fields_added); - } - - const std::vector<const RecordFieldIR *> &GetFieldsRemoved() const { - return fields_removed_; - } - - const std::vector<const RecordFieldIR *> &GetFieldsAdded() const { - return fields_added_; - } - - void SetVTableLayoutDiff(std::unique_ptr<VTableLayoutDiffIR> &&vtable_diffs) { - vtable_diffs_ = std::move(vtable_diffs); - } - - void SetTypeDiff(std::unique_ptr<TypeDiffIR> &&type_diff) { - type_diff_ = std::move(type_diff); - } - - void SetAccessDiff(std::unique_ptr<AccessSpecifierDiffIR> &&access_diff) { - access_diff_ = std::move(access_diff); - } - - void SetBaseSpecifierDiffs( - std::unique_ptr<CXXBaseSpecifierDiffIR> &&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<TypeDiffIR> type_diff_; - std::unique_ptr<VTableLayoutDiffIR> vtable_diffs_; - std::vector<RecordFieldDiffIR> field_diffs_; - std::vector<const RecordFieldIR *> fields_removed_; - std::vector<const RecordFieldIR *> fields_added_; - std::unique_ptr<AccessSpecifierDiffIR> access_diff_; - std::unique_ptr<CXXBaseSpecifierDiffIR> 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<const EnumFieldIR *> &&fields_removed) { - fields_removed_ = std::move(fields_removed); - } - - const std::vector<const EnumFieldIR *> &GetFieldsRemoved() const { - return fields_removed_; - } - - void SetFieldsAdded(std::vector<const EnumFieldIR *> &&fields_added) { - fields_added_ = std::move(fields_added); - } - - const std::vector<const EnumFieldIR *> &GetFieldsAdded() const { - return fields_added_; - } - - void SetFieldsDiff(std::vector<EnumFieldDiffIR> &&fields_diff) { - fields_diff_ = std::move(fields_diff); - } - - const std::vector<EnumFieldDiffIR> &GetFieldsDiff() const { - return fields_diff_; - } - - void SetUnderlyingTypeDiff( - std::unique_ptr<std::pair<std::string, std::string>> &&utype_diff) { - underlying_type_diff_ = std::move(utype_diff); - } - - const std::pair<std::string, std::string> *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<std::pair<std::string, std::string>> underlying_type_diff_; - std::vector<const EnumFieldIR *> fields_removed_; - std::vector<const EnumFieldIR *> fields_added_; - std::vector<EnumFieldDiffIR> 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<IRDiffDumper> 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 <string> + + +namespace header_checker { +namespace repr { + + +template <typename T> +inline std::string GetReferencedTypeMapKey(T &element) { + return element.GetReferencedType(); +} + +template <> +inline std::string GetReferencedTypeMapKey<ArrayTypeIR>(ArrayTypeIR &element) { + return element.GetReferencedType() + ":" + std::to_string(element.GetSize()); +} + +template <> +inline std::string GetReferencedTypeMapKey<BuiltinTypeIR>( + BuiltinTypeIR &element) { + return element.GetLinkerSetKey(); +} + +inline static std::string BoolToString(bool val) { + return val ? "true" : "false"; +} + +template <> +inline std::string GetReferencedTypeMapKey<QualifiedTypeIR>( + 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 T> +typename AbiElementMap<T>::iterator AddToMapAndTypeGraph( + T &&element, AbiElementMap<T> *map_to_update, + AbiElementMap<const TypeIR *> *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<Json::UInt64>(key, value, 0); +} + + +void JsonObject::Set(const std::string &key, int64_t value) { + SetOmissible<Json::Int64>(key, value, 0); +} + + +void JsonObject::Set(const std::string &key, const std::string &value) { + SetOmissible<const std::string &>(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 <json/value.h> + +#include <map> +#include <string> + +#include <llvm/Support/raw_ostream.h> + + +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 <typename T> + 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<AccessSpecifierIR, std::string> access_ir_to_json{ + {AccessSpecifierIR::PublicAccess, "public"}, + {AccessSpecifierIR::ProtectedAccess, "protected"}, + {AccessSpecifierIR::PrivateAccess, "private"}, +}; + +static const std::map<RecordTypeIR::RecordKind, std::string> + record_kind_ir_to_json{ + {RecordTypeIR::RecordKind::struct_kind, "struct"}, + {RecordTypeIR::RecordKind::class_kind, "class"}, + {RecordTypeIR::RecordKind::union_kind, "union"}, +}; + +static const std::map<VTableComponentIR::Kind, std::string> + 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<ElfSymbolIR::ElfSymbolBinding, std::string> + 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 <typename K, typename V> +static inline const V &FindInMap(const std::map<K, V> &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 <json/reader.h> +#include <json/writer.h> + +#include <llvm/Support/raw_ostream.h> + +#include <cstdlib> +#include <fstream> +#include <sstream> +#include <string> + + +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<const RecordTypeIR *>(lm)); + break; + case EnumTypeKind: + key = "enum_types"; + converted = ConvertEnumTypeIR(static_cast<const EnumTypeIR *>(lm)); + break; + case PointerTypeKind: + key = "pointer_types"; + converted = ConvertPointerTypeIR(static_cast<const PointerTypeIR *>(lm)); + break; + case QualifiedTypeKind: + key = "qualified_types"; + converted = + ConvertQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm)); + break; + case ArrayTypeKind: + key = "array_types"; + converted = ConvertArrayTypeIR(static_cast<const ArrayTypeIR *>(lm)); + break; + case LvalueReferenceTypeKind: + key = "lvalue_reference_types"; + converted = ConvertLvalueReferenceTypeIR( + static_cast<const LvalueReferenceTypeIR *>(lm)); + break; + case RvalueReferenceTypeKind: + key = "rvalue_reference_types"; + converted = ConvertRvalueReferenceTypeIR( + static_cast<const RvalueReferenceTypeIR *>(lm)); + break; + case BuiltinTypeKind: + key = "builtin_types"; + converted = ConvertBuiltinTypeIR(static_cast<const BuiltinTypeIR *>(lm)); + break; + case FunctionTypeKind: + key = "function_types"; + converted = ConvertFunctionTypeIR(static_cast<const FunctionTypeIR *>(lm)); + break; + case GlobalVarKind: + key = "global_vars"; + converted = ConvertGlobalVarIR(static_cast<const GlobalVarIR *>(lm)); + break; + case FunctionKind: + key = "functions"; + converted = ConvertFunctionIR(static_cast<const FunctionIR *>(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_representation_json.cpp b/vndk/tools/header-checker/src/repr/json/ir_reader.cpp index 32e25127c..72875901c 100644 --- a/vndk/tools/header-checker/src/repr/json/ir_representation_json.cpp +++ b/vndk/tools/header-checker/src/repr/json/ir_reader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018 The Android Open Source Project +// 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. @@ -12,7 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "repr/json/ir_representation_json.h" +#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 <json/reader.h> #include <json/writer.h> @@ -29,494 +34,20 @@ namespace header_checker { namespace repr { -// Conversion between IR enums and JSON strings. -static const std::map<AccessSpecifierIR, std::string> access_ir_to_json{ - {AccessSpecifierIR::PublicAccess, "public"}, - {AccessSpecifierIR::ProtectedAccess, "protected"}, - {AccessSpecifierIR::PrivateAccess, "private"}, -}; - static const std::map<std::string, AccessSpecifierIR> access_json_to_ir(CreateInverseMap(access_ir_to_json)); -static const AccessSpecifierIR default_access_ir = - AccessSpecifierIR::PublicAccess; - -static const std::map<RecordTypeIR::RecordKind, std::string> - record_kind_ir_to_json{ - {RecordTypeIR::RecordKind::struct_kind, "struct"}, - {RecordTypeIR::RecordKind::class_kind, "class"}, - {RecordTypeIR::RecordKind::union_kind, "union"}, -}; - static const std::map<std::string, RecordTypeIR::RecordKind> 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<VTableComponentIR::Kind, std::string> - 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<std::string, VTableComponentIR::Kind> 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<ElfSymbolIR::ElfSymbolBinding, std::string> - elf_symbol_binding_ir_to_json{ - {ElfSymbolIR::ElfSymbolBinding::Weak, "weak"}, - {ElfSymbolIR::ElfSymbolBinding::Global, "global"}, -}; - static const std::map<std::string, ElfSymbolIR::ElfSymbolBinding> 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 <typename K, typename V> -static inline const V &FindInMap(const std::map<K, V> &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<Json::UInt64>(key, value, 0); -} - -void JsonObject::Set(const std::string &key, int64_t value) { - SetOmissible<Json::Int64>(key, value, 0); -} - -void JsonObject::Set(const std::string &key, const std::string &value) { - SetOmissible<const std::string &>(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<const RecordTypeIR *>(lm)); - break; - case EnumTypeKind: - key = "enum_types"; - converted = ConvertEnumTypeIR(static_cast<const EnumTypeIR *>(lm)); - break; - case PointerTypeKind: - key = "pointer_types"; - converted = ConvertPointerTypeIR(static_cast<const PointerTypeIR *>(lm)); - break; - case QualifiedTypeKind: - key = "qualified_types"; - converted = - ConvertQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm)); - break; - case ArrayTypeKind: - key = "array_types"; - converted = ConvertArrayTypeIR(static_cast<const ArrayTypeIR *>(lm)); - break; - case LvalueReferenceTypeKind: - key = "lvalue_reference_types"; - converted = ConvertLvalueReferenceTypeIR( - static_cast<const LvalueReferenceTypeIR *>(lm)); - break; - case RvalueReferenceTypeKind: - key = "rvalue_reference_types"; - converted = ConvertRvalueReferenceTypeIR( - static_cast<const RvalueReferenceTypeIR *>(lm)); - break; - case BuiltinTypeKind: - key = "builtin_types"; - converted = ConvertBuiltinTypeIR(static_cast<const BuiltinTypeIR *>(lm)); - break; - case FunctionTypeKind: - key = "function_types"; - converted = ConvertFunctionTypeIR(static_cast<const FunctionTypeIR *>(lm)); - break; - case GlobalVarKind: - key = "global_vars"; - converted = ConvertGlobalVarIR(static_cast<const GlobalVarIR *>(lm)); - break; - case FunctionKind: - key = "functions"; - converted = ConvertFunctionIR(static_cast<const FunctionIR *>(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) { diff --git a/vndk/tools/header-checker/src/repr/json/ir_representation_json.h b/vndk/tools/header-checker/src/repr/json/ir_reader.h index 7099cabe6..797e65e9b 100644 --- a/vndk/tools/header-checker/src/repr/json/ir_representation_json.h +++ b/vndk/tools/header-checker/src/repr/json/ir_reader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2018 The Android Open Source Project +// 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. @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef IR_REPRESENTATION_JSON_H_ -#define IR_REPRESENTATION_JSON_H_ +#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 <json/value.h> @@ -24,117 +26,6 @@ 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 <typename T> - 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 <typename T> class JsonArrayRef; // This class loads values from a read-only JSON object. @@ -292,4 +183,4 @@ class JsonToIRReader : public TextFormatToIRReader { } // namespace header_checker -#endif // IR_REPRESENTATION_JSON_H_ +#endif // HEADER_CHECKER_REPR_JSON_IR_READER_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 <llvm/Support/raw_ostream.h> + +#include <fstream> +#include <iostream> +#include <memory> +#include <string> + + +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<uint64_t, uint64_t> &sizes = type_diff_ir->GetSizes(); + const std::pair<uint32_t, uint32_t> &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 <typename T> +static bool CopyBaseSpecifiersDiffIRToProtobuf( + google::protobuf::RepeatedPtrField<T> *dst, + const std::vector<CXXBaseSpecifierIR> &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<const RecordFieldIR *> &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<RecordFieldDiffIR> &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<std::string, std::string> *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<abi_dump::EnumFieldDecl> *dst, + const std::vector<const EnumFieldIR *> &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<abi_diff::EnumFieldDeclDiff> *dst, + const std::vector<EnumFieldDiffIR> &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<std::string, std::string> *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/ir_representation_protobuf.h b/vndk/tools/header-checker/src/repr/protobuf/converter.h index 8f55eb822..8f4829a76 100644 --- a/vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.h +++ b/vndk/tools/header-checker/src/repr/protobuf/converter.h @@ -1,4 +1,4 @@ -// Copyright (C) 2017 The Android Open Source Project +// 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. @@ -12,29 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef IR_REPRESENTATION_PROTOBUF_H_ -#define IR_REPRESENTATION_PROTOBUF_H_ +#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" -#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 <google/protobuf/text_format.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <llvm/Support/raw_ostream.h> 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) { @@ -309,182 +301,71 @@ class IRDiffToProtobufConverter { 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<abi_dump::TranslationUnit> tu_ptr_; -}; - - -class ProtobufTextFormatToIRReader : public TextFormatToIRReader { - private: - template <typename T> - using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>; - - public: - ProtobufTextFormatToIRReader(const std::set<std::string> *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<RecordFieldIR> RecordFieldsProtobufToIR( - const RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp); - - std::vector<CXXBaseSpecifierIR> RecordCXXBaseSpecifiersProtobufToIR( - const RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs); - - std::vector<EnumFieldIR> EnumFieldsProtobufToIR( - const RepeatedPtrField<abi_dump::EnumFieldDecl> &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); +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()); +} - bool AddElfObjectIR(const ElfObjectIR *elf_object_ir, DiffKind diff_kind); +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; +} - bool AddElfFunctionIR(const ElfFunctionIR *elf_function_ir, - DiffKind diff_kind); +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; +} - protected: - std::unique_ptr<abi_diff::TranslationUnitDiff> diff_tu_; -}; +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 // IR_REPRESENTATION_PROTOBUF_H_ + +#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 <string> +#include <fstream> + +#include <llvm/Support/raw_ostream.h> + +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/text_format.h> + + +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<const RecordTypeDiffIR *>(message), type_stack, + diff_kind); + case EnumTypeKind: + return AddEnumTypeDiffIR( + static_cast<const EnumTypeDiffIR *>(message), type_stack, diff_kind); + case GlobalVarKind: + return AddGlobalVarDiffIR( + static_cast<const GlobalVarDiffIR*>(message), type_stack, diff_kind); + case FunctionKind: + return AddFunctionDiffIR( + static_cast<const FunctionDiffIR*>(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<const RecordTypeIR *>(message), diff_kind); + case EnumTypeKind: + return AddLoneEnumTypeDiffIR( + static_cast<const EnumTypeIR *>(message), diff_kind); + case GlobalVarKind: + return AddLoneGlobalVarDiffIR( + static_cast<const GlobalVarIR*>(message), diff_kind); + case FunctionKind: + return AddLoneFunctionDiffIR( + static_cast<const FunctionIR*>(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<const ElfFunctionIR *>(elf_symbol), + diff_kind); + break; + case ElfSymbolIR::ElfObjectKind: + return AddElfObjectIR(static_cast<const ElfObjectIR *>(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 <string> + + +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<abi_diff::TranslationUnitDiff> 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 <fstream> + +#include <llvm/Support/raw_ostream.h> + +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/text_format.h> + + +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 <typename CFunctionLikeMessage> +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 <typename CFunctionLikeMessage> +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<const RecordTypeIR *>(lm)); + case EnumTypeKind: + return AddEnumTypeIR(static_cast<const EnumTypeIR *>(lm)); + case PointerTypeKind: + return AddPointerTypeIR(static_cast<const PointerTypeIR *>(lm)); + case QualifiedTypeKind: + return AddQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm)); + case ArrayTypeKind: + return AddArrayTypeIR(static_cast<const ArrayTypeIR *>(lm)); + case LvalueReferenceTypeKind: + return AddLvalueReferenceTypeIR( + static_cast<const LvalueReferenceTypeIR *>(lm)); + case RvalueReferenceTypeKind: + return AddRvalueReferenceTypeIR( + static_cast<const RvalueReferenceTypeIR*>(lm)); + case BuiltinTypeKind: + return AddBuiltinTypeIR(static_cast<const BuiltinTypeIR*>(lm)); + case FunctionTypeKind: + return AddFunctionTypeIR(static_cast<const FunctionTypeIR*>(lm)); + case GlobalVarKind: + return AddGlobalVarIR(static_cast<const GlobalVarIR*>(lm)); + case FunctionKind: + return AddFunctionIR(static_cast<const FunctionIR*>(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<const ElfFunctionIR *>(em)); + case ElfSymbolIR::ElfObjectKind: + return AddElfObjectIR(static_cast<const ElfObjectIR *>(em)); + } + return false; +} + +bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) { + abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types(); + if (!added_record_type) { + 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<abi_dump::TranslationUnit> 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 <fstream> + +#include <google/protobuf/text_format.h> + + +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 <typename T> +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<RecordFieldIR> +ProtobufTextFormatToIRReader::RecordFieldsProtobufToIR( + const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp) { + std::vector<RecordFieldIR> 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<CXXBaseSpecifierIR> +ProtobufTextFormatToIRReader::RecordCXXBaseSpecifiersProtobufToIR( + const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs) { + std::vector<CXXBaseSpecifierIR> 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<EnumFieldIR> +ProtobufTextFormatToIRReader::EnumFieldsProtobufToIR( + const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp) { + std::vector<EnumFieldIR> 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 <set> +#include <string> +#include <vector> + +#include <google/protobuf/text_format.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> + + +namespace header_checker { +namespace repr { + + +class ProtobufTextFormatToIRReader : public TextFormatToIRReader { + private: + template <typename T> + using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>; + + + public: + ProtobufTextFormatToIRReader(const std::set<std::string> *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<RecordFieldIR> RecordFieldsProtobufToIR( + const RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp); + + std::vector<CXXBaseSpecifierIR> RecordCXXBaseSpecifiersProtobufToIR( + const RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs); + + std::vector<EnumFieldIR> EnumFieldsProtobufToIR( + const RepeatedPtrField<abi_dump::EnumFieldDecl> &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 <llvm/Support/raw_ostream.h> - -#include <fstream> -#include <iostream> -#include <memory> -#include <string> - - -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 <typename T> -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<RecordFieldIR> -ProtobufTextFormatToIRReader::RecordFieldsProtobufToIR( - const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp) { - std::vector<RecordFieldIR> 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<CXXBaseSpecifierIR> -ProtobufTextFormatToIRReader::RecordCXXBaseSpecifiersProtobufToIR( - const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs) { - std::vector<CXXBaseSpecifierIR> 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<EnumFieldIR> -ProtobufTextFormatToIRReader::EnumFieldsProtobufToIR( - const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp) { - std::vector<EnumFieldIR> 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 <typename CFunctionLikeMessage> -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 <typename CFunctionLikeMessage> -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<uint64_t, uint64_t> &sizes = type_diff_ir->GetSizes(); - const std::pair<uint32_t, uint32_t> &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 <typename T> -static bool CopyBaseSpecifiersDiffIRToProtobuf( - google::protobuf::RepeatedPtrField<T> *dst, - const std::vector<CXXBaseSpecifierIR> &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<const RecordFieldIR *> &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<RecordFieldDiffIR> &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<std::string, std::string> *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<abi_dump::EnumFieldDecl> *dst, - const std::vector<const EnumFieldIR *> &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<abi_diff::EnumFieldDeclDiff> *dst, - const std::vector<EnumFieldDiffIR> &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<std::string, std::string> *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<const RecordTypeIR *>(lm)); - case EnumTypeKind: - return AddEnumTypeIR(static_cast<const EnumTypeIR *>(lm)); - case PointerTypeKind: - return AddPointerTypeIR(static_cast<const PointerTypeIR *>(lm)); - case QualifiedTypeKind: - return AddQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm)); - case ArrayTypeKind: - return AddArrayTypeIR(static_cast<const ArrayTypeIR *>(lm)); - case LvalueReferenceTypeKind: - return AddLvalueReferenceTypeIR( - static_cast<const LvalueReferenceTypeIR *>(lm)); - case RvalueReferenceTypeKind: - return AddRvalueReferenceTypeIR( - static_cast<const RvalueReferenceTypeIR*>(lm)); - case BuiltinTypeKind: - return AddBuiltinTypeIR(static_cast<const BuiltinTypeIR*>(lm)); - case FunctionTypeKind: - return AddFunctionTypeIR(static_cast<const FunctionTypeIR*>(lm)); - case GlobalVarKind: - return AddGlobalVarIR(static_cast<const GlobalVarIR*>(lm)); - case FunctionKind: - return AddFunctionIR(static_cast<const FunctionIR*>(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<const ElfFunctionIR *>(em)); - case ElfSymbolIR::ElfObjectKind: - return AddElfObjectIR(static_cast<const ElfObjectIR *>(em)); - } - return false; -} - -bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) { - abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types(); - if (!added_record_type) { - 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<const RecordTypeDiffIR *>(message), type_stack, - diff_kind); - case EnumTypeKind: - return AddEnumTypeDiffIR( - static_cast<const EnumTypeDiffIR *>(message), type_stack, diff_kind); - case GlobalVarKind: - return AddGlobalVarDiffIR( - static_cast<const GlobalVarDiffIR*>(message), type_stack, diff_kind); - case FunctionKind: - return AddFunctionDiffIR( - static_cast<const FunctionDiffIR*>(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<const RecordTypeIR *>(message), diff_kind); - case EnumTypeKind: - return AddLoneEnumTypeDiffIR( - static_cast<const EnumTypeIR *>(message), diff_kind); - case GlobalVarKind: - return AddLoneGlobalVarDiffIR( - static_cast<const GlobalVarIR*>(message), diff_kind); - case FunctionKind: - return AddLoneFunctionDiffIR( - static_cast<const FunctionIR*>(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<const ElfFunctionIR *>(elf_symbol), - diff_kind); - break; - case ElfSymbolIR::ElfObjectKind: - return AddElfObjectIR(static_cast<const ElfObjectIR *>(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 |
