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 &¶meter_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