summaryrefslogtreecommitdiffstats
path: root/vndk
diff options
context:
space:
mode:
authorLogan Chien <loganchien@google.com>2019-03-14 15:48:35 +0800
committerLogan Chien <loganchien@google.com>2019-03-20 17:06:13 +0800
commitfb0213fe3d98be7fc591bec657b75613075a05c4 (patch)
tree99c74103a768003e86ea7feab98dffde7a1505f3 /vndk
parenta58b9d9f6a09d413967c29358fdad54dd04a9574 (diff)
downloadandroid_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')
-rw-r--r--vndk/tools/header-checker/Android.bp13
-rw-r--r--vndk/tools/header-checker/src/diff_merge/merge_abi_diff.cpp8
-rw-r--r--vndk/tools/header-checker/src/dumper/abi_wrappers.cpp2
-rw-r--r--vndk/tools/header-checker/src/dumper/abi_wrappers.h1
-rw-r--r--vndk/tools/header-checker/src/dumper/ast_processing.h1
-rw-r--r--vndk/tools/header-checker/src/linker/header_abi_linker.cpp2
-rw-r--r--vndk/tools/header-checker/src/repr/abi_diff_helpers.h5
-rw-r--r--vndk/tools/header-checker/src/repr/ir_diff_dumper.cpp44
-rw-r--r--vndk/tools/header-checker/src/repr/ir_diff_dumper.h68
-rw-r--r--vndk/tools/header-checker/src/repr/ir_diff_representation.h358
-rw-r--r--vndk/tools/header-checker/src/repr/ir_dumper.cpp45
-rw-r--r--vndk/tools/header-checker/src/repr/ir_dumper.h51
-rw-r--r--vndk/tools/header-checker/src/repr/ir_reader.cpp (renamed from vndk/tools/header-checker/src/repr/ir_representation.cpp)80
-rw-r--r--vndk/tools/header-checker/src/repr/ir_reader.h275
-rw-r--r--vndk/tools/header-checker/src/repr/ir_representation.h671
-rw-r--r--vndk/tools/header-checker/src/repr/ir_representation_internal.h86
-rw-r--r--vndk/tools/header-checker/src/repr/json/converter.cpp67
-rw-r--r--vndk/tools/header-checker/src/repr/json/converter.h134
-rw-r--r--vndk/tools/header-checker/src/repr/json/ir_dumper.cpp431
-rw-r--r--vndk/tools/header-checker/src/repr/json/ir_dumper.h103
-rw-r--r--vndk/tools/header-checker/src/repr/json/ir_reader.cpp (renamed from vndk/tools/header-checker/src/repr/json/ir_representation_json.cpp)483
-rw-r--r--vndk/tools/header-checker/src/repr/json/ir_reader.h (renamed from vndk/tools/header-checker/src/repr/json/ir_representation_json.h)121
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/abi_diff.h26
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/abi_dump.h26
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/converter.cpp289
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/converter.h (renamed from vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.h)253
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.cpp371
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/ir_diff_dumper.h95
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/ir_dumper.cpp494
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/ir_dumper.h81
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/ir_reader.cpp386
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/ir_reader.h110
-rw-r--r--vndk/tools/header-checker/src/repr/protobuf/ir_representation_protobuf.cpp1504
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 &&parameter_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 &&parameter_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 &&parameter : 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 &&parameter: 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 &&parameter: 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 &&parameter: 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 &&parameter: 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 &&parameter : 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