blob: addca8894f7d05c473ea6a54ce9ea5364895f7ec [file] [log] [blame]
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "repr/json/ir_reader.h"
#include "repr/ir_dumper.h"
#include "repr/ir_reader.h"
#include "repr/ir_representation_internal.h"
#include "repr/json/api.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 const std::map<std::string, AccessSpecifierIR>
access_json_to_ir(CreateInverseMap(access_ir_to_json));
static const std::map<std::string, RecordTypeIR::RecordKind>
record_kind_json_to_ir(CreateInverseMap(record_kind_ir_to_json));
static const std::map<std::string, VTableComponentIR::Kind>
vtable_component_kind_json_to_ir(
CreateInverseMap(vtable_component_kind_ir_to_json));
static const std::map<std::string, ElfSymbolIR::ElfSymbolBinding>
elf_symbol_binding_json_to_ir(
CreateInverseMap(elf_symbol_binding_ir_to_json));
JsonObjectRef::JsonObjectRef(const Json::Value &json_value, bool &ok)
: object_(json_value.isObject() ? json_value : json_empty_object), ok_(ok) {
if (!json_value.isObject()) {
ok_ = false;
}
}
const Json::Value &
JsonObjectRef::Get(const std::string &key, const Json::Value &default_value,
IsExpectedJsonType is_expected_type) const {
if (!object_.isMember(key)) {
return default_value;
}
const Json::Value &value = object_[key];
if (!(value.*is_expected_type)()) {
ok_ = false;
return default_value;
}
return value;
}
bool JsonObjectRef::GetBool(const std::string &key) const {
return Get(key, json_false, &Json::Value::isBool).asBool();
}
int64_t JsonObjectRef::GetInt(const std::string &key) const {
return Get(key, json_0, &Json::Value::isIntegral).asInt64();
}
uint64_t JsonObjectRef::GetUint(const std::string &key) const {
return Get(key, json_0, &Json::Value::isIntegral).asUInt64();
}
std::string JsonObjectRef::GetString(const std::string &key) const {
return Get(key, json_empty_string, &Json::Value::isString).asString();
}
JsonObjectRef JsonObjectRef::GetObject(const std::string &key) const {
return JsonObjectRef(Get(key, json_empty_object, &Json::Value::isObject),
ok_);
}
JsonArrayRef<JsonObjectRef>
JsonObjectRef::GetObjects(const std::string &key) const {
return JsonArrayRef<JsonObjectRef>(
Get(key, json_empty_array, &Json::Value::isArray), ok_);
}
JsonArrayRef<std::string>
JsonObjectRef::GetStrings(const std::string &key) const {
return JsonArrayRef<std::string>(
Get(key, json_empty_array, &Json::Value::isArray), ok_);
}
template <>
JsonObjectRef JsonArrayRef<JsonObjectRef>::Iterator::operator*() const {
return JsonObjectRef(array_[index_], ok_);
}
template <> std::string JsonArrayRef<std::string>::Iterator::operator*() const {
return array_[index_].asString();
}
static AccessSpecifierIR GetAccess(const JsonObjectRef &type_decl) {
std::string access(type_decl.GetString("access"));
if (access.empty()) {
return default_access_ir;
}
return FindInMap(access_json_to_ir, access,
"Failed to convert JSON to AccessSpecifierIR");
}
static RecordTypeIR::RecordKind
GetRecordKind(const JsonObjectRef &record_type) {
std::string kind(record_type.GetString("record_kind"));
if (kind.empty()) {
return default_record_kind_ir;
}
return FindInMap(record_kind_json_to_ir, kind,
"Failed to convert JSON to RecordKind");
}
static VTableComponentIR::Kind
GetVTableComponentKind(const JsonObjectRef &vtable_component) {
std::string kind(vtable_component.GetString("kind"));
if (kind.empty()) {
return default_vtable_component_kind_ir;
}
return FindInMap(vtable_component_kind_json_to_ir, kind,
"Failed to convert JSON to VTableComponentIR::Kind");
}
static ElfSymbolIR::ElfSymbolBinding
GetElfSymbolBinding(const JsonObjectRef &elf_symbol) {
std::string binding(elf_symbol.GetString("binding"));
if (binding.empty()) {
return default_elf_symbol_binding_ir;
}
return FindInMap(elf_symbol_binding_json_to_ir, binding,
"Failed to convert JSON to ElfSymbolBinding");
}
bool JsonIRReader::ReadDumpImpl(const std::string &dump_file) {
Json::Value tu_json;
Json::CharReaderBuilder builder;
builder["collectComments"] = false;
std::ifstream input(dump_file);
std::string errorMessage;
if (!Json::parseFromStream(builder, input, &tu_json, &errorMessage)) {
llvm::errs() << "Failed to parse JSON: " << errorMessage << "\n";
return false;
}
bool ok = true;
JsonObjectRef tu(tu_json, ok);
if (!ok) {
llvm::errs() << "Translation unit is not an object\n";
return false;
}
ReadFunctions(tu);
ReadGlobalVariables(tu);
ReadEnumTypes(tu);
ReadRecordTypes(tu);
ReadFunctionTypes(tu);
ReadArrayTypes(tu);
ReadPointerTypes(tu);
ReadQualifiedTypes(tu);
ReadBuiltinTypes(tu);
ReadLvalueReferenceTypes(tu);
ReadRvalueReferenceTypes(tu);
ReadElfFunctions(tu);
ReadElfObjects(tu);
if (!ok) {
llvm::errs() << "Failed to convert JSON to IR\n";
return false;
}
return true;
}
void JsonIRReader::ReadTemplateInfo(const JsonObjectRef &type_decl,
TemplatedArtifactIR *template_ir) {
TemplateInfoIR template_info_ir;
for (auto &&referenced_type : type_decl.GetStrings("template_args")) {
TemplateElementIR template_element_ir(referenced_type);
template_info_ir.AddTemplateElement(std::move(template_element_ir));
}
template_ir->SetTemplateInfo(std::move(template_info_ir));
}
void JsonIRReader::ReadTypeInfo(const JsonObjectRef &type_decl,
TypeIR *type_ir) {
type_ir->SetLinkerSetKey(type_decl.GetString("linker_set_key"));
type_ir->SetSourceFile(type_decl.GetString("source_file"));
type_ir->SetName(type_decl.GetString("name"));
type_ir->SetReferencedType(type_decl.GetString("referenced_type"));
type_ir->SetSelfType(type_decl.GetString("self_type"));
type_ir->SetSize(type_decl.GetUint("size"));
type_ir->SetAlignment(type_decl.GetUint("alignment"));
}
void JsonIRReader::ReadRecordFields(const JsonObjectRef &record_type,
RecordTypeIR *record_ir) {
for (auto &&field : record_type.GetObjects("fields")) {
RecordFieldIR record_field_ir(
field.GetString("field_name"), field.GetString("referenced_type"),
field.GetUint("field_offset"), GetAccess(field));
record_ir->AddRecordField(std::move(record_field_ir));
}
}
void JsonIRReader::ReadBaseSpecifiers(const JsonObjectRef &record_type,
RecordTypeIR *record_ir) {
for (auto &&base_specifier : record_type.GetObjects("base_specifiers")) {
CXXBaseSpecifierIR record_base_ir(
base_specifier.GetString("referenced_type"),
base_specifier.GetBool("is_virtual"), GetAccess(base_specifier));
record_ir->AddCXXBaseSpecifier(std::move(record_base_ir));
}
}
void JsonIRReader::ReadVTableLayout(const JsonObjectRef &record_type,
RecordTypeIR *record_ir) {
VTableLayoutIR vtable_layout_ir;
for (auto &&vtable_component : record_type.GetObjects("vtable_components")) {
VTableComponentIR vtable_component_ir(
vtable_component.GetString("mangled_component_name"),
GetVTableComponentKind(vtable_component),
vtable_component.GetInt("component_value"),
vtable_component.GetBool("is_pure"));
vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir));
}
record_ir->SetVTableLayout(std::move(vtable_layout_ir));
}
void JsonIRReader::ReadEnumFields(const JsonObjectRef &enum_type,
EnumTypeIR *enum_ir) {
for (auto &&field : enum_type.GetObjects("enum_fields")) {
EnumFieldIR enum_field_ir(field.GetString("name"),
field.GetInt("enum_field_value"));
enum_ir->AddEnumField(std::move(enum_field_ir));
}
}
void JsonIRReader::ReadFunctionParametersAndReturnType(
const JsonObjectRef &function, CFunctionLikeIR *function_ir) {
function_ir->SetReturnType(function.GetString("return_type"));
for (auto &&parameter : function.GetObjects("parameters")) {
ParamIR param_ir(parameter.GetString("referenced_type"),
parameter.GetBool("default_arg"),
parameter.GetBool("is_this_ptr"));
function_ir->AddParameter(std::move(param_ir));
}
}
FunctionIR JsonIRReader::FunctionJsonToIR(const JsonObjectRef &function) {
FunctionIR function_ir;
function_ir.SetLinkerSetKey(function.GetString("linker_set_key"));
function_ir.SetName(function.GetString("function_name"));
function_ir.SetAccess(GetAccess(function));
function_ir.SetSourceFile(function.GetString("source_file"));
ReadFunctionParametersAndReturnType(function, &function_ir);
ReadTemplateInfo(function, &function_ir);
return function_ir;
}
FunctionTypeIR
JsonIRReader::FunctionTypeJsonToIR(const JsonObjectRef &function_type) {
FunctionTypeIR function_type_ir;
ReadTypeInfo(function_type, &function_type_ir);
ReadFunctionParametersAndReturnType(function_type, &function_type_ir);
return function_type_ir;
}
RecordTypeIR
JsonIRReader::RecordTypeJsonToIR(const JsonObjectRef &record_type) {
RecordTypeIR record_type_ir;
ReadTypeInfo(record_type, &record_type_ir);
ReadTemplateInfo(record_type, &record_type_ir);
record_type_ir.SetAccess(GetAccess(record_type));
ReadVTableLayout(record_type, &record_type_ir);
ReadRecordFields(record_type, &record_type_ir);
ReadBaseSpecifiers(record_type, &record_type_ir);
record_type_ir.SetRecordKind(GetRecordKind(record_type));
record_type_ir.SetAnonymity(record_type.GetBool("is_anonymous"));
return record_type_ir;
}
EnumTypeIR JsonIRReader::EnumTypeJsonToIR(const JsonObjectRef &enum_type) {
EnumTypeIR enum_type_ir;
ReadTypeInfo(enum_type, &enum_type_ir);
enum_type_ir.SetUnderlyingType(enum_type.GetString("underlying_type"));
enum_type_ir.SetAccess(GetAccess(enum_type));
ReadEnumFields(enum_type, &enum_type_ir);
return enum_type_ir;
}
void JsonIRReader::ReadGlobalVariables(const JsonObjectRef &tu) {
for (auto &&global_variable : tu.GetObjects("global_vars")) {
GlobalVarIR global_variable_ir;
global_variable_ir.SetName(global_variable.GetString("name"));
global_variable_ir.SetAccess(GetAccess(global_variable));
global_variable_ir.SetSourceFile(global_variable.GetString("source_file"));
global_variable_ir.SetReferencedType(
global_variable.GetString("referenced_type"));
global_variable_ir.SetLinkerSetKey(
global_variable.GetString("linker_set_key"));
module_->AddGlobalVariable(std::move(global_variable_ir));
}
}
void JsonIRReader::ReadPointerTypes(const JsonObjectRef &tu) {
for (auto &&pointer_type : tu.GetObjects("pointer_types")) {
PointerTypeIR pointer_type_ir;
ReadTypeInfo(pointer_type, &pointer_type_ir);
module_->AddPointerType(std::move(pointer_type_ir));
}
}
void JsonIRReader::ReadBuiltinTypes(const JsonObjectRef &tu) {
for (auto &&builtin_type : tu.GetObjects("builtin_types")) {
BuiltinTypeIR builtin_type_ir;
ReadTypeInfo(builtin_type, &builtin_type_ir);
builtin_type_ir.SetSignedness(builtin_type.GetBool("is_unsigned"));
builtin_type_ir.SetIntegralType(builtin_type.GetBool("is_integral"));
module_->AddBuiltinType(std::move(builtin_type_ir));
}
}
void JsonIRReader::ReadQualifiedTypes(const JsonObjectRef &tu) {
for (auto &&qualified_type : tu.GetObjects("qualified_types")) {
QualifiedTypeIR qualified_type_ir;
ReadTypeInfo(qualified_type, &qualified_type_ir);
qualified_type_ir.SetConstness(qualified_type.GetBool("is_const"));
qualified_type_ir.SetVolatility(qualified_type.GetBool("is_volatile"));
qualified_type_ir.SetRestrictedness(
qualified_type.GetBool("is_restricted"));
module_->AddQualifiedType(std::move(qualified_type_ir));
}
}
void JsonIRReader::ReadArrayTypes(const JsonObjectRef &tu) {
for (auto &&array_type : tu.GetObjects("array_types")) {
ArrayTypeIR array_type_ir;
ReadTypeInfo(array_type, &array_type_ir);
array_type_ir.SetUnknownBound(array_type.GetBool("is_of_unknown_bound"));
module_->AddArrayType(std::move(array_type_ir));
}
}
void JsonIRReader::ReadLvalueReferenceTypes(const JsonObjectRef &tu) {
for (auto &&lvalue_reference_type : tu.GetObjects("lvalue_reference_types")) {
LvalueReferenceTypeIR lvalue_reference_type_ir;
ReadTypeInfo(lvalue_reference_type, &lvalue_reference_type_ir);
module_->AddLvalueReferenceType(std::move(lvalue_reference_type_ir));
}
}
void JsonIRReader::ReadRvalueReferenceTypes(const JsonObjectRef &tu) {
for (auto &&rvalue_reference_type : tu.GetObjects("rvalue_reference_types")) {
RvalueReferenceTypeIR rvalue_reference_type_ir;
ReadTypeInfo(rvalue_reference_type, &rvalue_reference_type_ir);
module_->AddRvalueReferenceType(std::move(rvalue_reference_type_ir));
}
}
void JsonIRReader::ReadFunctions(const JsonObjectRef &tu) {
for (auto &&function : tu.GetObjects("functions")) {
FunctionIR function_ir = FunctionJsonToIR(function);
module_->AddFunction(std::move(function_ir));
}
}
void JsonIRReader::ReadRecordTypes(const JsonObjectRef &tu) {
for (auto &&record_type : tu.GetObjects("record_types")) {
RecordTypeIR record_type_ir = RecordTypeJsonToIR(record_type);
module_->AddRecordType(std::move(record_type_ir));
}
}
void JsonIRReader::ReadFunctionTypes(const JsonObjectRef &tu) {
for (auto &&function_type : tu.GetObjects("function_types")) {
FunctionTypeIR function_type_ir = FunctionTypeJsonToIR(function_type);
module_->AddFunctionType(std::move(function_type_ir));
}
}
void JsonIRReader::ReadEnumTypes(const JsonObjectRef &tu) {
for (auto &&enum_type : tu.GetObjects("enum_types")) {
EnumTypeIR enum_type_ir = EnumTypeJsonToIR(enum_type);
module_->AddEnumType(std::move(enum_type_ir));
}
}
void JsonIRReader::ReadElfFunctions(const JsonObjectRef &tu) {
for (auto &&elf_function : tu.GetObjects("elf_functions")) {
ElfFunctionIR elf_function_ir(elf_function.GetString("name"),
GetElfSymbolBinding(elf_function));
module_->AddElfFunction(std::move(elf_function_ir));
}
}
void JsonIRReader::ReadElfObjects(const JsonObjectRef &tu) {
for (auto &&elf_object : tu.GetObjects("elf_objects")) {
ElfObjectIR elf_object_ir(elf_object.GetString("name"),
GetElfSymbolBinding(elf_object));
module_->AddElfObject(std::move(elf_object_ir));
}
}
std::unique_ptr<IRReader> CreateJsonIRReader(
const std::set<std::string> *exported_headers) {
return std::make_unique<JsonIRReader>(exported_headers);
}
} // namespace repr
} // header_checker