Home | History | Annotate | Download | only in json
      1 // Copyright (C) 2019 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "repr/json/ir_dumper.h"
     16 
     17 #include "repr/ir_dumper.h"
     18 #include "repr/ir_reader.h"
     19 #include "repr/ir_representation_internal.h"
     20 #include "repr/json/api.h"
     21 #include "repr/json/converter.h"
     22 
     23 #include <json/reader.h>
     24 #include <json/writer.h>
     25 
     26 #include <llvm/Support/raw_ostream.h>
     27 
     28 #include <cstdlib>
     29 #include <fstream>
     30 #include <sstream>
     31 #include <string>
     32 
     33 
     34 namespace header_checker {
     35 namespace repr {
     36 
     37 
     38 static void AddAccess(JsonObject &type_decl, AccessSpecifierIR value) {
     39   if (value != default_access_ir) {
     40     type_decl.Set("access",
     41                   FindInMap(access_ir_to_json, value,
     42                             "Failed to convert AccessSpecifierIR to JSON"));
     43   }
     44 }
     45 
     46 static void AddRecordKind(JsonObject &record_type,
     47                           RecordTypeIR::RecordKind value) {
     48   if (value != default_record_kind_ir) {
     49     record_type.Set("record_kind",
     50                     FindInMap(record_kind_ir_to_json, value,
     51                               "Failed to convert RecordKind to JSON"));
     52   }
     53 }
     54 
     55 static void AddVtableComponentKind(JsonObject &vtable_component,
     56                                    VTableComponentIR::Kind value) {
     57   if (value != default_vtable_component_kind_ir) {
     58     vtable_component.Set(
     59         "kind", FindInMap(vtable_component_kind_ir_to_json, value,
     60                           "Failed to convert VTableComponentIR::Kind to JSON"));
     61   }
     62 }
     63 
     64 static void AddElfSymbolBinding(JsonObject &elf_symbol,
     65                                 ElfSymbolIR::ElfSymbolBinding value) {
     66   if (value != default_elf_symbol_binding_ir) {
     67     elf_symbol.Set("binding",
     68                    FindInMap(elf_symbol_binding_ir_to_json, value,
     69                              "Failed to convert ElfSymbolBinding to JSON"));
     70   }
     71 }
     72 
     73 void IRToJsonConverter::AddTemplateInfo(
     74     JsonObject &type_decl, const TemplatedArtifactIR *template_ir) {
     75   JsonArray args;
     76   for (auto &&template_element_ir : template_ir->GetTemplateElements()) {
     77     args.append(template_element_ir.GetReferencedType());
     78   }
     79   type_decl.Set("template_args", args);
     80 }
     81 
     82 void IRToJsonConverter::AddTypeInfo(JsonObject &type_decl,
     83                                     const TypeIR *type_ir) {
     84   type_decl.Set("linker_set_key", type_ir->GetLinkerSetKey());
     85   type_decl.Set("source_file", type_ir->GetSourceFile());
     86   type_decl.Set("name", type_ir->GetName());
     87   type_decl.Set("size", (uint64_t)type_ir->GetSize());
     88   type_decl.Set("alignment", (uint64_t)type_ir->GetAlignment());
     89   type_decl.Set("referenced_type", type_ir->GetReferencedType());
     90   type_decl.Set("self_type", type_ir->GetSelfType());
     91 }
     92 
     93 static JsonObject ConvertRecordFieldIR(const RecordFieldIR *record_field_ir) {
     94   JsonObject record_field;
     95   record_field.Set("field_name", record_field_ir->GetName());
     96   record_field.Set("referenced_type", record_field_ir->GetReferencedType());
     97   AddAccess(record_field, record_field_ir->GetAccess());
     98   record_field.Set("field_offset", (uint64_t)record_field_ir->GetOffset());
     99   return record_field;
    100 }
    101 
    102 void IRToJsonConverter::AddRecordFields(JsonObject &record_type,
    103                                         const RecordTypeIR *record_ir) {
    104   JsonArray fields;
    105   for (auto &&field_ir : record_ir->GetFields()) {
    106     fields.append(ConvertRecordFieldIR(&field_ir));
    107   }
    108   record_type.Set("fields", fields);
    109 }
    110 
    111 static JsonObject
    112 ConvertBaseSpecifierIR(const CXXBaseSpecifierIR &base_specifier_ir) {
    113   JsonObject base_specifier;
    114   base_specifier.Set("referenced_type", base_specifier_ir.GetReferencedType());
    115   base_specifier.Set("is_virtual", base_specifier_ir.IsVirtual());
    116   AddAccess(base_specifier, base_specifier_ir.GetAccess());
    117   return base_specifier;
    118 }
    119 
    120 void IRToJsonConverter::AddBaseSpecifiers(JsonObject &record_type,
    121                                           const RecordTypeIR *record_ir) {
    122   JsonArray base_specifiers;
    123   for (auto &&base_ir : record_ir->GetBases()) {
    124     base_specifiers.append(ConvertBaseSpecifierIR(base_ir));
    125   }
    126   record_type.Set("base_specifiers", base_specifiers);
    127 }
    128 
    129 static JsonObject
    130 ConvertVTableComponentIR(const VTableComponentIR &vtable_component_ir) {
    131   JsonObject vtable_component;
    132   AddVtableComponentKind(vtable_component, vtable_component_ir.GetKind());
    133   vtable_component.Set("component_value",
    134                        (int64_t)vtable_component_ir.GetValue());
    135   vtable_component.Set("mangled_component_name", vtable_component_ir.GetName());
    136   vtable_component.Set("is_pure", vtable_component_ir.GetIsPure());
    137   return vtable_component;
    138 }
    139 
    140 void IRToJsonConverter::AddVTableLayout(JsonObject &record_type,
    141                                         const RecordTypeIR *record_ir) {
    142   JsonArray vtable_components;
    143   for (auto &&vtable_component_ir :
    144        record_ir->GetVTableLayout().GetVTableComponents()) {
    145     vtable_components.append(ConvertVTableComponentIR(vtable_component_ir));
    146   }
    147   record_type.Set("vtable_components", vtable_components);
    148 }
    149 
    150 void IRToJsonConverter::AddTagTypeInfo(JsonObject &type_decl,
    151                                        const TagTypeIR *tag_type_ir) {
    152   type_decl.Set("unique_id", tag_type_ir->GetUniqueId());
    153 }
    154 
    155 JsonObject IRToJsonConverter::ConvertRecordTypeIR(const RecordTypeIR *recordp) {
    156   JsonObject record_type;
    157 
    158   AddAccess(record_type, recordp->GetAccess());
    159   AddRecordKind(record_type, recordp->GetRecordKind());
    160   record_type.Set("is_anonymous", recordp->IsAnonymous());
    161   AddTypeInfo(record_type, recordp);
    162   AddRecordFields(record_type, recordp);
    163   AddBaseSpecifiers(record_type, recordp);
    164   AddVTableLayout(record_type, recordp);
    165   AddTagTypeInfo(record_type, recordp);
    166   AddTemplateInfo(record_type, recordp);
    167   return record_type;
    168 }
    169 
    170 void IRToJsonConverter::AddFunctionParametersAndSetReturnType(
    171     JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) {
    172   function.Set("return_type", cfunction_like_ir->GetReturnType());
    173   AddFunctionParameters(function, cfunction_like_ir);
    174 }
    175 
    176 void IRToJsonConverter::AddFunctionParameters(
    177     JsonObject &function, const CFunctionLikeIR *cfunction_like_ir) {
    178   JsonArray parameters;
    179   for (auto &&parameter_ir : cfunction_like_ir->GetParameters()) {
    180     JsonObject parameter;
    181     parameter.Set("referenced_type", parameter_ir.GetReferencedType());
    182     parameter.Set("default_arg", parameter_ir.GetIsDefault());
    183     parameter.Set("is_this_ptr", parameter_ir.GetIsThisPtr());
    184     parameters.append(parameter);
    185   }
    186   function.Set("parameters", parameters);
    187 }
    188 
    189 JsonObject
    190 IRToJsonConverter::ConvertFunctionTypeIR(const FunctionTypeIR *function_typep) {
    191   JsonObject function_type;
    192   AddTypeInfo(function_type, function_typep);
    193   AddFunctionParametersAndSetReturnType(function_type, function_typep);
    194   return function_type;
    195 }
    196 
    197 JsonObject IRToJsonConverter::ConvertFunctionIR(const FunctionIR *functionp) {
    198   JsonObject function;
    199   AddAccess(function, functionp->GetAccess());
    200   function.Set("linker_set_key", functionp->GetLinkerSetKey());
    201   function.Set("source_file", functionp->GetSourceFile());
    202   function.Set("function_name", functionp->GetName());
    203   AddFunctionParametersAndSetReturnType(function, functionp);
    204   AddTemplateInfo(function, functionp);
    205   return function;
    206 }
    207 
    208 static JsonObject ConvertEnumFieldIR(const EnumFieldIR *enum_field_ir) {
    209   JsonObject enum_field;
    210   enum_field.Set("name", enum_field_ir->GetName());
    211   // Never omit enum values.
    212   enum_field["enum_field_value"] = Json::Int64(enum_field_ir->GetValue());
    213   return enum_field;
    214 }
    215 
    216 void IRToJsonConverter::AddEnumFields(JsonObject &enum_type,
    217                                       const EnumTypeIR *enum_ir) {
    218   JsonArray enum_fields;
    219   for (auto &&field : enum_ir->GetFields()) {
    220     enum_fields.append(ConvertEnumFieldIR(&field));
    221   }
    222   enum_type.Set("enum_fields", enum_fields);
    223 }
    224 
    225 JsonObject IRToJsonConverter::ConvertEnumTypeIR(const EnumTypeIR *enump) {
    226   JsonObject enum_type;
    227   AddAccess(enum_type, enump->GetAccess());
    228   enum_type.Set("underlying_type", enump->GetUnderlyingType());
    229   AddTypeInfo(enum_type, enump);
    230   AddEnumFields(enum_type, enump);
    231   AddTagTypeInfo(enum_type, enump);
    232   return enum_type;
    233 }
    234 
    235 JsonObject
    236 IRToJsonConverter::ConvertGlobalVarIR(const GlobalVarIR *global_varp) {
    237   JsonObject global_var;
    238   global_var.Set("referenced_type", global_varp->GetReferencedType());
    239   global_var.Set("source_file", global_varp->GetSourceFile());
    240   global_var.Set("name", global_varp->GetName());
    241   global_var.Set("linker_set_key", global_varp->GetLinkerSetKey());
    242   AddAccess(global_var, global_varp->GetAccess());
    243   return global_var;
    244 }
    245 
    246 JsonObject
    247 IRToJsonConverter::ConvertPointerTypeIR(const PointerTypeIR *pointerp) {
    248   JsonObject pointer_type;
    249   AddTypeInfo(pointer_type, pointerp);
    250   return pointer_type;
    251 }
    252 
    253 JsonObject
    254 IRToJsonConverter::ConvertQualifiedTypeIR(const QualifiedTypeIR *qualtypep) {
    255   JsonObject qualified_type;
    256   AddTypeInfo(qualified_type, qualtypep);
    257   qualified_type.Set("is_const", qualtypep->IsConst());
    258   qualified_type.Set("is_volatile", qualtypep->IsVolatile());
    259   qualified_type.Set("is_restricted", qualtypep->IsRestricted());
    260   return qualified_type;
    261 }
    262 
    263 JsonObject
    264 IRToJsonConverter::ConvertBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) {
    265   JsonObject builtin_type;
    266   builtin_type.Set("is_unsigned", builtin_typep->IsUnsigned());
    267   builtin_type.Set("is_integral", builtin_typep->IsIntegralType());
    268   AddTypeInfo(builtin_type, builtin_typep);
    269   return builtin_type;
    270 }
    271 
    272 JsonObject
    273 IRToJsonConverter::ConvertArrayTypeIR(const ArrayTypeIR *array_typep) {
    274   JsonObject array_type;
    275   AddTypeInfo(array_type, array_typep);
    276   return array_type;
    277 }
    278 
    279 JsonObject IRToJsonConverter::ConvertLvalueReferenceTypeIR(
    280     const LvalueReferenceTypeIR *lvalue_reference_typep) {
    281   JsonObject lvalue_reference_type;
    282   AddTypeInfo(lvalue_reference_type, lvalue_reference_typep);
    283   return lvalue_reference_type;
    284 }
    285 
    286 JsonObject IRToJsonConverter::ConvertRvalueReferenceTypeIR(
    287     const RvalueReferenceTypeIR *rvalue_reference_typep) {
    288   JsonObject rvalue_reference_type;
    289   AddTypeInfo(rvalue_reference_type, rvalue_reference_typep);
    290   return rvalue_reference_type;
    291 }
    292 
    293 bool JsonIRDumper::AddLinkableMessageIR(const LinkableMessageIR *lm) {
    294   std::string key;
    295   JsonObject converted;
    296   // No RTTI
    297   switch (lm->GetKind()) {
    298   case RecordTypeKind:
    299     key = "record_types";
    300     converted = ConvertRecordTypeIR(static_cast<const RecordTypeIR *>(lm));
    301     break;
    302   case EnumTypeKind:
    303     key = "enum_types";
    304     converted = ConvertEnumTypeIR(static_cast<const EnumTypeIR *>(lm));
    305     break;
    306   case PointerTypeKind:
    307     key = "pointer_types";
    308     converted = ConvertPointerTypeIR(static_cast<const PointerTypeIR *>(lm));
    309     break;
    310   case QualifiedTypeKind:
    311     key = "qualified_types";
    312     converted =
    313         ConvertQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm));
    314     break;
    315   case ArrayTypeKind:
    316     key = "array_types";
    317     converted = ConvertArrayTypeIR(static_cast<const ArrayTypeIR *>(lm));
    318     break;
    319   case LvalueReferenceTypeKind:
    320     key = "lvalue_reference_types";
    321     converted = ConvertLvalueReferenceTypeIR(
    322         static_cast<const LvalueReferenceTypeIR *>(lm));
    323     break;
    324   case RvalueReferenceTypeKind:
    325     key = "rvalue_reference_types";
    326     converted = ConvertRvalueReferenceTypeIR(
    327         static_cast<const RvalueReferenceTypeIR *>(lm));
    328     break;
    329   case BuiltinTypeKind:
    330     key = "builtin_types";
    331     converted = ConvertBuiltinTypeIR(static_cast<const BuiltinTypeIR *>(lm));
    332     break;
    333   case FunctionTypeKind:
    334     key = "function_types";
    335     converted = ConvertFunctionTypeIR(static_cast<const FunctionTypeIR *>(lm));
    336     break;
    337   case GlobalVarKind:
    338     key = "global_vars";
    339     converted = ConvertGlobalVarIR(static_cast<const GlobalVarIR *>(lm));
    340     break;
    341   case FunctionKind:
    342     key = "functions";
    343     converted = ConvertFunctionIR(static_cast<const FunctionIR *>(lm));
    344     break;
    345   default:
    346     return false;
    347   }
    348   translation_unit_[key].append(converted);
    349   return true;
    350 }
    351 
    352 bool JsonIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *elf_symbol_ir) {
    353   std::string key;
    354   switch (elf_symbol_ir->GetKind()) {
    355   case ElfSymbolIR::ElfFunctionKind:
    356     key = "elf_functions";
    357     break;
    358   case ElfSymbolIR::ElfObjectKind:
    359     key = "elf_objects";
    360     break;
    361   default:
    362     return false;
    363   }
    364   JsonObject elf_symbol;
    365   elf_symbol.Set("name", elf_symbol_ir->GetName());
    366   AddElfSymbolBinding(elf_symbol, elf_symbol_ir->GetBinding());
    367   translation_unit_[key].append(elf_symbol);
    368   return true;
    369 }
    370 
    371 static std::string DumpJson(const JsonObject &obj) {
    372   std::ostringstream output_stream;
    373   Json::StyledStreamWriter writer(/* indentation */ " ");
    374   writer.write(output_stream, obj);
    375   return output_stream.str();
    376 }
    377 
    378 static void WriteTailTrimmedLinesToFile(const std::string &path,
    379                                         const std::string &output_string) {
    380   std::ofstream output_file(path);
    381   size_t line_start = 0;
    382   while (line_start < output_string.size()) {
    383     size_t trailing_space_start = line_start;
    384     size_t index;
    385     for (index = line_start;
    386          index < output_string.size() && output_string[index] != '\n';
    387          index++) {
    388       if (output_string[index] != ' ') {
    389         trailing_space_start = index + 1;
    390       }
    391     }
    392     // Only write this line if this line contains non-whitespace characters.
    393     if (trailing_space_start != line_start) {
    394       output_file.write(output_string.data() + line_start,
    395                         trailing_space_start - line_start);
    396       output_file.write("\n", 1);
    397     }
    398     line_start = index + 1;
    399   }
    400 }
    401 
    402 bool JsonIRDumper::Dump(const ModuleIR &module) {
    403   DumpModule(module);
    404   std::string output_string = DumpJson(translation_unit_);
    405   WriteTailTrimmedLinesToFile(dump_path_, output_string);
    406   return true;
    407 }
    408 
    409 JsonIRDumper::JsonIRDumper(const std::string &dump_path)
    410     : IRDumper(dump_path), translation_unit_() {
    411   const std::string keys[] = {
    412     "record_types",
    413     "enum_types",
    414     "pointer_types",
    415     "lvalue_reference_types",
    416     "rvalue_reference_types",
    417     "builtin_types",
    418     "qualified_types",
    419     "array_types",
    420     "function_types",
    421     "functions",
    422     "global_vars",
    423     "elf_functions",
    424     "elf_objects",
    425   };
    426   for (auto key : keys) {
    427     translation_unit_[key] = JsonArray();
    428   }
    429 }
    430 
    431 std::unique_ptr<IRDumper> CreateJsonIRDumper(const std::string &dump_path) {
    432   return std::make_unique<JsonIRDumper>(dump_path);
    433 }
    434 
    435 
    436 }  // namespace repr
    437 }  // header_checker
    438