Merge "Support VNDK ABI dump in JSON format"
am: d3b65417c2
Change-Id: I486e698da7aa169e6e0229c0301e670ec68e75f3
This commit is contained in:
@@ -60,6 +60,7 @@ cc_binary_host {
|
|||||||
static_libs: [
|
static_libs: [
|
||||||
"libheader-abi-util",
|
"libheader-abi-util",
|
||||||
"libheader-checker-proto",
|
"libheader-checker-proto",
|
||||||
|
"libjsoncpp",
|
||||||
"libclangToolingCore",
|
"libclangToolingCore",
|
||||||
"libclangTooling",
|
"libclangTooling",
|
||||||
"libclangFrontendTool",
|
"libclangFrontendTool",
|
||||||
@@ -97,6 +98,7 @@ cc_defaults {
|
|||||||
static_libs: [
|
static_libs: [
|
||||||
"libheader-abi-util",
|
"libheader-abi-util",
|
||||||
"libheader-checker-proto",
|
"libheader-checker-proto",
|
||||||
|
"libjsoncpp",
|
||||||
"libLLVMObject",
|
"libLLVMObject",
|
||||||
"libLLVMBitReader",
|
"libLLVMBitReader",
|
||||||
"libLLVMMC",
|
"libLLVMMC",
|
||||||
@@ -162,6 +164,7 @@ cc_library_host_static {
|
|||||||
"header-abi-util/src/abi_diff_helpers.cpp",
|
"header-abi-util/src/abi_diff_helpers.cpp",
|
||||||
"header-abi-util/src/collect_exported_headers.cpp",
|
"header-abi-util/src/collect_exported_headers.cpp",
|
||||||
"header-abi-util/src/ir_representation.cpp",
|
"header-abi-util/src/ir_representation.cpp",
|
||||||
|
"header-abi-util/src/ir_representation_json.cpp",
|
||||||
"header-abi-util/src/ir_representation_protobuf.cpp",
|
"header-abi-util/src/ir_representation_protobuf.cpp",
|
||||||
"header-abi-util/src/so_file_parser.cpp",
|
"header-abi-util/src/so_file_parser.cpp",
|
||||||
"header-abi-util/src/version_script_parser.cpp",
|
"header-abi-util/src/version_script_parser.cpp",
|
||||||
@@ -169,6 +172,7 @@ cc_library_host_static {
|
|||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"libheader-checker-proto",
|
"libheader-checker-proto",
|
||||||
|
"libjsoncpp",
|
||||||
],
|
],
|
||||||
|
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ static llvm::cl::opt<abi_util::TextFormatIR> text_format(
|
|||||||
"text-format", llvm::cl::desc("Specify text format of abi dump"),
|
"text-format", llvm::cl::desc("Specify text format of abi dump"),
|
||||||
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
|
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
|
||||||
"ProtobufTextFormat", "ProtobufTextFormat"),
|
"ProtobufTextFormat", "ProtobufTextFormat"),
|
||||||
|
clEnumValN(abi_util::TextFormatIR::Json, "Json", "JSON"),
|
||||||
clEnumValEnd),
|
clEnumValEnd),
|
||||||
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
|
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
|
||||||
llvm::cl::cat(header_checker_category));
|
llvm::cl::cat(header_checker_category));
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ using AbiElementList = std::list<T>;
|
|||||||
|
|
||||||
enum TextFormatIR {
|
enum TextFormatIR {
|
||||||
ProtobufTextFormat = 0,
|
ProtobufTextFormat = 0,
|
||||||
|
Json = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CompatibilityStatusIR {
|
enum CompatibilityStatusIR {
|
||||||
|
|||||||
@@ -0,0 +1,275 @@
|
|||||||
|
// Copyright (C) 2018 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
#ifndef IR_JSON_
|
||||||
|
#define IR_JSON_
|
||||||
|
|
||||||
|
#include <ir_representation.h>
|
||||||
|
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
// Classes which act as middle-men between clang AST parsing routines and
|
||||||
|
// message format specific dumpers.
|
||||||
|
namespace abi_util {
|
||||||
|
|
||||||
|
enum AccessSpecifier {
|
||||||
|
public_access = 1,
|
||||||
|
private_access = 2,
|
||||||
|
protected_access = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RecordKind {
|
||||||
|
struct_kind = 1,
|
||||||
|
class_kind = 2,
|
||||||
|
union_kind = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VTableComponentKind {
|
||||||
|
VCallOffset = 0,
|
||||||
|
VBaseOffset = 1,
|
||||||
|
OffsetToTop = 2,
|
||||||
|
RTTI = 3,
|
||||||
|
FunctionPointer = 4,
|
||||||
|
CompleteDtorPointer = 5,
|
||||||
|
DeletingDtorPointer = 6,
|
||||||
|
UnusedFunctionPointer = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AccessSpecifier AccessIRToJson(AccessSpecifierIR access) {
|
||||||
|
switch (access) {
|
||||||
|
case AccessSpecifierIR::PublicAccess:
|
||||||
|
return AccessSpecifier::public_access;
|
||||||
|
|
||||||
|
case AccessSpecifierIR::ProtectedAccess:
|
||||||
|
return AccessSpecifier::protected_access;
|
||||||
|
|
||||||
|
case AccessSpecifierIR::PrivateAccess:
|
||||||
|
return AccessSpecifier::private_access;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return AccessSpecifier::public_access;
|
||||||
|
}
|
||||||
|
// Should not be reached
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AccessSpecifierIR AccessJsonToIR(AccessSpecifier access) {
|
||||||
|
switch (access) {
|
||||||
|
case AccessSpecifier::public_access:
|
||||||
|
return AccessSpecifierIR::PublicAccess;
|
||||||
|
|
||||||
|
case AccessSpecifier::protected_access:
|
||||||
|
return AccessSpecifierIR::ProtectedAccess;
|
||||||
|
|
||||||
|
case AccessSpecifier::private_access:
|
||||||
|
return AccessSpecifierIR::PrivateAccess;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return AccessSpecifierIR::PublicAccess;
|
||||||
|
}
|
||||||
|
// Should not be reached
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RecordKind RecordKindIRToJson(RecordTypeIR::RecordKind kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case RecordTypeIR::RecordKind::struct_kind:
|
||||||
|
return RecordKind::struct_kind;
|
||||||
|
|
||||||
|
case RecordTypeIR::RecordKind::class_kind:
|
||||||
|
return RecordKind::class_kind;
|
||||||
|
|
||||||
|
case RecordTypeIR::RecordKind::union_kind:
|
||||||
|
return RecordKind::union_kind;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return RecordKind::struct_kind;
|
||||||
|
}
|
||||||
|
// Should not be reached
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RecordTypeIR::RecordKind RecordKindJsonToIR(RecordKind kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case RecordKind::struct_kind:
|
||||||
|
return RecordTypeIR::struct_kind;
|
||||||
|
|
||||||
|
case RecordKind::class_kind:
|
||||||
|
return RecordTypeIR::class_kind;
|
||||||
|
|
||||||
|
case RecordKind::union_kind:
|
||||||
|
return RecordTypeIR::union_kind;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return RecordTypeIR::struct_kind;
|
||||||
|
}
|
||||||
|
// Should not be reached
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VTableComponentKind
|
||||||
|
VTableComponentKindIRToJson(VTableComponentIR::Kind kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case VTableComponentIR::Kind::VCallOffset:
|
||||||
|
return VTableComponentKind::VCallOffset;
|
||||||
|
|
||||||
|
case VTableComponentIR::Kind::VBaseOffset:
|
||||||
|
return VTableComponentKind::VBaseOffset;
|
||||||
|
|
||||||
|
case VTableComponentIR::Kind::OffsetToTop:
|
||||||
|
return VTableComponentKind::OffsetToTop;
|
||||||
|
|
||||||
|
case VTableComponentIR::Kind::RTTI:
|
||||||
|
return VTableComponentKind::RTTI;
|
||||||
|
|
||||||
|
case VTableComponentIR::Kind::FunctionPointer:
|
||||||
|
return VTableComponentKind::FunctionPointer;
|
||||||
|
|
||||||
|
case VTableComponentIR::Kind::CompleteDtorPointer:
|
||||||
|
return VTableComponentKind::CompleteDtorPointer;
|
||||||
|
|
||||||
|
case VTableComponentIR::Kind::DeletingDtorPointer:
|
||||||
|
return VTableComponentKind::DeletingDtorPointer;
|
||||||
|
|
||||||
|
case VTableComponentIR::Kind::UnusedFunctionPointer:
|
||||||
|
return VTableComponentKind::UnusedFunctionPointer;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VTableComponentKind::UnusedFunctionPointer;
|
||||||
|
}
|
||||||
|
// Should not be reached
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VTableComponentIR::Kind
|
||||||
|
VTableComponentKindJsonToIR(VTableComponentKind kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case VTableComponentKind::VCallOffset:
|
||||||
|
return VTableComponentIR::Kind::VCallOffset;
|
||||||
|
|
||||||
|
case VTableComponentKind::VBaseOffset:
|
||||||
|
return VTableComponentIR::Kind::VBaseOffset;
|
||||||
|
|
||||||
|
case VTableComponentKind::OffsetToTop:
|
||||||
|
return VTableComponentIR::Kind::OffsetToTop;
|
||||||
|
|
||||||
|
case VTableComponentKind::RTTI:
|
||||||
|
return VTableComponentIR::Kind::RTTI;
|
||||||
|
|
||||||
|
case VTableComponentKind::FunctionPointer:
|
||||||
|
return VTableComponentIR::Kind::FunctionPointer;
|
||||||
|
|
||||||
|
case VTableComponentKind::CompleteDtorPointer:
|
||||||
|
return VTableComponentIR::Kind::CompleteDtorPointer;
|
||||||
|
|
||||||
|
case VTableComponentKind::DeletingDtorPointer:
|
||||||
|
return VTableComponentIR::Kind::DeletingDtorPointer;
|
||||||
|
|
||||||
|
case VTableComponentKind::UnusedFunctionPointer:
|
||||||
|
return VTableComponentIR::Kind::UnusedFunctionPointer;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return VTableComponentIR::Kind::UnusedFunctionPointer;
|
||||||
|
}
|
||||||
|
// Should not be reached
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classes that wrap constructor 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) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRToJsonConverter {
|
||||||
|
private:
|
||||||
|
static void AddTemplateInfo(JsonObject &type_decl,
|
||||||
|
const abi_util::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 &tag_type,
|
||||||
|
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);
|
||||||
|
|
||||||
|
static JsonObject ConvertElfFunctionIR(const ElfFunctionIR *elf_function_ir);
|
||||||
|
|
||||||
|
static JsonObject ConvertElfObjectIR(const ElfObjectIR *elf_object_ir);
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonIRDumper : public IRDumper, public IRToJsonConverter {
|
||||||
|
public:
|
||||||
|
JsonIRDumper(const std::string &dump_path);
|
||||||
|
|
||||||
|
bool AddLinkableMessageIR(const LinkableMessageIR *) override;
|
||||||
|
|
||||||
|
bool AddElfSymbolMessageIR(const ElfSymbolIR *) override;
|
||||||
|
|
||||||
|
bool Dump() override;
|
||||||
|
|
||||||
|
~JsonIRDumper() override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonObject translation_unit_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace abi_util
|
||||||
|
|
||||||
|
#endif // IR_JSON_
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <abi_diff_helpers.h>
|
#include <abi_diff_helpers.h>
|
||||||
#include <ir_representation.h>
|
#include <ir_representation.h>
|
||||||
|
#include <ir_representation_json.h>
|
||||||
#include <ir_representation_protobuf.h>
|
#include <ir_representation_protobuf.h>
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
@@ -40,8 +41,9 @@ std::unique_ptr<IRDumper> IRDumper::CreateIRDumper(
|
|||||||
switch (text_format) {
|
switch (text_format) {
|
||||||
case TextFormatIR::ProtobufTextFormat:
|
case TextFormatIR::ProtobufTextFormat:
|
||||||
return std::make_unique<ProtobufIRDumper>(dump_path);
|
return std::make_unique<ProtobufIRDumper>(dump_path);
|
||||||
|
case TextFormatIR::Json:
|
||||||
|
return std::make_unique<JsonIRDumper>(dump_path);
|
||||||
default:
|
default:
|
||||||
// Nothing else is supported yet.
|
|
||||||
llvm::errs() << "Text format not supported yet\n";
|
llvm::errs() << "Text format not supported yet\n";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,369 @@
|
|||||||
|
// Copyright (C) 2018 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <ir_representation_json.h>
|
||||||
|
|
||||||
|
#include <json/writer.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace abi_util {
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddTemplateInfo(
|
||||||
|
JsonObject &type_decl, const abi_util::TemplatedArtifactIR *template_ir) {
|
||||||
|
Json::Value &elements = type_decl["template_info"];
|
||||||
|
elements = JsonArray();
|
||||||
|
for (auto &&template_element_ir : template_ir->GetTemplateElements()) {
|
||||||
|
Json::Value &element = elements.append(JsonObject());
|
||||||
|
element["referenced_type"] = template_element_ir.GetReferencedType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddTypeInfo(JsonObject &type_decl,
|
||||||
|
const TypeIR *type_ir) {
|
||||||
|
Json::Value &type_info = type_decl["type_info"];
|
||||||
|
type_info = JsonObject();
|
||||||
|
type_info["linker_set_key"] = type_ir->GetLinkerSetKey();
|
||||||
|
type_info["source_file"] = type_ir->GetSourceFile();
|
||||||
|
type_info["name"] = type_ir->GetName();
|
||||||
|
type_info["size"] = Json::UInt64(type_ir->GetSize());
|
||||||
|
type_info["alignment"] = type_ir->GetAlignment();
|
||||||
|
type_info["referenced_type"] = type_ir->GetReferencedType();
|
||||||
|
type_info["self_type"] = type_ir->GetSelfType();
|
||||||
|
}
|
||||||
|
|
||||||
|
static JsonObject ConvertRecordFieldIR(const RecordFieldIR *record_field_ir) {
|
||||||
|
JsonObject record_field;
|
||||||
|
record_field["field_name"] = record_field_ir->GetName();
|
||||||
|
record_field["referenced_type"] = record_field_ir->GetReferencedType();
|
||||||
|
record_field["access"] = AccessIRToJson(record_field_ir->GetAccess());
|
||||||
|
record_field["field_offset"] = Json::UInt64(record_field_ir->GetOffset());
|
||||||
|
return record_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddRecordFields(JsonObject &record_type,
|
||||||
|
const RecordTypeIR *record_ir) {
|
||||||
|
Json::Value &fields = record_type["fields"];
|
||||||
|
fields = JsonArray();
|
||||||
|
for (auto &&field_ir : record_ir->GetFields()) {
|
||||||
|
fields.append(ConvertRecordFieldIR(&field_ir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JsonObject
|
||||||
|
ConvertBaseSpecifierIR(const CXXBaseSpecifierIR &base_specifier_ir) {
|
||||||
|
JsonObject base_specifier;
|
||||||
|
base_specifier["referenced_type"] = base_specifier_ir.GetReferencedType();
|
||||||
|
base_specifier["is_virtual"] = base_specifier_ir.IsVirtual();
|
||||||
|
base_specifier["access"] = AccessIRToJson(base_specifier_ir.GetAccess());
|
||||||
|
return base_specifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddBaseSpecifiers(JsonObject &record_type,
|
||||||
|
const RecordTypeIR *record_ir) {
|
||||||
|
Json::Value &base_specifiers = record_type["base_specifiers"];
|
||||||
|
base_specifiers = JsonArray();
|
||||||
|
for (auto &&base_ir : record_ir->GetBases()) {
|
||||||
|
base_specifiers.append(ConvertBaseSpecifierIR(base_ir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JsonObject
|
||||||
|
ConvertVTableLayoutIR(const VTableLayoutIR &vtable_layout_ir) {
|
||||||
|
JsonObject vtable_layout;
|
||||||
|
Json::Value &vtable_components = vtable_layout["vtable_components"];
|
||||||
|
vtable_components = JsonArray();
|
||||||
|
for (auto &&vtable_component_ir : vtable_layout_ir.GetVTableComponents()) {
|
||||||
|
Json::Value &vtable_component = vtable_components.append(JsonObject());
|
||||||
|
vtable_component["kind"] =
|
||||||
|
VTableComponentKindIRToJson(vtable_component_ir.GetKind());
|
||||||
|
vtable_component["component_value"] =
|
||||||
|
Json::Int64(vtable_component_ir.GetValue());
|
||||||
|
vtable_component["mangled_component_name"] = vtable_component_ir.GetName();
|
||||||
|
vtable_component["is_pure"] = vtable_component_ir.GetIsPure();
|
||||||
|
}
|
||||||
|
return vtable_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddVTableLayout(JsonObject &record_type,
|
||||||
|
const RecordTypeIR *record_ir) {
|
||||||
|
const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout();
|
||||||
|
record_type["vtable_layout"] = ConvertVTableLayoutIR(vtable_layout_ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddTagTypeInfo(JsonObject &record_type,
|
||||||
|
const abi_util::TagTypeIR *tag_type_ir) {
|
||||||
|
Json::Value &tag_type = record_type["tag_info"];
|
||||||
|
tag_type = JsonObject();
|
||||||
|
tag_type["unique_id"] = tag_type_ir->GetUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject IRToJsonConverter::ConvertRecordTypeIR(const RecordTypeIR *recordp) {
|
||||||
|
JsonObject record_type;
|
||||||
|
|
||||||
|
record_type["access"] = AccessIRToJson(recordp->GetAccess());
|
||||||
|
record_type["record_kind"] = RecordKindIRToJson(recordp->GetRecordKind());
|
||||||
|
record_type["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;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject
|
||||||
|
IRToJsonConverter::ConvertElfObjectIR(const ElfObjectIR *elf_object_ir) {
|
||||||
|
JsonObject elf_object;
|
||||||
|
elf_object["name"] = elf_object_ir->GetName();
|
||||||
|
return elf_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject
|
||||||
|
IRToJsonConverter::ConvertElfFunctionIR(const ElfFunctionIR *elf_function_ir) {
|
||||||
|
JsonObject elf_function;
|
||||||
|
elf_function["name"] = elf_function_ir->GetName();
|
||||||
|
return elf_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddFunctionParametersAndSetReturnType(
|
||||||
|
JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) {
|
||||||
|
function["return_type"] = cfunction_like_ir->GetReturnType();
|
||||||
|
AddFunctionParameters(function, cfunction_like_ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddFunctionParameters(
|
||||||
|
JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) {
|
||||||
|
Json::Value ¶meters = function["parameters"];
|
||||||
|
parameters = JsonArray();
|
||||||
|
for (auto &¶meter_ir : cfunction_like_ir->GetParameters()) {
|
||||||
|
Json::Value ¶meter = parameters.append(JsonObject());
|
||||||
|
parameter["referenced_type"] = parameter_ir.GetReferencedType();
|
||||||
|
parameter["default_arg"] = parameter_ir.GetIsDefault();
|
||||||
|
parameter["is_this_ptr"] = parameter_ir.GetIsThisPtr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
function["access"] = AccessIRToJson(functionp->GetAccess());
|
||||||
|
function["linker_set_key"] = functionp->GetLinkerSetKey();
|
||||||
|
function["source_file"] = functionp->GetSourceFile();
|
||||||
|
function["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["name"] = enum_field_ir->GetName();
|
||||||
|
enum_field["enum_field_value"] = Json::Int64(enum_field_ir->GetValue());
|
||||||
|
return enum_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRToJsonConverter::AddEnumFields(JsonObject &enum_type,
|
||||||
|
const EnumTypeIR *enum_ir) {
|
||||||
|
Json::Value &enum_fields = enum_type["enum_fields"];
|
||||||
|
enum_fields = JsonArray();
|
||||||
|
for (auto &&field : enum_ir->GetFields()) {
|
||||||
|
enum_fields.append(ConvertEnumFieldIR(&field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject IRToJsonConverter::ConvertEnumTypeIR(const EnumTypeIR *enump) {
|
||||||
|
JsonObject enum_type;
|
||||||
|
enum_type["access"] = AccessIRToJson(enump->GetAccess());
|
||||||
|
enum_type["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["referenced_type"] = global_varp->GetReferencedType();
|
||||||
|
global_var["source_file"] = global_varp->GetSourceFile();
|
||||||
|
global_var["name"] = global_varp->GetName();
|
||||||
|
global_var["linker_set_key"] = global_varp->GetLinkerSetKey();
|
||||||
|
global_var["access"] = AccessIRToJson(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["is_const"] = qualtypep->IsConst();
|
||||||
|
qualified_type["is_volatile"] = qualtypep->IsVolatile();
|
||||||
|
qualified_type["is_restricted"] = qualtypep->IsRestricted();
|
||||||
|
return qualified_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject
|
||||||
|
IRToJsonConverter::ConvertBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) {
|
||||||
|
JsonObject builtin_type;
|
||||||
|
builtin_type["is_unsigned"] = builtin_typep->IsUnsigned();
|
||||||
|
builtin_type["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 *em) {
|
||||||
|
std::string key;
|
||||||
|
JsonObject elf_symbol;
|
||||||
|
elf_symbol["name"] = em->GetName();
|
||||||
|
switch (em->GetKind()) {
|
||||||
|
case ElfSymbolIR::ElfFunctionKind:
|
||||||
|
key = "elf_functions";
|
||||||
|
break;
|
||||||
|
case ElfSymbolIR::ElfObjectKind:
|
||||||
|
key = "elf_objects";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
translation_unit_[key].append(elf_symbol);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonIRDumper::Dump() {
|
||||||
|
std::ofstream output(dump_path_);
|
||||||
|
Json::StyledStreamWriter writer(/* indentation */ " ");
|
||||||
|
writer.write(output, translation_unit_);
|
||||||
|
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 abi_util
|
||||||
Reference in New Issue
Block a user