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