1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2 // -*- mode: C++ -*- 3 // 4 // Copyright 2020-2024 Google LLC 5 // 6 // Licensed under the Apache License v2.0 with LLVM Exceptions (the 7 // "License"); you may not use this file except in compliance with the 8 // License. You may obtain a copy of the License at 9 // 10 // https://llvm.org/LICENSE.txt 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 // 18 // Author: Maria Teguiani 19 // Author: Giuliano Procida 20 // Author: Ignes Simeonova 21 22 #ifndef STG_COMPARISON_H_ 23 #define STG_COMPARISON_H_ 24 25 #include <cstddef> 26 #include <cstdint> 27 #include <functional> 28 #include <optional> 29 #include <ostream> 30 #include <string> 31 #include <string_view> 32 #include <unordered_map> 33 #include <utility> 34 #include <vector> 35 36 #include "graph.h" 37 #include "runtime.h" 38 39 namespace stg { 40 namespace diff { 41 42 struct Ignore { 43 enum Value { 44 // noise reduction 45 SYMBOL_TYPE_PRESENCE, 46 TYPE_DECLARATION_STATUS, 47 PRIMITIVE_TYPE_ENCODING, 48 MEMBER_SIZE, 49 ENUM_UNDERLYING_TYPE, 50 QUALIFIER, 51 SYMBOL_CRC, 52 // ABI compatibility testing 53 INTERFACE_ADDITION, 54 TYPE_DEFINITION_ADDITION, 55 }; 56 57 using Bitset = uint16_t; 58 59 Ignore() = default; 60 template <typename... Values> IgnoreIgnore61 explicit Ignore(Values... values) { 62 for (auto value : {values...}) { 63 Set(value); 64 } 65 } 66 SetIgnore67 void Set(Value other) { 68 bitset = bitset | (1 << other); 69 } TestIgnore70 bool Test(Value other) const { 71 return (bitset & (1 << other)) != 0; 72 } 73 74 Bitset bitset = 0; 75 }; 76 77 std::optional<Ignore::Value> ParseIgnore(std::string_view ignore); 78 79 struct IgnoreUsage {}; 80 std::ostream& operator<<(std::ostream& os, IgnoreUsage); 81 82 using Comparison = std::pair<std::optional<Id>, std::optional<Id>>; 83 84 struct DiffDetail { DiffDetailDiffDetail85 DiffDetail(const std::string& text, const Comparison& edge) 86 : text(text), edge(edge) {} 87 std::string text; 88 Comparison edge; 89 }; 90 91 struct Diff { 92 // This diff node corresponds to an entity that is reportable, if it or any of 93 // its children (excluding reportable ones) has changed. 94 bool holds_changes = false; 95 // This diff node contains a local (non-recursive) change. 96 bool has_changes = false; 97 std::vector<DiffDetail> details; 98 AddDiff99 void Add(const std::string& text, const Comparison& comparison) { 100 details.emplace_back(text, comparison); 101 } 102 }; 103 104 struct HashComparison { operatorHashComparison105 size_t operator()(const Comparison& comparison) const { 106 size_t seed = 0; 107 const std::hash<std::optional<Id>> h; 108 combine_hash(seed, h(comparison.first)); 109 combine_hash(seed, h(comparison.second)); 110 return seed; 111 } combine_hashHashComparison112 static void combine_hash(size_t& seed, size_t hash) { 113 seed ^= hash + 0x9e3779b97f4a7c15 + (seed << 12) + (seed >> 4); 114 } 115 }; 116 117 using Outcomes = std::unordered_map<Comparison, Diff, HashComparison>; 118 119 std::pair<Id, std::vector<std::string>> ResolveTypedefs( 120 const Graph& graph, Id id); 121 122 Comparison Compare(Runtime& runtime, Ignore ignore, const Graph& graph, 123 Id root1, Id root2, Outcomes& outcomes); 124 125 } // namespace diff 126 } // namespace stg 127 128 #endif // STG_COMPARISON_H_ 129