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 #ifndef HEADER_CHECKER_REPR_IR_READER_H_ 16 #define HEADER_CHECKER_REPR_IR_READER_H_ 17 18 #include "repr/ir_representation.h" 19 20 #include <cstdint> 21 #include <list> 22 #include <memory> 23 #include <set> 24 #include <string> 25 #include <utility> 26 27 28 namespace header_checker { 29 namespace repr { 30 31 32 class IRReader { 33 public: 34 struct MergeStatus { MergeStatusMergeStatus35 MergeStatus(bool was_newly_added, const std::string &type_id) 36 : was_newly_added_(was_newly_added), type_id_(type_id) {} 37 MergeStatusMergeStatus38 MergeStatus() {} 39 40 // type_id_ always has the global_type_id corresponding to the type this 41 // MergeStatus corresponds to. For 42 // generic reference types (pointers, qual types, l(r)value references etc), 43 // this will be a proactively added type_id, which will be added to the 44 // parent type_graph if the we decide to add the referencing type to the 45 // parent post ODR checking. 46 bool was_newly_added_ = false; 47 48 std::string type_id_; 49 }; 50 51 public: IRReader(const std::set<std::string> * exported_headers)52 IRReader(const std::set<std::string> *exported_headers) 53 : module_(new ModuleIR(exported_headers)) {} 54 ~IRReader()55 virtual ~IRReader() {} 56 57 virtual bool ReadDump(const std::string &dump_file) = 0; 58 GetModule()59 ModuleIR &GetModule() { 60 return *module_; 61 } 62 TakeModule()63 std::unique_ptr<ModuleIR> TakeModule() { 64 return std::move(module_); 65 } 66 Merge(IRReader && addend)67 void Merge(IRReader &&addend) { 68 MergeElements(&module_->functions_, std::move(addend.module_->functions_)); 69 MergeElements(&module_->global_variables_, 70 std::move(addend.module_->global_variables_)); 71 MergeElements(&module_->record_types_, 72 std::move(addend.module_->record_types_)); 73 MergeElements(&module_->enum_types_, 74 std::move(addend.module_->enum_types_)); 75 MergeElements(&module_->pointer_types_, 76 std::move(addend.module_->pointer_types_)); 77 MergeElements(&module_->lvalue_reference_types_, 78 std::move(addend.module_->lvalue_reference_types_)); 79 MergeElements(&module_->rvalue_reference_types_, 80 std::move(addend.module_->rvalue_reference_types_)); 81 MergeElements(&module_->array_types_, 82 std::move(addend.module_->array_types_)); 83 MergeElements(&module_->builtin_types_, 84 std::move(addend.module_->builtin_types_)); 85 MergeElements(&module_->qualified_types_, 86 std::move(addend.module_->qualified_types_)); 87 } 88 89 template <typename T> 90 MergeStatus MergeReferencingTypeInternalAndUpdateParent( 91 const IRReader &addend, const T *addend_node, 92 AbiElementMap<MergeStatus> *local_to_global_type_id_map, 93 AbiElementMap<T> *parent_map, const std::string &updated_self_type_id); 94 95 MergeStatus DoesUDTypeODRViolationExist( 96 const TypeIR *ud_type, const IRReader &addend, 97 const std::string &ud_type_unique_id, 98 AbiElementMap<MergeStatus> *local_to_global_type_id_map_); 99 100 MergeStatus MergeReferencingTypeInternal( 101 const IRReader &addend, ReferencesOtherType *references_type, 102 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 103 104 MergeStatus MergeReferencingType( 105 const IRReader &addend, const TypeIR *addend_node, 106 AbiElementMap<MergeStatus> *local_to_global_type_id_map, 107 const std::string &updated_self_type_id); 108 109 MergeStatus MergeGenericReferringType( 110 const IRReader &addend, const TypeIR *addend_node, 111 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 112 113 template <typename T> 114 std::pair<MergeStatus, typename AbiElementMap<T>::iterator> 115 UpdateUDTypeAccounting( 116 const T *addend_node, const IRReader &addend, 117 AbiElementMap<MergeStatus> *local_to_global_type_id_map, 118 AbiElementMap<T> *specific_type_map); 119 120 MergeStatus MergeTypeInternal( 121 const TypeIR *addend_node, const IRReader &addend, 122 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 123 124 void MergeCFunctionLikeDeps( 125 const IRReader &addend, CFunctionLikeIR *cfunction_like_ir, 126 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 127 128 MergeStatus MergeFunctionType( 129 const FunctionTypeIR *addend_node, const IRReader &addend, 130 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 131 132 MergeStatus MergeEnumType( 133 const EnumTypeIR *addend_node, const IRReader &addend, 134 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 135 136 void MergeEnumDependencies( 137 const IRReader &addend, EnumTypeIR *added_node, 138 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 139 140 MergeStatus MergeRecordAndDependencies( 141 const RecordTypeIR *addend_node, const IRReader &addend, 142 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 143 144 void MergeRecordDependencies( 145 const IRReader &addend, RecordTypeIR *added_node, 146 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 147 148 void MergeRecordFields( 149 const IRReader &addend, RecordTypeIR *added_node, 150 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 151 152 void MergeRecordCXXBases( 153 const IRReader &addend, RecordTypeIR *added_node, 154 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 155 156 void MergeRecordTemplateElements( 157 const IRReader &addend, RecordTypeIR *added_node, 158 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 159 160 MergeStatus IsBuiltinTypeNodePresent( 161 const BuiltinTypeIR *builtin_type, const IRReader &addend, 162 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 163 164 void MergeGlobalVariable( 165 const GlobalVarIR *addend_node, const IRReader &addend, 166 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 167 168 void MergeGlobalVariables( 169 const IRReader &addend, 170 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 171 172 void MergeFunctionDeps( 173 FunctionIR *added_node, const IRReader &addend, 174 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 175 176 void MergeFunction( 177 const FunctionIR *addend_node, const IRReader &addend, 178 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 179 180 void MergeGraphs(const IRReader &addend); 181 182 void UpdateIRReaderTypeGraph( 183 const TypeIR *addend_node, const std::string &added_type_id, 184 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 185 186 MergeStatus IsTypeNodePresent( 187 const TypeIR *addend_node, const IRReader &addend, 188 AbiElementMap<MergeStatus> *local_to_global_type_id_map); 189 190 MergeStatus MergeType( 191 const TypeIR *addend_type, const IRReader &addend, 192 AbiElementMap<MergeStatus> *merged_types_cache); 193 194 std::string AllocateNewTypeId(); 195 196 static std::unique_ptr<IRReader> CreateIRReader( 197 TextFormatIR text_format, 198 const std::set<std::string> *exported_headers = nullptr); 199 200 protected: 201 template <typename Augend, typename Addend> MergeElements(Augend * augend,Addend && addend)202 inline void MergeElements(Augend *augend, Addend &&addend) { 203 augend->insert(std::make_move_iterator(addend.begin()), 204 std::make_move_iterator(addend.end())); 205 } 206 207 std::unique_ptr<ModuleIR> module_; 208 209 uint64_t max_type_id_ = 0; 210 }; 211 212 213 } // namespace repr 214 } // namespace header_checker 215 216 217 #endif // HEADER_CHECKER_REPR_IR_READER_H_ 218